尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

goose 上下文压缩渲染模板解析:compaction_summary.md 如何决定压缩后的会话上下文

goose 上下文压缩渲染模板解析:compaction_summary.md 如何决定压缩后的会话上下文 goose 上下文压缩渲染模板解析compaction_summary.md 如何决定压缩后的会话上下文【免费下载链接】goosean open source, extensible AI agent that goes beyond code suggestions - install, execute, edit, and test with any LLM项目地址: https://gitcode.com/GitHub_Trending/goose3/goose本文以 goose 的goose-context-managementcrate 中的compaction_summary.md模板文件为核心完整讲解它作为压缩后上下文渲染器的职责、全部变量与段落结构、底层 miniJinja 渲染机制以及如何不重新编译 goose 就能用~/.config/goose/prompts/compaction_summary.md覆盖它来定制压缩后的会话记忆。读完后你可以准确理解 goose 上下文压缩compaction链路的最后一公里并具备安全修改该模板做实验例如只保留前三条用户意图的能力。一、模板在压缩链路中的位置先摘要、后渲染goose 的对话压缩分两步摘要summarize当会话 token 超过阈值时compaction.md 会把完整对话历史塞给模型要求模型在analysis草稿区之后输出一个且仅一个符合固定 schema 的 JSON 代码块字段包括user_intent、technical_concepts、files、errors_and_fixes、problem_solving、user_messages、pending_tasks、current_work、next_step。渲染rendercompaction_summary.md就是这个 JSON 的渲染模板——它把结构化摘要转换成压缩后供 agent 继续会话的Conversation Summary文本作为压缩后对话的第一条消息。在模板文件头部Jinja 注释块渲染时会被丢弃中作者直接写明了它的定位与可覆盖性{# This template is user-overridable: place a modified copy at ~/.config/goose/prompts/compaction_summary.md to experiment with what the post-compaction context contains (e.g. user_intent[:3] to keep only the three most important goals) without rebuilding goose. key_code is wrapped via the code_fence filter so embedded fences cannot break out of the block. #}这段注释给出了两个关键事实其一该模板是用户可覆盖的只需把修改版放到用户配置目录即可实验压缩后上下文包含什么注释中甚至给出了具体示例——user_intent[:3]只保留最重要的三条用户目标其二files[].key_code字段会经过code_fence过滤器包装保证摘要里引用的代码块内部的围栏fence不会逃逸破坏渲染出的 Markdown 结构。渲染入口在 summarize.rs 的apply_structured_summary它先尝试StructuredSummary::parse解析模型输出解析成功后用summary.render_with(summary_template)渲染如果模型没有遵守结构化格式比如忽略 schema 的模型、或用户自定义了摘要 prompt则原样保留模型的原始文本作为摘要——这是整条链路的无损回退lossless fallback。二、模板全文逐段解析下面按原文档结构逐段说明 compaction_summary.md 的内容。除头部注释外模板由 9 个全部条件渲染的段落组成——某个字段为空时对应整个段落含标题都不输出避免渲染出摘要的摘要。# Conversation Summary {% if user_intent %} ## User Intent {% for item in user_intent %} - {{ item }} {% endfor %} {% endif %} {% if technical_concepts %} ## Technical Concepts {% for item in technical_concepts %} - {{ item }} {% endfor %} {% endif %} {% if files %} ## Files Code {% for file in files %} {% if file.path %} ### {{ file.path }} {% endif %} {{ file.summary }} {% if file.key_code %} {{ file.key_code | code_fence }} {% endif %} {% endfor %} {% endif %} {% if errors_and_fixes %} ## Errors Fixes {% for item in errors_and_fixes %} - {{ item }} {% endfor %} {% endif %} {% if problem_solving %} ## Problem Solving {% for item in problem_solving %} - {{ item }} {% endfor %} {% endif %} {% if user_messages %} ## User Messages {% for item in user_messages %} - {{ item }} {% endfor %} {% endif %} {% if pending_tasks %} ## Pending Tasks {% for item in pending_tasks %} - {{ item }} {% endfor %} {% endif %} {% if current_work %} ## Current Work {{ current_work }} {% endif %} {% if next_step %} ## Next Step {{ next_step }} {% endif %}2.1 段落与变量对照表渲染出的段落模板变量数据结构输出形态语义对应摘要 prompt 的要求## User Intentuser_intent字符串数组无序列表所有用户目标与请求最重要的排在最前## Technical Conceptstechnical_concepts字符串数组无序列表讨论过的所有工具、方法与概念## Files Codefiles对象数组path/summary/key_code每个文件一个### 路径小节 摘要 代码围栏被查看或编辑过的文件做了什么、为什么、关键代码## Errors Fixeserrors_and_fixes字符串数组无序列表踩到的 bug、解决方式错误信息须逐字引用## Problem Solvingproblem_solving字符串数组无序列表已解决或进行中的问题及关键决策选了什么、否了什么、为什么## User Messagesuser_messages字符串数组无序列表所有用户消息长的工具参数/结果可截断## Pending Taskspending_tasks字符串数组无序列表所有未解决的用户请求按重要度降序## Current Workcurrent_work可选字符串整段文本请求摘要时的正在进行的工作## Next Stepnext_step可选字符串整段文本仅在能直接延续某条用户指令时输出这些字段与 compaction.md 中要求的 JSON schema 逐一对应也与 structured.rs 中StructuredSummary结构体的字段一一对应。2.2 Files Code 段的三个细节Files Code段是唯一处理对象数组的段落有三个值得注意的实现细节{% if file.path %}是可选标题文件条目若没有路径容忍性解析可能产生只有summary的条目则跳过###标题直接输出摘要。{{ file.summary }}无条件输出只要files列表非空每个条目的摘要都会进入压缩后上下文。{{ file.key_code | code_fence }}是防逃逸围栏key_code存放的是从这个文件摘出的重要代码、函数签名或 diff其本身很可能包含 围栏。code_fence过滤器会动态加长围栏长度下文第三节详述保证摘要内嵌代码块不会被提前闭合。2.3 一个真实渲染结果structured.rs 的测试夹具FULL_RESPONSE展示了模型输出 → 模板渲染的完整形态。给定如下模型响应analysis之后的 JSON{ user_intent: [Fix the parser bug, Add a regression test], technical_concepts: [off-by-one, tokenizer], files: [ {path: src/parser.rs, summary: Fixed off-by-one in scan loop, key_code: fn scan(mut self) { .. }} ], errors_and_fixes: [Panic on empty input, fixed with early return], problem_solving: [Root-caused via failing unit test], user_messages: [fix the parser bug, add a test], pending_tasks: [Add a regression test], current_work: Writing the regression test in tests/parser.rs, next_step: Finish the regression test }测试renders_markdown_sections验证渲染结果依次包含## User Intent、- Fix the parser bug、### src/parser.rs、fn scan(mut self) { .. }、## Next Step——即压缩后的第一条消息就是一篇结构化的会话交接文档下一轮 agent 读到它即可无缝续接工作。三、渲染机制miniJinja 环境、块修剪与 code_fence 过滤器模板不是被简单替换而是由 templates.rs 中的render函数渲染pub fn renderT: Serialize(template: str, context: T) - ResultString, MiniJinjaError { let mut env Environment::new(); env.set_trim_blocks(true); env.set_lstrip_blocks(true); env.add_filter(code_fence, code_fence); env.add_template(template, template)?; let rendered env .get_template(template)? .render(MJValue::from_serialize(context))?; Ok(rendered.trim().to_string()) }三个要点trim_blockslstrip_blocksJinja 标签行{% if %}、{% for %}不产生多余空行/缩进这是模板能渲染出干净 Markdown 的前提。code_fence过滤器动态加长围栏它扫描代码中最长的连续反引号串用最长串 1 且至少 3个反引号作为围栏保证内嵌围栏无法提前闭合fn code_fence(code: String) - String { let longest_run code.chars().fold((0usize, 0usize), |(max, run), c| { if c { (max.max(run 1), run 1) } else { (max, 0) } }).0; let fence .repeat((longest_run 1).max(3)); format!({fence}\n{}\n{fence}, code.trim_end_matches(\n)) }对应测试render_fences_exceed_backtick_runs_in_key_code当key_code内部含有 4 个反引号的围栏时外层围栏必须是 5 个且后面的## Errors Fixes标题一定出现在代码块闭合围栏之后。 3.上下文整体 trim渲染结果首尾空白被裁掉保证作为消息内容时干净无冗余。goosecrate 侧在 prompt_template.rs 有一份语义相同的code_fence实现用于 CLI 的模板渲染路径两处行为一致。四、模板变量的数据源StructuredSummary 的字段、顺序与容忍解析模板里的每个变量都不是凭空传入的而是 structured.rs 中StructuredSummary序列化进 miniJinja 上下文的产物。理解这个结构体就理解了模板能引用什么、不能引用什么pub struct StructuredSummary { pub user_intent: VecString, pub technical_concepts: VecString, pub files: VecFileActivity, pub errors_and_fixes: VecString, pub problem_solving: VecString, pub user_messages: VecString, pub pending_tasks: VecString, pub current_work: OptionString, pub next_step: OptionString, /// 未知顶层字段被保留便于用户自定义摘要 prompt /// 新增的字段仍能到达自定义的渲染模板 #[serde(flatten)] pub extra: serde_json::MapString, serde_json::Value, }顺序即优先级结构体注释明确说明所有列表按重要度降序排列消费方渲染模板、做截断实验的自定义 prompt可以从尾部裁剪。这直接支撑了模板头部注释里的user_intent[:3]玩法——自定义模板里取前 3 个元素就是丢弃尾部低重要度条目。extra用#[serde(flatten)]收留未知字段如果你同时自定义了摘要 promptcompaction.md让模型多输出一个decisions字段它不会导致解析失败而是留在extra里自定义渲染模板即可读取它。字段级容忍解析lenient_string_list/lenient_file_list等反序列化器会把模型加戏的输出转成字符串而不是丢弃整个摘要例如{error: .., fix: ..}这样的对象条目会变成error: ...; fix: ...null条目被剔除纯数字变成数字字符串——因为一个字段形状不对不应毁掉一份好摘要。StructuredSummary::parse本身还有一套严格的 JSON 提取规则json_candidates只接受锚定在/analysis之后、json围栏内或文本开头的、花括号配平的对象模型把摘要 JSON 写在散文中、或中途截断的 JSON都会让parse返回None从而触发第五节讲的原始文本回退。五、不重新编译 goose 的覆盖机制~/.config/goose/prompts/compaction_summary.md模板头部注释承诺的不重新编译即可覆盖由以下调用链实现压缩发起时context_mgmt/mod.rs 的compaction_templates()同时解析两个模板fn compaction_templates() - Resultgoose_context_management::Templates { Ok(Templates { compaction: crate::prompt_template::template_source(compaction.md)?, summary: crate::prompt_template::template_source(compaction_summary.md)?, }) }prompt_template.rs 的template_source的查找顺序是先查Paths::config_dir()/prompts/下的同名文件Linux/macOS 上即~/.config/goose/prompts/存在则读取用户版本否则回退到编译进二进制的内建版本crates/goose/src/prompts/与goose-context-managementcrate 内嵌的 prompts 目录。compaction_summary.md是正式注册的模板之一注册表描述为 Renders the structured compaction output into the post-compaction context见 prompt_template.rs因此也可通过 goose 的模板管理命令list_templates/save_template/reset_template查看、保存和重置。覆盖时的注意事项由实现可推断的行为边界你的自定义模板仍然以StructuredSummary含extra作为渲染上下文——模型多输出的字段可读但内建字段名不可更改除非你同时改compaction.md让模型输出不同 schema并在模板里只依赖extra中的键。自定义模板若渲染出空字符串summarize.rs 会记录警告并保留模型的原始输出而不是写入空摘要所以写坏模板的代价是降级而非崩溃。由于渲染上下文是结构体序列化的模板里只能引用上面第四节列出的变量名写一个不存在的变量会得到 Jinja 的未定义值空不会报错但会丢内容——覆盖后建议用一次真实压缩验证输出。六、与阈值、回退机制的配合compaction_summary.md只在压缩确实发生时才被执行其触发与兜底逻辑同样值得关注自动压缩阈值lib.rs 定义DEFAULT_COMPACTION_THRESHOLD: f64 0.8即默认在上下文窗口占用到 80% 时触发实际运行时可被GOOSE_AUTO_COMPACT_THRESHOLD参数覆盖context_mgmt/mod.rs取值 0.0或 1.0视为无效而回退到 0.8。压缩器自身的上下文溢出重试summarize.rs 定义REMOVAL_PERCENTAGES: [u32; 5] [0, 10, 20, 50, 100]——摘要请求本身超限ContextLengthExceeded时依次剥离 10%、20%、50%、100% 的工具响应从中间向两端删见filter_tool_responses后重试。工具响应全删完仍超限则报错且错误信息明确给出建议换更大上下文窗口的模型、禁用部分扩展以减少工具 schema 体积、或开新会话。两级回退模型输出可解析 → 用本模板渲染不可解析 → 保留原始文本。测试unusable_responses_fall_back_to_raw_text覆盖了散文、空对象、仅未知字段、截断 JSON、散文中引用 JSON、scratchpad 内围栏示例等多种必须回退的情形确保回退路径不会被误触发。七、小结compaction_summary.md是 goose 上下文压缩链路中模型结构化输出 → agent 可读交接文档的最后一环它以 9 个条件段落把StructuredSummary的九个字段渲染成# Conversation Summary文档空字段整段省略code_fence过滤器保证files[].key_code中的嵌套围栏不会破坏输出结构它通过template_source的用户优先查找机制支持~/.config/goose/prompts/compaction_summary.md覆盖配合StructuredSummary.extra的 flatten 设计允许实验不同的压缩后上下文形态而无需重新编译解析失败或模板渲染为空时链路始终回退到模型原始输出压缩功能不会因模板问题而中断。相关文件索引模板本体 compaction_summary.md、配套摘要 prompt compaction.md、结构化输出与解析 structured.rs、渲染实现 templates.rs、摘要主流程 summarize.rs、用户覆盖机制 prompt_template.rs、压缩触发逻辑 context_mgmt/mod.rs、crate 总览 README。【免费下载链接】goosean open source, extensible AI agent that goes beyond code suggestions - install, execute, edit, and test with any LLM项目地址: https://gitcode.com/GitHub_Trending/goose3/goose创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表