两者均是用来获取集合,但是又存在一些差异。
用于获取已经存在的集合。如果集合不存在,直接抛异常。该方法适合你确定集合一定已经提前建好的场景。
方法签名如下:
col = client.get_collection(
name: str, # 集合名称
embedding_function = None # 嵌入函数
)注意:
(1)1.5.9 会把 embedding function 的配置持久存入集合元信息。get_collection 不传 embedding_function,会自动加载持久化的那个,不会抛异常。如果你手动传了另一个 embedding_function,只是当前客户端会话覆盖持久化的 ef,不会报错。但不推荐这么做(向量维度不匹配会在 add/query 时报错)。
(2)构建期参数 space、ef_construction、max_neighbors 不可以修改,一旦创建后,永久固定,想改只能克隆 / 重建集合。
(3)调用 client.get_collection(name="xxx"),服务端会返回该集合持久保存的 configuration(含hnsw)、metadata、embedding 配置,不需要在 get_collection 里再次填写 hnsw 参数。
示例:在 create_collection() 和 get_collection() 时使用不同的 embedding_function,并不会报错。如果在调用 add() 时 embedding_function 计算出的向量维度不一致会报错,如 768 和 1024。
import chromadb
# 默认嵌入函数
from chromadb.api import DefaultEmbeddingFunction
# 导入自定义的函数
from common.custom_embedding import AliQwenEmbeddingFunction
client = chromadb.EphemeralClient()
# 创建时使用自定义阿里云嵌入函数
col1 = client.create_collection(name="notes", embedding_function=AliQwenEmbeddingFunction())
col1.add(ids=["q1", "q2"], documents=[
"订单付款后多久发货?一般 48 小时内出库",
"如何申请退款?在订单详情页点击申请退款",
], metadatas=[
{"category": "物流"},
{"category": "售后"},
])
# 获取集合时使用其他嵌入函数
col2 = client.get_collection(name="notes", embedding_function=DefaultEmbeddingFunction())
col2.add(ids=["q3", "q4"], documents=[
"发票怎么开?在个人中心-发票管理里申请电子发票",
"快递丢了怎么办?联系客服补发或全额退款",
], metadatas=[
{"category": "财务"},
{"category": "售后"},
])执行上面代码,会出现如下错误:
chromadb.errors.InvalidArgumentError: Collection expecting embedding with dimension of 1024, got 384
这是因为,DefaultEmbeddingFunction() 底层使用的是 all-MiniLM-L6-v2 模型,默认是 384 维。而自定义的 AliQwenEmbeddingFunction() 底层采用 qwen3.7-text-embedding-flash 模型,是 1024 维。两者维度不一致,所以报错了。即使维度一样也不建议这么做,不同模型计算的向量是存在差异的,会导致后续检索不准确。
如果我们先设置 DefaultEmbeddingFunction(),再在 get_collection() 设置 AliQwenEmbeddingFunction(),例如:
import chromadb
# 默认嵌入函数
from chromadb.api import DefaultEmbeddingFunction
# 导入自定义的函数
from common.custom_embedding import AliQwenEmbeddingFunction
client = chromadb.EphemeralClient()
# 创建时使用自定义阿里云嵌入函数
client.create_collection(name="notes", embedding_function=DefaultEmbeddingFunction())
# 获取集合时使用其他嵌入函数
client.get_collection(name="notes", embedding_function=AliQwenEmbeddingFunction())运行代码,出错了:ValueError: An embedding function already exists in the collection configuration, and a new one is provided. If this is intentional, please embed documents separately. Embedding function conflict: new: NotImplemented vs persisted: default
为什么会报错呢?需要分析源码 validate_embedding_function_conflict_on_get() 函数:
def validate_embedding_function_conflict_on_get(
embedding_function: Optional[EmbeddingFunction], # type: ignore
persisted_ef_config: Optional[Dict[str, Any]],
) -> None:
"""
校验传入的 embedding_function 参数和集合持久化保存的嵌入函数配置 之间不存在冲突。
调用 get_collection / get_or_create_collection 获取已有集合时执行。
规则:
1. 如果集合元数据里已经持久保存了EF配置(persisted_ef_config不为空)
2. 并且用户在get接口显式传入了新的 embedding_function 实例
3. 并且两个EF的name不相等,则判定冲突,抛出ValueError
"""
# 集合持久化存在EF配置,同时用户get时显式传入了 embedding_function
if persisted_ef_config is not None and embedding_function is not None:
if (
# 当前传入EF的name不是 default
embedding_function.name() != "default"
# 持久化配置中存在name字段
and persisted_ef_config.get("name") is not None
# 持久化EF名称 和 当前传入EF名称不一致
and persisted_ef_config.get("name") != embedding_function.name()
):
raise ValueError(
f"An embedding function already exists in the collection configuration, and a new one is provided. If this is intentional, please embed documents separately. Embedding function conflict: new: {embedding_function.name()} vs persisted: {persisted_ef_config.get('name')}"
)
# 校验通过,无冲突直接返回
return None代码报错是因为,create_collection(..,embedding_function=DefaultEmbeddingFunction()) 时 persisted_ef_config.name 为 default。自定义 AliQwenEmbeddingFunction 的 persisted_ef_config.name 为 NotImplemented:
persisted_ef_config:{"name": "default"} → persisted_ef_config.get("name") = "default"(不为 None)
get 传入 ef:AliQwenEmbeddingFunction → embedding_function.name() = "NotImplemented"
判断内部三条件:
"NotImplemented" != "default" → True
persisted name 不为 None → True
"default" != "NotImplemented" → True
全部满足 → raise 报错,也就是你看到的异常。
client.get_collection(name="notes", embedding_function=DefaultEmbeddingFunction()) 不报错,因为第一个条件就不满足,embedding_function.name() != "default",if 语句跳过执行。
结论: 当传入的 embedding_function 是 DefaultEmbeddingFunction(.name() 返回 "default"),内层冲突校验直接跳过,不再做名字比对。
业务开发推荐,幂等。
如果集合已经存在,直接返回。如果集合不存在,就新建。幂等接口,重复执行不会报错。适合启动脚本、业务代码,不知道集合是否存在,一键保证集合可用。
方法签名如下:
col = client.get_or_create_collection(
name: str, # 集合名称
metadata: dict | None = None, # 元数据
configuration: dict | None = None, # 配置信息
embedding_function = None # 嵌入函数
)注意,如果集合已经存在,后续传入的 configuration、metadata 不会覆盖原有集合配置。只有集合不存在的时候,才会使用你传入的 configuration / metadata 创建新集合。
import chromadb
client = chromadb.EphemeralClient()
try:
# 取不到就报错
col = client.get_collection("notes")
# 取不到就建,取到就返回(最常用)
col = client.get_or_create_collection("notes", embedding_function=None)
except Exception as e:
print("集合不存在时 get_collection 就是会报错:", type(e).__name__, e)
# 输出结果:
# 集合不存在时 get_collection 就是会报错: NotFoundError Collection [notes] does not exist关于嵌入函数的一个大坑:
1.1.13 之前的版本,嵌入函数不会存在服务端。get_collection() 拿到的集合会用默认嵌入函数,跟你建库时用的不是同一个,然后你 query 的时候就会得到一堆莫名其妙的结果 —— 因为查询向量和库里的向量来自两个模型,根本不在一个空间里。
老版本的写法必须显式传。
新版本(1.1.13+)会把嵌入函数配置存进 configuration,客户端自动解析,不用再传了。但为了保险,我还是习惯显式传一遍,尤其是自定义嵌入函数的时候。
import chromadb
from common.custom_embedding import AliQwenEmbeddingFunction
client = chromadb.EphemeralClient()
col = client.get_or_create_collection("notes", embedding_function=AliQwenEmbeddingFunction(),
metadata={"embedding_function_name":"AliQwenEmbeddingFunction"})
print(col.configuration)
# {'hnsw': {...}, 'spann': None, 'embedding_function': None}
print(col._embedding_function)
# <common.custom_embedding.AliQwenEmbeddingFunction object at 0x0000020DD6202BA0>
print(col.metadata)
# {'embedding_function_name': 'AliQwenEmbeddingFunction'}注意,col.configuration 打印的 embedding_function 总是为 None,实际 embedding_function 是存放在私有变量 _embedding_function 上的。建议单独将当前使用的 embedding_function 信息存放在 metadata 上,即使私有字段 _embedding_function 不可用,也能正常查看集合的 embedding_function 信息。