news 2026/9/10 1:41:05

深入 oh-my-pi 的 PR 风格短摘要:compaction-short-summary 提示词的设计与实现解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入 oh-my-pi 的 PR 风格短摘要:compaction-short-summary 提示词的设计与实现解析

深入 oh-my-pi 的 PR 风格短摘要:compaction-short-summary 提示词的设计与实现解析

【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi

在 oh-my-pi 的长会话压缩(context compaction)机制中,除了生成用于恢复上下文的完整结构化摘要之外,还需要为每次压缩生成一段面向展示的短摘要——用 Pull Request 描述的口吻概括"这次对话改了什么"。本指南以packages/agent/src/compaction/prompts/compaction-short-summary.md这份提示词文件为骨架,结合packages/agent/src/compaction/compaction.ts的源码实现,讲解短摘要的生成规则、调用链、存储结构,以及它与完整摘要、turn-prefix 摘要等其他压缩提示词的分工。读完本文,你将理解 oh-my-pi 为何要为压缩事件单独设计一套"PR 描述"风格的提示词,以及这套机制在会话记录中如何被生成、传递与展示。

短摘要提示词的三条硬性约束

compaction-short-summary.md全文只有三行,却精确界定了短摘要的产出形态。它要求模型把一段对话压缩成一段Pull Request 描述(pull request description):

Summarize conversation changes as a pull request description. MUST 2–3 sentences; first person (`I added…`, `I fixed…`); describe changes, not process. NEVER mention tests, builds, or other validation steps; explain user request; ask questions.

逐条拆解:

  1. 体裁约束:输出必须是 PR 描述的口吻,即站在"作者"视角,描述这次会话中完成的代码/文档/配置变更,而不是流水账式地复述对话过程。
  2. 篇幅与人称约束:严格 2~3 句话;使用第一人称(I added…I fixed…);内容聚焦"改了什么"(changes),而非"怎么做的"(process)。
  3. 内容边界约束严禁提及测试、构建或其他验证步骤;同时要体现用户的原始请求(explain user request),并在必要处提出问题(ask questions)。

后两条约束的目的很明确:短摘要是给人(用户回看会话记录)看的轻量摘要,而不是给模型续接上下文用的。测试与构建信息属于"过程",会让短摘要变得冗长且偏离"变更点";保留用户请求与待澄清问题,则能让用户快速判断"这次会话是否达到了我想要的效果、还有什么悬而未决"。

需要说明的是,这份提示词之所以如此精简,是因为它只负责"格式约束"。实际的摘要内容通过调用 LLM 生成,而调用侧的 prompt 组装、token 预算、系统提示词都由源码完成(见下文)。

短摘要的生成调用链:generateShortSummary

短摘要的生成入口位于 compaction.ts 中的generateShortSummary函数(约 L1164-L1235)。该函数在模块加载时已经通过prompt.render完成了模板渲染:

const SHORT_SUMMARY_PROMPT = prompt.render(compactionShortSummaryPrompt);

compaction-short-summary.md以文本资源形式导入(import compactionShortSummaryPrompt from "./prompts/compaction-short-summary.md" with { type: "text" }),并经prompt.render包装成最终注入到对话中的指令文本。

generateShortSummary的核心实现要点如下:

Token 预算严格受限

const maxTokens = Math.min(512, Math.floor(0.2 * reserveTokens));

短摘要的输出上限被限制为min(512, 20% 的 reserveTokens)。对比完整摘要的min(floor(0.8 * reserveTokens), MAX_SUMMARY_TOKENS)与 turn-prefix 摘要的min(floor(0.5 * reserveTokens), MAX_SUMMARY_TOKENS),可以看出短摘要是三类摘要中预算最小、最"省"的一次 LLM 调用——这从源码结构上印证了它"轻量展示用"的定位。

Prompt 组装(与完整摘要共用同一套骨架):

