资讯详情

oh-my-pi 提交分析 Map 阶段提示词深度解析:从文件 Diff 到事实观察的提取管线

📅 2026/9/10 14:56:52 | 华诺云谱 👁 阅读
oh-my-pi 提交分析 Map 阶段提示词深度解析:从文件 Diff 到事实观察的提取管线
oh-my-pi 提交分析 Map 阶段提示词深度解析从文件 Diff 到事实观察的提取管线【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-piMap 阶段是 oh-my-pipackages/coding-agent一个 IDE 深度集成的 Coding Agent自动提交分析 map-reduce 流水线中的第一环它把一批文件 Diff 交给模型只要求提取有事实依据的观察不要求分类、不要求归纳。本文以 map.md 为骨架结合 map-reduce.ts、prompts.ts、markdown.ts 与 diff.ts 等源码完整讲解该提示词的逐段语义、模板渲染机制、批次编排、输出解析与容错设计帮助你理解并复用这套先映射、后归约的提交信息生成策略。Map 阶段在提交分析流水线中的定位oh-my-pi 的提交分析conventional commit 生成位于 packages/coding-agent/src/commit/conventional/该目录下除 map.md 外还维护了同一套提示词族analysis.md完整 Diff 的一次性分类含 scope 判定规则、changelog 元数据fast.md轻量快速提交信息生成map.mdmap 阶段逐文件提取事实观察reduce.mdreduce 阶段把观察合并为单一分类summary.md、summary-rewrite.md摘要生成与改写。提示词族由 prompts.ts 统一加载ConventionalPromptFamily类型枚举了analysis | fast | map | reduce | summary | summary-rewrite六类PROMPT_BY_FAMILY通过 Vite 的with { type: text }将.md作为文本导入import mapPrompt from ./prompts/map.md with { type: text };renderConventionalPrompt(family, context)是渲染入口它定位模板中的!-- USER --分隔符分隔符之前的部分作为system提示之后的部分作为user模板交给prompt.renderHandlebars 风格模板引擎以context填充后返回{ system, user }。对 map 模板而言system 部分是角色定义与提取规则user 部分则是files循环与可选的related_files块。触发条件什么时候进入 map-reduce 流程并非所有提交都会走 map-reduce。判定函数shouldUseMapReduce(diff, config)位于 map-reduce.ts它基于 config.ts 中的ConventionalGenerationConfig计算export function shouldUseMapReduce(diff: string, config: ConventionalGenerationConfig): boolean { if (!config.mapReduceEnabled) return false; let totalTokens 0; let hasIncludedFile false; for (const file of includedFiles(parsePromptDiff(diff), config)) { hasIncludedFile true; const tokens file.tokenEstimate(); if (tokens MAX_FILE_TOKENS) return true; // 单文件超过 50_000 tokens totalTokens tokens; if (totalTokens config.mapReduceThreshold) return true; // 累计达到阈值 } return hasIncludedFile totalTokens config.mapReduceThreshold; }关键阈值与默认值见 config.ts 的DEFAULT_CONVENTIONAL_GENERATION_CONFIG配置项默认值含义mapReduceEnabledtrue是否启用 map-reduce 两阶段流程mapReduceThreshold5_000全部有效文件的 token 估算累计达到该值即启用mapBatchTokenBudget16_000单个 map 批次的 token 预算上限excludedFiles锁文件清单以.endsWith匹配后从输入中剔除如Cargo.lock、package-lock.json、bun.lock、uv.lock等单文件 token 估算由ConventionalFileDiff.tokenEstimate()提供diff.ts(header content 的码点长度) / 4向下取整、最少为 1是一个确定性的四字符一 token 近似。测试 commit-conventional.test.ts 中通过mapReduceThreshold: 1之类的极小值来强制走 map-reduce 路径验证行为。提示词逐段解读角色、指令、范围、输出格式与校验map.md 的 system 部分由五个 XML 风格的语义块构成逐段含义如下。角色声明roleroleExpert code analyst extracting grounded observations from a batch of file diffs./role把模型限定为从一批文件 Diff 中提取有依据观察的资深代码分析师。这里的关键词是grounded有依据后续所有规则都在强化只写 Diff 里看得见的事实这一约束为 reduce 阶段的可信合成打下基础。提取指令instructions指令块是 map 阶段的行为核心逐条拆解只提取能被当前文件 Diff 支撑的事实观察保持精确Extract only factual observations supported by each current file diff. Be precise.——这是唯一性原则观察必须落在当前文件的 Diff 上related_files仅用于解析名称或引用不得为这些文件添加观察Use related_files only to resolve names or references; do not add observations about those files.——related_files 只是上下文不是观察来源对files中每个file返回 05 条观察——给出数量上限防止对单文件过度展开使用过去式动词 具体对象 可选目的的句式——统一时态与句式便于 reduce 阶段做字符串级归并每条观察控制在 100 字符以内覆盖该文件中有意义的变更省略格式化、纯注释与 import 顺序调整——过滤低信号变更属于同一整体的相关编辑应合并但不得猜测或过度概括对用户可见的行为变更新能力、默认值变更、修复、移除要明确且事实性地标注不得提及 commit 类型、scope、changelog 或任何 reduce 阶段的分类——map 与 reduce 职责严格分离map 只产出原料。范围界定scopeInclude: functions, methods, types, API changes, behavior/logic changes, error handling, performance, security. Exclude: import reordering, whitespace/formatting, comment-only changes, debug statements.白名单函数/方法/类型、API 变更、行为或逻辑变更、错误处理、性能、安全与黑名单import 重排、空白与格式、纯注释、调试语句并用让模型在什么值得写上有明确裁决标准。输出格式output_formatmap 阶段的输出是每文件一个#标题 -子弹列表的 Markdown# src/config.rs - added TOML configuration loading - changed default timeout to 30s # src/main.rs - changed CLI parsing to accept config paths # src/empty.rs配套规则每个输入文件恰好一个#标题path必须与file path...中完全一致观察以-子弹列在标题下必须覆盖每一个输入文件某文件没有相关观察时只输出其#标题、不带任何子弹——这个空标题约定非常关键它是后续解析器判定文件已处理的信号。验证清单verification三条自检每条观察都能被该文件的 Diff 直接支撑没有观察只依赖related_files没有重复、琐碎或分类导向的观察。模板末尾还有一句总纲Observations only. Reduce phase handles classification and synthesis.只产出观察分类与综合由 reduce 阶段负责。模板变量与 Handlebars 渲染map.md 的用户段位于!-- USER --之后包含两个 Handlebars 块files {{#each files}} file path{{path}} {{diff}} /file {{/each}} /files {{#if context_header}} related_files {{ context_header }} /related_files {{/if}}渲染时注入两个变量files形如{ path, diff }的对象数组与可选的context_headerrelated_files 文本。在 map-reduce.ts 的mapFileBatch中可以看到实际装配const promptFiles files.map(file ({ path: file.filename, diff: renderFileDiffForBatch(file, budget) })); const prompts renderConventionalPrompt(map, { files: promptFiles, context_header: contextHeader });renderFileDiffForBatch(file, budget)会按批次 token 预算裁剪单个文件的 Diff若文件 token 估算与字节数都在预算内则完整保留否则克隆文件、调用truncate截断内容保留头部 15 行、尾部 10 行中间以... (truncated N lines) ...占位参见 diff.ts。related_files 上下文的构造逻辑ContextHeaders类map-reduce.ts负责为每个批次生成同一次变更中的其他文件概览其核心是inferFileDescriptionmap-reduce.ts这个基于文件名与内容启发式的分类器文件名含test→test file含prompt/system→prompt template后缀.md→documentation含config或后缀.toml/.yaml/.yml→configuration含error→error definitions含type→type definitionsmod.rs/lib.rs→module exportsmain.rs/main.go/main.py→entry point内容含class/def/fn→implementation含struct/enum→type definitions含async/await→async code否则兜底source code。headerForFiles(currentFiles)取出不在当前批次中的其他文件按additions deletions行数降序排列最多展示MAX_CONTEXT_FILES 20个超出时追加... and N more files提示。特别地当提交文件总数超过 100 时直接退化为一行(Large commit with N total files)避免超大提交生成巨型上下文。这些相关文件描述正是 map 提示词中只用来解析名称或引用的那部分上下文。批次编排与并发执行mapPhasemap-reduce.ts是 map 阶段的运行时编排值得注意的工程细节二进制文件短路isBinary的文件不进入模型调用直接产出固定的Binary file changed.观察并保留其增删行数与状态预算计算effectiveMapBudget(totalTokens, config.mapBatchTokenBudget)先按totalTokens * 5 / (16 * 4)估算理想批次预算再夹在MIN_MAP_BATCH_TOKENS 4_000与用户配置的mapBatchTokenBudget默认 16_000之间贪心分批buildLlmFileBatches过滤掉二进制文件后用buildBatchesForIndices做 token预算 ×1与字节预算 ×4双预算的贪心装箱单文件超过预算时独占一个批次并发度MAP_PHASE_CONCURRENCY 16mapWithConcurrency用固定数量 worker 的竞速模式worker 循环取下一个 index处理批次保证长尾批次不被阻塞进度反馈每个批次调用inference.complete时携带progressLabel如Mapping batch 2/5 (3 files)…toolName为create_file_observationspromptFamily为map。输出解析宽容的 Markdown 契约map 提示词要求不带 fences 输出但模型输出往往不守规矩。解析器parseFileObservationsMarkdownmarkdown.ts对多种形态做了宽容处理JSON 形态{files:[{path, observations}]}或纯数组均可解析字段兼容path/file、observations/detailsMarkdown 形态逐行扫描行首可匹配#标题、file:/file / 反引号包裹等变体正则^(?:#\s*)?(?:file\s*[:-]\s*)??(.?)?\s*:??$且候选必须含/或.才被视为文件标题避免把普通句子误判为路径子弹行支持- * • – 以及有序列表1.解析结果会去掉每条观察末尾的句号stripTrailingPeriod统一为无句号事实句。随后mapResponseToObservationsmap-reduce.ts把解析结果映射回文件顺序匹配策略分三档候选路径与文件名完全相等文件名basename 唯一时按 basename 匹配最后按路径后缀匹配pathSuffixMatches。若模型因max_tokens/length停止且某文件无观察会回填Updated basename.兜底观察完全无匹配的文件同样回填兜底批次结果全部返回后任何缺失观察的文件会抛出Missing map observation for filename错误——保证 reduce 阶段拿到的观察集合与输入文件一一对应。观察如何进入 reduce 阶段runMapReducemap-reduce.ts在 map 完成后调用renderObservationsMarkdown把观察渲染成 reduce 的输入# src/foo.rs (12/-4) - added retry logic for network calls - changed default timeout to 30s未修改文件会标注状态added/deleted/renamed与N/-N行数map-reduce.ts然后连同condenseStat处理过的 git stat、scope 候选与类型定义一起注入 reduce.md 模板由 reduce 阶段产出单一# type(scope): summary标题、36 条细节与可选的Fixes:issue 引用。至此完成map 提取事实观察 → reduce 综合分类的完整闭环最终分析结果会用于生成 conventional commit 消息。小结与复用建议map.md 的设计精髓可以提炼为三条原则职责分离map 只做逐文件、逐条、有依据的事实提取05 条/文件、≤100 字符/条、过去式句式分类、scope、changelog 全部留给 reduce从提示词层面杜绝模型在原料阶段就下结论契约优先明确的# 文件- 子弹输出格式、空标题表示无观察的约定配合 markdown.ts 的宽容解析与三档路径匹配让输出稳定可机器消费资源可控token 估算驱动触发阈值默认 5_000、批预算默认 16_000、并发 16、单文件 50_000 token 上限与按优先级截断保证超大提交也可控地完成分析。如果你需要在自己的 Agent 流水线中复用这套模式可以直接参考 map.md 的提示词结构配合 map-reduce.ts 的分批与并发编排以及 markdown.ts 的解析器若要调整触发灵敏度只需修改 config.ts 中mapReduceThreshold、mapBatchTokenBudget等设置。相关行为在 commit-conventional.test.ts 中有配套测试可参考。【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。