@TeachTheMachine: 管理语言模型中的小上下文窗口
摘要
本文讨论了管理大型语言模型中小上下文窗口的实用策略,包括滑动窗口截断和结合检索增强生成的令牌预算,并提供了Python代码示例。
查看缓存全文
缓存时间: 2026/08/19 04:36
管理语言模型中的小型上下文窗口
https://t.co/GAiKlmrUjK
管理语言模型中的小型上下文窗口 - MachineLearningMastery.com
来源:https://machinelearningmastery.com/managing-small-context-windows-in-language-models/ 本文将介绍三种管理大型语言模型小型上下文窗口的实用策略,并附有可运行的 Python 示例,演示其中两种策略的实现方法。
我们将涵盖的主题包括:
- 滑动窗口方法如何通过上下文截断保持令牌使用量平稳可预测
- 令牌预算分配结合检索增强生成如何确保只有最相关的上下文能放入提示词
- 针对更专业用例的其他策略简要概述——滚动摘要、提示压缩和观察掩蔽
管理语言模型中的小型上下文窗口
简介
顶级 AI 领域似乎对能够处理巨大上下文窗口的语言模型(例如在单次提示中输入整本书)颇为着迷。然而,他们不愿轻易承认的是,在实际的大语言模型应用中,这些巨大的上下文窗口伴随着各种限制和挑战,包括高昂的 API 成本、不可接受的响应时间,甚至更糟的“中间信息丢失”问题——模型会忽略深埋在巨大提示词中间的数据。因此,使用经过智能管理的小型上下文窗口反而可能带来更优的效果:降低延迟、最小化成本,并迫使模型专注于对生成响应真正重要的内容。
本文将揭示管理并掌握语言模型中小型上下文窗口的三种最广泛采用的实用策略,并附带模仿其中某些实现方式的示例,以帮助更好理解。
上下文截断:滑动窗口
业界普遍认为,滑动窗口可能是管理语言模型缩短上下文窗口最常见、最简单的策略。它不是将整个用户对话历史提供给模型,而是将上下文视为先进先出队列:当新的交互(交换的消息)进来时,最旧的消息便被丢弃。只需定义上下文窗口大小,并在保留足够历史上下文与控制延迟/成本之间取得平衡即可。
通过滑动窗口截断上下文的主要优势在于,对令牌使用量和计算开销具有绝对控制力和可预测性。模型在任意时间处理的最大交互次数保持固定,从而保持延迟稳定且无意外。
为更好理解此方法的工作原理,请看以下 Python 代码,其中您可以自由调整max_turns(上下文窗口大小)的值,观察它如何影响注入当前提示词的“记忆”:
class SlidingWindowMemory:
def __init__(self, max_turns=3):
"""只保留对话中最近的 `max_turns` 轮。"""
self.max_turns = max_turns
self.history = []
def add_interaction(self, user_text, ai_text):
self.history.append({"user": user_text, "ai": ai_text})
# 滑动窗口背后的逻辑:如果超过限制,则丢弃最早的轮次
if len(self.history) > self.max_turns:
self.history = self.history[-self.max_turns:]
def build_prompt(self, new_query):
prompt = "System: 基于近期上下文简洁回答。\n\n"
for turn in self.history:
prompt += f"User: {turn['user']}\nAI: {turn['ai']}\n"
prompt += f"User: {new_query}\nAI:"
return prompt
# --- 测试滑动窗口机制:可自由调整 max_turns 的值 ---
memory = SlidingWindowMemory(max_turns=2)
# 模拟一段较长的对话
memory.add_interaction("Hi, I'm learning Python.", "Great choice!")
memory.add_interaction("What are lists?", "Lists are mutable arrays.")
memory.add_interaction("Can they hold mixed types?", "Yes, they can.")
# 提示词将只包含最近 'max_turns' 轮交互,从而节省令牌
print(memory.build_prompt("How do I append to one?"))
输出:
System: 基于近期上下文简洁回答。
User: What are lists?
AI: Lists are mutable arrays.
User: Can they hold mixed types?
AI: Yes, they can.
User: How do I append to one?
AI:
您也可以尝试通过添加自己的新memory.add_interaction()调用及额外的查询-响应对来扩展对话历史,以测试较大上下文窗口下的机制。
令牌预算分配与 RAG(检索增强生成)
RAG 系统通过引擎补充大语言模型,该引擎引用和检索外部文档,用有依据的相关上下文丰富原始用户提示。小型上下文窗口可能直觉上迫使对要包含在上下文中的数据采取严格筛选的态度。为此,令牌预算分配将上下文窗口划分为多个区域,每个区域有严格限制。例如,令牌预算标准可能允许最多 20% 的上下文用于系统指令,20% 用于聊天历史(包括最新的用户查询),剩余的 60% 用于检索到的数据。这纳入了更动态的检索和数据分块行为,一旦达到预算限制即停止插入。
令牌预算分配的主要优势是防止过大的检索文档快速耗尽提示词,并确保只包含高度相关、信息集中的内容,从而避免前文提到的“中间信息丢失”等问题。
以下代码片段展示了该机制在 Python 中的使用,使用简单的词数作为令牌预算分配的免费轻量级代理——为了更真实,您可以考虑采用通用的经验法则:平均 1 词 = 1.3 个令牌。函数内部的循环展示了如何可靠地打包提示词而不超出强制限制:
def build_budgeted_prompt(system_prompt, retrieved_chunks, user_query, max_words=50):
"""将上下文块打包到提示词中,直到达到严格的词数预算。"""
# 计算必需元素的固定开销
base_words = len(system_prompt.split()) + len(user_query.split())
current_words = base_words
included_chunks = []
for chunk in retrieved_chunks:
chunk_words = len(chunk.split())
# 仅在符合严格预算时才添加该块
if current_words + chunk_words <= max_words:
included_chunks.append(chunk)
current_words += chunk_words
else:
print(f"已达预算!已排除 {len(retrieved_chunks) - len(included_chunks)} 个块。")
break
context_str = "\n---\n".join(included_chunks)
return f"{system_prompt}\n\nContext:\n{context_str}\n\nUser: {user_query}"
# --- 测试预算提示词机制 ---
system_msg = "Use the context to answer."
query = "What is the capital of Spain?"
docs = [
"Seville is a city in Andalusia, Spain.",
"Madrid is the capital of Spain.", # 我们希望这个能被包含
"Spain is located in Southwestern Europe.", # 这个可能会被截断
"The population of Spain is roughly 47 million."
]
# 设置一个非常小的预算以观察截止效果
print(build_budgeted_prompt(system_msg, docs, query, max_words=30))
输出:
已达预算!已排除 1 个块。
Use the context to answer.
Context:
Seville is a city in Andalusia, Spain.
---
Madrid is the capital of Spain.
---
Spain is located in Southwestern Europe.
User: What is the capital of Spain?
超越基础:其他策略
最后,让我们快速概述其他一些管理小型上下文窗口的策略,特别是针对专业用例。请注意,其中一些策略的实现通常需要实时 API 调用或额外的外部依赖项。
- 滚动摘要: 此方法使用辅助大语言模型进行摘要,将较旧的对话历史压缩为紧凑的段落,替代原始提示文本。它有助于在不增加令牌膨胀的情况下保留长期记忆,但需要额外的 API 调用来请求和获取摘要,从而引入额外开销和潜在成本。
- 提示压缩: 与其依赖辅助模型,不如调用算法在将原始上下文输入主模型之前,删除填充词、冗余数据和停用词。这可以在不影响输入质量或语义意图的情况下显著降低延迟,但如果应用过于激进,可能会剥离模型生成可接受响应所需的微妙但有价值的细节。
- 观察掩蔽: 此方法评估上下文以隐藏或掩蔽较旧的、结构性的噪声(例如基于代理的系统中的数据库查询或中间代码执行日志),同时保持核心逻辑不变。这是由大语言模型驱动的自主智能体中常用的技术,使它们能够专注于眼前目标,而不被过去的内部步骤分散注意力。然而,它的实现更为复杂,因为需要确定哪些观察可以安全掩蔽而不损害智能体的推理链。
结束语
小型上下文窗口不应被视为限制,而应被视为一种架构特性,用于防止成本过高和延迟过大等主要问题。本文介绍了多种有效管理大语言模型中小型上下文窗口的策略,以在不妥协准确性的情况下,获得更快、更经济的解决方案。
暂无评论。
相似文章
不要轻信大上下文窗口
分析表明,LLM 声称的大上下文窗口具有误导性,因为有效注意力在约 10 万 token 时会下降。为开发者提供实用建议:通过使用工件(artifacts)和切换(handoffs)将会话保持在“智能区”。
更大的上下文窗口只是让你中间有个更大的死区
对847次AI代理运行的分析显示,较大的上下文窗口会导致性能下降,原因是注意力悬崖,而Synap被介绍为一个工具,可以高效地管理上下文并减少token使用量。
训练驱动的 Agentic Context Management(自主上下文管理)
本文提出了一种训练驱动的自主上下文管理方法:在一个极简的 agentic 框架(一个用于调用自身、一个用于读取任意 token 区间)上对一个小型模型(Qwen3.6-35B-A3B)进行微调,使其在长文档基准测试中,仅使用 8K token 的上下文,就能达到 GPT-5.4 使用 1M token 上下文时的性能水平。
更大的上下文窗口对智能体来说其实是错误的方向吗?
作者质疑将注意力集中在扩大AI智能体的上下文窗口上是否适得其反,认为积累的垃圾信息会拖慢长时间会话,并建议保持工作上下文小巧、使用外部记忆。
理解大语言模型推理在上下文长度和注意力架构下的能耗缩放
本文对大语言模型推理的能耗进行了系统性实证研究,分析了如多头注意力(Multi-Head Attention)、分组查询注意力(Grouped Query Attention)和滑动窗口注意力(Sliding Window Attention)等注意力架构如何影响不同上下文长度和工作负载下的能耗缩放。