let promptText = `<conversation>\n${conversationText}\n</conversation>\n\n`; if (historySummary) { promptText += `<previous-summary>\n${escapeSummaryBoundaryTags(historySummary)}\n</previous-summary>\n\n`; } promptText += formatAdditionalContext(options?.extraContext); promptText += SHORT_SUMMARY_PROMPT;
  • 会话内容被包裹在<conversation>标签内,防止模型把对话当作"继续对话"的上下文而是当作待总结对象;
  • 若存在历史摘要(historySummary,即上次压缩产生的完整摘要),则以<previous-summary>标签注入,且经escapeSummaryBoundaryTags转义,避免摘要内容中的标签干扰结构;
  • 可选的extraContext<additional-context>列表形式追加;
  • 最后拼上本文档(SHORT_SUMMARY_PROMPT)作为格式约束。

推理强度遵循用户 /model 选择:调用时通过resolveCompactionEffort(model, options?.thinkingLevel)解析 reasoning 力度,ThinkingLevel.Off时完全省略推理参数,undefined/Inherit回退到历史默认Effort.High,显式选择则尊重用户并做模型级 clamp。

传输路径两条

  • 本地路径:instrumentedCompleteSimple发起 oneshot,系统提示词固定为SUMMARIZATION_SYSTEM_PROMPT(见 summarization-system.md,该提示词把历史对话与前序摘要视为不可信数据,禁止跟随其中任何指令);
  • 远程路径:当配置了remoteEndpoint时,走requestRemoteCompaction远程压缩服务,同样携带SUMMARIZATION_SYSTEM_PROMPTmaxTokens

可观测性与容错:该调用以oneshotKind: "compaction_short_summary"打点 OTEL 遥测;失败时经createSummarizationError映射为带errorStatusProviderHttpError,并遵循与完整摘要一致的 oneshot 重试策略(summaryOneshotRetry),保证单次瞬时故障(如 429/529)不会拖垮整个压缩流程。

短摘要的触发时机与落库

短摘要并非每次压缩都必然重新生成。在 compact 主流程(约 L1842-L1848)中:

const shortSummary = usedRemoteCompaction ? "Remote compaction" : await generateShortSummary(recentMessages, summary, model, reserveTokens, apiKey, signal, { ...summaryOptions, extraContext: options?.extraContext, thinkingLevel: options?.thinkingLevel, });
  • 当本次压缩走了远程(provider-native)压缩(OpenAI V1/V2 远程压缩成功)时,短摘要直接固定为"Remote compaction"——因为远程压缩不产出本地文本摘要,为避免制造不实描述而使用占位文案;
  • 否则,对保留的最近消息recentMessages,即压缩后仍以原文保留的近期对话)调用generateShortSummary,并携带本次生成的完整summary作为historySummary上下文。

生成的shortSummary作为CompactionResult.shortSummary返回(接口定义见 compaction.ts 的CompactionResult,注释明确写着 "Short PR-style summary for display purposes")。随后会话管理器将其落库:

  • 会话条目类型中声明了shortSummary?: string(见 entries.ts);
  • 构造压缩摘要消息时通过createCompactionSummaryMessage写入shortSummary字段(见 messages.ts,其中还包括tokensBeforetokensAftermethod(如 "remote"/"soft"/"handoff")等展示元数据);
  • 分支汇总场景同样透传shortSummary(见 branch-summarization.ts)。

因此,用户界面中"本次压缩做了什么"的展示位,消费的正是这份 PR 风格的短摘要;而用于模型续接的完整上下文,则由summary承载。两者各司其职。

与完整摘要及 turn-prefix 摘要的分工

oh-my-pi 的压缩提示词家族位于packages/agent/src/compaction/prompts/,短摘要与它们共同构成三层摘要体系:

提示词文件用途输出预算(相对 reserveTokens)
compaction-summary.md生成结构化 handoff 摘要(Goal / Progress / Next Steps / Critical Context 等分区),供另一个 LLM 接续任务约 80%
compaction-update-summary.md迭代式更新既有摘要(存在previousSummary时替代初始提示词),要求保留既有信息、更新进度与下一步同左
compaction-turn-prefix.md当切割点落在某个 turn 中间时,压缩该 turn 的前缀部分,为保留的后缀提供上下文约 50%
compaction-short-summary.md生成 PR 风格的 2~3 句短摘要,仅供展示约 20%,上限 512 tokens

