LangChain+OpenAI网页爬取文本触发API上下文长度超限错误
解决LangChain RAG中OpenAI上下文长度超限问题
核心问题排查
你遇到的情况大概率是链的构建逻辑错误,导致整个语料被直接传入OpenAI,而非仅检索到的相关片段。以下是逐步排查和解决方法:
1. 检查RAG链的正确结构
确保你使用的是RetrievalQA这类专门的检索增强链,而非手动将全部文本拼接进Prompt。错误的写法会直接把所有文档内容传给模型,哪怕文本量小也可能因为隐性的重复或格式问题触发超限。
正确的链构建示例:
from langchain.chains import RetrievalQA from langchain.vectorstores import FAISS from langchain.embeddings.openai import OpenAIEmbeddings from langchain.text_splitter import CharacterTextSplitter from langchain.document_loaders import TextLoader # 加载并分割已清洗后的文本 loader = TextLoader("cleaned_crawled_text.txt") documents = loader.load() # 调整分割参数,避免单块文本过大 text_splitter = CharacterTextSplitter( chunk_size=500, # 根据模型上下文限制调整,比如gpt-3.5-turbo设为500-1000 chunk_overlap=50, separator="\n" ) split_docs = text_splitter.split_documents(documents) # 向量化并构建向量库 embeddings = OpenAIEmbeddings() vector_store = FAISS.from_documents(split_docs, embeddings) # 创建检索器,限制返回的相关片段数量 retriever = vector_store.as_retriever(search_kwargs={"k": 3}) # 只取Top3相关片段 # 构建RetrievalQA链 qa_chain = RetrievalQA.from_chain_type( llm=OpenAI(model_name="gpt-3.5-turbo"), chain_type="stuff", retriever=retriever, return_source_documents=True # 可选:返回检索到的源片段用于调试 ) # 测试查询 query = "你的问题" result = qa_chain({"query": query}) print(result["result"])
2. 验证文本分割效果
即使总token数少,若存在单个超大文本块,也会导致传入模型的上下文超限。可以添加代码打印每个分割块的token数:
from langchain.llms import OpenAI llm = OpenAI(model_name="gpt-3.5-turbo") for i, doc in enumerate(split_docs): token_count = llm.get_num_tokens(doc.page_content) print(f"Chunk {i}: {token_count} tokens")
如果发现某块token数接近模型上限(比如gpt-3.5-turbo是4096),需进一步调小chunk_size。
3. 检查Prompt模板是否正确
确保Prompt模板中使用的是{context}变量(由检索器传入的相关片段),而非直接引入全部文档内容。错误示例会把整个语料硬编码进Prompt:
# 错误写法:直接传入全部文本 wrong_prompt = PromptTemplate( template="根据以下所有文本回答问题:\n{full_documents}\n\n问题:{question}", input_variables=["full_documents", "question"] ) # 正确写法:使用检索到的context correct_prompt = PromptTemplate( template="根据以下上下文回答问题:\n{context}\n\n问题:{question}\n回答:", input_variables=["context", "question"] )
若使用自定义Prompt,需在构建RetrievalQA时指定:
qa_chain = RetrievalQA.from_chain_type( llm=OpenAI(model_name="gpt-3.5-turbo"), chain_type="stuff", retriever=retriever, chain_type_kwargs={"prompt": correct_prompt} )
4. 调试传入模型的实际上下文
手动打印检索到的片段,确认传入模型的内容仅为相关部分:
# 手动获取检索结果 retrieved_docs = retriever.get_relevant_documents(query) print("检索到的片段:") for doc in retrieved_docs: print(f"- {doc.page_content[:100]}...") # 打印前100字符
若输出的是全部语料,说明检索器未正确工作,需检查向量库构建过程是否有误(比如分割后的文档未正确存入)。
内容的提问来源于stack exchange,提问作者Ja4H3ad
相关产品推荐
相关产品推荐

