add() 方法用于向指定的集合添加数据。
方法签名如下:
collection.add(
ids, # 必填,str 或 List[str]
embeddings, # 可选,二维 float 数组
metadatas, # 可选,dict 或 List[dict]
documents, # 可选,str 或 List[str]
images, # 可选,np.ndarray 或 List[np.ndarray]
uris, # 可选,str 或 List[str]
)参数详细说明:
类型为 str | List[str],表示每条记录的唯一主键 ID,ID 重复会抛出 DuplicateIDError 错误,例如:
import chromadb
client = chromadb.EphemeralClient()
# 获取集合
col = client.get_or_create_collection("demo_collection", embedding_function=None)
# 添加数据
col.add(
ids=["r1", "r1"],
metadatas=[
{"cat": "售后"},
{"cat": "财务"}
],
documents=[
"退款流程:在订单页点申请退款",
"发票开具:在订单详情页申请电子发票"
],
)运行示例,输出错误信息如下:
chromadb.errors.DuplicateIDError: Expected IDs to be unique, found duplicates of: r1 in add.
注意:
集合内 ID 必须唯一,add 遇到重复 ID 直接抛异常 DuplicateIDError(这一点和 upsert 不同,upsert 会覆盖)
推荐业务唯一标识,如 chunk_001、doc_pdf_page_5
批量传入时,ids[0]对应第 0 条记录,和其他数组下标对应,示例:ids=["id_01", "id_02"]
类型为 List[List[float]] 二维浮点数组,每一行是一条向量。
用来存放你提前算好的向量,直接存入索引,Chroma 不再调用 EmbeddingFunction 计算向量,推荐这样做。例如:
import chromadb
client = chromadb.EphemeralClient()
col = client.get_or_create_collection("demo_col", embedding_function=None)
col.add(
ids=["d1", "d2"],
embeddings=[
[1.001, 1.002, 1.003],
[0.980, 1.102, 0.996]
],
documents=["今天天气不错", "明天要下雨"],
metadatas=[
{"source": "news"},
{"source": "weather"}
],
)
print(f"集合合计数量 {col.count()}")
# 结果:
# 集合合计数量 2注意:
向量维度必须和集合内已存在向量维度完全一致,否则报错,例如:
import chromadb
client = chromadb.EphemeralClient()
col = client.get_or_create_collection("demo_col", embedding_function=None)
# 向量维度为 3
col.add(
ids=["d1", "d2"],
embeddings=[
[1.001, 1.002, 1.003],
[0.980, 1.102, 0.996]
],
documents=["今天天气不错", "明天要下雨"],
metadatas=[
{"source": "news"},
{"source": "weather"}
],
)
# 向量维度为 5
col.add(
ids=["d3"],
embeddings=[
[1.001, 1.002, 1.003, 1.459, 0.896],
],
documents=["今天天气不错"],
metadatas=[
{"source": "news"},
],
)运行上面代码,你会收到如下错误信息:
chromadb.errors.InvalidArgumentError: Collection expecting embedding with dimension of 3, got 5
类型为 dict | List[Optional[dict]],用来存储每条记录的元数据,用于 where 条件过滤检索。
支持的值类型有 str / int / float / bool,也支持一维数组,但是不支持嵌套复杂对象。如果单条记录为 None 代表这条记录没有元数据。
注意:批量添加数据时,列表长度必须等于 ids 长度。
示例,见 embeddings 参数。
类型为 str | List[str],用来存储原始文本片段(chunk),Chroma 会原样存储文本,query 的时候可以取回原文。
如果你不想自己计算向量,可以交给集合的 EmbeddingFunction 自动计算,实际使用中,推荐自己使用中文嵌入模型进行计算。
类型为 np.ndarray | List[np.ndarray],用于存储图像像素数组,配合多模态 EmbeddingFunction(OpenCLIP)使用,自动生成图片向量。适合多模态场景,纯文本 RAG 一般不用这个参数。
类型为 str | List[str],存储资源定位地址(本地文件路径 /http 链接) ,标记文档原始文件路径。
在多模态图片场景中,配合多模态 Embedding,从 URI 读取图片。
下面介绍三种 col.add() 方法的写法:
写法一:只给文本,让 Chroma 帮你算向量
col.add(
ids=["d1", "d2"],
documents=["今天天气不错", "明天要下雨"],
metadatas=[{"source": "news"}, {"source": "weather"}],
)这是最省事的写法,但有两个前提:集合挂了嵌入函数,且你能接受它的速度。每批都要过一遍模型,几千条数据能让你等上好一会儿。
写法二:只给向量
col.add(
ids=["d1", "d2"],
embeddings=[[0.12, -0.33, 0.58], [0.44, 0.21, -0.09]],
metadatas=[{"source": "news"}, {"source": "weather"}],
)注意,没有 documents。这样查回来的 documents 是 None,只有 metadata 和距离。通常在主库已经存了正文、Chroma 只用来找 id 的场景下这么干,能省一半存储空间。
写法三:两个都给(最推荐)
col.add(
ids=["d1", "d2"],
embeddings=[[0.12, -0.33, 0.58], [0.44, 0.21, -0.09]],
documents=["今天天气不错", "明天要下雨"],
)你已经有向量了,Chroma 不会重算;同时把原文存进去,查的时候能直接拿到文本。
如果你觉得写列表麻烦,不想写列表的时候,可以直接传标量,ids/documents/uris 都支持:
import chromadb
client = chromadb.EphemeralClient()
col = client.get_or_create_collection("demo_col", embedding_function=None)
col.add(
ids="d1",
embeddings=[1.001, 1.002, 1.003],
documents="今天天气不错",
metadatas={"source": "news"},
)不过实际项目里我很少这么写,统一用列表省得后面批量化要改代码。
ids、embeddings、documents、metadatas、uris 这几个,只要传了就必须是同样的长度(或者标量)。对不上会直接报 ValueError。例如:
import chromadb
client = chromadb.EphemeralClient()
col = client.get_or_create_collection("demo_col", embedding_function=None)
col.add(
ids=["d1", "d2"],
embeddings=[
[1.001, 1.002, 1.003],
[0.980, 1.102, 0.996]
],
documents=["今天天气不错", "明天要下雨", "这里长度不一致"], # 看这里
metadatas=[
{"source": "news"},
{"source": "weather"}
],
)运行上面代码,你将得到如下错误:
ValueError: Unequal lengths for fields: ids: 2, metadatas: 2, embeddings: 2, documents: 3 in add.
这是全章最重要的一条:
import chromadb
client = chromadb.EphemeralClient()
col = client.get_or_create_collection("demo_col", embedding_function=None)
col.add(ids=["m1"], embeddings=[[1, 0, 0]], documents=["第一版"])
col.add(ids=["m1"], embeddings=[[0, 1, 0]], documents=["第二版"])
print(col.count()) # 1
print(col.get(ids=["m1"])["documents"]) # ['第一版']第二次 add 没有任何反应,也不报错。 你以为更新了,其实什么都没发生。
想要 "有就更新,没有就插入",用 upsert。
col.add(ids=["a"], embeddings=[[1, 0, 0]]) # 集合维度变成 3
col.add(ids=["b"], embeddings=[[1, 0, 0, 0]]) # 报错chromadb.errors.InvalidArgumentError: Collection expecting embedding with
dimension of 3, got 4集合的维度由第一条写入的数据决定,之后就锁死了。