news 2026/9/7 17:27:59

Zed 编辑预测训练管线解析:teacher_jumps 提示词如何让模型做出“长距离“跨文件编辑预测

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Zed 编辑预测训练管线解析:teacher_jumps 提示词如何让模型做出“长距离“跨文件编辑预测

Zed 编辑预测训练管线解析:teacher_jumps 提示词如何让模型做出"长距离"跨文件编辑预测

【免费下载链接】zedCode at the speed of thought – Zed is a high-performance, multiplayer code editor from the creators of Atom and Tree-sitter.项目地址: https://gitcode.com/GitHub_Trending/ze/zed

本文围绕 Zed 仓库中 teacher_jumps.md 这一提示词模板展开,讲解 Zed 编辑预测(edit prediction)数据管线中"teacher-jumps"方案的核心设计:基于内容哈希标记(Hashed Regions)的跨文件编辑寻址、"永不回退用户编辑"的规则体系、NO_EDITS兜底机制,以及模板中{{edit_history}}{{context}}{{cursor_excerpt}}三个占位符如何被 format_prompt.rs 组装、模型响应又如何被解析回可应用的补丁。读完本文,你可以理解该提示词每一节规则的意图,并能在 edit_prediction_cli 中定位到对应的实现与测试。

一、teacher_jumps 在 Zed 编辑预测管线中的位置

Zed 的编辑预测功能需要大量高质量的"用户下一步会怎么改代码"样本。edit_prediction_cli(下称epCLI)就是训练数据管线工具:它从真实仓库/提交中构造示例(Example),通过上下文检索补齐相关代码,用一个大模型("teacher")生成预测补丁,再评分、蒸馏出学生模型可用的训练数据。

teacher_jumps.md就是其中teacher-jumps这条预测路线的提示词模板。"jumps"(跳跃)指的是:预测不局限于光标附近的可编辑区域,模型可以输出针对当前文件其他位置、甚至其他文件的编辑——即"长距离编辑预测"。与普通teacher路线相比,它的两个关键特征是:

  1. 全上下文打标记:当前文件和所有相关代码片段(related excerpts)都被插入形如<|marker_b1f8|>的哈希区域标记,模型用"标记对"来寻址要改写的代码区间;
  2. 有序编辑序列输出:模型可以输出多个代码块,每个代码块对应一次编辑,按预期的编辑顺序排列。

模板通过 prompt_assets.rs 的get_prompt("teacher_jumps.md")加载:启用dynamic_promptsfeature 时直接从src/prompts目录读取(便于开发期热改提示词),否则在编译期通过fs_embed!内嵌到二进制中。

二、模板结构与占位符体系

teacher_jumps.md全文由以下部分构成:

  1. 任务定义(Instructions):告诉模型它是"代码编辑器中的编辑预测助手",基于用户最近的编辑历史和可见代码预测下一步编辑;
  2. 关注点与规则(Focus on / Rules):定义预测的取舍原则与硬性约束;
  3. 输入格式(Input Format):说明模型会看到哪三类输入、标记标记(marker)如何工作;
  4. 输出格式(Output Format):定义以标记为界的 span 输出协议;
  5. 7 个少样本示例(Example 1–7):覆盖补全、拼写延续、跨文件重命名、NO_EDITS、删除保护、两段式编辑(补代码+补 import)、改写已接受预测等场景;
  6. 任务段(Your task):三个占位符注入真实数据。

文末的任务段是模板与运行时的唯一接口:

# 1. User Edit History

{{edit_history}}

