Zed 编辑预测单元测试样例格式详解flask--add-import-statement 案例精读【免费下载链接】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本文以 flask--add-import-statement.md 这个真实评测样例为切入点逐段拆解 Zed 编辑预测Edit Prediction单元测试样例的完整结构——前置元数据、编辑历史、光标位置标注与多个候选期望补丁——并结合 example_spec.rs、example.rs 等源码说明这些 Markdown 字段如何被解析为ExampleSpec结构体、又如何参与预测与打分流程帮助读者读懂乃至独立编写合规的评测样例。1. 什么是编辑预测单元测试样例Zed 的编辑预测功能即行内代码续写依赖一套完整的评测基础设施给定用户在某个仓库的某个修订版本上、光标处于某处、之前刚做过一串编辑这一上下文让模型产出一个补丁patch与新的光标位置再与预先记录的期望补丁对比打分。crates/edit_prediction_cli/evals/目录存放的就是这一流程的单元测试样例目录中按仓库名--行为描述的命名规则组织了 19 个样例例如flask--add-import-statement、tree-sitter--if-let-to-match、vscode--add-async-and-await等。从源码看样例支持三种文件扩展名。example.rs 中的read_example_files函数按扩展名分发.json与.jsonl直接反序列化为Example后者每行一条而.md文件则走parse_markdown_example最终委托给ExampleSpec::from_markdown完成解析。本案例所属的.md格式正是人工撰写、代码评审和版本管理最友好的形态。2. 样例文件逐段精读下面完整列出 flask--add-import-statement.md 的全部内容然后分段解释。该样例取材于 Flask 仓库的src/flask/logging.py用户把一行合法的from werkzeug.local import LocalProxy误敲成了imfrom werkzeug.local import LocalProxy光标停在坏行行首期望模型把这行重写为正确的 import 语句。2.1 前置元数据锁定源仓库与修订版本 repository_url https://github.com/pallets/flask revision 2fec0b206c6e83ea813ab26597e15c96fab08be7 文件以分隔的 TOML 前置块开头。example_spec.rs 中对应的FrontMatter结构体定义了两个必填字段与两个可选字段字段必填说明repository_url是评测上下文所属的 git 仓库地址评测时会据此拉取 worktree 加载真实项目revision是精确的 commit 哈希保证上下文可复现tags否样例标签列表用于筛选uncommitted_diff_requires_edit_history_rollback否标记未提交 diff 是否包含需要回滚的编辑历史2.2 Edit History用户此前的编辑序列## Edit History diff --- a/src/flask/logging.py b/src/flask/logging.py -4,7 4,7 import sys import typing as t -from werkzeug.local import LocalProxy imfrom werkzeug.local import LocalProxy from .globals import request## Edit History 段落用一段或多段统一 diff 记录预测发生之前用户刚刚做过的编辑。这是编辑预测与静态补全的本质区别模型看到的不仅是文件内容还有用户行为的最近趋势。本样例中用户把正确的 import 行改成了 imfrom ... 这种残缺写法模型需要判断这是输入中的中间态并给出整行重写。 该段落还支持一个可选约定在某段 diff 之前单独写一行 // User accepted prediction:。同目录的 [flask--rename-accepted-prediction.md](https://link.gitcode.com/i/68d3abf83b140e35774155a1a9f9084b) 就用了它表示紧随其后的那段 diff 并非用户手打、而是用户接受了一条模型预测产生的编辑——这对训练与蒸馏是有价值的信号。解析逻辑在 [example_spec.rs](https://link.gitcode.com/i/c8731f66782f34f30026fc785d190fbd#L79) 中以常量 ACCEPTED_PREDICTION_MARKER 实现from_markdown 状态机识别到该标记后会在合并编辑历史时重新插入这行注释保证序列化/反序列化往返一致同文件测试 test_from_markdown_accepted_prediction_marker 验证了这一点。 ### 2.3 Cursor Position文件节选与光标标记 text ## Cursor Position src/flask/logging.py from __future__ import annotations import logging import sys import typing as t imfrom werkzeug.local import LocalProxy # ^[CURSOR_POSITION] from .globals import request if t.TYPE_CHECKING: # pragma: no cover from .sansio.app import App## Cursor Position 段落的代码围栏由两部分构成 1. **围栏 info string 是光标所在文件路径**本例为 src/flask/logging.py。解析器把围栏 info 直接存入 cursor_path见 [example_spec.rs](https://link.gitcode.com/i/c8731f66782f34f30026fc785d190fbd#L393-L396) 中 Section::CursorPosition 分支spec.cursor_path Path::new(block_info)。 2. **围栏内容是该文件的光标周边节选excerpt并内嵌一行光标标记**。标记行以语言注释形式写在光标行的下一行包含 [CURSOR_POSITION] 字符串和一个指向光标列的箭头。 箭头有两种语法定义在 [cursor_excerpt()](https://link.gitcode.com/i/c8731f66782f34f30026fc785d190fbd#L417-L473) 的文档注释与实现中 | 箭头 | 光标列语义 | | --- | --- | | ^ | 光标列 ^ 字符在标记行中的位置本例 # ^[CURSOR_POSITION] 中 ^ 位于第 0 列即 imfrom 行行首 | | | 光标列 光标行上第一个非空白字符的位置用于列位置小于注释前缀长度的场景 | 解析时cursor_excerpt() 会定位 [CURSOR_POSITION]常量 CURSOR_POSITION_MARKER定义于 [udiff.rs](https://link.gitcode.com/i/4c8837e9856d65da1788b34bbdfec3cc)算出标记行范围按 ^ 或 规则得出光标列把光标定位在**标记行的上一行**然后删除标记行、修剪尾部空行返回纯文本节选 节选内光标字节偏移。若文本中直接内嵌了 |user_cursor|常量 INLINE_CURSOR_MARKER则走更简单的内联分支删除标记、其位置即光标偏移。[example_spec.rs](https://link.gitcode.com/i/c8731f66782f34f30026fc785d190fbd#L520-L657) 的 test_cursor_excerpt_with_caret 测试覆盖了行首、行内、行尾、文件末尾等边界列位test_cursor_excerpt_with_inline_marker 则验证内联标记。 ### 2.4 Expected Patch多个可接受的期望补丁 diff ## Expected Patch diff --- a/src/flask/logging.py b/src/flask/logging.py -1,21 1,21 from __future__ import annotations import logging import sys import typing as t -imfrom werkzeug.local import LocalProxy import # ^[CURSOR_POSITION] from werkzeug.local import LocalProxy from .globals import request--- a/src/flask/logging.py b/src/flask/logging.py -1,21 1,21 from __future__ import annotations import logging import sys import typing as t - -imfrom werkzeug.local import LocalProxy import werkzeug # ^[CURSOR_POSITION] from werkzeug.local import LocalProxy from .globals import request本样例的 ## Expected Patch 段包含**两个** diff这是该格式的关键能力之一同一个 prompt 允许存在多个都被判为正确的期望输出。两个候选补丁都完成把 imfrom 坏行修成正确 import这一意图但终态与光标落点不同 - 候选一该行变为 import光标停在 import 之后第 6 列# ^[CURSOR_POSITION] 中 ^ 的位置 - 候选二该行变为 import werkzeug光标停在 werkzeug 之后第 15 列。 注意期望补丁里的光标标注复用了与 Cursor Position 段完全相同的标记注释行语法只是出现在 diff 的 新增行之后。ExampleSpec 中 expected_patches 的类型是 VecString[example_spec.rs](https://link.gitcode.com/i/c8731f66782f34f30026fc785d190fbd#L45)解析时每个独立的 diff 代码块都会 push 进这个向量。expected_patches_with_cursor_positions()[example_spec.rs](https://link.gitcode.com/i/c8731f66782f34f30026fc785d190fbd#L489-L502)则把每个补丁展开为 (补丁, Option光标偏移) 二元组文档注释明确光标偏移是应用补丁后的新文本中、相对于 hunk 起点的偏移。与之配对的 encode_cursor_in_patch / extract_cursor_from_patch 实现在 [zeta_prompt 的 udiff 模块](https://link.gitcode.com/i/8cf86432955fccb741be205f3fa44e30)负责含光标标注的补丁文本与干净补丁 光标偏移之间的双向转换同文件测试 test_expected_patches_with_cursor_positions 还验证了编码的幂等性。 ## 3. 源码级解析Markdown 如何变成 ExampleSpec ExampleSpec 结构体[example_spec.rs](https://link.gitcode.com/i/c8731f66782f34f30026fc785d190fbd#L25-L54)是样例的核心数据模型除本节已讲到的字段外还包括 - name样例名缺省时取文件名不含扩展名见 [example.rs](https://link.gitcode.com/i/2432e3998eb78e151c970bd15799da1c#L270-L276) 中 md 分支对 example.spec.name 的兜底填充 - reasoning / uncommitted_diff可选的推理说明与未提交 diff段落分别对应 ## Reasoning、## Uncommitted Diff 标题 - recently_opened_files / recently_viewed_files对应 ## Recently Opened Files、## Recently Viewed Files 段落每行一个路径可附 tab 分隔的光标偏移 - rejected_patch对应 ## Rejected Patch 段落供 DPO拒绝采样偏好训练使用——[example.rs](https://link.gitcode.com/i/2432e3998eb78e151c970bd15799da1c#L64-L73) 的 ExamplePrompt.rejected_output 字段注释即标明 For DPO。 全部合法的二级标题常量集中在 [example_spec.rs](https://link.gitcode.com/i/c8731f66782f34f30026fc785d190fbd#L71-L79)解析器 from_markdown[L258](https://link.gitcode.com/i/c8731f66782f34f30026fc785d190fbd#L258) 起用 pulldown_cmark 遍历 Markdown 事件流维护一个 Section 状态机Start / UncommittedDiff / RecentlyOpenedFiles / RecentlyViewedFiles / EditHistory / CursorPosition / ExpectedPatch / RejectedPatch / Other按当前标题把代码块内容归位到对应字段。约束方面 - 标题层级只允许 H1作为样例名与 H2作为段落出现 H5 及更深层级会直接报错缩进代码块非围栏也会报错 - **Cursor Position 是唯一硬性必填的段落**解析结束时若 cursor_path 或 cursor_position 为空anyhow::bail!(Missing cursor position codeblock)[example_spec.rs](https://link.gitcode.com/i/c8731f66782f34f30026fc785d190fbd#L410-L412) - Edit History 可以为空to_markdown 序列化空历史时会输出 (No edit history) 占位文本。 Example 结构[example.rs](https://link.gitcode.com/i/2432e3998eb78e151c970bd15799da1c#L21-L54)在 ExampleSpec 之上还挂载了运行期产物prompt_inputs光标节选、光标偏移、关联文件等 Zeta prompt 输入、prompt格式化后的 prompt 与期望输出、predictions模型实际预测、score与期望补丁的匹配分数以及 qa 结果。也就是说.md 样例只是输入规格跑完预测与打分后整个 Example 可序列化为 JSON 留档复现。 ## 4. 样例如何被消费从格式化到打分 评测流程由 edit_prediction_cliCLI 命令名 ep见 [main.rs](https://link.gitcode.com/i/7699f3e72c612f4de19562f23ce4eeb6)串联与本样例直接相关的环节有两个 **1格式化 prompt。** [format_prompt.rs](https://link.gitcode.com/i/65df2e2cc29f0e32f6b3db846ff844d8) 不存在——正确路径是 [crates/edit_prediction_cli/src/format_prompt.rs](https://link.gitcode.com/i/65df2e2cc29f0e32f6b3db846ff844d8)。其中 TeacherPrompt 把 ExampleSpec 渲染为教师模型提示词编辑历史最多保留最后 128 行MAX_HISTORY_LINES光标节选被 |editable_region_start| / |editable_region_end| 包围、光标位置注入 |user_cursor| 标记[format_prompt.rs](https://link.gitcode.com/i/65df2e2cc29f0e32f6b3db846ff844d8#L143-L152)关联文件上下文按 1024 token 预算截断。教师模型的响应再由 TeacherPrompt::parse 还原为统一 diff 与实际光标位置。 **2预测与打分。** [score.rs](https://link.gitcode.com/i/d51ca66bc0c97155ccea0ecd4c529feb) 的 run_scoring 先执行预测可复用 JSON 中已存的 predictions随后在后台任务中调用 expected_patches_with_cursor_positions() 取出所有期望补丁经 edit_prediction_metrics::prepare_expected_patches 归一化后逐条调用 score_prediction 比对。因此本样例中两个候选补丁的语义就是模型预测的补丁与光标位置只要与其中任意一个匹配即被视为正确。评测的上下文检索量默认受 EVAL_RELATED_CONTEXT_TOKENS_LIMIT 4000[score.rs](https://link.gitcode.com/i/c9bf31fa812bf0fae11ea1a14100e7e7)约束。 ## 5. 如何运行这些单元测试 仓库提供了现成的 CI 入口 [script/run-unit-evals](https://link.gitcode.com/i/73ea51ca0a59388ccd6bad4ddb4146a9)其核心就是一行 nextest 调用 bash GPUI_TEST_TIMEOUT1500 cargo nextest run --workspace --no-fail-fast \ --features unit-eval --no-capture -E test(::eval_)即开启unit-evalfeature、用::eval_过滤器只跑评测相关测试、不捕获输出以便观察进度并把测试超时放宽到 1500 秒。脚本还支持UNIT_EVAL_COMMIT环境变量先git fetch并切换到指定提交再跑用于对历史版本做回归评测。若要针对单个样例做更细粒度的分析可直接使用epCLI。main.rs 定义了全局参数--name按样例名过滤、--repo按仓库过滤、--limit/--offset控制处理数量、--max-parallelism默认 10、--output/-o指定输出、--markdown把输出写成每样例一个.md文件、--failfast遇错即停、--in-place原地更新样例文件把预测与分数写回。输入文件即本样例所在目录下的.md/.json/.jsonl路径。6. 编写合规样例的要点清单综合以上解析逻辑手写一个评测样例时需满足以包裹的 TOML 前置块开头repository_url与revision必填## Cursor Position必须存在围栏 info string 写光标文件路径围栏内是包含光标行的节选文本下一行用语言注释加^[CURSOR_POSITION]或行首列场景的[CURSOR_POSITION]标注光标列## Edit History用统一 diff 描述用户此前的编辑若其中某段来自被接受的预测前缀一行// User accepted prediction:## Expected Patch可写一个或多个 diff光标用同样的标记注释行标在新增行上多个 diff 表示多个可接受答案只使用 H1/H2 标题代码块一律用围栏形式文件名遵循仓库名--行为描述命名如flask--add-import-statement样例名缺省即取文件名。掌握这套格式后无论是要读懂 Zed 编辑预测评测如何复现真实编辑场景还是要为新场景补充单元测试样例、定位某次预测质量回退都可以直接以evals/目录中的这些 Markdown 文件为蓝本进行扩展。【免费下载链接】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),仅供参考