如何在文档检索链中控制上下文 Token 数量

心靈之曲

心靈之曲

2026-07-25

525人浏览

原创

如何在文档检索链中控制上下文 Token 数量

本文介绍在 LangChain 中通过预处理文档分块(而非运行时截断)来规避大模型上下文超限问题,重点解决 create_retrieval_chain 场景下因未切分原始文档导致 context_length_exceeded 错误的典型实践。

本文介绍在 langchain 中通过预处理文档分块(而非运行时截断)来规避大模型上下文超限问题,重点解决 `create_retrieval_chain` 场景下因未切分原始文档导致 `context_length_exceeded` 错误的典型实践。

在使用 LangChain 构建检索增强对话系统(RAG Chatbot)时,一个常见但易被忽视的关键问题是:文档入库方式直接影响检索链的上下文安全边界。如您所遇,即使使用了 ChatOpenAI 和 create_retrieval_chain 等现代链式 API,若原始文档以整篇形式(如数万字符的长文本)直接存入向量数据库(如 Qdrant),则 retriever.invoke() 返回的单个 Document 可能包含远超模型最大上下文(如 gpt-3.5-turbo 的 8192 tokens)的内容——这会导致后续 document_chain 渲染 prompt 时直接触发 OpenAI 的 context_length_exceeded 报错。

根本原因在于:LangChain 的 create_stuff_documents_chain 默认将所有检索到的 Document 的 page_content 拼接进 占位符,而它不具备自动 token 截断或动态压缩能力。运行时限制(如 max_tokens_limit)在当前版本(langchain==0.1.9)中已废弃且不可用;ReduceDocumentsChain 等旧式链因严重依赖已移除的 LLMChain/OpenAI 类,无法与 ChatOpenAI 兼容,亦不推荐用于新项目。

✅ 正确解法:在数据写入阶段即完成语义合理、长度可控的文本分块(Chunking),而非试图在检索或生成阶段“事后补救”。

以下是推荐的端到端实践方案:

1. 使用 RecursiveCharacterTextSplitter 替代基础 CharacterTextSplitter

虽然问题中使用了 CharacterTextSplitter,但生产环境更推荐 RecursiveCharacterTextSplitter——它能按优先级顺序(\n\n, \n, " ", "")智能切分,保留段落结构,避免生硬截断:

稿定AI绘图
稿定AI绘图

稿定推出的AI绘画工具

下载
from langchain.text_splitter import RecursiveCharacterTextSplitter

def create_chunks(text: str, chunk_size: int = 800, chunk_overlap: int = 100) -> list[str]:
    text_splitter = RecursiveCharacterTextSplitter(
        separators=["\n\n", "\n", " ", ""],
        chunk_size=chunk_size,
        chunk_overlap=chunk_overlap,
        length_function=len,
        keep_separator=False,
        strip_whitespace=True,
    )
    return text_splitter.split_text(text)

# 存储前分块
chunks = create_chunks(file_contents)
vector_ids = qdrant_collection.add_texts(chunks)  # ✅ 不再 add_documents([Document(...)])

⚠️ 注意:add_texts() 接收字符串列表,内部自动创建 Document(page_content=chunk);避免手动构造含超长 page_content 的 Document 对象。

2. 配置检索器返回数量与相似度阈值

分块后,还需控制检索结果数量,防止过多 chunk 拼接仍超限:

retriever = existing_vector_store.as_retriever(
    search_kwargs={
        "k": 3,  # 最多返回3个chunk(通常足够)
        "score_threshold": 0.4,  # 过滤低相关性结果(需Qdrant支持)
    }
)

3. (可选)在 Prompt 中显式约束上下文长度

虽非强制,但可在 system prompt 中加入轻量提示,辅助 LLM 聚焦关键信息:

SYSTEM_TEMPLATE = """
你是一个精准、简洁的助手。请严格基于以下上下文回答问题,忽略无关内容。
若上下文未提供答案,请回答“我无法确定”。

<context>
{context}
</context>
"""

总结与最佳实践

  • 核心原则:Token 限制是端到端工程问题,必须在 数据摄入(Ingestion)阶段解决,而非 推理(Inference)阶段修补。
  • 分块策略建议:chunk_size=500–1000(对应约 150–300 tokens),overlap=100–200,平衡语义完整性与冗余度。
  • 避免陷阱
    • ❌ 不要尝试在 RunnablePassthrough.assign(context=...) 中对 docs 做 truncate_by_token() —— LangChain 无内置 token 计数器,且 page_content 是字符串,需额外依赖 tiktoken 才能精确计算,易引入性能瓶颈与逻辑错误;
    • ❌ 不要降级使用已废弃的 ConversationalRetrievalChain 或 ReduceDocumentsChain,它们与 ChatOpenAI 不兼容且维护成本高;
    • ✅ 优先升级 langchain 至 >=0.1.16 后,可探索 ContextualCompressionRetriever + EmbeddingsFilter 等更高级压缩方案,但当前版本下分块是最稳定、最可控的方案。

通过前置分块,您不仅解决了 token 超限问题,还显著提升了检索精度(细粒度 chunk 更易匹配用户 query)和系统鲁棒性——这才是 RAG 架构设计的正确起点。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
python打包成可执行文件
python打包成可执行文件

本专题为大家带来python打包成可执行文件相关的文章,大家可以免费的下载体验。

2023.07.20

1104

4

python能做什么
python能做什么

python能做的有:可用于开发基于控制台的应用程序、多媒体部分开发、用于开发基于Web的应用程序、使用python处理数据、系统编程等等。本专题为大家提供python相关的各种文章、以及下载和课程。

2023.07.25

2071

7

format在python中的用法
format在python中的用法

Python中的format是一种字符串格式化方法,用于将变量或值插入到字符串中的占位符位置。通过format方法,我们可以动态地构建字符串,使其包含不同值。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.31

1185

3

python教程
python教程

Python已成为一门网红语言,即使是在非编程开发者当中,也掀起了一股学习的热潮。本专题为大家带来python教程的相关文章,大家可以免费体验学习。

2023.08.03

8797

23

python环境变量的配置
python环境变量的配置

Python是一种流行的编程语言,被广泛用于软件开发、数据分析和科学计算等领域。在安装Python之后,我们需要配置环境变量,以便在任何位置都能够访问Python的可执行文件。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

1479

5

python eval
python eval

eval函数是Python中一个非常强大的函数,它可以将字符串作为Python代码进行执行,实现动态编程的效果。然而,由于其潜在的安全风险和性能问题,需要谨慎使用。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.04

1550

5

scratch和python区别
scratch和python区别

scratch和python的区别:1、scratch是一种专为初学者设计的图形化编程语言,python是一种文本编程语言;2、scratch使用的是基于积木的编程语法,python采用更加传统的文本编程语法等等。本专题为大家提供scratch和python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

881

5

python合并两个列表
python合并两个列表

Python是一种强大的编程语言,具有许多方便的功能和工具。在Python中,有多种方法可以合并两个列表。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.10

530

4

python是前端还是后端
python是前端还是后端

Python属于前端也属于后端,其灵活性和丰富的生态系统使得开发人员能够在不同的领域中灵活运用。本专题为大家提供python相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.11

1111

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.4万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 131.8万人学习