# 2. Related excerpts {{context}} # 3. Current File {{cursor_excerpt}} ``` 在 [format_prompt.rs](https://link.gitcode.com/i/74770d825931dfc24590382170683cb0#L395-L401) 中,`TeacherJumpsPrompt::format_prompt` 正是执行这三个 `replace`: ```rust let prompt_template = crate::prompt_assets::get_prompt("teacher_jumps.md"); let prompt = prompt_template .replace("{{context}}", &context) .replace("{{edit_history}}", &edit_history) .replace("{{cursor_excerpt}}", &cursor_excerpt); ``` 三类占位内容各有明确的装配逻辑与预算约束: | 占位符 | 内容 | 预算/约束(源码出处) | |---|---|---| | `{{edit_history}}` | 按时间顺序的用户编辑 diff | 由 `format_edit_history_within_budget` 在 **4000 token** 预算内截取(`MAX_HISTORY_TOKENS = 4000`,[format_prompt.rs](https://link.gitcode.com/i/74770d825931dfc24590382170683cb0#L370)) | | `{{context}}` | 当前文件之外所有相关代码片段 | `--related-files-budget` 控制,默认 **8192 token**(`DEFAULT_RELATED_FILES_BUDGET`,[main.rs](https://link.gitcode.com/i/e4ca06001a1fda91af9ba3493877040a#L372)) | | `{{cursor_excerpt}}` | 当前文件全文(含标记与 `<|user_cursor|>`) | 必须有覆盖光标位置的上下文片段,否则直接报错(见下文) | 其中 `format_context` 的装配细节值得注意([format_prompt.rs](https://link.gitcode.com/i/74770d825931dfc24590382170683cb0#L475-L596)): - 每个片段渲染时用 `hashed_regions::write_snippet_with_markers` 注入标记; - token 预算按 **字节数除以 3** 粗估,按片段的 `order` 排序后贪心装填,装不下的片段整体丢弃,被省略的行以 `...` 标示; - **当前文件被显式跳过**——它有自己的 `Current File` 段落(`format_cursor_excerpt`),避免在 prompt 中出现两次; - 历史数据中可能只有 `cursor_excerpt` 而没有走过 current-file 上下文检索,此时 `hashed_regions::ensure_cursor_file_excerpt` 会先做归一化,合成当前文件的上下文片段。 另外,teacher-jumps 对上下文有硬性前提:光标所在文件必须被某个 related-file 片段覆盖,否则 `format_prompt` 会返回错误,提示需要 "current-file context retrieval (e.g. `ep context --type=current-file,...`)"([format_prompt.rs](https://link.gitcode.com/i/74770d825931dfc24590382170683cb0#L380-L383))。这与 [hashed_regions.rs](https://link.gitcode.com/i/ba17c870ccff4c1f00c1259c52e1fc34) 模块头注释一致:**在 hashed regions 格式下,所有上下文(包括当前文件)都统一存放在 related files 中**,通过 `ContextSource::CurrentFile` 进入。 ## 三、规则体系:保护用户意图,允许修正机器产物 `Rules` 一节是整个提示词中约束力最强的部分,其核心是一条"不可违反"的原则和一条"例外通道": ### 3.1 永不回退用户最近的编辑 提示词明确要求模型**绝不能撤销或还原用户刚刚做出的编辑**,并给出可操作的判定准则: - 编辑历史中 `-` 开头的行(被删除的内容)即使让代码看起来不完整、坏掉,也**不得恢复**; - `+` 开头的行(新增内容)不得删除或大幅改写; - 代码在用户编辑后看起来坏掉或不完整时,应输出 `NO_EDITS`,而不是"修复"它; - **关键自检**:"如果你的预测会让代码更接近用户编辑之前的样子,就输出 `NO_EDITS`"; - 永远不要假设某次删除是笔误——用户可能正在重写中。 这条规则直接对应 Example 5:用户在 Nix 配置里把 `/tmp/crashdb` 删成 `/tmp/cr`,表面看是"半截单词",但补全 `ashdb` 就等于恢复被删除的内容,正确行为是 `NO_EDITS`。 ### 3.2 例外:已被接受的预测产物可以被修正 编辑历史中以 `// User accepted prediction:` 开头的 hunk,表示这段代码来自**上一轮预测被用户接受**后落入缓冲区的内容。提示词规定:这些 hunk 可以被编辑、修正甚至替换——"永不回退"保护的是用户*当前的输入意图*,而机器生成的脚手架不在此列。 Example 7 完整演示了这一例外:用户接受了一个预测生成的 `calculate_rectangle_perimeter(width, height)` 函数骨架,随后开始把 `rectangle` 重命名为 `sq...`。正确预测是把函数名补成 `calculate_square_perimeter`,**同时**把参数从 `(width, height)` 改为 `(side)`——因为参数正是被接受预测自动生成的,改它不算回退用户输入,而是"改进机器脚手架"。这个"用户手打的不能碰、机器生成的可以改"的二分法,是长距离预测能安全地做重构传播(propagation)的前提。 ### 3.3 其余预测风格规则 - 不要机械套用模式,要基于上下文推理什么改动合理; - 不只修语法错误,要找更大的重构模式并系统性地应用(例如签名变更后更新所有调用点); - 保持既有格式,**不得**做与真实编辑无关的空白行增删; - 编辑历史与周边代码暗示不同编辑时,**优先最近的编辑**(最能代表当前意图); - 光标附近的半截文本视为用户正在输入,基于上下文补全; - 补全时优先"节省有意义的按键",代码场景下"宁可给出可能被拒绝的实质性预测,也不要只省几个键的最小预测"; - 编辑散文/文档(Markdown、注释、纯文本)时保守处理:只补全当前片段或句子,不生成额外的自由文本。 ## 四、标记寻址协议:`<|marker_xxxx|>` 如何工作 这是 teacher-jumps 区别于普通 teacher 路线的机制核心。模板的 `Input Format` 一节向模型说明了标记的语义: - 当前文件和每个 related excerpt 中都插入了形如 `<|marker_b1f8|>` 的标记,每个标记有**唯一的四字符标识符,由标记附近的代码内容派生**; - 标记位于块边界上,把代码切分为可编辑的 span;**同一 excerpt 中任意两个标记之间的 span 都可以被整体改写**; - 片段内部的 `...` 表示有代码被跳过。 实现层在 [zeta_prompt/src/hashed_regions.rs](https://link.gitcode.com/i/4cba5f0733c5841a2a96a4b2c1016b37)。该模块是 "Smart Regions" 多区域格式的一个变体(V0609HashedRegions),其设计动机(摘自模块头注释): - 标记标识符是**内容派生的短哈希**(4 个 base64url 字符,`TAG_ID_LEN = 4`),而非顺序编号; - 因此哈希标识是**自描述的**:无需复现 prompt 的确切渲染顺序就能把标记映射回位置; - 于是标记可以放在**全部 prompt 上下文**中,且 related files 的预算截断不会导致剩余标记的寻址漂移; - 标记表由 `build_marker_table` 生成,**确定性**且不依赖后续的任何截断——这正是模型输出能被事后解析回补丁的关键(解析时用同一张表重建寻址)。 输出协议(`Output Format` 一节)把上述机制固化为一组可验证的约束: 1. 先简述用户意图与需要变更的位置,然后输出**一个 markdown 代码块序列**,每个代码块对应一次编辑,按用户预期的编辑顺序排列; 2. 每个代码块必须**以标记开头、以标记结尾**,两个标记必须来自**同一个 excerpt**,且起始标记在前; 3. 两标记之间的内容是该片段的**完整替换**——"你没有提前停止的权利":即使实际改动只触及 span 开头,也必须原样复写到结束标记;未复现的原行视为被删除; 4. 选择**最窄的**标记对,使预测编辑被完整包含,以最小化无谓输出; 5. 未变更行必须忠实复现;删代码时优先选择结束标记位于删除代码**之后**的 span;"输出到结束标记前就停止"会被判为截断(malformed),而不是删除; 6. 输出中不得包含中间标记,只允许首尾两个; 7. 所有编辑都作用于**原始快照**:不同编辑的 span 不得重叠,后面的编辑不得依赖前面编辑插入的文本; 8. 无需编辑时输出仅含 `NO_EDITS` 的单个代码块; 9. 若预测输出中存在用户大概率接下来要编辑的位置,可用 `<|user_cursor|>` 标出(**至多一次**)。 这组协议与 Example 4 形成呼应:用户把 `add` 函数里的 `a - b` 修正为 `a + b`,代码已完整正确,模型应当说明意图后输出 `NO_EDITS`——即"没有清晰的下一步编辑"本身是一等公民的合法输出。 ### 7 个少样本示例各教什么 | 示例 | 场景 | 教会模型的行为 | |---|---|---| | Example 1 | `total += ;` 光标停在空操作数处,related excerpt 里有 `Product` 结构体定义 | 利用其他文件中的类型定义,推断应填 `product.price` | | Example 2 | 用户打出 `epr`,疑似 `eprintln!` 拼错一半 | **延续**用户轨迹而非纠正:补成 `eprintln!("<|user_cursor|>")` 并把光标放进字符串里让用户自己填内容 | | Example 3 | 当前文件里 `fetch_user` 改名为 `fetch_user_cached`,`src/server.rs` 片段里仍是旧名 | 跨文件完成重命名:对 `server.rs` 中调用点输出一个标记 span 编辑 | | Example 4 | 修完 `a - b` → `a + b` 的 bug,代码已完整 | 输出 `NO_EDITS` | | Example 5 | 用户删除字符留下 `/tmp/cr`,看似半截 | 不得恢复被删内容,输出 `NO_EDITS`(即使代码"看起来坏了") | | Example 6 | `timestamp = datetime.` 半截,且 `datetime` 未导入 | 输出**两个**编辑:先补 `datetime.now(<|user_cursor|>)`,再在文件头 span 中插入 `from datetime import datetime` | | Example 7 | 接受过预测生成的函数,用户开始重命名 | 修改机器生成的参数 `(width, height)` → `(side)`,属于改进脚手架而非回退输入 | ## 五、运行时装配:从 Example 到 Prompt 把模板落到代码上,`TeacherJumpsPrompt::format_prompt`([format_prompt.rs](https://link.gitcode.com/i/74770d825931dfc24590382170683cb0#L374-L402))的执行链是: ``` build_marker_table(prompt_inputs) // 为每个 related-file 片段分配哈希标记 locate_cursor_in_related_files(...) // 定位光标所在片段;找不到则报错 format_edit_history(...) // 4000 token 预算内的编辑历史 format_context(..., budget, cursor_file_ix)// 相关片段(跳过当前文件),budget 内贪心装填 format_cursor_excerpt(...) // 当前文件 + 标记 + <|user_cursor|> 替换 {{context}} / {{edit_history}} / {{cursor_excerpt}} ``` 值得注意的是 `ensure_cursor_file_excerpt` 的调用位置:在 [run_format_prompt](https://link.gitcode.com/i/74770d825931dfc24590382170683cb0#L46-L59) 中,只有 provider 是 `TeacherJumps` 或 `TeacherJumpsNonBatching` 时才执行该归一化——因为其他 teacher 路线允许"光标文件不在 related files 里",而 teacher-jumps 的寻址协议要求光标文件必须是可寻址的 related file 之一。 ## 六、响应解析:把标记 span 序列还原为补丁 模型响应不是直接可应用的,`TeacherJumpsPrompt::parse`([format_prompt.rs](https://link.gitcode.com/i/74770d825931dfc24590382170683cb0#L404-L458))负责解析,逻辑与模板规则一一对应: 1. 若**最后一个代码块**内容恰为 `NO_EDITS`(或响应以 `NO_EDITS` 结尾),返回空补丁与空光标; 2. 否则抽取全部代码块,只保留包含 `MARKER_TAG_PREFIX`(`<|marker_`)的块;一个都没有则报 "no marker-bounded edit codeblocks found in model response"; 3. 对每个代码块调用 `hashed_regions::extract_marker_span` 提取 `(起始标记, 结束标记, 内容)`; 4. 交给 `hashed_regions::build_patch_from_spans`——与学生模型解析器共用的哈希区域补丁组装器——校验 span 合法性(同 excerpt、不重叠、作用于原始快照等),产出 `(patch, cursor)`; 5. 若响应带 `<|user_cursor|>`,进一步通过 `ActualCursor::from_editable_region` 换算出预测后的光标位置。 解析失败时不会中断整批任务:在 [predict.rs](https://link.gitcode.com/i/6eb69d45e06dd446e51e05503aad27e9) 中,解析错误被记录在 `ExamplePrediction.error` 字段里(原始输出保留,可用 `parse-output` 复查),"一个坏示例不再中止整个(已经付费的)批次"。`format_prompt.rs` 内嵌的大组测试(`test_teacher_jumps_parse_rejects_truncated_span`、`test_teacher_jumps_parse_rejects_span_across_gapped_excerpts`、`test_teacher_jumps_parse_sequence_across_files` 等,[format_prompt.rs](https://link.gitcode.com/i/74770d825931dfc24590382170683cb0#L868-L1320))逐条验证了第四节的输出协议,例如:截断 span 被拒绝、跨越不连续片段的 span 被拒绝、`NO_EDITS` 被识别等。 ## 七、如何选用 teacher-jumps:CLI 参数与后端 `ep` CLI 通过 `--provider` 参数选择预测路线。从 [main.rs](https://link.gitcode.com/i/e4ca06001a1fda91af9ba3493877040a#L491-L546) 的 `FromStr` 实现可以看到 teacher-jumps 的完整取值空间: | provider 字符串 | 解析结果 | |---|---| | `teacher-jumps` 或 `teacher_jumps` | `TeacherJumps(默认后端)` | | `teacher-jumps:<backend>` | 指定后端的批处理(batched)路线 | | `teacher-jumps-non-batching:<backend>`(含下划线别名) | 非批处理路线 | 后端(`TeacherBackend`)取值与对应模型名: | 别名 | 枚举 | 实际模型名 | |---|---|---| | `sonnet45`、`sonnet`、`claude`(默认) | `Sonnet45` | `claude-sonnet-4-5` | | `sonnet46` | `Sonnet46` | `claude-sonnet-4-6` | | `gpt52` | `Gpt52` | `gpt-5.2` | | `gpt54`、`gpt`、`openai` | `Gpt54` | `gpt-5.4` | | `gpt55` | `Gpt55` | `gpt-5.5` | 典型用法(`Display` 实现确认了 `predict --provider=...` 的书写形式): ``` ep predict --provider=teacher-jumps:sonnet46 ep predict --provider=teacher_jumps:gpt52 ``` 与 teacher-jumps 相关的可调参数: - `--related-files-budget`:`format-prompt` 时相关片段的 token 预算,默认 8192(`TeacherJumpsPrompt::DEFAULT_RELATED_FILES_BUDGET`,[main.rs](https://link.gitcode.com/i/e4ca06001a1fda91af9ba3493877040a#L345-L348));调大意味着模型能"看见"更多文件、支持更远的 jumps,但也会推高截断风险与成本; - `--repetitions`:同一示例重复预测次数(非批处理路线会以不同 seed 采样); - `--cache-only`:只消费已缓存响应,不排队新请求; - `--wait`:批处理 provider 等待全部批次完成后退出。 数据侧还有一个版本门槛:`pull_examples` 要求捕获数据来自 Zed **0.224.1** 及以上版本(`MIN_CAPTURE_VERSION`,[main.rs](https://link.gitcode.com/i/e4ca06001a1fda91af9ba3493877040a#L662-L669)),因为该版本才引入了"编辑历史中携带预测编辑、区分开源仓库"的请求 schema。仓库内 [evals 目录](https://link.gitcode.com/i/ca5554400d4fbe7fd70ab178845f9212) 下的 `.md` 评测用例(如 `flask--add-import-statement.md`、`flask--rename-accepted-prediction.md`、`zed--add-eprintln.md` 等)覆盖了与模板示例同类的典型场景,可作为观察该协议实际表现的材料。 ## 八、小结 `teacher_jumps.md` 是 Zed 编辑预测数据管线中 teacher-jumps 路线的提示词模板,其设计可以归纳为三点: 1. **内容哈希标记**(`<|marker_b1f8|>`)替代顺序编号,使全部上下文(当前文件 + 所有 related excerpts)可被统一寻址,且抗预算截断——这是"跨文件、长距离"编辑预测得以成立的基础设施,实现在 [hashed_regions.rs](https://link.gitcode.com/i/4cba5f0733c5841a2a96a4b2c1016b37); 2. **意图保护规则**:以"预测若让代码回到编辑前就输出 `NO_EDITS`"为自检基准,严格保护用户的删除/重写,仅对被接受的预测产物放行修正——这让模型敢做重命名传播、import 补全这类多位置重构; 3. **可解析的输出协议**:标记对 span + 不重叠 + 作用于原始快照 + `NO_EDITS` 哨兵 + 至多一次 `<|user_cursor|>`,配合 [parse 与批量容错逻辑](https://link.gitcode.com/i/db3c2ffd86121ad57f8a9c3c17339342),把自由文本响应稳定地还原成训练管线可消费的补丁。 如果你要复现或调试这条管线,从 [TeacherJumpsPrompt](https://link.gitcode.com/i/74770d825931dfc24590382170683cb0#L360-L402) 与其测试模块入手,再对照 [hashed_regions.rs](https://link.gitcode.com/i/4cba5f0733c5841a2a96a4b2c1016b37) 的标记表构建与补丁组装,即可完整走通"示例 → 提示词 → 响应 → 补丁"的闭环。

