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

ConversationalRetrievalChain调大k值触发Token超限问题求助

解决ConversationalRetrievalChain增大k值时的令牌超限问题

当使用ConversationalRetrievalChain检索器时,增大返回文档数参数k(例如设为10)会触发令牌数超过模型最大上下文长度的警告,具体错误提示:

WARNING:ctransformers:Number of tokens (1554) exceeded maximum context length (512).

默认k=4时运行正常,但CSV数据有1000行,需要更大的k值覆盖更多相关数据,以下是可行的解决方法:

1. 调整LLM的上下文长度参数

你使用的Llama-2-7B-GGUF模型实际支持4096的上下文长度,但CTransformers初始化时默认可能限制为512。需要显式设置context_length参数:

llm = CTransformers(model=llm_model_name,
                    model_type='llama',
                    max_new_tokens=8145,
                    temperature=1.0,
                    context_length=4096)  # 设置为模型支持的最大上下文长度

同时,ConversationalRetrievalChain的max_tokens_limit要预留足够空间给生成的新令牌,建议设为3500:

qa = ConversationalRetrievalChain.from_llm(llm,
                                        retriever=db2.as_retriever(search_kwargs={'k': 10}),
                                        memory=memory,
                                        output_key="answer",
                                        verbose=True,
                                        max_tokens_limit=3500)  # 匹配上下文长度,预留生成空间

2. 优化文本分块大小

当前chunk_size=200的分块可能过大,导致单文档块令牌数较多,k=10时总令牌数超限。可以减小分块大小并增加重叠度,保证上下文连贯:

text_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=20)  # 减小分块大小,增加重叠
docs = text_splitter.split_documents(documents)

这样每个文档块的令牌数减少,即使k=10,总令牌数也更容易控制在上下文长度内。

3. 检索后按令牌数筛选文档

先检索更多文档,再根据令牌总数过滤掉超出部分,避免一次性传入过多内容:

from langchain.schema import Document
from transformers import AutoTokenizer

# 初始化模型对应的tokenizer
tokenizer = AutoTokenizer.from_pretrained("TheBloke/Llama-2-7B-GGUF")

def filter_docs_by_token_count(docs, max_total_tokens):
    total_tokens = 0
    filtered_docs = []
    for doc in docs:
        doc_tokens = len(tokenizer.encode(doc.page_content))
        if total_tokens + doc_tokens <= max_total_tokens:
            filtered_docs.append(doc)
            total_tokens += doc_tokens
        else:
            break
    return filtered_docs

# 先检索20条文档,再筛选到令牌数上限内
retriever = db2.as_retriever(search_kwargs={'k': 20})
filtered_docs = filter_docs_by_token_count(retriever.get_relevant_documents(traducao), 3500)

# 将筛选后的文档传入链中(可自定义链逻辑或使用RetrievalQAWithSourcesChain)

4. 切换到更大上下文窗口的模型

如果上述方法仍无法满足需求,可更换为支持更大上下文的模型,比如Llama-2-7B-32K-GGUF,它支持32768的上下文长度:

llm_model_name = "TheBloke/Llama-2-7B-32K-GGUF"
llm = CTransformers(model=llm_model_name,
                    model_type='llama',
                    max_new_tokens=8145,
                    temperature=1.0,
                    context_length=32768)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 18:45:09