如何在LangChain的load_summarize_chain(map_reduce)中控制序列长度?解决Token超限
解决LangChain map_reduce模式下序列长度超限问题
你遇到的token序列长度超过模型上限的问题,核心原因有两个:一是文本分割时用字符数而非token数,导致实际chunk的token量可能接近甚至超过模型限制;二是map阶段生成的总结输出过长,combine阶段将所有map结果拼接后直接突破token上限。以下是具体解决方法:
1. 改用基于token的文本分割
原代码用len作为长度计算函数,这是按字符数分割,但字符数和token数并不等价(比如中文每个汉字通常对应2个token)。应该换成基于token的计数方式,确保每个chunk的token数严格低于模型最大输入限制:
from langchain.chains.summarize import load_summarize_chain from langchain.text_splitter import RecursiveCharacterTextSplitter # 基于LLM内置的token计数函数分割 splitter = RecursiveCharacterTextSplitter( chunk_size=800, # 设为模型最大token数的70%-80%,留足prompt的token空间 chunk_overlap=50, length_function=llm.get_num_tokens, ) docs = splitter.create_documents([text])
也可以直接使用TokenTextSplitter:
from langchain.text_splitter import TokenTextSplitter splitter = TokenTextSplitter( chunk_size=800, chunk_overlap=50, encoding_name="cl100k_base" # 根据模型选择对应编码,比如GPT系列用cl100k_base ) docs = splitter.create_documents([text])
2. 限制map阶段的输出长度
在map prompt中明确要求生成简短总结,强制控制输出token数:
from langchain.prompts import PromptTemplate map_prompt = PromptTemplate( input_variables=["text"], template="请用不超过150个token总结以下内容:\n{text}" ) combine_prompt = PromptTemplate( input_variables=["text"], template="请将以下多个总结合并为一个连贯的简短总结:\n{text}" ) summary_chain = load_summarize_chain( llm=llm, chain_type="map_reduce", map_prompt=map_prompt, combine_prompt=combine_prompt, )
3. 优化combine阶段的处理
如果map阶段的结果数量仍然很多,可以通过参数让combine过程分阶段进行,先分组合并小总结,再合并最终结果:
summary_chain = load_summarize_chain( llm=llm, chain_type="map_reduce", map_prompt=map_prompt, combine_prompt=combine_prompt, reduce_llm=llm, # 可指定同模型或不同模型用于reduce阶段 combine_chain_kwargs={"verbose": True} # 可选,查看combine过程日志 )
4. 匹配模型的token限制
确认你使用的模型最大token数(比如你的模型是1024),所有阶段的输入(prompt+文本)都要低于这个值。比如map阶段的prompt+chunk的token数要控制在900以内,留足输出的token空间。
内容的提问来源于stack exchange,提问作者E.K.
相关产品推荐
相关产品推荐