【免费下载链接】zedCode at the speed of thought – Zed is a high-performance, multiplayer code editor from the creators of Atom and Tree-sitter.项目地址: https://gitcode.com/GitHub_Trending/ze/zed

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

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

从单体到微服务再到事件驱动:架构演进实战路径与避坑指南

做了十来年架构&#xff0c;从最开始一个人维护一套SSH单体应用&#xff0c;到后来带团队把系统拆成几十个微服务&#xff0c;再到近两年开始把核心链路逐步迁到事件驱动架构&#xff0c;这条演进路线其实踩了非常多的坑。很多时候网上讲架构演进都是拿现成的结论讲&#xff0c…

作者头像 李华
网站建设 2026/9/7 17:27:05

2026年AI写小说软件推荐:存稿管理与断更应对榜(5款)

断更是网文作者的噩梦&#xff1a;要么是灵感枯竭写不出来&#xff0c;要么是现实事务打断节奏&#xff0c;要么是稿子写到一半丢了。AI写小说软件在应对断更上能做三件事&#xff1a;帮作者积累存稿、在断更后快速恢复状态、在稿件安全上兜底。本文依据各产品官方公开资料&…

作者头像 李华
网站建设 2026/9/7 17:26:05

单片机毕设项目:基于 STM32 单片机的温室阈值配置与自动报警系统设计 基于 STM32 单片机的按键可控农业环境智能监控装置设计(010507)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机&#xff0c;Java、小程序技术领域和毕业项目实战 ✌️…

作者头像 李华