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

Chroma向量DB中原始与压缩块检索的提示词长度异常问题

问题描述

我用Chroma向量DB检索相关文本块来响应用户查询,创建了两个Chroma实例,分别存储原始文本块和压缩文本块(通过移除冠词及部分停用词实现压缩)。理论上基于原始块生成的提示词token长度应该大于压缩块的,但在k值(检索文档数)、查询内容、块大小都相同的情况下,多次出现相反情况,导致提示词没达到压缩效果。

代码片段
from langchain.text_splitter import RecursiveCharacterTextSplitter
CHROMA_PATH_COMPR = 'docs/chroma_22225311123335326326622123155783567999592220111221823527982/'
CHROMA_PATH = 'docs/chroma_323333322253371255175333363916217279211239913512622611/'

text_splitter = RecursiveCharacterTextSplitter(chunk_size=1400,chunk_overlap=700,separators=["\n\n", "\n", ". ", " ", ""])

def input_file():
    file_path = input("Enter file path : ")
    loader = PyPDFLoader(file_path)
    pages = loader.load()
    return pages

def get_original_chunks(pages):
   orig_chunks= text_splitter.split_documents(pages)
   return orig_chunks

def retrieve_relevant_chunks_original(orig_chunks,query):
    db_chroma = Chroma.from_documents(documents= orig_chunks,embedding=getembeddings(),persist_directory=CHROMA_PATH,collection_name="OriginalChunks")
    vector_store_retriever_orig = db_chroma.as_retriever(search_type="mmr",search_kwargs={'k':5,'lambda_mult':0.1})
    retrieved_context = vector_store_retriever_orig.get_relevant_documents(query)
    return retrieved_context

def get_compressed_chunks(orig_chunks,query):
    compressedchunks=[]
    startTime = timeit.default_timer()
    for i in range(len(orig_chunks)):
        orig_chunks[i].page_content = compressprompt(orig_chunks[i].page_content)
        compressedchunks.append(orig_chunks[i])
    endTime = timeit.default_timer()
    time_compr = endTime-startTime
    print("Time taken to compress chunks = \t",time_compr)
    db_chroma_compr = Chroma.from_documents(documents= compressedchunks,embedding=getembeddings(),persist_directory=CHROMA_PATH_COMPR,collection_name="CompressedChunks")
    vector_store_retriever_compr = db_chroma_compr.as_retriever(search_type="mmr",search_kwargs={'k':5,'lambda_mult':0.1})
    retrieved_compr_context = vector_store_retriever_compr.get_relevant_documents(query)
    return retrieved_compr_context
问题分析

出现这种反常识情况的核心原因如下:

  • 检索结果不匹配:原始块和压缩块的embedding基于不同文本生成,MMR检索返回的文档集合可能完全不同。即使k值相同,原始块检索到的可能是本身较短的文本块,而压缩块检索到的可能是原本较长、即使压缩后token数仍比前者多的块。
  • 压缩效果不稳定:如果原始文本中停用词、冠词占比极低,压缩后的token数减少有限;极端情况下,若文本以短词为主,移除少量停用词后token数差异不明显,甚至可能因分割逻辑或其他因素出现反超。
  • 代码数据污染:get_compressed_chunks函数直接修改了orig_chunks的page_content属性,会导致后续复用orig_chunks时数据被污染,影响原始块检索结果的一致性。
  • Token计数误差:如果通过字符数估算token数,而非用专业工具精确统计,可能产生感知误差,实际原始块的token数确实更少。
解决方案建议
  • 隔离原始数据:压缩时复制原始chunk对象,避免直接修改原数据:
    import copy
    # 修改get_compressed_chunks中的循环逻辑
    for chunk in orig_chunks:
        compressed_chunk = copy.deepcopy(chunk)
        compressed_chunk.page_content = compressprompt(chunk.page_content)
        compressedchunks.append(compressed_chunk)
    
  • 精确统计Token数:用tiktoken工具精确统计检索结果的token数,排除估算误差:
    import tiktoken
    def count_tokens(text, model="gpt-3.5-turbo"):
        enc = tiktoken.encoding_for_model(model)
        return len(enc.encode(text))
    # 分别统计原始和压缩检索结果的总token数
    orig_total = sum(count_tokens(doc.page_content) for doc in retrieved_context)
    compr_total = sum(count_tokens(doc.page_content) for doc in retrieved_compr_context)
    
  • 验证压缩函数有效性:单独测试compressprompt函数,对多个原始块统计压缩前后的token变化,确保压缩逻辑能稳定减少token数。
  • 固定对比样本:如果要验证压缩效果,先手动选择几个固定的文本块,分别用原始和压缩版本计算token数,排除检索结果不一致的干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 11:30:17