codewithkyrian/chromadb-php

Chroma开源嵌入数据库的PHP客户端

0.3.0 2024-06-15 23:19 UTC

This package is auto-updated.

Last update: 2024-09-04 12:57:12 UTC


README

一个用于无缝与Chroma矢量数据库交互的PHP库。

Total Downloads Latest Version on Packagist MIT Licensed GitHub Tests Action Status

注意:此包与框架无关,可以在任何PHP项目中使用。如果您使用Laravel,您可能想查看此处的特定于Laravel的包,它提供更接近Laravel的体验,并包含一些额外功能。

描述

Chroma是一个开源的矢量数据库,允许您按比例存储、搜索和分析高维数据。它旨在快速、可扩展和可靠。它使构建需要高维矢量搜索的LLM(大型语言模型)应用程序和服务变得容易。

ChromaDB PHP为从PHP与Chroma交互提供了一个简单直观的接口。它使您能够

  • 创建、读取、更新和删除文档。
  • 执行查询和聚合。
  • 管理集合和索引。
  • 处理身份验证和授权。
  • 无缝利用其他ChromaDB功能。
  • 等等...

小示例

use Codewithkyrian\ChromaDB\ChromaDB;

$chromaDB = ChromaDB::client();

// Check current ChromaDB version
echo $chromaDB->version();

// Create a collection
$collection = $chromaDB->createCollection('test-collection');

echo $collection->name; // test-collection
echo $collection->id; // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx

// Insert some documents into the collection
$ids = ['test1', 'test2', 'test3'];
$embeddings = [
    [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0],
    [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0],
    [10.0, 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0],
];
$metadatas = [
    ['url' => 'https://example.com/test1'],
    ['url' => 'https://example.com/test2'],
    ['url' => 'https://example.com/test3'],
];

$collection->add($ids, $embeddings, $metadatas);

