Context Engineering 上下文工程
版本: v0.27.0+ | 基于 Manus AI 最佳实践 | KV-Cache 优化
Context Engineering 模块实现了 KV-Cache 友好的 Prompt 构建策略,基于 Manus AI 博客 的最佳实践。通过稳定的 Prompt 前缀、只追加模式、显式缓存断点和任务目标重述,最大化 LLM 推理时的 KV-Cache 命中率,降低延迟与 Token 开销。
核心特性
- ⚡ KV-Cache 优化: 稳定 Prompt 前缀 + 确定性工具序列化,缓存命中率 80%+
- 📝 只追加模式: 对话历史 append-only,不修改已有消息,保证缓存一致性
- 🔗 4 级上下文注入: Instinct / 代码知识图谱 / 长期记忆 / EvoMap 社区知识自动注入
- 🗜️ 可恢复压缩: 长内容压缩保留 URL/路径等引用,按需恢复完整数据
- 🎯 任务目标重述: 上下文末尾自动重述任务目标和进度,解决"丢失中间"问题
- 📊 错误学习: 保留错误历史供模型学习,自动避免重复犯错
系统架构
┌──────────────────────────────────────────────────┐
│ Context Engineering 构建流程 │
├──────────────────────────────────────────────────┤
│ 第一部分: 静态内容 (可缓存) │
│ ┌────────────────┐ ┌──────────────────────┐ │
│ │ System Prompt │ │ 工具定义 (按名称排序) │ │
│ │ (清理动态内容) │ │ (确定性序列化) │ │
│ └────────────────┘ └──────────────────────┘ │
│ ──── 缓存断点 ──── │
│ 第二部分: 动态内容 (只追加) │
│ ┌──────────────────────────────────────────┐ │
│ │ 对话历史 → 错误上下文 → Instinct 模式 │ │
│ │ → 代码知识图谱 → 长期记忆 → EvoMap │ │
│ └──────────────────────────────────────────┘ │
│ 第三部分: 任务重述 │
│ ┌──────────────────────────────────────────┐ │
│ │ 当前任务目标 + 进度 (todo.md 机制) │ │
│ └──────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘系统概述
核心能力
| 能力 | 说明 | 效果 |
|---|---|---|
| KV-Cache 优化 | 稳定前缀 + 确定性序列化,最大化缓存命中 | 降低推理延迟 |
| 上下文注入管道 | 4 个注入点自动丰富 Prompt 上下文 | 提升回答质量 |
| 可恢复压缩 | 长观察数据压缩,保留 URL/路径等可恢复引用 | 减少 Token 消耗 |
| 任务目标重述 | 上下文末尾重述目标,解决"丢失中间"问题 | 保持任务聚焦 |
| 错误学习 | 保留错误历史供模型学习,避免重复犯错 | 提升成功率 |
单例模式
模块通过 getContextEngineering() 提供全局单例,确保整个应用共享同一份缓存和统计数据:
const { getContextEngineering } = require("./llm/context-engineering");
// 首次调用创建实例,后续调用返回同一实例
const ce = getContextEngineering({ maxHistoryMessages: 100 });核心原则
Context Engineering 遵循 Manus AI 总结的 4 条核心原则:
1. 保持 Prompt 前缀稳定
System Prompt 中自动移除时间戳、UUID、Session ID 等动态内容,替换为占位符,确保静态部分的哈希值不变:
原始: "当前时间: 2026-02-26T10:30:00Z, 会话: abc-123-def"
清理: "当前时间: [DATE], 会话: session_id: [SESSION]"清理规则:
| 模式 | 替换为 | 示例 |
|---|---|---|
| ISO 日期/时间戳 | [DATE] | 2026-02-26T10:30:00Z -> [DATE] |
| 时间 (HH:MM:SS) | [TIME] | 10:30:00 -> [TIME] |
| UUID | [UUID] | 550e8400-e29b-... -> [UUID] |
| Session ID | [SESSION] | session_id: xyz -> session_id: [SESSION] |
2. 采用只追加模式
对话历史以 append-only 方式追加,不修改已有消息。清理时仅移除非核心元数据(timestamp、id、messageId),保留 role、content、function_call、tool_calls、name 等核心字段。
3. 显式标记缓存断点
在静态部分(System Prompt + 工具定义)与动态部分(对话历史)之间标记缓存断点,帮助 LLM 服务端优化 KV-Cache 分片:
result.metadata.cacheBreakpoints.push(result.messages.length);4. 任务目标重述到上下文末尾
长上下文中,模型容易"遗忘"中间信息。通过在消息数组末尾重述当前任务目标和进度,确保模型始终聚焦于正确的任务:
## Current Task Status
**Objective**: 优化数据库查询性能
**Progress**:
[x] Step 1: 分析慢查询日志
[>] Step 2: 创建索引
[ ] Step 3: 验证性能提升
**Current Focus**: Step 2 - 创建索引Prompt 构建流程
buildOptimizedPrompt() 方法按三部分结构构建消息数组:
┌─────────────────────────────────────────────┐
│ 第一部分: 静态内容 (可缓存) │
│ ┌─────────────────────────────────────────┐ │
│ │ 1. System Prompt (清理后) │ │
│ │ 2. 工具定义 (确定性序列化,按名称排序) │ │
│ └─────────────────────────────────────────┘ │
│ ── 缓存断点 ── │
├─────────────────────────────────────────────┤
│ 第二部分: 动态内容 (只追加) │
│ ┌─────────────────────────────────────────┐ │
│ │ 3. 对话历史 (清理后) │ │
│ │ 4. 错误上下文 (最近 N 条) │ │
│ │ 4.5 Instinct 已学习模式 │ │
│ │ 4.6 Code Knowledge Graph 架构洞察 │ │
│ │ 4.7 长期记忆 + 用户偏好 │ │
│ │ 4.8 EvoMap 社区知识 │ │
│ └─────────────────────────────────────────┘ │
├─────────────────────────────────────────────┤
│ 第三部分: 任务重述 (解决丢失中间) │
│ ┌─────────────────────────────────────────┐ │
│ │ 5. 当前任务目标 + 进度 (todo.md 机制) │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────┘工具定义序列化
工具定义支持两种模式:
| 模式 | 触发条件 | 特点 |
|---|---|---|
| 技能分组模式 | 传入 unifiedRegistry 且有技能 | 按技能分组,包含 instructions 和 examples |
| 普通列表模式 | 仅传入 tools 数组 | 按名称排序,纯工具列表 |
技能分组模式 会为每个技能生成包含 Instructions(截断至 200 字符)、Examples(最多 3 条)和 Tools 的结构化定义,未归属技能的工具归入 "Other Tools" 分组。参数 JSON 超过 500 字符时自动截断。
上下文注入管道
在对话历史之后、任务重述之前,Context Engineering 依次执行 4 个注入步骤。每个步骤都是非关键的(non-critical),失败时静默跳过,不影响主流程。
| 步骤 | 注入器 | 注入方法 | 说明 | 设置方法 |
|---|---|---|---|---|
| 4.5 | InstinctManager | buildInstinctContext(hint, 5) | 注入已学习的行为模式(top 5) | setInstinctManager() |
| 4.6 | CodeKnowledgeGraph | buildKGContext() | 注入代码架构洞察(实体/关系) | setCodeKnowledgeGraph() |
| 4.7 | Memory + Preferences | buildPreferenceContext(5) + buildMemoryContext(hint, 3) | 注入用户偏好和相关历史记忆 | setMemoryAugManager() / setPreferenceLearner() |
| 4.8 | EvoMapAssetBridge | buildEvoMapContext(hint, 3) | 注入全球 Agent 验证的社区知识 | setEvoMapBridge() |
上下文提示(Context Hint)
步骤 4.5、4.7、4.8 使用上下文提示来匹配相关内容。提示来源优先级:
taskContext.objective- 当前任务目标(如果有)- 最近 2~3 条消息的
content拼接 - 作为 fallback
注入器设置示例
const ce = getContextEngineering();
// 注入 Instinct 学习模式
const { getInstinctManager } = require("./llm/instinct-manager");
ce.setInstinctManager(getInstinctManager());
// 注入代码知识图谱
const {
CodeKnowledgeGraph,
} = require("./ai-engine/cowork/code-knowledge-graph");
ce.setCodeKnowledgeGraph(new CodeKnowledgeGraph(db));
// 注入长期记忆
const {
MemoryAugmentedGeneration,
} = require("./llm/memory-augmented-generation");
ce.setMemoryAugManager(new MemoryAugmentedGeneration(db));
// 注入用户偏好
const { UserPreferenceLearner } = require("./llm/user-preference-learner");
ce.setPreferenceLearner(new UserPreferenceLearner(db));
// 注入 EvoMap 社区知识
const { EvoMapAssetBridge } = require("./evomap/evomap-asset-bridge");
ce.setEvoMapBridge(new EvoMapAssetBridge());可恢复压缩器
RecoverableCompressor 实现了 Manus 的可恢复压缩策略:对超长观察数据进行压缩,同时保留可恢复的引用信息(URL、文件路径、SQL 查询),以便后续按需恢复完整内容。
压缩阈值
| 内容类型 | 阈值(字符数) | 保留的引用信息 |
|---|---|---|
webpage | 2,000 | URL、标题、摘要(200字符) |
file | 5,000 | 文件路径、文件名、大小 |
dbResult | 1,000 | SQL 查询、列名、前 10 行 |
default | 3,000 | 预览文本(1000字符) |
压缩输出格式
所有压缩结果统一为 compressed_ref 对象:
{
_type: "compressed_ref", // 固定标识
refType: "webpage", // 内容类型
url: "https://example.com", // 可恢复引用
title: "页面标题",
summary: "摘要内容...",
originalLength: 15000, // 原始长度
recoverable: true // 是否可恢复
}压缩与恢复示例
const { RecoverableCompressor } = require("./llm/context-engineering");
const compressor = new RecoverableCompressor();
// 压缩网页内容
const ref = compressor.compress(
{
url: "https://docs.example.com/guide",
title: "开发指南",
content: "非常长的网页内容...(15000字符)",
summary: "这是一份开发指南...",
},
"webpage",
);
// 检查是否为压缩引用
compressor.isCompressedRef(ref); // true
// 恢复内容(需要提供恢复函数)
const original = await compressor.recover(ref, {
fetchWebpage: async (url) => {
// 重新获取网页内容
return await fetch(url).then((r) => r.text());
},
});恢复函数映射
| refType | 恢复函数 | 参数 |
|---|---|---|
webpage | fetchWebpage() | ref.url |
file | readFile() | ref.path |
dbResult | runQuery() | ref.query |
注意: 当
recoverable为false时(如纯文本字符串无 URL),调用recover()会抛出错误。
配置参考
构造函数选项
通过 getContextEngineering(options) 或 new ContextEngineering(options) 传入:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enableKVCacheOptimization | boolean | true | 启用 KV-Cache 优化(清理动态内容) |
enableTodoMechanism | boolean | true | 启用任务目标重述(todo.md 机制) |
maxHistoryMessages | number | 50 | 最大历史消息数,超过后触发压缩 |
preserveErrors | boolean | true | 保留错误历史供模型学习 |
maxPreservedErrors | number | 5 | 最大保留的错误条数 |
配置示例
const ce = getContextEngineering({
enableKVCacheOptimization: true,
enableTodoMechanism: true,
maxHistoryMessages: 100,
preserveErrors: true,
maxPreservedErrors: 10,
});API 参考
ContextEngineering 类
| 方法 | 参数 | 返回值 | 说明 |
|---|---|---|---|
buildOptimizedPrompt(opts) | { systemPrompt, messages, tools, taskContext, unifiedRegistry } | { messages, metadata } | 构建 KV-Cache 友好的 Prompt |
recordError(error) | { step, message, resolution } | void | 记录错误供模型学习 |
resolveError(index, text) | number, string | void | 标记错误已解决并附加解决方案 |
setCurrentTask(task) | { objective, steps, currentStep } | void | 设置当前任务上下文 |
updateTaskProgress(step, s) | number, string | void | 更新任务进度 |
getCurrentTask() | 无 | Object | null | 获取当前任务上下文 |
clearTask() | 无 | void | 清除任务上下文 |
clearErrors() | 无 | void | 清除错误历史 |
getStats() | 无 | Object | 获取缓存命中等统计信息 |
resetStats() | 无 | void | 重置统计数据 |
setInstinctManager(mgr) | Object | void | 注入 InstinctManager |
setCodeKnowledgeGraph(kg) | Object | void | 注入 CodeKnowledgeGraph |
setEvoMapBridge(bridge) | Object | void | 注入 EvoMapAssetBridge |
setMemoryAugManager(mgr) | Object | void | 注入 MemoryAugmentedGeneration |
setPreferenceLearner(pl) | Object | void | 注入 UserPreferenceLearner |
buildOptimizedPrompt 返回值
{
messages: [
{ role: "system", content: "..." }, // 清理后的 System Prompt
{ role: "system", content: "..." }, // 工具定义
{ role: "user", content: "..." }, // 对话历史...
{ role: "assistant", content: "..." },
{ role: "system", content: "..." }, // 注入的上下文
{ role: "system", content: "..." }, // 任务重述
],
metadata: {
cacheBreakpoints: [2], // 缓存断点位置(索引)
staticPartLength: 2, // 静态部分消息数
dynamicPartLength: 4, // 动态部分消息数
wasCacheOptimized: true, // 是否命中缓存(静态部分未变化)
}
}RecoverableCompressor 类
| 方法 | 参数 | 返回值 | 说明 |
|---|---|---|---|
compress(content, type) | any, string | any | Object | 压缩内容,保留引用 |
isCompressedRef(data) | any | boolean | 判断是否为压缩引用 |
recover(ref, recoveryFns) | Object, Object | Promise<any> | 异步恢复压缩内容 |
使用示例
基础用法
const { getContextEngineering } = require("./llm/context-engineering");
const ce = getContextEngineering();
// 构建优化后的 Prompt
const result = ce.buildOptimizedPrompt({
systemPrompt: "你是一个智能助手。当前时间: 2026-02-26T10:00:00Z",
messages: [
{ role: "user", content: "帮我优化这段代码" },
{ role: "assistant", content: "好的,我来分析..." },
{ role: "user", content: "还需要添加错误处理" },
],
tools: [
{ name: "read_file", description: "读取文件", parameters: {} },
{ name: "write_file", description: "写入文件", parameters: {} },
],
});
// result.messages 即可直接发送给 LLM
console.log(result.metadata.wasCacheOptimized); // true(第二次调用时)带任务上下文
const ce = getContextEngineering();
// 设置任务
ce.setCurrentTask({
objective: "重构用户认证模块",
steps: [
{ description: "分析现有代码" },
{ description: "设计新架构" },
{ description: "实现新模块" },
{ description: "编写测试" },
],
currentStep: 1,
});
// 构建 Prompt(末尾自动附加任务重述)
const result = ce.buildOptimizedPrompt({
systemPrompt: "你是架构师",
messages: [...],
taskContext: ce.getCurrentTask(),
});
// 更新进度
ce.updateTaskProgress(2, "in_progress");错误学习
const ce = getContextEngineering();
// 记录错误
ce.recordError({
step: "代码生成",
message: "TypeScript 类型错误: Property 'x' does not exist",
});
// 标记解决方案
ce.resolveError(0, "添加了接口定义并使用类型断言");
// 下次构建 Prompt 时,错误上下文自动包含在内
// 模型可以学习避免类似错误与统一工具注册表集成
const ce = getContextEngineering();
const registry = getUnifiedToolRegistry();
// 使用技能分组模式生成工具定义
const result = ce.buildOptimizedPrompt({
systemPrompt: "你是智能助手",
messages: [...],
unifiedRegistry: registry, // 传入注册表实例
});
// 工具按技能分组,附带 instructions 和 examples性能统计
通过 getStats() 获取运行时统计数据:
const stats = ce.getStats();统计字段
| 字段 | 类型 | 说明 |
|---|---|---|
cacheHits | number | KV-Cache 命中次数 |
cacheMisses | number | KV-Cache 未命中次数 |
totalCalls | number | buildOptimizedPrompt 总调用次数 |
compressionSavings | number | 压缩节省的字符数 |
cacheHitRate | number | 命中率 (0~1) |
cacheHitRatePercent | string | 命中率百分比 (如 "85.50%") |
统计示例
const stats = ce.getStats();
console.log(stats);
// {
// cacheHits: 42,
// cacheMisses: 8,
// totalCalls: 50,
// compressionSavings: 0,
// cacheHitRate: 0.84,
// cacheHitRatePercent: "84.00%"
// }
// 重置统计
ce.resetStats();缓存命中判定: 当 System Prompt(清理后)和工具定义的 MD5 哈希值与上次调用一致时,视为缓存命中。通常在会话进行中,静态部分不变,命中率应稳定在 80% 以上。
故障排除
缓存命中率过低
症状: cacheHitRate 低于 50%
可能原因:
- System Prompt 中包含未被清理规则覆盖的动态内容
- 工具列表在每次调用间发生变化
- 使用了不同的
unifiedRegistry实例
解决方案:
- 检查 System Prompt 是否有自定义动态内容,考虑手动移除
- 确保工具列表在会话内保持稳定
- 使用
getStats()监控命中率变化趋势
注入上下文未生效
症状: Instinct/KG/Memory 等上下文未出现在生成的 Prompt 中
可能原因:
- 注入器未正确设置(未调用
setXxx()方法) - 注入器的
buildXxxContext()返回空值 - 注入器内部抛出异常(被静默捕获)
解决方案:
- 确认已调用对应的
set方法注入管理器实例 - 单独测试注入器的
build*Context()方法是否返回有效内容 - 临时添加 try-catch 日志排查注入器内部错误
消息数组过长
症状: Prompt 超出模型上下文窗口限制
可能原因:
maxHistoryMessages设置过大- 错误历史累积过多
- 注入上下文过于冗长
解决方案:
- 降低
maxHistoryMessages值(建议 20~50) - 减少
maxPreservedErrors值 - 结合 SessionManager 的自动压缩功能管理对话长度
RecoverableCompressor 恢复失败
症状: recover() 抛出 "Content is not recoverable" 错误
原因: 压缩引用的 recoverable 为 false,通常是纯文本内容无法定位源头
解决方案: 压缩时提供结构化数据(包含 url、path 或 query),而非纯字符串
相关文档
- SessionManager 会话管理 - 智能会话上下文管理
- Hooks 系统 - 事件钩子与中间件
- Cowork 多智能体 - 多 Agent 协作框架
- Skills 技能系统 - 95+ 内置技能
- EvoMap 协议 - 社区知识共享
源码位置
| 文件 | 说明 |
|---|---|
desktop-app-vue/src/main/llm/context-engineering.js | 主模块(ContextEngineering + RecoverableCompressor) |
desktop-app-vue/src/main/llm/instinct-manager.js | Instinct 学习管理器(注入步骤 4.5) |
desktop-app-vue/src/main/ai-engine/cowork/code-knowledge-graph.js | 代码知识图谱(注入步骤 4.6) |
desktop-app-vue/src/main/ai-engine/unified-tool-registry.js | 统一工具注册表(技能分组工具序列化) |
关键文件
| 文件 | 说明 |
|---|---|
desktop-app-vue/src/main/llm/context-engineering.js | ContextEngineering + RecoverableCompressor 主模块 |
desktop-app-vue/src/main/llm/instinct-manager.js | Instinct 学习管理器(注入步骤 4.5) |
desktop-app-vue/src/main/ai-engine/cowork/code-knowledge-graph.js | 代码知识图谱(注入步骤 4.6) |
desktop-app-vue/src/main/llm/memory-augmented-generation.js | 长期记忆管理(注入步骤 4.7) |
desktop-app-vue/src/main/ai-engine/unified-tool-registry.js | 统一工具注册表(技能分组序列化) |
智能上下文,高效推理
