每天学习一个Agent - Context Engineering Foundation
Prompt
一个简单高效的Prompt应该有三部分组成:任务描述、限制与约束、输出格式
|
|
比如:Write a poem about the ocean using only words with 5 letters or less in 4 lines
- 任务[TASK]: Write a poem about the ocean
- 限制[CONSTRAINTS]: using only words with 5 letters
- 输出格式[OUTPUT FORMAT]: in 4 lines
+Examples
增加示例构建最简单的Few-Shot,让LLM完成 ICL(In-Context Learning)
,但是增加几个示例,怎么选择示例才能获得最好的收益,这个就是上下文工程要解决的问题了
|
|
示例格式
可以以不同的格式Pattern增加示例,几种常用的格式:
|
|
- 前缀-后缀:最简单,适用于简单任务
- 输入输出对:界限清楚,适用于结构化数据
- COT:包含推理步骤,适用于复杂任务
示例数量
当然示例的个数不是越多越好,$Accuracy= f(num_examplar)$ 总体曲线类似于对数函数,随着示例数量的增加收益递减,一般的示例个数建议:
任务类型 | 示例个数 |
---|---|
分类 | 1-3个/每种类型 |
生成 | 2-5 |
结构化参数提取 | 2-4(覆盖所有字段) |
推理 | 2-3(包含思考过程) |
翻译 | 3-5(不同复杂程度) |
示例可以存储到数据库中,根据用户输入召回相似度最高的几个示例填充到上下文中,如可以存储到向量数据库中,直接根据Embedding语义召回,或者存储到结构化数据库中,根据标签分类召回
示例选择组装的几个注意点:
- 示例的格式跟效果是有关系的,可以根据不同任务选择不同的示例展现格式
- 示例的选择比较重要,要保障示例的多样性、边缘场景等,示例的顺序也会影响最终结果
- 示例的个数增加获得收益递减,考虑成本、效果与上下文长度,要选择合理的示例个数
+Memory/State
没有记忆与状态,与LLM的对话就会不连续,体验不好
最简单的方式是把之前的对话记录直接全部加到对话上下文中,但是随着对话历史增加,上下文超长,怎么获取最佳的性价比,就又来到了上下文工程的领域
记忆管理策略
一般我们可能有这样一些策略:
策略 | 说明 |
---|---|
滑动窗口 | 保留最近N次对话 |
总结 | 保留最近几次对话,压缩/总结更早之前对话历史 |
KV存储 | 提取对话记录里的关键事实信息KV存储(如"username”: “Alex”),后续对话直接填充提取后的KV关键事实 |
优先级裁剪 | 根据对话历史的重要性丢弃 |
语义分块 | 将对话根据主题分组,后续根据主题选择填充 |
除了对话历史,在对话过程还有一些流程状态或者变量 State,比如:
|
|
记忆类型与流转
上面说的都是短期记忆,对于需要长期存储的内容,可以放到外部存储中存储,比如在对话信息中提取的关键信息,领域的知识信息等,几种常见的记忆:
- Short-term Memory/瞬时记忆
- 最近几轮的对话
- 刚刚收到的指令
- Working Memory/工作记忆
- 当前的任务
- 当前任务用的变量State
- 任务的进展
- 任务的中间变量
- Long-term Memory/长期记忆
- 用户画像
- 历史对话事实
- 对话偏好
这些记忆的管理需要一个记忆管理器,记忆管理器不光负责记忆的存储和召回,还需要管理信息在各层之间流转,升级、降级、淘汰等生命周期管理
Multi-Agent
受限于上下文窗口大小限制、并行处理、多视角分析限制等问题,引入多Agent系统,多Agent系统有专业化、并行化、编排协同等特点,多Agent如何设计协同共享也作为上下文工程的一个关键部分
多Agent系统几个关键组件
- 编排器Orchestrator:协同多个Agents,管理工作流,一个编排器可以基于规则或者使用LLM实现,主要负责:
- 任务分解
- Agent选择与编排
- 信息路由
- 冲突仲裁解决
- 任务进展监控
- 合并输出
- 共享内存Shared Memory:各个Agent都可以访问使用的公共信息
- 工作内存:当前任务状态和中间结果
- 知识库:事实,检索信息
- 流程日志:推理与执行的过程记录
- 输出Buffer:存储输出结果,合成最终结果
- 多专家Agents:根据场景定义的多个不同专业的Agents
多Agent系统几种常见的控制流
模式 | 核心动作 | 适用场景 |
---|---|---|
SEQUENTIAL 串行流水线 |
Cell₁→Cell₂→Cell₃ 单向流动 | 步骤有先后依赖,比如“先检索→再总结→最后润色” |
PARALLEL 并行 Map-Reduce |
Split→N 个 Cell 同时跑→Merge 汇总 | 子任务互不依赖,比如“同时翻译 10 段文本” |
FEEDBACK LOOP 反馈闭环 |
Cell→Cell→…→把输出再送回前面重跑 | 需要迭代优化,比如“写代码→跑测试→修 bug→再测试” |
HIERARCHICAL 层级指挥 |
Boss Cell 指挥多个 Team Lead,每个 Lead 再管一批 Cell | 任务本身有层级,比如“项目经理拆需求→各组开发→集成” |
几个影响多Agent性能的关键要素:
- 专业清晰度:每一个Agent的特长专业角色是否清晰定义
- 记忆管理:高效存储和召回信息
- 编排逻辑:协调系统是否高效
- 错误处理:Agent错误输出的鲁棒性
- 反馈机制:能够从结果中学习提升
- 任务分解:问题分解成子任务的效果
多Agent系统的一些评估指标与及格线
指标 | 及格线 | 白话解释 | 不达标时常见症状 |
---|---|---|---|
End-to-end Accuracy | >90% | 全流程最终答案正确率 | 低于 90% → 需要回炉重排上下文或加纠错 Agent |
Total Token Usage | <50% 对比单一大 prompt | 比“一口气塞全部”省一半以上 token | 超标 → 检索/摘要策略太粗,Context Builder 没剪干净 |
Latency (per step) | <5 s | 每一步(Agent)推理耗时 | 超时 → 该 Agent的 prompt 过长或模型本身慢 |
Error Recovery Rate | >80% | 出错了能在下一轮自己修好的比例 | 太低 → 缺少 Feedback Loop 或记忆回写机制 |
Context Window Utilization | >70% | 实际用掉的窗口占可用窗口的比例 | 过低 → 信息没充分利用;过高 → 临近溢出风险 |
多Agent系统相比于单Agent优势
- 处理大于单个上下文长度的问题:把 100 万字拆成 200 份,每份 4K,仍能拼出全局结论
- 通过专门的验证Agent自我纠正:安排“校对Agent”专门挑错,发现 bug 就回炉
- 超越单个Agent的复杂多步推理能力:原来一次只能解 3 步方程,现在 30 步也能链式推理
- 处理过程可以适应新信息加入:任务跑一半用户甩来新 PDF,Agent能热插拔更新
- 多视角更平衡的分析:让“乐观/悲观/法律/财务”四种Agent各写一份,再汇总
- 抵御单Agent故障的韧性:某个Agent崩溃或幻觉,其他Agent投票把它踢掉
- 领域专业化:给不同Agent喂医学/法律/代码语料,它们自动成为单领域专家
多Agent系统面临的一些挑战
挑战 | 一句话场景 | 速修方案 |
---|---|---|
Error Propagation 错误级联 |
第 1 个Agent把“2024”写成“2042”,后面所有Agent全跟着错。 | 给每步加验证Agent+回滚机制;错就立即重算。 |
Coordination Overhead 协调延迟 |
等 5 个Agent串行投票,用户已经刷新页面。 | 把串行改并行 Map-Reduce;关键路径拆最细。 |
Information Bottlenecks 信息漏斗 |
100 页报告被第 1 个Agent压缩成 3 句话,关键数字丢了。 | 用摘要+原始片段双通道;只丢噪音不丢金子。 |
Debugging Difficulty 难调试 |
系统突然胡说八道,却不知道是哪个Agent出的错。 | 给每个Agent打日志 trace-id;一键回放历史上下文。 |
Cost Scaling 成本爆炸 |
一个任务 20 个Agent × 4k token ≈ 80k token,钱包直接报警。 | 动态裁剪+缓存重复计算;只让必要Agent跑必要 token。 |
System Design Complexity 复杂到秃头 |
流程图 30 个框,上线后天天改配置。 | 用声明式 YAML描述系统,单元测试跑 100 个 mock case 再上线。 |
多Agent系统开发最佳实践
最佳实践 | 一句话落地 | 常见踩坑 |
---|---|---|
Start Simple 先简单 |
MVP 只跑 1-2 个 Agent,验证能跑通再加功能 | 一上来就 20 个Agent,3 天后调试崩溃 |
Measure Cell Performance 单测Agent |
每个 Agent独立跑 100 条样本,看准确率 & token 消耗 | 整体指标 OK,拆开后发现某个 Agent 只有 60% 正确率 |
Explicit Contracts 接口契约 |
用 JSON Schema / Pydantic 写明输入输出,谁改字段 CI 立刻报警 | 口头约定“大概是个字符串”,上线后互相甩锅 |
Comprehensive Logging 全程日志 |
每步输入、输出、耗时、异常全落盘,带 trace-id 可追踪 | 出错后只能“玄学重启” |
Fault Tolerance 容灾设计 |
Agent遇到脏数据返回默认值 + 错误码,不直接崩溃 | 一个空字符串让整条链雪崩 |
Verification Cells 质检Agent |
每个关键步骤后加“验证Agent”,发现错误立即重试或报警 | 把希望寄托在“下游会修” |
Progressive Enhancement 渐进增强 |
先把主链路跑通,再逐步加缓存、并行、重试 | 一次性上线 5 个优化,出错不知砍哪个 |
Parallel When Possible 并行优先 |
用 Map-Reduce 跑独立子任务,减少串行等待 | 明明可并行却串行,用户等 30 秒 |