Agent 速成笔记 · 第 9 章 上下文工程

Agent 速成笔记 · 第 9 章 上下文工程

源:Datawhale《Hello-Agents》第 9 章 | 定位:概念原理 + 工程实现 | 一句话:在有限的「注意力预算」里,工程化地决定"下一次模型调用应该看到什么"。


0. 一章速览(30 秒)

  • 一句话:上下文工程(Context Engineering)就是在每次模型调用前,以可复用、可度量、可演进的方式拼装输入 tokens——用尽可能少、但高信号密度的内容,最大化得到期望行为的概率。
  • 本章解决什么问题:智能体循环运行会不断产生新数据,而窗口有限、内容越多模型越"走神";必须系统性地决定什么该进、什么该丢、超限怎么压。
  • 必须记住的 5 个点:
    1. 上下文 = 采样时进入模型的那组 tokens,是有限资源且边际收益递减。
    2. 失效模式:上下文腐蚀(context rot)——窗口内 token 越多,准确回忆能力反而下降。
    3. 长时程三条手段:压缩整合(Compaction)/ 结构化笔记(Structured note-taking)/ 子代理架构(Sub-agent)。
    4. 工程骨架 GSSC 流水线:Gather → Select → Structure → Compress;选择阶段用"相关性 + 新近性"加权打分加贪心填充。
    5. 工具层三件套: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 为什么稀缺:架构层面的三个根源

  1. 注意力被"拉薄":Transformer 让每个 token 能与上下文中所有 token 建立关联,理论上形成 n² 级别的两两注意力关系。上下文越长,模型对这些关系的建模能力越被稀释,于是产生"上下文规模"与"注意力集中度"的张力。
  2. 训练分布偏短:注意力模式来源于训练数据分布,而短序列通常比长序列更常见;模型对"全上下文依赖"的经验更少,专门参数也更少。
  3. 位置编码插值的代价:位置编码插值(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 设计动机:要解决四个问题

  1. 统一入口:把 Gather-Select-Structure-Compress 抽象为可复用流水线,减少每个 Agent 里重复的模板代码。
  2. 稳定形态:输出固定骨架的上下文模板,便于调试、A/B 测试与评估。
  3. 预算守护:在 token 预算内尽量保留高价值信息,对超限上下文提供兜底压缩。
  4. 最小规则:不引入来源 / 优先级等分类维度,避免复杂度增长——基于相关性与新近性的简单评分在多数场景已足够有效。

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:

  1. 系统指令:relevance_score 直接置 1.0(始终保留、不参与评分),metadata 标 type=system_instruction、priority=high。
  2. 记忆系统检索:limit=10,min_importance=0.3。
  3. RAG 检索:limit=5,min_score=0.3。
  4. 对话历史:只保留最近 5 条(conversation_history[-5:]),每条基础相关性 0.6,内容拼成 role: content。
  5. 自定义信息包:调用方传入的 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 的新近性分数,供加权求和使用。

  • 选择流程(五步):
    1. 把所有包按 metadata["type"] 拆成系统指令与其他两组。
    2. 计算 remaining_tokens = available_tokens - system_tokens;若 ≤ 0,说明系统指令已占满预算,直接返回系统指令并告警。
    3. 给其他包打分:默认分数为 0.5 的包会重新计算相关性,再算新近性并求综合分;同时用 min_relevance 过滤掉低质量信息。
    4. 按综合分降序排序。
    5. 贪心填充:从高到低,装得下就装,装不下就停止。
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 三类典型场景

  1. 长期项目追踪:重构可能持续数天甚至数周,笔记可记录 task_state(阶段状态与进度)、conclusion(阶段结论)、blocker(阻塞点)、action(下一步计划)。
  2. 研究任务管理:文献综述时记录每篇论文核心观点、待深入调研的主题、重要参考文献。
  3. 与 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. 高频考点 & 易错点速查

  1. 上下文 = 采样时的那组 tokens,不等于提示词;要管的是整个上下文状态(系统指令、工具、MCP、外部数据、消息历史)。
  2. context rot 是性能梯度而非"悬崖式崩溃"——注意力预算有限、边际收益递减。三个架构根源:n² 注意力被拉薄、训练分布偏短、位置编码插值的精度代价。
  3. 系统提示两极误区:过度硬编码与过于空泛;目标是"最小必要信息集",而"最小"≠"最短"。
  4. 臃肿工具集是高发坑,判据是"人类工程师都说不准用哪个工具";解药是 MVTS。
  5. 预检索与 JIT 不是二选一:混合策略(前置少量高价值 + 按需探索)通常更优,边界由任务动态性与时效要求决定。
  6. Compaction 调参顺序:先召回、后精确;轻触式压缩是清理深历史中的工具调用与结果。子代理回传摘要常见 1,000–2,000 tokens。
  7. GSSC 四阶段名称与顺序;Select 综合分 = w_rel × 相关性 + w_rec × 新近性,两权重之和必须为 1.0。
  8. 系统指令不参与评分、relevance_score=1.0、始终保留,reserve_ratio(默认 0.2)就是给它预留的。贪心填充遇放不下是 break 停止,不是跳过。
  9. Compress 兜底:分段累加,剩余额度 > 50 tokens 才部分保留;token 估算"中文 1 字≈1、英文 1 词≈1.3"。
  10. Gather 关键数字:记忆 limit=10 / min_importance=0.3,RAG limit=5 / min_score=0.3,历史只留最近 5 条(相关性 0.6)。新近性为指数衰减 exp(-0.1 × age_hours / 24),钳制 [0.1, 1.0]。
  11. 结构化笔记是上下文之外的持久化,与 MemoryTool 的分工是"项目式任务 vs 对话式记忆"。笔记相关性排序:blocker 0.9 > action 0.8 > task_state 0.75 > conclusion 0.7。
  12. TerminalTool 四层安全:命令白名单 / 沙箱 / 超时 / 输出上限;cd 必须 resolve() 后校验 relative_to(workspace)。
  13. 三层分工:即时访问(TerminalTool)+ 会话记忆(MemoryTool)+ 持久笔记(NoteTool),由 ContextBuilder 统一编排。
  14. 习题考点映射:① context rot 成因、JIT 取舍、系统提示误区;② GSSC 各阶段失效后果、上下文质量评估、混合压缩;③ 笔记自动整理、命令安全与审批、重构助手流程;④ 三层协调、断点续传、任务依赖调度;⑤ 渐进式披露与探索引导。

11. 与前后章节的衔接

本章的输入来自第 8 章:MemoryTool 与 RAGTool 正是 GSSC 流水线 Gather 阶段的两个检索数据源,而压缩整合、结构化笔记、子代理架构也是在第 8 章记忆系统之上的工程化升级。本章的输出是一整套可复用的上下文基础设施——ContextBuilder、NoteTool、TerminalTool,以及由它们编排成的长程智能体(代码库维护助手)。它向上承接"记忆与检索",向下为跨会话的复杂任务打底:文中的子代理架构与"多智能体研究系统"的结论,正是后续多智能体协作主题的前置概念;而下一章将转向智能体通信协议。


12. 课后练习

在线试卷:https://md-quiz-online.app.workbuddy.host/

posted @ 2026-09-28 17:08  测试小罡  阅读(10)  评论(0)    收藏  举报