写这份笔记时是 chromadb 1.5.9。
几个版本相关的点,看到老教程时要留个心眼:
1.0.0(正式版2025年3月,预发布版4月)
核心服务端由Python改为Rust重写,读写性能、并发稳定性大幅提升;
破坏性变更:内置鉴权功能被移除,旧鉴权环境变量全部失效:
CHROMA_SERVER_AUTHN_PROVIDER、CHROMA_SERVER_AUTHN_CREDENTIALS、CHROMA_AUTH_TOKEN_TRANSPORT_HEADER
1.0+ 版本如果需要接口鉴权,必须在反向代理/网关层自行实现(Nginx、Traefik等)(第 10 章给方案)。
1.1.13 之前
在 1.1.13 版本之前,get_collection() 方法不会自动恢复你建集合时用的嵌入函数,得手动再传一遍。
现在新版本会把它存在服务端配置里,客户端自动解析。
你要是还在老版本上,记得每次 get_collection(name=..., embedding_function=ef) 传递 embedding_function 嵌入函数。
集合命名规则
在 1.x 里校验得很严,长度必须 3~512,只能含 a-zA-Z0-9._-,且首尾必须是字母或数字。我第一次写 create_collection("t1") 直接被拒:
import chromadb
client = chromadb.EphemeralClient()
col = client.create_collection("t1")运行示例,输出如下:
chromadb.errors.InvalidArgumentError: Validation error:
name: Expected a name containing 3-512 characters from [a-zA-Z0-9._-],
starting and ending with a character in [a-zA-Z0-9]. Got: t1存储格式完全不兼容
1.x(含1.5.9)依然存在 chroma.sqlite3 文件,但它只存元数据、集合信息、文档ID、metadata、全文索引;向量与 HNSW 索引保存在独立的 UUID 命名目录下。
0.x 版本的 chroma.sqlite3 的表结构完全不一样,不能直接拷贝给1.x 打开,没有自动原地迁移。旧数据只能通过旧版本客户端全量 get 读出,再用新版客户端 add/upsert 导入。
注意:不要手动改 chroma.sqlite3、不要直接用 sqlite 工具删记录。 Rust 内核会维护 sqlite 与磁盘上向量段文件的一致性;手动修改 sqlite 会导致元数据与向量文件脱节,集合直接损坏、查不出来。
add /upsert/update 的行为差异(非常容易踩坑)
add():如果 ID 已存在 → 静默丢弃,不报异常,不会覆盖,日志也不一定提示;
update():如果 ID 不存在 → 直接忽略,不会新增;
upsert():存在就更新,不存在就新增; 老教程很多直接用 add 做幂等写入,升级 1.x 后会出现 “更新无效” 的隐蔽 bug,幂等场景一律用 upsert。
get () /query () 默认不返回 embeddings
老版本默认带回向量;1.x include 默认只包含 metadatas, documents,embeddings 需要显式写:
client.get(ids=["q1"], include=["embeddings", "documents", "metadatas"])否则 embeddings 字段是 None,调试半天找不到向量。
PersistentClient 自动持久化,不再需要 .persist ()
0.x 需要手动调用 client.persist() 持久化;1.x Rust 内核自动持久化,.persist() 方法已经被移除,抄老代码会直接抛方法不存在异常。
多租户、多数据库默认开启
该架构底层 0.x 就存在,但 1.x 远程 HTTP 服务场景必须重视。
服务初始化后自带预置:default_tenant、default_database。 HttpClient 连接远端 Chroma 时,即使你不写 tenant/database 参数,客户端也会默认传入 default_tenant + default_database。
如果集合是创建在其他自定义租户/数据库下,两边不匹配就会出现“集合明明存在但 get_collection 找不到”的隐蔽问题。
很多 0.x 老教程完全不提租户与数据库,远程部署时极易踩坑。