ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

oh-my-pi 分支摘要提示词解析:branch-summary.md 如何把被放弃的会话分支压缩为结构化上下文

oh-my-pi 分支摘要提示词解析:branch-summary.md 如何把被放弃的会话分支压缩为结构化上下文 oh-my-pi 分支摘要提示词解析branch-summary.md 如何把被放弃的会话分支压缩为结构化上下文【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi本文围绕 oh-my-pi 中 branch-summary.md 这一提示词模板展开它是会话树session tree导航场景下分支摘要branch summary功能的输出格式契约规定了模型在用户离开当前对话分支时必须产出的固定结构Goal / Constraints / Progress / Key Decisions / Next Steps。读完本文你能理解该提示词每个字段的用途与约束掌握它在 branch-summarization.ts 中的完整调用链、token 预算与配置项branchSummary.*的行为以及摘要生成后如何回注上下文供后续轮次继续对话。一、问题背景会话树导航中离开分支会丢失什么oh-my-pi 的会话不是一条线性消息流而是一棵树每条消息是一个节点用户在 agent-session.ts 的navigateTree()中可以在树内跳转到任意位置例如回到某个早期消息重新提问形成一条新的兄弟分支。文件头注释branch-summarization.ts直接说明了动机When navigating to a different point in the session tree, this generates a summary of the branch being left so context isnt lost.如果不做处理从分支 A 跳回公共祖先改走分支 B 时A 上积累的目标、进度、决策就会从模型上下文中彻底消失。分支摘要机制的做法是在跳转发生前对被放弃的那段分支调用一次 LLM把整段对话压缩成一份结构化摘要并以branch_summary类型的条目持久化到新分支的目标位置之后随上下文一起被重新注入。而 branch-summary.md 就是这次 LLM 调用的输出格式规范——它不描述做什么做什么由系统提示词和conversation块负责而是强制规定输出必须长什么样。二、提示词原文与逐节解析branch-summary.md 全文如下这是它对模型施加的完整契约You MUST create a structured summary of the conversation branch for context when returning. You MUST use EXACT format: ## Goal [What is the user trying to accomplish in this branch?] ## Constraints Preferences - [Constraints, preferences, requirements mentioned] - [(none) if none mentioned] ## Progress ### Done - [x] [Completed tasks/changes] ### In Progress - [ ] [Work started but not finished] ### Blocked - [Issues preventing progress] ## Key Decisions - **[Decision]**: [Brief rationale] ## Next Steps 1. [What should happen next to continue] Sections MUST be kept concise. You MUST preserve exact file paths, function names, error messages.整份提示词由三部分组成开头的一句任务声明必须为该分支创建结构化摘要以便返回时恢复上下文、中间的 EXACT format 模板、结尾的两条硬约束各节必须保持简洁必须精确保留文件路径、函数名、错误信息。逐节看其设计意图## Goal这一分支要达成什么一句话回答用户在这条分支上试图完成什么。它的作用是在分支被放弃后把分支级的意图锚定下来——当用户回到这个位置继续对话时模型不需要重读原始对话就能知道这条探索线当初在干什么。## Constraints Preferences约束与偏好以项目符号列出用户在分支中提到的约束、偏好和硬性要求特别地模板要求没有时必须显式写(none)。这个占位符纪律很典型它让下游消费者以及后续把摘要再压缩进 compaction 摘要的流程能通过固定格式判断这一节是空的而不是把整节误读为缺失或遗漏。## Progress三态进度清单这是模板中信息密度最高的一节按状态拆成三个子节### Done用- [x]勾选框列出已完成的任务/变更### In Progress用- [ ]未勾选框列出已启动但未完成的工作### Blocked列出阻碍推进的问题。三态划分对应的是恢复执行所需的完整状态哪些不需要再做、哪些要接着做、哪些被卡住了。勾选框[x]/[ ]语法让这节天然兼容 todo 类工具的呈现习惯也让后续 LLM 在解析摘要时能机械地区分状态。## Key Decisions决策与理由格式固定为- **[Decision]**: [Brief rationale]——决策加粗、冒号后跟简短理由。分支探索中模型往往会做架构选择、取舍权衡选了方案 X 因为 Y这些决策是分支中最不可再生成的信息原始对话可以压缩但为什么这么定一旦丢失恢复后的对话就可能重复讨论已经否决过的方向。## Next Steps有序续作清单编号列表回答接下来应该做什么才能继续。它与Progress/In Progress的区别在于In Progress 是事实描述进行到哪一步Next Steps 是可执行计划下一步动作。结尾两条硬约束的作用Sections MUST be kept concise摘要最终要放进上下文窗口与主对话竞争 token冗长摘要会挤占真实对话的预算You MUST preserve exact file paths, function names, error messages这是对摘要失真的防御。分支摘要最常见的失败模式是模型把src/foo/bar.ts概括成某个源文件、把错误消息意译成近似描述导致恢复后无法定位。模板通过把这三类标识符单列为必须精确保留压低这种失真概率。三、提示词在代码中的位置默认指令与可覆盖性branch-summary.md 作为文本资源被直接导入并渲染为常量// packages/agent/src/compaction/branch-summarization.ts import branchSummaryPrompt from ./prompts/branch-summary.md with { type: text }; import branchSummaryPreamble from ./prompts/branch-summary-preamble.md with { type: text }; const BRANCH_SUMMARY_PREAMBLE prompt.render(branchSummaryPreamble); const BRANCH_SUMMARY_PROMPT prompt.render(branchSummaryPrompt);branch-summarization.ts 与 branch-summarization.ts它作为默认指令参与提示词组装并且可以被customInstructions覆盖// generateBranchSummary() 内L332-L333 const instructions customInstructions || BRANCH_SUMMARY_PROMPT; const promptText conversation\n${conversationText}\n/conversation\n\n${instructions};也就是说发给模型的单条 user 消息结构是conversation标签包裹的序列化对话文本 换行 指令默认即 branch-summary.md 的内容。GenerateBranchSummaryOptions接口还暴露了其余可调项branch-summarization.tsmodel/apiKey/signal用哪个模型、如何取消customInstructions?: string整体替换默认提示词宿主应用可以换一套格式契约reserveTokens?: number默认 16384为提示词 响应预留的 token 空间metadata?: Recordstring, unknown转发给底层 API 请求的元数据convertToLlm?: ConvertToLlm宿主侧消息转换器telemetry?: AgentTelemetry提供时该次 LLM 调用会包在 OTEL chat span 中并打上pi.gen_ai.oneshot.kind branch_summary标签completeImpl?宿主可替换底层完成传输把请求路由到自己的 provider 并发限流器。四、完整生成链路从节点收集到摘要落盘4.1 收集被放弃分支的条目collectEntriesForBranchSummary(session, oldLeafId, targetId)branch-summarization.ts的逻辑是取旧叶子oldLeafId到根的路径集合oldPath以及目标targetId到根的路径targetPath从targetPath的末端向前扫找到同时出现在oldPath中的最深节点即公共祖先commonAncestorId从旧叶子沿parentId回溯到公共祖先收集沿途所有SessionEntry再反转为时间顺序。注意注释明确说明回溯不在 compaction 边界处停下——边界上的既有压缩摘要也会被纳入成为分支摘要的输入上下文getMessageFromEntry会把compaction条目转换为摘要消息见 branch-summarization.ts。4.2 token 预算内的两遍遍历prepareBranchEntries(entries, tokenizer, tokenBudget)branch-summarization.ts做两件事第一遍不计预算累计文件操作追踪。遍历所有条目只从pi 自己生成的branch_summary条目fromExtension ! true的details中取readFiles/modifiedFiles并入fileOps。这样嵌套场景一次分支摘要覆盖了此前另一段已被摘要的分支能保持累计的文件追踪不丢失。第二遍受预算约束从最新到最旧填充消息。逐条把SessionEntry转成AgentMessage先提取 assistant 消息里工具调用涉及的文件操作再估算 token工具结果会先按truncateToolResultForSummary截断再计数见estimateBranchSummaryTokensbranch-summarization.ts超预算即停。两个细节值得注意被标记useless true且非错误的toolResult直接丢弃branch-summarization.ts避免无信息量的大 payload 吃掉分支摘要的 token 预算、挤掉更有价值的旧条目——branch-summarization.test.ts 中有专门用例验证保留有信息量的工具结果、丢弃 useless 工具结果预算将满时compaction/branch_summary类型的摘要条目会被优先塞入totalTokens tokenBudget * 0.9时强行纳入branch-summarization.ts因为既有摘要本身就是高密度上下文比普通消息更值得保留。4.3 LLM 调用与后处理generateBranchSummary的组装流程branch-summarization.ts// L316-L318token 预算 上下文窗口 − 预留 const contextWindow model.contextWindow || 128000; const tokenBudget contextWindow - reserveTokens; // reserveTokens 默认 16384 // L328-L329转换并序列化对话防止模型把它当成要继续的对话 const llmMessages (options.convertToLlm ?? defaultConvertToLlm)(messages); const conversationText serializeConversationForSummary(llmMessages, preferredDialect(model.id));LLM 调用参数系统提示词为SUMMARIZATION_SYSTEM_PROMPTmaxTokens: 2048摘要上限并带oneshotKind: branch_summary遥测标签branch-summarization.ts。拿到响应后还有三步后处理前置前言拼接BRANCH_SUMMARY_PREAMBLE来自 branch-summary-preamble.md内容为 User explored another conversation branch, then returned here. Exploration summary:让摘要自带身份标识——读摘要的人/模型知道这是探索过另一条分支后带回的产物追加文件清单computeFileLists(fileOps)算出 read/modified 文件列表upsertFileOperations把它们以files标签写进摘要尾部路径带(Read)/(Write)/(RW)标注旧版本的read-files/modified-files标签会被剥除自愈见 packages/agent/CHANGELOG.md返回结构化结果{ summary, readFiles, modifiedFiles }加上aborted/error状态位其中readFiles/modifiedFiles会随摘要条目一起持久化为details。五、触发点navigateTree 中的会话树跳转真正的业务触发在 agent-session.ts 的navigateTree()约 L9640 起前置校验options.summarize为真时必须已有可用模型No model available for summarization计算摘要锚点一般情况下就是targetId在ask工具重新作答的特殊协议下锚点改为targetEntry.parentId新兄弟节点会挂在那里否则会漏掉旧答案条目L9700-L9712对应 issue #5895 的修复注释调用collectEntriesForBranchSummary(this.sessionManager, oldLeafId, summaryAnchorId)得到待摘要条目与公共祖先扩展钩子优先若注册了session_before_tree钩子扩展可以取消导航或自己提供一个摘要result.summary此时跳过内置 LLM 摘要并置fromExtension trueL9729-L9744否则读配置组并生成摘要// L9755-L9771 const branchSummarySettings this.settings.getGroup(branchSummary); const result await generateBranchSummary(entriesToSummarize, { model, apiKey: this.#modelRegistry.resolver(model, this.sessionId), signal: this.#branchSummaryAbortController.signal, customInstructions: this.#obfuscateTextForProvider(options.customInstructions), reserveTokens: branchSummarySettings.reserveTokens, metadata: this.agent.metadataForProvider(model.provider), convertToLlm: messages this.#convertToLlmForSideRequest(messages), telemetry: resolveTelemetry(this.agent.telemetry, this.sessionId), completeImpl: async (requestModel, requestContext, requestOptions) { const stream await this.#sideStreamFn(requestModel, requestContext, requestOptions); return stream.result(); }, });摘要落盘位置注释写得很明确——Summary is attached at the navigation target position (newLeafId), not the old branchL9844-L9857。有摘要时调sessionManager.branchWithSummary(newLeafId, summaryText, summaryDetails, fromExtension)在目标位置创建branch_summary条目summaryDetails即{ readFiles, modifiedFiles }L9780-L9783。随后重建会话上下文、重置 advisors、从分支同步 todo并视情况发出session_tree事件。HTML 导出同样消费这个条目template.js 会渲染带 Branch Summary 标题的独立区块树形视图里则显示[branch summary]:前缀L555。六、相关配置项分支摘要由 settings-schema.ts 中两个设置项控制设置项类型默认值说明branchSummary.enabledbooleanfalse离开分支时是否提示/执行摘要UI 位于 context 标签的 General 组描述为 Prompt to summarize when leaving a branchbranchSummary.reserveTokensnumber16384传入generateBranchSummary的reserveTokens即tokenBudget contextWindow - reserveTokens中的预留量适用前提navigateTree的summarize选项开启对应 UI 的 enabled 语义且当前会话已选择模型若走session_before_tree扩展钩子提供了摘要则内置 LLM 路径不执行。七、摘要如何回到上下文落盘的branch_summary条目不是终点而是新的上下文来源messages.ts 的createBranchSummaryMessage()把branch_summary条目转回消息渲染模板是 branch-summary-context.mdBranch-return summary: summary {{summary}} /summary主 compaction 流程同样处理这类条目compaction.ts 把branch_summary条目转成BranchSummaryMessage所以分支摘要在后续整段压缩时会作为高价值上下文参与下一次再发生分支跳转时这些摘要条目本身又会进入collectEntriesForBranchSummary的收集范围其details中的文件清单被累计prepareBranchEntries第一遍遍历实现跨多次跳转的文件追踪传递。八、测试验证branch-summarization.test.ts用 mock 模型走通generateBranchSummary全链路验证 useless 工具结果被丢弃、有信息量的工具结果保留并用prepareBranchEntries在不同 token 预算100 / 700下验证新→旧填充与截断行为compaction-telemetry.test.ts验证generateBranchSummary的 OTEL span 确实打上pi.gen_ai.oneshot.kind branch_summary标签。九、实践要点小结格式契约是硬性的## Goal/## Constraints Preferences/## ProgressDone / In Progress / Blocked/## Key Decisions/## Next Steps五个区块缺一不可空约束要写(none)进度用[x]/[ ]勾选框决策用加粗决策: 理由格式。保真优先文件路径、函数名、错误消息必须逐字保留——这是摘要能支撑恢复后继续工作的前提。预算意识摘要输入预算是contextWindow - reserveTokens默认预留 16384输出上限maxTokens: 2048各节保持简洁的提示词要求与这套预算机制是配套的。可替换性customInstructions可以整体替换默认提示词扩展可以通过session_before_tree钩子完全接管摘要生成宿主也可以通过completeImpl把这次请求纳入自己的并发限流。落点在新分支摘要条目挂在导航目标位置而非被放弃的旧分支上确保回到目标位置后的上下文立刻携带另一条分支探索过什么的信息。对希望接入或定制该机制的开发者建议从 branch-summarization.ts 的GenerateBranchSummaryOptions接口读起再到 agent-session.ts 的navigateTree触发路径最后对照 branch-summarization.test.ts 验证边界行为。【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表