You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Gradio的RAG聊天机器人ChromaDB检索旧向量问题排查

ChromaDB数据存储机制

ChromaDB有两种核心运行模式:

  • 内存模式(默认):所有数据仅存于内存中,进程重启或客户端实例销毁后数据会丢失。如果复用同一个Chroma客户端实例,旧数据会一直保留在内存里。
  • 持久化模式:通过指定persist_directory参数,将数据存储到本地磁盘文件夹中。下次初始化客户端时,会自动加载该目录下的已有数据。

Chroma的核心单元是Collection(集合),每个集合独立存储向量、文档和元数据。常用的集合操作:

  • get_or_create_collection(name):如果指定名称的集合已存在,则返回该集合;否则创建新集合。
  • create_collection(name):创建新集合,若同名集合已存在则报错(需配合exist_ok=True参数才能覆盖)。
  • delete_collection(name):删除指定名称的集合。
数据未更新的核心原因

结合你的场景,问题大概率出在旧数据未被清除,新数据只是追加或未覆盖旧集合:

  1. 复用旧Collection实例:如果每次上传PDF时调用get_or_create_collection,会直接复用之前创建的集合,新PDF数据会追加进去,但检索时仍会匹配旧数据(尤其是旧数据与问题更相关时)。
  2. 内存模式下未重置客户端:默认内存模式下,若没有销毁旧的Chroma客户端实例,旧数据会一直留在内存中,新上传的PDF数据只是被添加到同一集合,而非替换。
  3. 持久化目录未清理:如果使用了持久化模式,旧数据会存在本地文件夹中,若未清空该目录就重新初始化客户端,会直接加载旧数据。
  4. Retriever实例未重新生成:如果复用了之前生成的Retriever,它会一直指向旧的Collection,自然只会返回旧数据。
针对代码的修复方案

方案1:内存模式下替换数据

每次上传新PDF时,先删除旧集合,再创建新集合,确保完全替换数据:

import chromadb
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings

def process_new_pdf(pdf_file):
    # 1. 初始化新的Chroma客户端(销毁旧实例)
    chroma_client = chromadb.Client()
    
    # 2. 删除旧集合(如果存在)
    try:
        chroma_client.delete_collection(name="pdf_collection")
    except:
        pass
    
    # 3. 创建全新的集合
    collection = chroma_client.create_collection(name="pdf_collection")
    
    # 4. 处理PDF、生成embeddings(替换成你的PDF处理逻辑)
    documents = your_pdf_processing_function(pdf_file)
    embeddings = OpenAIEmbeddings().embed_documents(documents)
    
    # 5. 将新数据添加到集合
    collection.add(embeddings=embeddings, documents=documents)
    
    # 6. 生成全新的Retriever
    retriever = Chroma(collection=collection, embedding_function=OpenAIEmbeddings()).as_retriever()
    return retriever

方案2:持久化模式下替换数据

如果需要持久化数据,每次上传新PDF时先清空持久化目录:

import chromadb
import shutil
import os
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings

PERSIST_DIR = "./chroma_pdf_store"

def process_new_pdf(pdf_file):
    # 1. 清空旧的持久化目录
    if os.path.exists(PERSIST_DIR):
        shutil.rmtree(PERSIST_DIR)
    
    # 2. 初始化持久化客户端
    chroma_client = chromadb.PersistentClient(path=PERSIST_DIR)
    
    # 3. 创建新集合
    collection = chroma_client.create_collection(name="pdf_collection")
    
    # 4. 处理PDF、生成embeddings
    documents = your_pdf_processing_function(pdf_file)
    embeddings = OpenAIEmbeddings().embed_documents(documents)
    
    # 5. 添加新数据并持久化
    collection.add(embeddings=embeddings, documents=documents)
    
    # 6. 生成新的Retriever
    retriever = Chroma(
        persist_directory=PERSIST_DIR,
        collection_name="pdf_collection",
        embedding_function=OpenAIEmbeddings()
    ).as_retriever()
    return retriever

关键注意事项

  • 不要在全局作用域初始化Chroma客户端或Retriever,必须在每次上传PDF的函数内部重新创建。
  • 如果使用Gradio的状态变量存储Retriever,每次上传新PDF后要更新状态变量为新生成的Retriever。

内容的提问来源于stack exchange,提问作者Husnain Izhar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 02:45:57