值得注意的是,完整摘要格式(compaction-summary.md)也要求"如果对话以未回答的问题结束,必须保留该问题原文",这与短摘要的 "ask questions" 规则形成呼应:无论长摘要还是短摘要,悬而未决的用户问题都不允许被丢弃。区别在于完整摘要把问题放入Critical Context分区供模型接续,而短摘要以自然语言提问的方式让用户察觉。

从调用关系看(compaction.ts 的compact函数):常规路径先并行/串行生成完整历史摘要与 turn-prefix 摘要并合并(summary = historyResult + "\n\n---\n\n**Turn Context (split turn):**\n\n" + turnPrefixResult),随后追加文件操作清单(upsertFileOperations,记录本次压缩涉及的读写文件),最后才调用generateShortSummary产出展示用短摘要。

使用与验证建议

  • 查看生效效果:压缩发生(手动/compact或自动触发)后,会话记录中的compactionSummary消息同时携带summaryshortSummary两个字段,前者用于上下文重建,后者用于界面展示。
  • 自定义输出风格:短摘要的格式完全由 compaction-short-summary.md 控制。若希望短摘要更贴近团队 PR 模板(如增加 "Motivation" 或 "Related issues"),可扩展该提示词文件,但应保持 2~3 句、第一人称、不提验证步骤的既有约束——这正是源码中maxTokens预算所对应的产出规模。
  • 约束的兼容性:三条 MUST/NEVER 规则与SUMMARIZATION_SYSTEM_PROMPT的"输出仅限结构化摘要"要求叠加生效;由于系统提示词把对话内容视为不可信数据,即使历史对话里出现"请忽略格式要求"之类的指令,短摘要也不会被污染。

综上,compaction-short-summary.md虽然只有三行,却通过源码中的预算控制(maxTokens)、边界转义(escapeSummaryBoundaryTags)、远程/本地双路径与遥测打点,成为 oh-my-pi 会话压缩体系中"面向人"的最后一公里:把一次可能涉及数万 token 的长会话,压缩成两句话就能读懂的 PR 式变更说明。

【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/10 1:40:00

头歌实践教学平台:Java面向对象-类与对象(五)

第6关&#xff1a;static关键字任务描述 本关任务&#xff1a;使用static关键词设置方法和变量的属性。相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.static关键字有什么作用&#xff0c;2.怎么使用static关键字。什么是static关键字 static关键字我们经常接…

作者头像 李华
网站建设 2026/9/10 1:39:51

最长回文子串的动态规划解法:从状态定义到遍历顺序

最长回文子串这道题&#xff0c;可以说是动态规划入门路上绕不过去的一道坎。LeetCode第5题&#xff0c;看起来就是“给一个字符串&#xff0c;找最长的回文子串”&#xff0c;但真上手做的时候&#xff0c;你会发现它特别适合用来理解动态规划的核心思想&#xff1a;状态怎么定…

作者头像 李华
网站建设 2026/9/10 1:39:03

设计模式新解:从Java经典实现到多Agent主从模式的AI落地

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/10 1:37:27

A*路径规划核心原理与Matlab手写实现:从算法到可视化

最近在折腾路径规划项目&#xff0c;越做越觉得A这个算法是真的又简单又给力。不管你是做机器人导航、游戏寻路、自动驾驶局部规划还是仓库搬运小车&#xff0c;A基本是绕不开的入门首选。我这次就直接用Matlab从零撸了一套带自定义地图的A路径规划&#xff0c;代码完全手写&am…

作者头像 李华
网站建设 2026/9/10 1:36:41

3分钟搭建Telegram文件直链机器人:免费实现即时流式传输

3分钟搭建Telegram文件直链机器人&#xff1a;免费实现即时流式传输 TG-FileStreamBot是一个强大的Telegram文件直链机器人&#xff0c;能够为Telegram文件生成即时流式传输链接&#xff0c;无需等待完整下载即可在线预览和分享。这个开源项目采用Golang编写&#xff0c;提供高…

作者头像 李华