Agent 速成笔记 · 第 9 章 上下文工程
Agent 速成笔记 · 第 9 章 上下文工程
源:Datawhale《Hello-Agents》第 9 章 | 定位:概念原理 + 工程实现 | 一句话:在有限的「注意力预算」里,工程化地决定"下一次模型调用应该看到什么"。
0. 一章速览(30 秒)
- 一句话:上下文工程(Context Engineering)就是在每次模型调用前,以可复用、可度量、可演进的方式拼装输入 tokens——用尽可能少、但高信号密度的内容,最大化得到期望行为的概率。
- 本章解决什么问题:智能体循环运行会不断产生新数据,而窗口有限、内容越多模型越"走神";必须系统性地决定什么该进、什么该丢、超限怎么压。
- 必须记住的 5 个点:
- 上下文 = 采样时进入模型的那组 tokens,是有限资源且边际收益递减。
- 失效模式:上下文腐蚀(context rot)——窗口内 token 越多,准确回忆能力反而下降。
- 长时程三条手段:压缩整合(Compaction)/ 结构化笔记(Structured note-taking)/ 子代理架构(Sub-agent)。
- 工程骨架 GSSC 流水线:Gather → Select → Structure → Compress;选择阶段用"相关性 + 新近性"加权打分加贪心填充。
- 工具层三件套:ContextBuilder + NoteTool + TerminalTool。
1. 从提示工程到上下文工程(9.1)
1.1 什么是"上下文"
- 是什么:对 LLM 采样时所包含的那一组 tokens。它不只是"提示词",而是包括系统指令、工具定义、MCP(Model Context Protocol,模型上下文协议)描述、外部数据、消息历史等一切进入上下文窗口的信息。
- 问题变了:不再是"提示词该用什么句式与措辞",而是"什么样的上下文配置最可能让模型产出期望行为"。
- 工程问题的精确表述:在 LLM 的固有约束下,优化这些 tokens 的效用(utility),稳定拿到预期结果。这要求"在上下文中思考"——任一次调用时都审视 LLM 可见的整体状态,并预判它可能诱发什么行为。
1.2 与提示工程(Prompt Engineering)的关系
- 提示工程:关注如何编写与组织指令以获得更优结果,核心是"写出有效提示"(如系统提示的写法与结构化策略)。
- 上下文工程:在推理阶段,策划与维护"最优的信息集合(tokens)",内容不仅包含提示本身,还包含其他一切会进入上下文窗口的信息。
- 两者关系:在前沿模型厂商的视角里,上下文工程是提示工程的自然演进,而非替代。
- 为什么现在才成为刚需:早期用例(日常聊天除外)多是单轮分类或文本生成,打磨提示就够了;一旦构建要在更长时间范围、跨多次推理轮次工作的智能体,就必须管理整个上下文状态:系统指令、工具、MCP、外部数据、消息历史。
- 一句话记忆:上下文工程的"艺与术",在于从持续扩张的"候选信息宇宙"中甄别哪些内容应当进入有限的上下文窗口——循环运行的智能体持续产出新数据,必须被周期性提炼。
2. 为什么上下文工程重要(9.2)
2.1 上下文腐蚀(context rot)与"注意力预算"
- 现象:针堆找针(needle-in-a-haystack)类基准揭示——上下文腐蚀(context rot):随着窗口中的 tokens 增加,模型从上下文中准确回忆信息的能力反而下降。不同模型退化曲线可能更平滑,但这一特征几乎在所有模型上都会出现。
- 术语对应:这种"窗口变长、中段信息召回变差"的失效模式,业界通常称为中间遗忘(lost-in-the-middle);本章用上下文腐蚀与针堆找针基准描述同一件事。
- 关键结论:上下文必须被视作有限资源,且边际收益递减。如同人类有限的工作记忆,LLM 也有一笔注意力预算——每新增一个 token 都会消耗其中一部分。
- 容易踩的错:它不是"悬崖式崩溃",而是性能梯度——长上下文下模型依旧强大,只是信息检索与长程推理的精度下降。所以"支持 100K/200K 窗口"不构成"可以随便塞满"的理由。
2.2 为什么稀缺:架构层面的三个根源
- 注意力被"拉薄":Transformer 让每个 token 能与上下文中所有 token 建立关联,理论上形成 n² 级别的两两注意力关系。上下文越长,模型对这些关系的建模能力越被稀释,于是产生"上下文规模"与"注意力集中度"的张力。
- 训练分布偏短:注意力模式来源于训练数据分布,而短序列通常比长序列更常见;模型对"全上下文依赖"的经验更少,专门参数也更少。
- 位置编码插值的代价:位置编码插值(position encoding interpolation)等技术能让模型在推理时"适配"比训练期更长的序列,但会牺牲对 token 位置的精确理解。
三者共同形成的是一个性能梯度,而非突变。基于这个现实,有意识的上下文工程成为构建强健智能体的必需品。
3. 有效上下文的构成与"解剖学"(9.2.1)
在"有限注意力预算"的约束下,优秀的上下文工程目标是:用尽可能少、但高信号密度的 tokens,最大化获得期望结果的概率。指导思想一句话:信息充分但紧致。
3.1 三大组件的对照
| 组件 | 作用 | 典型失败模式 | 做法要点 |
|---|---|---|---|
| 系统提示 | 定义角色与行为准则 | 过度硬编码 / 过于空泛 | 分区组织,最小必要信息 |
| 工具 | 定义与信息、行动空间的契约 | 臃肿工具集,边界模糊 | 职责单一,建 MVTS |
| 示例 | 直接画像期望行为 | 罗列边界条件 | 精选多样且典型 |
3.2 系统提示(System Prompt)
- 要求:语言清晰直白,信息层级把握在"刚刚好"的高度。
- 两极误区:过度硬编码(写入复杂脆弱的 if-else 逻辑,维护成本高、易碎);过于空泛(只给宏观目标与泛化指引,缺少对期望输出的具体信号,或假定了错误的"共享上下文")。
- 做法:分区组织——如
<background_information>、<instructions>、工具指引、输出描述,用 XML 或 Markdown 分隔。 - 判据:追求能完整勾勒期望行为的"最小必要信息集",注意"最小"不等于"最短"。
- 调参顺序:先用最好的模型在最小提示上试跑,再依据失败模式增补指令与示例——不要一开始就把规则写满。
3.3 工具(Tools)
- 是什么:工具定义了智能体与信息、行动空间之间的契约;必须促进效率——既返回 token 友好的信息,又鼓励高效的智能体行为。
- 三条硬要求:职责单一、相互低重叠、接口语义清晰;对错误鲁棒;入参描述明确无歧义。
- 常见失败模式:臃肿工具集——功能边界模糊,"选哪个工具"本身就含混。判据一句:如果人类工程师都说不准用哪个工具,别指望智能体做得更好。
- 工程做法:甄别一个最小可行工具集(MVTS, Minimum Viable Tool Set),显著提升长期交互的稳定性与可维护性。
3.4 示例(Few-shot)
始终推荐提供示例,但应精挑一组多样且典型的例子里"画像"期望行为,而不是把"所有边界条件"一股脑塞进去——对 LLM 而言,好的示例胜过千言万语。
4. 上下文检索与智能体式搜索(9.2.2)
4.1 一个简洁的定义
智能体 = 在循环中自主调用工具的 LLM。 模型越强,自治水平可越高:更能独立探索复杂问题空间,并从错误中恢复。
4.2 从"预检索"到"及时上下文(JIT)"
- 旧范式:推理前一次性检索(embedding 检索),预先加载所有相关数据。
- 新范式:及时(Just-in-time, JIT)上下文——不预先加载数据,而是维护轻量化引用(文件路径、存储查询、URL 等),在运行时通过工具动态加载所需数据。
- 为什么更好:模型可撰写针对性查询、缓存必要结果,用
head/tail等命令分析大体量数据——无需把整块数据一次性塞入上下文。 - 认知类比:更贴近人类——不死记硬背全部信息,而是用文件系统、收件箱、书签等外部索引按需提取。
4.3 引用元数据本身就在传递信号
除了存储效率,引用的元数据也能帮助精化行为:目录层级、命名约定、时间戳都在隐含地传达"目的与时效"。例如 tests/test_utils.py 与 src/core/test_utils.py 的语义暗示就不同。
4.4 渐进式披露(Progressive Disclosure)
- 机制:允许智能体自主导航与检索,则每一步交互都会产生新的上下文,反过来指导下一步决策——文件大小暗示复杂度、命名暗示用途、时间戳暗示相关性。
- 效果:按层构建理解,只在工作记忆中保留"当前必要子集",并用"记笔记"做补充持久化,维持聚焦而非被"大而全"拖垮。
4.5 权衡与混合策略
- 代价:运行时探索通常比预计算检索更慢,且需要有"主见"的设计确保模型拿到正确工具与启发式;缺少引导时,智能体会误用工具、追逐死胡同、错过关键信息。
- 混合策略(不少场景更有效):前置加载少量高价值上下文保证速度,再让智能体按需自主探索。
- 落地做法:预放"项目约定说明(README / 指南)"文件,同时提供
glob、grep等原语即时检索具体文件,绕开过时索引与复杂语法树的沉没成本。 - 边界怎么定:取决于任务动态性与时效要求。
| 维度 | 预检索(embedding 一次到位) | JIT 及时上下文 |
|---|---|---|
| 时机 | 推理前 | 运行时按需 |
| 上下文占用 | 大,一次性塞入 | 小,只放引用与当前子集 |
| 时效性 | 可能过时 | 实时 |
| 代价 | 索引成本、沉没成本 | 探索更慢,需引导 |
| 适用 | 静态、时效要求低 | 动态、易变、体量大 |
5. 面向长时程任务的上下文工程(9.2.3)
场景:大型代码库迁移、跨数小时的系统性研究——行动序列远超上下文窗口,仍须保持连贯性、上下文一致与目标导向。指望无限增大上下文窗口并不能根治"上下文污染"与相关性退化,因此需要直接面向约束的工程手段。
5.1 压缩整合(Compaction)
- 定义:当对话接近上下文上限时,对其进行高保真总结,并用该摘要重启一个新的上下文窗口,以维持长程连贯性。
- 保留 / 丢弃:保留架构性决策、未解决缺陷、实现细节;丢弃重复的工具输出与噪声。新窗口 = 压缩摘要 + 最近少量高相关工件(如"最近访问的若干文件")。
- 调参顺序(考点):先优化召回(不遗漏关键信息),再优化精确度(剔除冗余)。安全的"轻触式"压缩是清理深历史中的工具调用与结果。
5.2 结构化笔记(Structured Note-taking)
- 定义:也称"智能体记忆"——以固定频率把关键信息写入上下文之外的持久化存储,后续按需拉回。
- 价值:以极低的上下文开销维持持久状态与依赖关系,如维护 TODO 列表、项目
NOTES.md、关键结论与阻塞项索引——跨数十次工具调用与多轮上下文重置,仍保持进度一致。 - 适用范围:非编码场景同样有效,如长期策略性任务、游戏或仿真中的目标管理与统计计数。
5.3 子代理架构(Sub-agent Architectures)
- 思想:由主代理负责高层规划与综合;多个专长子代理在"干净的上下文窗口"中各自深挖、调用工具并探索,最后仅回传凝练摘要。
- 摘要规模:常见 1,000–2,000 tokens。
- 好处:实现关注点分离——庞杂的搜索上下文留在子代理内部,主代理专注于整合与推理;适合需要并行探索的复杂研究、分析任务。
- 经验结论:公开的多智能体研究系统显示,该模式在复杂研究任务上相较单代理基线优势显著。
5.4 归纳:四大策略与取舍法则(写入 / 选择 / 压缩 / 隔离)
| 策略 | 对应手段 | 手法要点 | 适合的任务 |
|---|---|---|---|
| 写入 | 结构化笔记、记忆系统 | 关键信息落到上下文之外,按需拉回 | 有里程碑的迭代式开发与研究 |
| 选择 | Gather/Select、JIT 检索、工具裁剪 | 只让高信号内容进窗口,引用代替全文 | 信息量远超窗口、内容易变 |
| 压缩 | 压缩整合、分区压缩、截断 | 摘要后重启窗口;保结构、弃冗余 | 需要长对话连续性("接力") |
| 隔离 | 子代理架构 | 搜索留在子代理窗口,主代理只收摘要 | 复杂研究与分析、可并行探索 |
即便模型能力持续提升,"在长交互中维持连贯性与聚焦"仍是构建强健智能体的核心挑战。
6. ContextBuilder:GSSC 流水线(9.3)
6.1 设计动机:要解决四个问题
- 统一入口:把 Gather-Select-Structure-Compress 抽象为可复用流水线,减少每个 Agent 里重复的模板代码。
- 稳定形态:输出固定骨架的上下文模板,便于调试、A/B 测试与评估。
- 预算守护:在 token 预算内尽量保留高价值信息,对超限上下文提供兜底压缩。
- 最小规则:不引入来源 / 优先级等分类维度,避免复杂度增长——基于相关性与新近性的简单评分在多数场景已足够有效。
6.2 上下文的固定骨架(六个分区)
[Role & Policies] 角色与行为准则 / [Task] 当前任务 / [State] 当前状态 / [Evidence] 外部检索证据 / [Context] 历史对话与记忆 / [Output] 输出格式要求。
6.3 两个核心数据结构
- ContextPacket(候选信息包):信息基本单元,字段
content、timestamp、token_count、relevance_score(默认 0.5,初始化时钳制到 [0.0, 1.0])、metadata。统一封装大幅简化后续选择与排序。 - ContextConfig(构建配置):把所有可调参数收拢到一处。
| 参数 | 默认值 | 含义 |
|---|---|---|
max_tokens |
3000 | 最大 token 数量 |
reserve_ratio |
0.2 | 为系统指令预留的比例 |
min_relevance |
0.1 | 最低相关性阈值 |
enable_compression |
True | 是否启用压缩 |
recency_weight |
0.3 | 新近性权重 |
relevance_weight |
0.7 | 相关性权重 |
- 硬约束:
reserve_ratio、min_relevance必须在 [0, 1];且recency_weight + relevance_weight必须等于 1.0(断言校验)。reserve_ratio正是为系统指令这类关键信息预留空间,防止被挤占。
6.4 Gather:多源信息汇集
按固定顺序汇集五类信息,全部封装为 ContextPacket:
- 系统指令:
relevance_score直接置 1.0(始终保留、不参与评分),metadata 标type=system_instruction、priority=high。 - 记忆系统检索:
limit=10,min_importance=0.3。 - RAG 检索:
limit=5,min_score=0.3。 - 对话历史:只保留最近 5 条(
conversation_history[-5:]),每条基础相关性 0.6,内容拼成role: content。 - 自定义信息包:调用方传入的
custom_packets。
容错设计:每个外部数据源调用都包在 try-except 中,单个源失败只打警告,不影响整体流程。
6.5 Select:怎么算分、怎么填
流水线的核心,直接决定最终上下文的质量。
-
综合分数公式:combined_score = relevance_weight × relevance_score + recency_weight × recency
-
相关性怎么算:
_calculate_relevance用关键词重叠——分词后求 Jaccard 相似度(交集 / 并集)。生产环境应替换为向量相似度。 -
新近性怎么算:
_calculate_recency用指数衰减模型,24 小时内保持高分,之后逐渐衰减。
age_hours = (datetime.now() - timestamp).total_seconds() / 3600
decay_factor = 0.1 # 衰减系数
recency_score = math.exp(-decay_factor * age_hours / 24)
return max(0.1, min(1.0, recency_score)) # 限制在 [0.1, 1.0]
这段在干什么:把"这条信息是多久以前的"折算成一个 0.1~1.0 的新近性分数,供加权求和使用。
- 选择流程(五步):
- 把所有包按
metadata["type"]拆成系统指令与其他两组。 - 计算
remaining_tokens = available_tokens - system_tokens;若 ≤ 0,说明系统指令已占满预算,直接返回系统指令并告警。 - 给其他包打分:默认分数为 0.5 的包会重新计算相关性,再算新近性并求综合分;同时用
min_relevance过滤掉低质量信息。 - 按综合分降序排序。
- 贪心填充:从高到低,装得下就装,装不下就停止。
- 把所有包按
selected = system_packets.copy()
current_tokens = system_tokens
for score, packet in scored_packets:
if current_tokens + packet.token_count <= available_tokens:
selected.append(packet)
current_tokens += packet.token_count
else:
break # 预算已满,停止选择
这段在干什么:一个 0/1 背包式的贪心——按分数从高到低填到预算耗尽,保证有限预算里选出的都是"最值钱"的那批。
- 注意易错点:碰到放不下的包是 break(直接停止),而不是
continue跳过。
6.6 Structure:拼装成固定模板
- 分组:按
metadata["type"]归档——system_instruction进 Role;rag_result/knowledge进 Evidence;其余进 Context。 - 拼装顺序:
[Role & Policies]→[Task](用户查询)→[Evidence](多段用---分隔)→[Context]→[Output](固定提示"请基于以上信息,提供准确、有据的回答"),分区之间用空行连接。 - 固定骨架的三个好处:可读性(人和模型都更容易理解结构)、可调试性(能快速定位哪个分区出问题)、可扩展性(新增信息源只需新增一个分区)。
6.7 Compress:兜底压缩
- 触发条件:先算
current_tokens,只有超限才压缩,否则原样返回。 - 算法:按
"\n\n"把上下文切成 section 逐段累加——放得下就完整保留;放不下则算remaining_tokens,只有剩余额度大于 50 tokens 才部分保留(截断后追加[... 内容已压缩 ...]),否则直接 break。 - 截断估算:
char_per_token = len(text) / count_tokens(text)(除零时回退为 4),再max_chars = max_tokens × char_per_token。 - token 估算:中文 1 字符≈1 token,英文 1 单词≈1.3 tokens;生产环境应替换为真实 tokenizer。
- 设计原则:保持结构完整性——预算再紧也尽量保留每个分区的关键信息。生产环境可把"简单截断"升级为 LLM 摘要。
- 与滑动窗口的关系:本章的"滑动窗口"就是对话历史只保留最近 N 条(取 5 条、超 20 条即截断);截断与滑动窗口零额外调用、成本最低,LLM 摘要召回更好但要多花一次调用与延迟。
6.8 工程实践要点(最佳实践)
| 方向 | 具体做法 |
|---|---|
| 预算 | 按任务复杂度动态调整 max_tokens:简单任务小预算,复杂任务加预算 |
| 相关性 | 把关键词重叠换成向量相似度计算,提升检索质量 |
| 缓存 | 对不变的系统指令与知识库内容做缓存,避免重复计算 |
| 监控与评估 | 记录每次构建的统计(选中数量、token 使用率);对关键参数做 A/B 测试找最优配置 |
与 Agent 集成:run() 里先用 build(...) 生成上下文,作为 system 消息与用户输入一起发给 LLM;再把本轮问答追加进历史,并用截断摘要(如 response[:200])写入记忆,避免历史无限膨胀。
7. NoteTool:结构化笔记(9.4)
7.1 为什么需要它:与 MemoryTool 的分工
- MemoryTool 管"对话式记忆":短期工作记忆、情景记忆(episodic)、语义记忆(semantic)。
- NoteTool 管"项目式任务":一种更轻量、更人类友好的记录方式,四点价值——结构化记录(Markdown + YAML,机器可解析、人也易读易改)、版本友好(纯文本天然支持 Git)、低开销(无需数据库)、灵活分类(
type+tags多维检索)。
7.2 三类典型场景
- 长期项目追踪:重构可能持续数天甚至数周,笔记可记录
task_state(阶段状态与进度)、conclusion(阶段结论)、blocker(阻塞点)、action(下一步计划)。 - 研究任务管理:文献综述时记录每篇论文核心观点、待深入调研的主题、重要参考文献。
- 与 ContextBuilder 配合:每轮对话前用
search或list检索笔记,转成 ContextPacket 注入上下文。
7.3 存储格式:Markdown + YAML
- 笔记文件:每个笔记是独立
.md,---包裹的 YAML 前置元数据(id、title、type、tags、created_at、updated_at)+ Markdown 正文。 - 文件名即 ID:
note_{YYYYMMDD_HHMMSS}_{当前索引长度},写入后把file_path回填进元数据。 - 索引文件
notes_index.json:集中保存元数据与文件路径,三个作用——快速检索(不必打开每个文件)、元数据管理、完整性校验(检测文件缺失或损坏)。读取时用split('---\n', 2)切出 YAML 与正文,无分隔符则整段作正文。
7.4 七个核心操作
create(生成 ID + 元数据 + 写文件 + 更新索引)/ read / update(改字段并刷新 updated_at)/ search / list / summary / delete(先删文件再从索引移除)。
- search:按
query在标题与正文做不区分大小写的子串匹配,可叠加note_type/tags过滤(tags 取交集),结果按updated_at倒序取前limit条。 - list:只返回元数据(不读正文,省开销),支持同样的过滤与倒序。
- summary:返回
total_notes、type_distribution(按类型计数)与recent_notes(最近 5 条,含 id / title / type / updated_at)。
7.5 与 ContextBuilder 的深度集成
- 检索策略:先
list出 blocker 类型(limit=2,阻塞优先),再通用search(limit=3),合并去重后取前若干条。 - 转包时的相关性分数按类型固定(工程关键决策):
| 笔记类型 | 相关性分数 |
|---|---|
| blocker | 0.9 |
| action | 0.8 |
| task_state | 0.75 |
| conclusion | 0.7 |
- 内容前缀
[笔记:{title}],metadata 记type="note"、note_type、note_id,使 Structure 阶段能正确归位。 - 自动建笔记:输入含"问题/阻塞" →
blocker;含"计划/下一步" →action;否则conclusion。历史超过 10 条即截断为最近 10 条。
7.6 最佳实践
- 合理分类:
task_state阶段进展 /conclusion重要结论 /blocker阻塞问题(优先级最高)/action下一步计划 /reference参考资料。 - 清理归档:已解决的 blocker 更新为 conclusion;过时的 action 及时删除或更新;用 tags 做版本管理,如
["v1.0", "completed"]。 - 配合方式:每轮对话前检索;按类型设不同相关性;限制笔记数量避免上下文过载。
- 人机协作与自动化:笔记是可人工编辑的 Markdown,可用 Git 追踪演化、关键阶段人工审核;还可定期生成摘要报告与进度文档,或同步到 Notion / Confluence。
8. TerminalTool:即时文件系统访问(9.5)
8.1 为什么需要它
许多场景要求智能体即时访问和探索文件系统——查日志、分析代码库结构、检索配置文件。三类场景的共同特点是:需要实时、轻量级的文件系统访问,而不是预先索引和向量化。
- 代码库探索:
find . -name '*.py' -type f、grep -r 'class UserService' .、head -n 50 ...。 - 日志分析:
ls -lh、tail -n 100 app.log | grep ERROR、grep ERROR app.log | cut -d':' -f3 | sort | uniq -c。 - 数据文件预览:
head -n 5 data/sales.csv、wc -l data/*.csv。
传统方式要 rag_tool.add_document("./project/**/*.py")——耗时、占大量存储、可能过时;TerminalTool 则是快速、实时的。这正是 9.2.2 节"即时(JIT)上下文"理念的落地:不预先加载所有文件,而是按需探索。
8.2 四层安全机制
允许智能体执行命令是强大但危险的能力,TerminalTool 用四层机制兜住:
| 层级 | 机制 | 效果 |
|---|---|---|
| 第一层 | 命令白名单(ALLOWED_COMMANDS) |
只放只读命令,rm -rf / 之类立即被拒并提示允许列表 |
| 第二层 | 工作目录限制(沙箱) | 只能访问 workspace 及子目录,访问 /etc/passwd 或用 .. 逃逸均被拒 |
| 第三层 | 超时控制 | 每个命令有执行时间上限,防止无限循环或资源耗尽 |
| 第四层 | 输出大小限制 | 超过 max_output_size 的输出被截断,防止内存溢出 |
- 白名单覆盖:
ls、dir、tree、cat、head、tail、less、more、find、grep、egrep、fgrep、wc、sort、uniq、cut、awk、sed、pwd、cd、file、stat、du、df、echo、which、whereis。 - 超时:示例默认为 30 秒;代码库维护助手用 60 秒。
- 输出上限:示例为
10 * 1024 * 1024字节(即 10,485,760 字节),超出后截断并追加提示。
8.3 命令执行与目录导航的实现要点
- 执行:底层用
subprocess.run(command, shell=True, cwd=当前目录, capture_output=True, timeout=..., env=...)。四个关键处理——当前目录感知(cwd)、错误处理(stderr并入输出)、返回码检查(非零前置警告)、容错设计(超时与异常都捕获成返回字符串,不让智能体崩溃)。 cd的特殊处理:支持..、.、~(回 workspace)与相对路径;新路径要resolve()后再用relative_to(workspace)校验是否越界,还要检查存在性与是否为目录;可通过allow_cd=False禁用。- 由此支持多步探索:
ls -la→cd src→find . -name '*service*.py'→cat user_service.py。
8.4 与其他工具的协同
- 与 MemoryTool:把探到的项目结构写入语义记忆(
memory_type="semantic",importance=0.8)。 - 与 NoteTool:把日志分析发现的慢查询等写为 blocker 笔记,正文用代码块粘贴日志原文并写明下一步。
- 与 ContextBuilder:把
ls -R src、git log --oneline -10的输出包成 ContextPacket(相关性 0.7 / 0.8,source="terminal"),经custom_packets进入上下文。
其他常用模式:统计代码行数、查找所有 TODO 注释、定位函数定义、用 sed -n '/def process_data/,/^def /p' 取函数实现。
9. 长程智能体实战:代码库维护助手(9.6)
9.1 场景与三大挑战
维护一个约 50 个 Python 文件、基于 Flask 的中型 Web 应用(数据模型 / 业务逻辑 / API 接口,含技术债务)。助手要探索代码库、识别问题(重复代码、复杂度过高、缺测试)、追踪进度,并基于历史上下文给出连贯的重构建议。
| 挑战 | 解决手段 |
|---|---|
| 信息量超出上下文窗口 | TerminalTool 即时、按需探索,不预索引 |
| 跨会话状态管理(任务持续数天) | NoteTool 记录进展、待办与关键决策 |
| 上下文质量与相关性 | ContextBuilder 智能筛选与组织 |
9.2 三层架构与配置
即时访问层(TerminalTool,实时探索文件系统)+ 会话记忆层(MemoryTool,会话内工作记忆)+ 持久笔记层(NoteTool,跨会话结构化外部记忆),三层之上由 ContextBuilder 统一汇集、打分、拼装;配置为 max_tokens=4000、reserve_ratio=0.15、min_relevance=0.2,开启压缩,本案例不使用 RAG。
9.3 四种运行模式
run(user_input, mode=...) 的模式差异通过追加不同的系统指令片段实现,并在预处理阶段先收集对应的信息包:
| 模式 | 侧重 | 预处理动作 | 包相关性 |
|---|---|---|---|
explore |
代码探索 | find . -type f -name '*.py' | head -n 20 |
0.6 |
analyze |
问题分析 | 统计代码行数 + 抓 TODO|FIXME |
0.7 |
plan |
任务规划 | list 出 task_state 笔记(limit=3) |
0.8 |
auto |
自动决策 | 同 explore 的轻量探索 | 0.6 |
9.4 自动化知识管理与会话统计
回答命中"问题 / bug / 错误 / 阻塞" → 自动建 blocker 笔记;用户输入命中"计划 / 下一步 / 任务 / todo" → 自动建 action 笔记(正文取 response[:500])。对话历史超过 20 条(10 轮) 即截断。stats 记录 commands_executed、notes_created、issues_found,generate_report() 可导出 JSON 报告。
9.5 关键特性与可扩展方向
跨会话连贯性、智能上下文管理、即时文件系统访问、自动化知识管理与人机协作。可扩展方向:接 RAGTool 建代码向量索引、拆成探索者 / 分析者 / 规划者做多智能体协作、接测试工具验证重构、用 git 追踪变更、用 Gradio / Streamlit 做界面。
10. 高频考点 & 易错点速查
- 上下文 = 采样时的那组 tokens,不等于提示词;要管的是整个上下文状态(系统指令、工具、MCP、外部数据、消息历史)。
- context rot 是性能梯度而非"悬崖式崩溃"——注意力预算有限、边际收益递减。三个架构根源:n² 注意力被拉薄、训练分布偏短、位置编码插值的精度代价。
- 系统提示两极误区:过度硬编码与过于空泛;目标是"最小必要信息集",而"最小"≠"最短"。
- 臃肿工具集是高发坑,判据是"人类工程师都说不准用哪个工具";解药是 MVTS。
- 预检索与 JIT 不是二选一:混合策略(前置少量高价值 + 按需探索)通常更优,边界由任务动态性与时效要求决定。
- Compaction 调参顺序:先召回、后精确;轻触式压缩是清理深历史中的工具调用与结果。子代理回传摘要常见 1,000–2,000 tokens。
- GSSC 四阶段名称与顺序;Select 综合分 =
w_rel × 相关性 + w_rec × 新近性,两权重之和必须为 1.0。 - 系统指令不参与评分、
relevance_score=1.0、始终保留,reserve_ratio(默认 0.2)就是给它预留的。贪心填充遇放不下是 break 停止,不是跳过。 - Compress 兜底:分段累加,剩余额度 > 50 tokens 才部分保留;token 估算"中文 1 字≈1、英文 1 词≈1.3"。
- Gather 关键数字:记忆
limit=10 / min_importance=0.3,RAGlimit=5 / min_score=0.3,历史只留最近 5 条(相关性 0.6)。新近性为指数衰减exp(-0.1 × age_hours / 24),钳制 [0.1, 1.0]。 - 结构化笔记是上下文之外的持久化,与 MemoryTool 的分工是"项目式任务 vs 对话式记忆"。笔记相关性排序:blocker 0.9 > action 0.8 > task_state 0.75 > conclusion 0.7。
- TerminalTool 四层安全:命令白名单 / 沙箱 / 超时 / 输出上限;
cd必须resolve()后校验relative_to(workspace)。 - 三层分工:即时访问(TerminalTool)+ 会话记忆(MemoryTool)+ 持久笔记(NoteTool),由 ContextBuilder 统一编排。
- 习题考点映射:① context rot 成因、JIT 取舍、系统提示误区;② GSSC 各阶段失效后果、上下文质量评估、混合压缩;③ 笔记自动整理、命令安全与审批、重构助手流程;④ 三层协调、断点续传、任务依赖调度;⑤ 渐进式披露与探索引导。
11. 与前后章节的衔接
本章的输入来自第 8 章:MemoryTool 与 RAGTool 正是 GSSC 流水线 Gather 阶段的两个检索数据源,而压缩整合、结构化笔记、子代理架构也是在第 8 章记忆系统之上的工程化升级。本章的输出是一整套可复用的上下文基础设施——ContextBuilder、NoteTool、TerminalTool,以及由它们编排成的长程智能体(代码库维护助手)。它向上承接"记忆与检索",向下为跨会话的复杂任务打底:文中的子代理架构与"多智能体研究系统"的结论,正是后续多智能体协作主题的前置概念;而下一章将转向智能体通信协议。

浙公网安备 33010602011771号