1. 大模型上下文工程:从理论到实践
作为一名长期从事AI开发的工程师,我深刻理解上下文工程在大模型应用中的重要性。OpenClaw的上下文工程系统为我们提供了一个优秀的参考框架,让我们能够系统性地构建、管理和注入任务相关上下文信息。
1.1 什么是上下文工程?
很多人一看到"上下文"这个词,第一反应就是提示词或者RAG(检索增强生成)。这个理解不能说完全错误,但确实有些片面。就像把"写几行代码"等同于"软件工程"一样,这种理解忽略了上下文工程的系统性和复杂性。
在我看来,上下文工程是一整套系统性地构建、管理和注入与任务相关的上下文信息的工程方法。简单来说:
上下文工程,就是给大模型设计一套高可用、可治理、能长期稳定运行的输入系统
更具体地说,上下文可以理解为模型在当前这一轮推理中能看到的所有信息的总和。这包括但不限于:
- 系统提示词(System Prompt)
- 用户输入(User Input)
- 历史对话记录
- 工具返回结果
- 检索内容(RAG)
- 长期记忆(Memory)
所有这些信息拼在一起,才是模型真正用来思考、决策、输出答案的全部依据。
1.2 上下文工程要解决的核心问题
大模型在实际应用中存在三个主要短板,上下文工程就是为了补齐这些短板而存在的:
1.2.1 胡言乱语(Hallucination)
大模型在训练时从海量互联网数据中学习到了很多知识,但如果不加以引导,模型往往会泛泛而谈,回答不够准确,甚至捏造事实。上下文工程的任务之一,就是把模型不知道的、最新的、专属的信息精准地喂给它。
1.2.2 长度限制(Context Window)
所有模型都有固定的Token上限,复杂任务很容易把上下文撑爆。过长的内容会让模型注意力分散、抓不住重点,甚至直接报错。上下文工程要做的,就是在有限的Token预算里,只保留最关键的信息。
1.2.3 模型读不懂(Poor Comprehension)
如果输入信息没有逻辑、没有规范、杂乱无章,模型就无法有效解读。上下文工程需要把信息整理成模型能轻松理解的结构化格式。
1.3 上下文工程的核心目标
基于上述问题,上下文工程需要实现以下目标:
- 引导与约束:用背景、规则、示例给模型划定边界,让它只在规定范围内思考和输出。
- 提升准确性:注入最新数据、内部知识库、实时信息,从根源减少幻觉。
- 实现复杂任务:把单次无法完成的复杂任务,拆成多轮对话、思维链、工具调用,引导模型一步步推理落地。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. OpenClaw上下文工程实现详解
OpenClaw的上下文工程采用了流水线架构,整个提示词的组装过程像一条工厂流水线,原始数据从一端进入,经过一系列处理步骤,最终成品(完整的提示词)从另一端输出。
2.1 整体架构解析
从架构上看,OpenClaw的上下文工程可以分为三层:
2.1.1 资源管理层
这一层负责管理所有上下文的信息来源,核心工作是决定哪些信息必须保留、哪些可以删除、冲突信息如何处理。主要管理以下资源:
- 用户配置
- 工作区文档(如AGENTS.md、TOOLS.md等)
- 对话历史
- 工具列表
- 长期记忆
2.1.2 组装层
这一层负责把收集到的所有资源,按固定格式、固定顺序拼装。主要处理以下问题:
- 模型格式兼容问题
- 历史消息脏数据清理
- Token预算内的取舍权衡
2.1.3 保护层
这一层确保系统安全稳定运行,主要功能包括:
- 检测上下文是否即将溢出
- 自动触发压缩
- 防止系统因上下文过大崩溃
2.2 核心模块实现
2.2.1 上下文引擎
OpenClaw采用了可插拔的标准接口设计,定义了上下文管理全生命周期的契约。默认提供传统引擎,同时支持自定义扩展,比如接入RAG系统。
2.2.2 系统提示词构建器
这个模块负责生成Agent的"身份说明书"——一段高质量的系统提示词,它决定了Agent的能力上限。主要包括以下内容:
- 你是什么(身份定义)
- 你能做什么(能力范围)
- 你应该遵循什么规则(行为约束)
- 你的工作目录在哪里(环境信息)
Bootstrap加载器会读取工作区里的特殊配置文件,自动注入提示词:
- AGENTS.md:项目行为规则
- TOOLS.md:工具使用说明
- MEMORY.md:长期记忆
- SOUL.md:人格风格
会话清理器负责修复历史消息里的所有问题,保证送给模型的历史干净、合规、兼容。主要处理:
- 删除无效工具调用
- 压缩超限图片
- 修复消息顺序错乱
- 处理跨会话消息标记
当上下文快撑爆时,系统会启动上下文压缩器自动瘦身,确保不丢失关键信息。
2.3 上下文组装流程
2.3.1 确定上下文窗口大小
在开始组装任何内容之前,系统需要确定模型的上下文窗口大小(context window),也就是模型一次能够处理的最大token数量。不同的模型有不同的上下文窗口:小模型可能只有32K tokens,而大模型可能有200K甚至更多。
OpenClaw通过四个来源来获取这个数值,优先级从高到低是:
- 配置文件中的明确指定
- 模型元数据
- 默认值(200,000 tokens)
- 配置上限
系统还会执行保护检查:
- 硬性最小值(16000 tokens):低于此值会直接阻止运行
- 警告阈值(32000 tokens):低于此值会记录警告日志
2.3.2 加载项目上下文
确定上下文窗口大小后,系统开始收集项目特定的上下文信息。这些信息来自工作区中的特殊文件,被称为"Bootstrap文件"。
Bootstrap文件是开发者为Agent提供的"项目说明书",包括:
- AGENTS.md:告诉Agent在这个项目中应该如何表现
- TOOLS.md:解释项目中使用的特殊工具或命令
- MEMORY.md:记录重要的决策、约定或历史信息
- SOUL.md:定义Agent的人格和语气
- IDENTITY.md:定义项目身份和边界
- USER.md:提供用户特定的偏好和习惯
- HEARTBEAT.md:用于定时检查任务的指令
- BOOTSTRAP.md:仅在新工作区首次运行时提供初始化引导
加载这些文件时,系统需要考虑:
- 文件大小控制(单个文件上限20000字符,总大小上限150000字符)
- 会话过滤(不同会话可能需要不同的上下文)
- 上下文模式(完整模式、轻量模式、无模式)
2.3.3 管理记忆内容
OpenClaw的记忆系统分为两层:
- 工作区Markdown文件:
- MEMORY.md:存放持久化的内容
- memory/YYYY-MM-DD.md:每日流水
- 向量索引:存储在SQLite中,支持混合检索(向量检索70% + 关键词检索30%)
Agent访问记忆的方式:
- 主会话自动注入MEMORY.md
- 每日记忆通过工具按需访问(memory_search和memory_get)
2.3.4 加载可用工具
工具来源包括:
- 核心工具(read、write、exec等)
- 插件工具
- 渠道工具
工具筛选策略是分层的:
- Profile(minimal、coding、messaging等)
- Allow/Deny列表
- 沙箱限制
- 子Agent限制
- 群组策略
最终筛选出的工具会被格式化进系统提示词,每个工具一行,名称加简短描述。
2.3.5 构建系统提示词
系统提示词包含多个部分:
- 基础身份声明
- 工具列表
- 工具调用风格指南
- 安全指令
- Skills引导
- 记忆召回指令
- 工作区信息
- 运行时元数据
系统支持三种提示词模式:
- 完整模式(主Agent使用)
- 精简模式(子Agent使用)
- 无模式(最简单的场景)
2.3.6 清理会话历史
从会话文件中读取的历史消息需要经过仔细清理:
- 跨会话消息标记
- 图像处理(缩放或丢弃过大图片)
- 思考块处理(根据策略决定是否保留)
- 工具调用清理(验证名称、修复配对关系)
- 工具结果详情剥离
- Usage快照处理
- 提供商特定处理
- 模型变更检测
2.3.7 最终上下文组装
在收集了系统提示词和清理后的历史消息后,系统将它们组装成最终的上下文。核心工作是:
- 消息排序(确保按正确的时间顺序)
- token预算检查
- 保护最近的消息(总是完整保留最近几轮对话)
2.3.8 最终验证
在发送给大模型之前,系统执行最后一次验证:
- 提供商验证(不同提供商对消息格式有不同要求)
- Schema清理(移除不支持的关键字)
- 魔法字符串清理(替换可能触发安全机制的字符串)
2.4 上下文压缩机制
长期对话一定会填满上下文窗口,这时就会触发压缩。
2.4.1 触发条件
- 自动触发-上下文溢出:当大模型API返回上下文溢出错误时
- 自动触发-预算阈值:当前上下文大小超过预算的一定比例(通常是90%)
- 手动触发:用户发送/compact命令
2.4.2 压缩策略
OpenClaw提供三级压缩策略:
- 摘要压缩:使用大模型生成早期消息的摘要
- 截断压缩:直接丢弃早期的消息
- 混合压缩:摘要压缩+截断压缩结合
2.4.3 执行过程
- 计算token用量
- 设定压缩目标(默认压到预算80%)
- 生成高质量摘要
- 原子替换会话历史
- 压缩的安全保护(设置超时时间)
2.5 上下文引擎的可扩展设计
OpenClaw的上下文工程系统采用可插拔接口设计,开发者可以实现自己的上下文引擎来替换默认行为。
2.5.1 上下文引擎接口
ContextEngine接口包含以下方法:
- 引导阶段(bootstrap)
- 消息摄入(ingest/ingestBatch)
- 上下文组装(assemble)
- 上下文压缩(compact)
- 轮次后处理(afterTurn)
- 子代理管理(prepareSubagentSpawn/onSubagentEnded)
- 资源释放(dispose)
2.5.2 传统引擎实现
默认的LegacyContextEngine是一个最小化实现:
- ingest和afterTurn是空操作
- assemble方法透传消息
- 只有compact方法有实际实现
这种设计使得新的引擎可以逐步采用。
2.6 配置与调优
OpenClaw提供丰富的配置选项:
- contextTokens:上下文Token预算
- bootstrapMaxChars:单个Bootstrap文件最大字符
- bootstrapTotalMaxChars:所有Bootstrap总字符上限
- compaction.mode:压缩模式(auto/manual/off)
- compaction.target:压缩激进程度(budget/threshold)
调优建议:
- 监控Token使用,避免频繁溢出
- 精简Bootstrap文件,删除冗余内容
- 复杂任务用子Agent,降低主上下文压力
- 根据业务调整压缩阈值,平衡连续性与性能
3. 上下文工程的最佳实践
3.1 提示词工程与上下文工程的协作
很多人分不清提示词工程和上下文工程的区别,这里用最直白的方式说明:
- 提示词工程:如何提问、优化指令本身的设计、格式和措辞
- 上下文工程:给什么背景、筛选、加工和注入模型完成任务所需的外部知识和信息
标准工作流应该是:
- 上下文工程先行:通过RAG、记忆、工具,把最相关的背景资料筛选出来
- 提示词工程收尾:把资料+问题,用精心设计的模板组装,送给模型
举例说明:
用户问:"华为最新的旗舰手机是哪一款,什么价格?"
- 上下文工程:从新闻搜索到华为旗舰手机、价格等信息
- 提示词工程:设计模板→根据以下资料:{{context}},回答用户的问题:{{query}}
3.2 上下文管理的黄金法则
- 相关性优先:只保留与当前任务最相关的上下文
- 时效性平衡:新旧信息要有合理比例
- 结构化输入:确保模型能轻松理解上下文
- 安全边界:明确模型的权限和行为限制
- 可追溯性:保留足够的上下文以便调试和审计
3.3 常见问题与解决方案
3.3.1 上下文溢出
症状:模型返回上下文过长错误
解决方案:
- 启用自动压缩
- 优化提示词结构
- 拆分复杂任务为子任务
- 增加上下文窗口大小(如果模型支持)
3.3.2 信息丢失
症状:模型忘记之前的对话内容
解决方案:
- 优化记忆系统
- 增加关键信息的保留权重
- 使用摘要而非直接截断
- 实现长期记忆机制
3.3.3 性能下降
症状:随着对话轮次增加,响应速度变慢
解决方案:
- 优化上下文组装流程
- 减少不必要的上下文
- 使用更高效的序列化格式
- 考虑缓存机制
4. 从OpenClaw看上下文工程的未来
OpenClaw的上下文系统展示了如何用有限的token预算,尽可能把最该给模型看的信息整理好。它的核心思想是:
- 结构化设计:明确定义什么地方放工具、什么地方放记忆、哪里放技能,系统只需要拿数据往里填就行。
- 灵活扩展:通过ContextEngine接口,开发者可以轻松实现自己的上下文管理逻辑。
- 稳定可靠:完善的保护机制确保系统在各种边界条件下都能稳定运行。
未来,上下文工程可能会朝以下方向发展:
- 更智能的上下文选择:基于内容理解自动选择最相关的上下文
- 动态token分配:根据不同信息的重要性动态分配token预算
- 跨会话上下文共享:安全地共享不同会话间的有用信息
- 自适应压缩:根据任务类型自动选择最佳压缩策略
5. 给开发者的建议
如果你正在开发基于大模型的应用,以下建议可能对你有帮助:
- 从简单开始:不要一开始就追求完美的上下文管理系统,先实现基本功能再逐步优化。
- 重视可观测性:建立完善的日志和监控,了解上下文是如何被使用和变化的。
- 模块化设计:像OpenClaw一样,把不同功能解耦,便于单独测试和替换。
- 持续优化:定期审查上下文使用情况,寻找优化空间。
- 安全第一:始终考虑上下文可能包含的敏感信息,做好适当的过滤和保护。
OpenClaw的上下文工程实现为我们提供了一个优秀的参考案例。通过学习和借鉴它的设计理念,我们可以构建出更加强大、稳定的大模型应用系统。记住,好的上下文管理不仅能让模型表现得更好,还能显著提升用户体验和系统可靠性。
