Chroma 教程

id 的规则

🎉摘要:本文介绍了Chroma中Collection的id必须是字符串类型且全局唯一;重复id调用add静默忽略;使用update/upsert覆盖数据;建议使用有业务含义的id。

Chroma 的 Collection 中,id 是字符串,同一个 Collection 下,id 全局唯一。

不同 Collection、不同 Database、不同 Tenant 之间,id 互不冲突。

注意:id 只能是字符串类型,哪怕存数字语义,也必须写成字符串 "1",不能传整数 1,否则直接报错。例如:

import chromadb

# 获取内存模式客户端
client = chromadb.EphemeralClient()

# 获取集合,如果集合不存在,则创建集合
col = client.get_or_create_collection("demo_col", embedding_function=None)

# 写入数据
col.add(ids=["m1"], embeddings=[[1, 0, 0]])
print("字符串 id 添加成功")

col.add(ids=[2], embeddings=[[1, 1, 0]])
print("数字 id 添加成功")

运行示例,输出如下:

字符串 id 添加成功
Traceback (most recent call last):
...
ValueError: Expected ID to be a str, got 2 in add.

除此以外,还有几个要注意的,如下:

(1)重复的 id 调用 add 不会报错,会被静默忽略(不是覆盖)。例如:

import chromadb

# 获取内存模式客户端
client = chromadb.EphemeralClient()

# 获取集合,如果集合不存在,则创建集合
col = client.get_or_create_collection("demo_col", embedding_function=None)

# 写入数据,两条数据id相同
col.add(ids=["m1"], embeddings=[[1, 0, 0]])
col.add(ids=["m1"], embeddings=[[0, 1, 0]])   # 这句无效,不报错
print(f"集合中,向量数量:{col.count()}")   # 还是 1,embedding 还是 [1,0,0]

try:
    # get 默认不返回向量,只返回元信息,可通过 include 配置返回那些信息 
    datas = col.get(ids=["m1"], include=["embeddings", "documents", "metadatas"])
    print(f"查询结果:{datas}")
except Exception as e:
    print("看看集合列表时出错:", type(e).__name__, e)

运行上面代码,输出如下:

集合中,向量数量:1
查询结果:{'ids': ['m1'], 'embeddings': array([[1., 0., 0.]]), 'documents': [None], 
'uris': None, 'included': ['embeddings', 'documents', 'metadatas'], 
'data': None, 'metadatas': [None]}

从输出得知,id 为 m1 的记录,embeddings 还是 [1., 0., 0.],并没有被 [0, 1, 0] 覆盖。

(2)要覆盖请用 upsert 或 update,这是新手最常见的困惑之一。例如:

import chromadb

# 获取内存模式客户端
client = chromadb.EphemeralClient()

# 获取集合,如果集合不存在,则创建集合
col = client.get_or_create_collection("demo_col", embedding_function=None)

# 写入数据,两条数据id相同
col.add(ids=["m1"], embeddings=[[1, 0, 0]])
datas = col.get(ids=["m1"], include=["embeddings", "documents", "metadatas"])
print(f"add -> 查询结果:ids={datas["ids"]}, embeddings={datas["embeddings"]}")

# 使用 update 更新数据
col.update(ids=["m1"], embeddings=[[0, 1, 0]])
datas = col.get(ids=["m1"], include=["embeddings", "documents", "metadatas"])
print(f"update -> 查询结果:ids={datas["ids"]}, embeddings={datas["embeddings"]}")

# 使用 upsert 更新数据
col.upsert(ids=["m1"], embeddings=[[0, 0, 1]])
datas = col.get(ids=["m1"], include=["embeddings", "documents", "metadatas"])
print(f"upsert -> 查询结果:ids={datas["ids"]}, embeddings={datas["embeddings"]}")

运行上面代码,输出如下:

add -> 查询结果:ids=['m1'], embeddings=[[1. 0. 0.]]
update -> 查询结果:ids=['m1'], embeddings=[[0. 1. 0.]]
upsert -> 查询结果:ids=['m1'], embeddings=[[0. 0. 1.]]

一些建议:

(1)建议用有业务含义的 id,比如 f"{doc_id}_chunk_{idx}"。这样去重、更新、删除都方便,也方便跟主库对齐。

(2)id 不参与检索,但它可以在 query 里当过滤条件(ids=["id1","id2"] 表示只在这几条里搜)。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号