往一個已有數據的 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
