往一个已有数据的 collection 里用新 embedding 模型写数据,报
InvalidDimensionException: Embedding dimension X does not match collection dimensionality Y。根因是 collection 的维度在第一次 add 时被锁定、之后不可更改,换模型等于换维度,只能删掉旧 collection 重建。这是 Chroma 的有意设计,不是 bug。
Issue & Env(案发现场与环境)
- 业务场景:先用 A 模型(如 all-MiniLM-L6-v2,384 维)建库写入了一批文档,运行正常;把 embedding 模型换成 B(如 OpenAI text-embedding-3-large,1536 维,或 bge-small-zh-v1.5,512 维)后,往同一个 collection 继续 add 文档或执行 query,抛
InvalidDimensionException。 - 环境:chromadb 1.5.x(0.4+ 版本均有此行为),任意 embedding 模型组合。
- 关键区分:不是代码写错、不是模型加载失败,是 collection 的维度已经固定,与新模型的向量维度不一致。
StackTrace(堆栈日志)
用 384 维模型建库后换 1536 维模型写入时的典型报错(fixdevs 实测原文):
InvalidDimensionException:
Embedding dimension 1536 does not match collection dimensionality 384
Open WebUI 社区同款问题的变体(dev.to / open-webui issue #28316,640 维换 1024 维模型):
chromadb.errors.InvalidArgumentError: Collection expecting embedding with dimension of 640, got 1024
两个报错是同一类问题:左侧是 collection 已锁定的维度,右侧是新模型产出的维度。
Reproduce(复现代码)
import chromadb
from chromadb.utils import embedding_functions
client = chromadb.PersistentClient(path="./chroma_db")
# 1. 用 384 维模型建库(all-MiniLM-L6-v2,Chroma 默认)
col = client.get_or_create_collection("kb")
col.add(ids=["doc1"], documents=["你好,Chroma"])
print("count:", col.count()) # 1,此时维度锁定为 384
# 2. 换 512 维模型(bge-small-zh-v1.5)继续写 → 报错
ef = embedding_functions.SentenceTransformerEmbeddingFunction(
model_name="BAAI/bge-small-zh-v1.5", device="cpu")
col2 = client.get_collection("kb", embedding_function=ef)
col2.add(ids=["doc2"], documents=["第二条文档"]) # InvalidDimensionException
第 2 步的 add 抛出 InvalidDimensionException: Embedding dimension 512 does not match collection dimensionality 384。
Root Cause(根因分析)
维度在首次写入时锁定,且不可改
Chroma 官方 Cookbook 原文:
When creating a collection, its dimensionality is determined by the dimensionality of the first embedding added to it. Once the dimensionality is set, it cannot be changed.
创建 collection 时它不知道自己的维度,第一次 add 的向量维度决定 collection 的维度,之后锁死。官方 FAQ 里另一个问题的回答也是同一句核心结论:there's no 'alter collection, new dimension' operation(没有改维度操作)。
为什么不允许改
HNSW 索引为固定维度构建图结构,混维度做相似度计算会产生垃圾结果。所以 Chroma 选择在第一次写入时把维度焊死在 collection 配置里,宁可让用户报错,也不允许悄悄混用。这不是 bug,是防止静默数据污染的设计。
常见触发路径
- 建库时没传 embedding_function,用了默认 all-MiniLM-L6-v2(384 维),后面换成本地中文模型(512 维)或 OpenAI(1536 维)。
- 建库用的 embedding 函数和查询/继续写入时用的不一致。
- 换模型后没删旧 collection 直接写——Open WebUI 就是典型案例:记忆和文件 collection 建在 640 维,换 1024 维模型后所有插入被拒。
The Fix(解决方案)
方案一:删旧 collection 重建(数据可重新嵌入时)
import chromadb
from chromadb.utils import embedding_functions
client = chromadb.PersistentClient(path="./chroma_db")
# 1. 删掉锁在旧维度的 collection
client.delete_collection("kb")
# 2. 用新模型重建
ef = embedding_functions.SentenceTransformerEmbeddingFunction(
model_name="BAAI/bge-small-zh-v1.5", device="cpu")
col = client.get_or_create_collection("kb", embedding_function=ef)
# 3. 重新写入全部文档(新维度)
删除后要重新嵌入所有数据,文档越多耗时越长,这是换模型的固有成本。
方案二:只删有问题的 collection(多 collection 场景)
Open WebUI 修法(issue #28316 社区验证):先备份,停服务,SQLite 里查哪些 collection 是旧维度,再逐个 delete:
-- 在 Chroma 的 SQLite 数据目录(vector_db/)下
SELECT id, name, dimension FROM collections;
stale = ["file-xxxx", "user-memory-xxxx"] # 旧维度的 collection
for name in stale:
client.delete_collection(name)
预防:让维度来源唯一
- 建 collection 时就显式传 embedding_function,不依赖默认值,全流程只用一个模型。
- 重启进程后
get_collection也要传同一个 embedding 函数(否则 Chroma 找不到函数配置时行为不一致)。 - 想确认当前维度:
len(col.get(include=["embeddings"])["embeddings"][0])。
References(参考来源)
- Collection Dimensionality Mismatch — Chroma Cookbook 官方 FAQchroma-docs
- How to set dimensionality of my collections — Chroma Cookbook 官方 FAQchroma-docs
- Fix: ChromaDB Not Working — Persistent Client, Collection Errors, and Embedding Function Issuesfixdevs-blog
- Open WebUI Memory Broke After Switching Embedding Models: The Chroma Dimension Fixdevto
