概述
Chroma 是向量数据库,存向量用的。拥有针对向量的查询能力,根据向量的距离远近查询,这一点和传统数据库不一样。
安装与简单使用
用 pip install chromadb
命令安装。
为了创建数据库实例,先要创建一个 client。
import chromadb
chroma_client = chromadb.Client()
借助 client 创建一个 collection。这个 collection 就是实际的数据库对象了。
collection = chroma_client.create_collection(name="my_collection")
数据库的每项数据包含以下要素:
- ids,独一无二的标识
- documents,数据本体。通常是文本
- metadatas(可选),数据的额外描述
- embeddings(可选),
- uris(可选),指向
- data(可选)
可以这样向 collection 添加内容:
collection.add(
documents=["This is a document about pineapple", "This is a document about oranges"],
ids=["id1", "id2"],
)
查询:
results = collection.query(
query_texts=["This is a query document about hawaii"], # Chroma will embed this for you
n_results=2, # how many results to return
)
results
会是一个字典:
{
'documents': [[
'This is a document about pineapple',
'This is a document about oranges'
]],
'ids': [['id1', 'id2']],
'distances': [[1.0404009819030762, 1.243080496788025]],
'uris': None,
'data': None,
'metadatas': [[None, None]],
'embeddings': None,
}
数据库实例化
import chromadb
client
为了创建数据库实例,先要创建一个 client。
chroma_client = chromadb.Client()
除了 Client()
,也可以用 PersistentClient()
创建一个指定了持久化存储位置的 client。指定位置已有文件时 client 会自动从其加载。
client = chromadb.PersistentClient(path="/path/to/save/to")
创建好 client 后,可以用其自带的方法:
client.heartbeat() # 返回纳秒 heartbeat。用于确认 client 的连接状态
client.reset() # 清空并重置。不可逆
以上是直接创建 client 的方法。还有 server mode,可以让数据库服务独立于 python 脚本运行。以下的第一条命令在终端中运行。
chroma run --path /db_path
import chromadb
chroma_client = chromadb.HttpClient(host='localhost', port=8000)
若某个机器上只运行 server 而不涉及用 chromadb 开发,那台机器可以只安装 chromadb-client
包。
chromadb-client
没有默认的 embedding 生成方法。必须手动传入。
collection
collection 的实例化
借助 client 创建一个 collection。这个 collection 就是实际的数据库对象了。
collection = chroma_client.create_collection(name="my_collection")
由于 chroma 会用 name
生成 url,这个 name
有以下限制:
- 长度 3 到 63 个字符
- 开头和结尾只能是小写字母或数字
- 不能包含两个连续的点
- 不能是有效的 IP 地址
毕竟是向量数据库,在创建 collection 时可以指定自己的 embedding 方法。若不指定,默认使用 all-minilm-l6-v2 模型。
client.create_collection(name="my_collection")
可额外传入
embedding_function
指定自己的 embedding 方法,若不指定则会使用默认的 all-minilm-l6-v2 模型。获取已有 collection 时必须传入与创建时相同的embedding_function
。也可以不用管这个embedding_function
,在存数据时把 embedding 一并传入就行。可额外传入
metadata
参数指定其他设置。需要传入一个字典,
"hnsw:space"
,这个键可自定义 embedding 距离的计算方法。例如"cosine"
指定为余弦相似度,默认的"L2"
是欧氏距离
client 里与 collection 相关的方法:
create_collection(name)
,创建新 collection,并返回对象get_collection(name)
,获取已有的 collection,并返回对象get_or_create_collection(name)
,有则获取,没有则创建,并返回对象delete_collection(name)
,删除已有的 collection
collection 的方法:
peek()
,返回该 collection 中头 10 个数据。通常用于预览 collection 内容count()
,返回 collection 的数据条目数modify(name)
,重命名
collection 添加数据
collection.add(
ids=["id1", "id2", "id3", ...]
documents=["doc1", "doc2", "doc3", ...],
metadatas=[{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
embeddings=[[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2], ...],
)
ids
,必须传入的、独一无二标识。若出现重复,会导致新数据不被存入documents
,数据本体。若没提供embeddings
则会自动用documents
生成metadatas
,给一条数据标记一个字典,可以用于条件过滤embeddings
,手动传入的 embedding
可以选择不传入
documents
,而是传入ids
metadatas
embeddings
这样的组合。
collection 查询数据
collection.query(
query_embeddings=[[11.1, 12.1, 13.1],[1.1, 2.3, 3.2], ...],
n_results=10,
where={"metadata_field": "is_equal_to_this"},
where_document={"$contains":"search_string"}
)
collection.get(
ids=["id1", "id2", "id3", ...],
where={"style": "style1"}
)
query_embeddings
,用于查询的 embedding。可以一次查询多个 embeddingn_results
,对每个查询 embedding 返回多少个查询结果where
通过metadatas
限制查询,where_document
通过documents
限制查询ids
,通过独一无二的 id 获取数据
也可以不传入
query_embeddings
而是传入query_texts
进行查询。Chroma 会用预先设定的方法将字符串转换为 embedding。对于
collection.get()
,若没有传入ids
参数,就会只根据where
进行查询。
返回值会是一个字典:
{
'documents': [[
'This is a document about pineapple',
'This is a document about oranges'
]],
'ids': [['id1', 'id2']],
'distances': [[1.0404009819030762, 1.243080496788025]],
'uris': None,
'data': None,
'metadatas': [[None, None]],
'embeddings': None,
}
若只想要其中的一部分,可以在查询时传入 include
参数。
collection.query(
query_embeddings=[[11.1, 12.1, 13.1],[1.1, 2.3, 3.2], ...],
include=["documents"]
)
collection 更新数据
collection.update(
ids=["id1", "id2", "id3", ...],
documents=["doc1", "doc2", "doc3", ...],
metadatas=[{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
embeddings=[[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2], ...],
)
使用 update()
更新不存在的 id 时会发生错误。可以用 upsert()
在 id 不存在时就插入新数据:
collection.upsert(
ids=["id1", "id2", "id3", ...],
embeddings=[[1.1, 2.3, 3.2], [4.5, 6.9, 4.4], [1.1, 2.3, 3.2], ...],
metadatas=[{"chapter": "3", "verse": "16"}, {"chapter": "3", "verse": "5"}, {"chapter": "29", "verse": "11"}, ...],
documents=["doc1", "doc2", "doc3", ...],
)
collection 删除数据
collection.delete(
ids=["id1", "id2", "id3",...],
where={"chapter": "20"}
)
可以仅传入 where
而不传入 ids
。