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

LangChain检索链运行时提示词超出上下文窗口问题排查

问题:LangChain检索链运行时提示「Prompt size exceeds maximum context window」

运行LangChain的RetrievalQA链时,调用chain.run()出现「Prompt size exceeds maximum context window」错误,即使模板和问题的token数远小于模型2048的上下文限制。以下是实现代码:

from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings
from langchain.chains import RetrievalQA
from langchain_community.llms import GPT4All
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
from langchain.embeddings.huggingface import HuggingFaceEmbeddings
from langchain import PromptTemplate

local_path = (
   "/home/user/coding/facts/models/llama-2-7b-chat.Q5_K_M.gguf"  
)

callbacks = [StreamingStdOutCallbackHandler()]

llm = GPT4All(
    model=local_path, 
    callbacks=callbacks, 
    verbose=True,
    temp=0,
    streaming=True)

prompt_template = """
You are a chatbot which retrieves data from a vector database.
Your task is to answer user questions by only using the data provided by the retriever.
If the retriever does not find any source documents say: "I don't know the answer".

    -----------
    Context: {context}
    -----------
    Question: {question}
"""

qa_prompt=PromptTemplate(template=prompt_template, input_variables=['context', 'question'],max_length = 2048)

print("loading embeddings model")
model_name = "sentence-transformers/all-mpnet-base-v2"
model_kwargs = {'device': 'cpu'}
encode_kwargs = {'normalize_embeddings': False}
embeddings = HuggingFaceEmbeddings(
    model_name=model_name,
    model_kwargs=model_kwargs,
    encode_kwargs=encode_kwargs
)
db = Chroma(
    persist_directory="emb",
    embedding_function=embeddings
)
retriever = db.as_retriever()

chain = RetrievalQA.from_chain_type(
    llm=llm,
    retriever=retriever,
    chain_type="stuff",
    chain_type_kwargs={'prompt': qa_prompt}
)

print(len(qa_prompt.template))

result = chain.run("When was Mark Twain born?")

print(result)

原因分析

  • 你只统计了模板和问题的token数,但忽略了**{context}变量实际填充的检索文档内容**。stuff链类型会将检索到的所有文档内容直接拼接进context位置,如果这些文档的总token数(加上模板、问题)超过模型2048的上下文窗口,就会触发错误。
  • PromptTemplate的max_length参数仅用于限制模板本身的长度,无法控制最终填充后prompt的总长度,因此设置该参数无效。

解决方法

1. 查看context的实际内容

可以手动获取检索结果,查看文档内容并计算总token数:

# 手动获取检索到的文档
docs = retriever.get_relevant_documents("When was Mark Twain born?")
print("检索到的文档:")
for doc in docs:
    print(doc.page_content)
    print("---")

# 计算填充后prompt的总token数
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("sentence-transformers/all-mpnet-base-v2")
filled_prompt = qa_prompt.template.format(
    context="\n".join([d.page_content for d in docs]),
    question="When was Mark Twain born?"
)
total_tokens = len(tokenizer.encode(filled_prompt))
print(f"填充后prompt总token数:{total_tokens}")

2. 减少单次检索的文档数量

修改retriever的search_kwargs参数,限制返回的文档数量:

retriever = db.as_retriever(search_kwargs={"k": 2})  # 仅返回前2个最相关的文档

3. 改用其他链类型

如果文档较长,替换stuff为map_reduce、refine或map_rerank类型,这些类型会拆分文档分批处理:

chain = RetrievalQA.from_chain_type(
    llm=llm,
    retriever=retriever,
    chain_type="map_reduce",
    chain_type_kwargs={'prompt': qa_prompt}
)

4. 优化文档分块

如果原始文档本身过长,在生成向量库时需将文档拆分为更小的片段,降低单篇文档的token数,避免拼接后超出窗口限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 00:07:49