// Search for similar embeddings
$queryResponse = $collection->query(
    queryEmbeddings: [
        [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
    ],
    nResults: 2
);

// Print results
echo $queryResponse->ids[0][0]; // test1
echo $queryResponse->ids[0][1]; // test2

要求

  • PHP 8.1或更高版本
  • 运行在客户端/服务器模式下的ChromaDB 0.4.0或更高版本

运行ChromaDB

为了使用此库,您需要在某处运行ChromaDB。您可以本地运行它或在云端运行。(Chroma目前不支持云端,但很快就会支持。)

目前,ChromaDB只能在Python中以内存中运行。但是,您可以通过运行python项目或使用docker镜像(推荐)以客户端/服务器模式运行它。

要运行docker镜像,您可以使用以下命令

docker run -p 8000:8000 chromadb/chroma

您还可以使用.env文件传递一些环境变量

docker run -p 8000:8000 --env-file .env chromadb/chroma

或者如果您更喜欢使用docker-compose文件,可以使用以下

version: '3.9'

services:
  chroma:
    image: 'chromadb/chroma'
    ports:
      - '8000:8000'
    volumes:
      - chroma-data:/chroma/chroma

volumes:
  chroma-data:
    driver: local

然后使用以下命令运行它

docker-compose up -d

(有关如何运行ChromaDB的更多信息,请参阅Chroma文档。)

无论如何,您现在可以在http://localhost:8000访问ChromaDB。

安装

composer require codewithkyrian/chromadb-php

使用

连接到ChromaDB

use Codewithkyrian\ChromaDB\ChromaDB;

$chroma = ChromaDB::client();

默认情况下,ChromaDB将尝试使用默认数据库名称default_database和默认租户名称default_tenant连接到http://localhost:8000。但是,您可以通过使用工厂方法构造客户端来更改这些值。

use Codewithkyrian\ChromaDB\ChromaDB;

$chroma = ChromaDB::factory()
                ->withHost('http://localhost')
                ->withPort(8000)
                ->withDatabase('new_database')
                ->withTenant('new_tenant')
                ->connect();                

如果租户或数据库不存在,该包将自动为您创建它们。

身份验证

ChromaDB支持基于静态令牌的身份验证。要使用它,您需要按照文档中的说明启动Chroma服务器,传递所需的环境变量。如果您使用的是docker镜像,您可以使用--env标志或使用.env文件传递环境变量,对于docker-compose文件,您可以使用env_file选项或直接传递环境变量,如下所示

version: '3.9'
  
services:
  chroma:
    image: 'chromadb/chroma'
    ports:
      - '8000:8000'
    environment:
      - CHROMA_SERVER_AUTHN_CREDENTIALS=test-token
      - CHROMA_SERVER_AUTHN_PROVIDER=chromadb.auth.token_authn.TokenAuthenticationServerProvider
      
    ...

然后您可以使用工厂方法连接到ChromaDB

use Codewithkyrian\ChromaDB\ChromaDB;

$chroma = ChromaDB::factory()
                ->withAuthToken('test-token')
                ->connect();                

获取版本

echo $chroma->version(); // 0.4.0

创建集合

创建集合就像在客户端上调用createCollection方法并将集合名称传递给它一样简单。

$collection = $chroma->createCollection('test-collection');

如果集合已存在于数据库中,包将抛出异常。

插入文档

$ids = ['test1', 'test2', 'test3'];
$embeddings = [
    [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0],
    [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0],
    [10.0, 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0],
];
$metadatas = [
    ['url' => 'https://example.com/test1'],
    ['url' => 'https://example.com/test2'],
    ['url' => 'https://example.com/test3'],
];

$collection->add($ids, $embeddings, $metadatas);

要将文档插入到集合中,您需要提供以下内容

  • ids:文档ID数组。ID必须是唯一的,并且必须是字符串。
  • embeddings:文档嵌入数组。嵌入必须是长度一致的浮点数一维数组。您可以使用任何选择的嵌入模型来计算嵌入(只需确保在查询时也使用它即可)。
  • metadatas:文档元数据数组。元数据必须是键值对数组。

如果没有嵌入,可以传入文档并提供一个嵌入函数,该函数将用于为您计算嵌入。

传递嵌入函数

要使用嵌入函数,需要在创建集合时将其作为参数传入

use CodeWithKyrian\ChromaDB\EmbeddingFunction\EmbeddingFunctionInterface;

$embeddingFunction = new OpenAIEmbeddingFunction('api-key', 'org-id', 'model-name');

$collection = $chroma->createCollection('test-collection', embeddingFunction: $embeddingFunction);

嵌入函数必须是EmbeddingFunctionInterface的实例。有几个内置的嵌入函数可以用于

  • OpenAIEmbeddingFunction:此嵌入函数使用OpenAI API来计算嵌入。您可以使用它如下

    use CodeWithKyrian\Chroma\EmbeddingFunction\OpenAIEmbeddingFunction;
    
    $embeddingFunction = new OpenAIEmbeddingFunction('api-key', 'org-id', 'model-name');
    
    $collection = $chromaDB->createCollection('test-collection', embeddingFunction: $embeddingFunction);

    您可以从OpenAI仪表板获取您的OpenAI API密钥和组织ID,如果您的API密钥不属于组织,则可以省略组织ID。模型名称是可选的,默认为text-embedding-ada-002

  • JinaEmbeddingFunction:这是Jina嵌入模型的包装器。您可以通过传递您的Jina API密钥和所需的模型来使用它。默认为jina-embeddings-v2-base-en

    use Codewithkyrian\ChromaDB\Embeddings\JinaEmbeddingFunction;
    
    $embeddingFunction = new JinaEmbeddingFunction('api-key');
    
    $collection = $chromaDB->createCollection('test-collection', embeddingFunction: $embeddingFunction);
  • HuggingFaceEmbeddingServerFunction:此嵌入函数是HuggingFace Text Embedding Server的包装器。在使用之前,您需要在本地某处运行HuggingFace嵌入服务器。以下是使用方法

    use CodeWithKyrian\Chroma\EmbeddingFunction\HuggingFaceEmbeddingFunction;
    
    $embeddingFunction = new HuggingFaceEmbeddingFunction('api-key', 'model-name');
    
    $collection = $chromaDB->createCollection('test-collection', embeddingFunction: $embeddingFunction);

除了内置的嵌入函数外,您还可以通过实现EmbeddingFunction接口(包括匿名类)来创建自己的嵌入函数

use CodeWithKyrian\ChromaDB\EmbeddingFunction\EmbeddingFunctionInterface;

$embeddingFunction = new class implements EmbeddingFunctionInterface {
    public function generate(array $texts): array
    {
        // Compute the embeddings here and return them as an array of arrays
    }
};

$collection = $chroma->createCollection('test-collection', embeddingFunction: $embeddingFunction);

嵌入函数将为每个插入到集合中的文档批次调用,必须在创建集合或查询集合时提供。如果您不提供嵌入函数,并且不提供嵌入,则包将抛出异常。

使用嵌入函数将文档插入到集合中

$ids = ['test1', 'test2', 'test3'];
$documents = [
    'This is a test document',
    'This is another test document',
    'This is yet another test document',
];
$metadatas = [
    ['url' => 'https://example.com/test1'],
    ['url' => 'https://example.com/test2'],
    ['url' => 'https://example.com/test3'],
];

$collection->add(
    ids: $ids, 
    documents: $documents, 
    metadatas: $metadatas
);

获取集合

$collection = $chromaDB->getCollection('test-collection');

或使用嵌入函数

$collection = $chromaDB->getCollection('test-collection', embeddingFunction: $embeddingFunction);

请确保您提供的嵌入函数与创建集合时使用的嵌入函数相同。

统计集合中的项目数

$collection->count() // 2

更新集合

$collection->update(
    ids: ['test1', 'test2', 'test3'],
    embeddings: [
        [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0],
        [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0],
        [10.0, 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0],
    ],
    metadatas: [
        ['url' => 'https://example.com/test1'],
        ['url' => 'https://example.com/test2'],
        ['url' => 'https://example.com/test3'],
    ]
);

删除文档

$collection->delete(['test1', 'test2', 'test3']);

查询集合

$queryResponse = $collection->query(
    queryEmbeddings: [
        [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
    ],
    nResults: 2
);

echo $queryResponse->ids[0][0]; // test1
echo $queryResponse->ids[0][1]; // test2

要查询集合,您需要提供以下内容

  • queryEmbeddings(可选):查询嵌入数组。嵌入必须是浮点数一维数组。您可以使用任何选择的嵌入模型来计算嵌入(只需确保在插入时也使用它即可)。

  • nResults:要返回的结果数量。默认为10。

  • queryTexts(可选):查询文本数组。文本必须是字符串。如果您提供嵌入,则可以省略此内容。以下是一个示例

    $queryResponse = $collection->query(
        queryTexts: [
            'This is a test document'
        ],
        nResults: 2
    );
    
    echo $queryResponse->ids[0][0]; // test1
    echo $queryResponse->ids[0][1]; // test2
  • where(可选):用于根据其元数据过滤项目的where子句。以下是一个示例

    $queryResponse = $collection->query(
        queryEmbeddings: [
            [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
        ],
        nResults: 2,
        where: [
            'url' => 'https://example.com/test1'
        ]
    );
        
    echo $queryResponse->ids[0][0]; // test1

    where子句必须是一个键值对数组。键必须是字符串,值可以是字符串或有效过滤器值数组。以下是有效过滤器($eq$ne$in$nin$gt$gte$lt$lte)。

    • $eq:等于
    • $ne:不等于
    • $gt:大于
    • $gte:大于等于
    • $lt:小于
    • $lte:小于等于

    以下是一个示例

      $queryResponse = $collection->query(
          queryEmbeddings: [
              [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
          ],
          nResults: 2,
          where: [
              'url' => [
                  '$eq' => 'https://example.com/test1'
              ]
          ]
      );

    您还可以使用多个过滤器

        $queryResponse = $collection->query(
            queryEmbeddings: [
                [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
            ],
            nResults: 2,
            where: [
                'url' => [
                    '$eq' => 'https://example.com/test1'
                ],
                'title' => [
                    '$ne' => 'Test 1'
                ]
            ]
        );
  • whereDocument(可选):用于根据文档过滤项的where子句。以下是一个示例

    $queryResponse = $collection->query(
        queryEmbeddings: [
            [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
        ],
        nResults: 2,
        whereDocument: [
            'text' => 'This is a test document'
        ]
    );
            
    echo $queryResponse->ids[0][0]; // test1

    where子句必须是一个键值对数组。键必须是字符串,值可以是字符串或有效过滤器值数组。在这种情况下,只支持两个过滤键$contains$not_contains

    以下是一个示例

      $queryResponse = $collection->query(
          queryEmbeddings: [
              [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
          ],
          nResults: 2,
          whereDocument: [
              'text' => [
                  '$contains' => 'test document'
              ]
          ]
      );
  • include(可选):要包含在响应中的字段数组。可能的值是embeddingsdocumentsmetadatasdistances。默认为embeddingsmetadatas(默认不包含documents,因为它们可能很大)。

    $queryResponse = $collection->query(
        queryEmbeddings: [
            [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
        ],
        nResults: 2,
        include: ['embeddings']
    );

    distances仅适用于查询,不适用于获取。它返回查询嵌入与结果嵌入之间的距离。

有关查询和检索集合的其他相关信息,请参阅ChromaDB 文档

删除集合中的项

要删除集合中的文档,传递一个包含项ID的数组

$collection->delete(['test1', 'test2']);

$collection->count() // 1

传递ID是可选的。您可以使用where过滤器从集合中删除项

$collection->add(
    ['test1', 'test2', 'test3'],
    [
        [1.0, 2.0, 3.0, 4.0, 5.0],
        [6.0, 7.0, 8.0, 9.0, 10.0],
        [11.0, 12.0, 13.0, 14.0, 15.0],
    ], 
     [
        ['some' => 'metadata1'],
        ['some' => 'metadata2'],
        ['some' => 'metadata3'],
    ]
);

$collection->delete(
    where: [
        'some' => 'metadata1'
    ]
);

$collection->count() // 2

删除集合

删除集合就像传递要删除的集合名称一样简单。

$chroma->deleteCollection('test_collection');

测试

// Run chroma by running the docker compose file in the repo
docker compose up -d

composer test

贡献者

许可证

本项目采用MIT许可证。有关更多信息,请参阅LICENSE文件。