持久化与数据管理
数据存储位置
使用 Docker 启动时,数据存储在挂载的本地目录:
# 数据存在 ./chroma_data
docker run -d \
-p 8000:8000 \
-v $(pwd)/chroma_data:/chroma/chroma \
chromadb/chroma
# 目录结构
chroma_data/
└── chroma.sqlite3 # 索引和元数据
└── xxxxxxxx-xxxx/ # 向量数据(每个 Collection 一个目录)
备份与恢复
# 备份:直接复制整个 chroma_data 目录
cp -r ./chroma_data ./chroma_data_backup_20250101
# 恢复:停止 Chroma,替换数据目录,重启
docker stop chromadb
cp -r ./chroma_data_backup_20250101 ./chroma_data
docker start chromadb
数据量统计
// 查看各 Collection 的数据量
const collections = await client.listCollections()
for (const name of collections) {
const col = await client.getCollection({ name })
const count = await col.count()
console.log(`${name}: ${count} 条`)
}
增量更新策略
// 实际项目中,文档更新很常见,用 upsert 做增量更新
async function syncDocument(docId: string, content: string, metadata: object) {
const embeddings = await getEmbeddings([content])
// upsert:存在则更新,不存在则新增,不需要判断
await collection.upsert({
ids: [docId],
documents: [content],
embeddings: embeddings,
metadatas: [metadata],
})
}
// 删除已下架的文档
async function removeOutdatedDocs(source: string) {
await collection.delete({
where: { source },
})
console.log(`已删除来源为 ${source} 的所有文档`)
}
常见问题与踩坑
Q1:Connection refused 连接被拒绝
# Chroma 服务没启动,或端口不对
# 检查服务是否运行
docker ps | grep chroma
# 检查端口
curl http://localhost:8000/api/v2/heartbeat
# 如果换了端口,代码里也要对应修改
const client = new ChromaClient({ path: 'http://localhost:9000' })
Q2:检索结果和预期完全不符
最常见的原因是建库和查询用了不同的 Embedding 模型:
// ❌ 错误:建库用 A 模型,查询用 B 模型
// 建库时
const embedFnA = new OpenAIEmbeddings({ model: 'text-embedding-3-small' })
await Chroma.fromDocuments(docs, embedFnA, { collectionName: 'kb' })
// 查询时(不小心换了模型)
const embedFnB = new OpenAIEmbeddings({ model: 'text-embedding-3-large' })
const store = await Chroma.fromExistingCollection(embedFnB, { collectionName: 'kb' })
// 结果完全乱,因为向量空间不一样
// ✅ 正确:始终用同一个模型,建议把模型名写成常量
const EMBEDDING_MODEL = 'text-embedding-3-small'
const embeddings = new OpenAIEmbeddings({ model: EMBEDDING_MODEL })
Q3:Collection already exists 报错
// 不要用 createCollection,改用 getOrCreateCollection
const collection = await client.getOrCreateCollection({ name: 'my_docs' })
Q4:大批量数据导入很慢
// 分批处理,每批 100 条,避免单次请求太大
async function batchAdd(docs: Document[], batchSize = 100) {
for (let i = 0; i < docs.length; i += batchSize) {
const batch = docs.slice(i, i + batchSize)
// 批量计算 embedding
const embeddings = await getEmbeddings(batch.map(d => d.pageContent))
await collection.add({
ids: batch.map((_, j) => `doc_${i + j}`),
documents: batch.map(d => d.pageContent),
embeddings,
metadatas: batch.map(d => d.metadata),
})
console.log(`已导入 ${Math.min(i + batchSize, docs.length)} / ${docs.length}`)
}
}
Q5:元数据过滤没有效果
// 元数据的值只支持 string、number、boolean
// ❌ 不支持数组或嵌套对象作为元数据值
metadata: {
tags: ['ai', 'ml'], // ❌ 数组不支持
author: { name: '张三' }, // ❌ 嵌套对象不支持
}
// ✅ 正确:展平为基础类型
metadata: {
tag_ai: true, // 用布尔值模拟标签
tag_ml: true,
authorName: '张三', // 展平嵌套对象
}
Q6:距离分数怎么理解,多少算"相关"
// 余弦距离参考标准(不同数据集会有差异,以下是经验值)
// < 0.2 → 非常相关,几乎是同一个意思
// 0.2~0.4 → 比较相关,可以使用
// 0.4~0.6 → 有一定关联,谨慎使用
// > 0.6 → 基本不相关,建议过滤掉
// 在 RAG 中设置阈值过滤
const results = await collection.query({
queryTexts: ['用户问题'],
nResults: 10, // 多取一些
include: ['documents', 'distances'],
})
const DISTANCE_THRESHOLD = 0.5
const filteredDocs = results.documents[0].filter(
(_, i) => results.distances![0][i] < DISTANCE_THRESHOLD
)
if (filteredDocs.length === 0) {
console.log('没有找到足够相关的内容,建议直接告知用户')
}
总结:Chroma 核心 API 速查
// 客户端
const client = new ChromaClient({ path: 'http://localhost:8000' })
// Collection 管理
await client.createCollection({ name, metadata })
await client.getCollection({ name })
await client.getOrCreateCollection({ name, metadata }) // 最常用
await client.listCollections()
await client.deleteCollection({ name })
// 数据操作
await collection.add({ ids, documents, embeddings, metadatas })
await collection.upsert({ ids, documents, embeddings, metadatas }) // 推荐
await collection.update({ ids, documents, metadatas })
await collection.delete({ ids })
await collection.delete({ where })
await collection.get({ ids, where, include })
await collection.count()
// 检索
await collection.query({
queryTexts, // 文本查询(自动向量化)
queryEmbeddings, // 向量查询(自己传)
nResults,
where, // 元数据过滤
whereDocument, // 文档内容过滤
include,
})
💬 评论 0
还没有评论,快来抢沙发吧~