首页
/ Zed 编辑预测评测样本解读:用 zed--add-eprintln 评测剖析 Zeta 预测模型的"保守预测"与光标定位能力

Zed 编辑预测评测样本解读:用 zed--add-eprintln 评测剖析 Zeta 预测模型的"保守预测"与光标定位能力

2026-09-04 18:15:38作者:咎竹峻Karen

本文以仓库中的编辑预测(Edit Prediction)评测样本 zed--add-eprintln.md 为核心,逐段拆解该评测文件的 front matter、编辑历史、光标位置与期望补丁四个部分,并结合 ExampleSpec 的 Markdown 解析器游标标记定义 等源码,说明 Zed 是如何构造、解析和验证一条"预测下一步编辑"评测数据的。读完本文,你可以理解 Zed 编辑预测评测集的文件格式规范、[CURSOR_POSITION] 标记的解析机制,以及 ep 命令行工具如何加载并执行这类评测。

评测样本在 Zed 编辑预测体系中的位置

Zed 内置了"编辑预测"(代码续写)功能,其模型与评测数据由独立的 crate 支撑:edit_prediction 负责预测存储与数据收集,edit_prediction_ui 负责预测展示 UI,而 edit_prediction_cli 则提供了一个名为 ep 的命令行工具(见 Cargo.toml 中 [[bin]] name = "ep"),用于对编辑预测数据集做读取、加载、上下文检索、提示词生成、预测、打分与评估。

crates/edit_prediction_cli/evals/ 目录下存放的 Markdown 文件就是一组手工精选的评测样本,本文的主角 zed--add-eprintln.md 就是其中之一。与目录中其他样本(如 tree-sitter--tuple-to-struct-definition.mdvscode--add-async-and-await.md)一样,它固定了被测仓库(Zed 自身)、固定了 git revision(b7090c9fae7390a82021b994994c0f587744d96c),从而保证评测结果可复现。

该样本开头的一句话说明它考察的能力:

This example shows the model's preference for making conservative predictions, and ability to place the cursor within the predicted output.

即:用户只敲了三个字母 epr,一个"保守"(conservative)的模型应当只预测出唯一确定的最短补全 eprintln!("");,而不会凭空编造要打印什么内容;同时模型还需要能把光标放在预测输出内部(引号内、分号前)的正确位置。

评测文件结构逐段解析

下面把 zed--add-eprintln.md 的完整内容逐段展开,并对照解析器源码说明每一段的语义。

1. Front matter:锁定仓库与版本

+++
repository_url = "git@github.com:zed-industries/zed"
revision = "b7090c9fae7390a82021b994994c0f587744d96c"
+++

评测文件以 +++ 包裹的 TOML front matter 开头,声明被测仓库地址与精确 revision。源码中 ExampleSpec::from_markdown 会先剥离该段,用 toml::from_str::<FrontMatter> 解析出 repository_urlrevision、可选的 tags 以及 uncommitted_diff_requires_edit_history_rollback 标志。后续 ep load-project 阶段会依据这些信息创建 git worktree,把被测仓库检出到指定 revision,从而还原当时的文件内容。

ep 命令行也依赖 repository_url 的形式:Example::repo_name 能同时解析 git@github.com:owner/repohttps://github.com/owner/repo 两种写法,并把 worktree 组织到 WORKTREES_DIR/owner/repo 路径下。

2. Edit History:用户最近一次的编辑

--- a/crates/edit_prediction_ui/src/rate_prediction_modal.rs
+++ b/crates/edit_prediction_ui/src/rate_prediction_modal.rs
@@ -144,7 +144,7 @@
     fn select_next_edit(&mut self, _: &NextEdit, _: &mut Window, cx: &mut Context<Self>) {
+        epr
         let next_index = self
             .ep_store
             .read(cx)

"Edit History" 段给出触发预测前的编辑历史(unified diff 形式)。本例中用户刚刚在 select_next_edit 函数体内插入了一行 epr——这显然是一个 Rust 宏名的输入前缀。

解析器对该段的处理见 from_markdown 中的 Section::EditHistory 分支:代码块内容被原样拼入 edit_history 字段;若两个 diff 块之间出现 // User accepted prediction: 这样的注释行,解析器会将其标记到历史中(表示这一笔编辑本身是用户对先前预测的接受,供模型学习"预测被接受后用户如何继续编辑"的模式)。

值得一提的是,rate_prediction_modal.rs 正是当前仓库中存在的文件 rate_prediction_modal.rs。评测钉住的 revision 中该方法调用的是 shown_predictions(),而当前版本(L159-L166)已演进为 rateable_predictions()——这恰好说明为什么评测文件必须固定 revision,而不能直接引用"最新代码"。

3. Cursor Position:光标位置与 [CURSOR_POSITION] 标记

    fn select_next_edit(&mut self, _: &NextEdit, _: &mut Window, cx: &mut Context<Self>) {
        epr
        // ^[CURSOR_POSITION]
        let next_index = self
            .ep_store
            .read(cx)
            .shown_predictions()
            .skip(self.selected_index)
            .enumerate()
            .skip(1) // Skip straight to the next item

"Cursor Position" 段的 fenced code block 的 info string 是光标所在文件的路径,块内容是光标附近的代码摘录,光标本身用一行注释标记。

标记语法有严格的定义,见 ExampleSpec::cursor_excerpt 的文档注释

  • 标记行必须位于光标行的下一行,且包含 [CURSOR_POSITION] 字样;
  • 行内必须有一个 ^<
    • ^:光标列就是 ^ 字符所在的列(指向上一行光标);
    • <:光标列是该行第一个非空白字符的列(用于光标位于行首、^ 会被注释前缀挤偏的情况)。

本例中 // ^[CURSOR_POSITION]^ 位于第 8 列,正好对准上一行 epr 末尾之后,即光标停在 epr 之后、尚未补全的位置。

解析实现上,cursor_excerpt() 会先查找内联标记 <|user_cursor|>,否则定位 [CURSOR_POSITION] 标记行,从 ^/< 计算出列号,最后剥掉标记行,返回"干净摘录 + 摘录内光标字节偏移"二元组(L436-L472)。这两个常量在 zeta_prompt/src/udiff.rs 中定义:

pub const CURSOR_POSITION_MARKER: &str = "[CURSOR_POSITION]";
pub const INLINE_CURSOR_MARKER: &str = "<|user_cursor|>";

该 crate 内的单元测试(test_cursor_excerpt_with_caret)覆盖了 ^ 标记在行中间、行首 < 标记、行尾、文件末尾无换行等多种边界,与评测文件中手写的标记必须完全一致。

4. Expected Patch:期望的预测输出(含补丁内光标)

--- a/crates/edit_prediction_ui/src/rate_prediction_modal.rs
+++ b/crates/edit_prediction_ui/src/rate_prediction_modal.rs
@@ -144,14 +144,14 @@
     fn select_next_edit(&mut self, _: &NextEdit, _: &mut Window, cx: &mut Context<Self>) {
-        epr
+        eprintln!("");
#                   ^[CURSOR_POSITION]
         let next_index = self
             .ep_store
             .read(cx)
             .shown_predictions()
             .skip(self.selected_index)
             .enumerate()
             .skip(1) // Skip straight to the next item

"Expected Patch" 段是标准答案:模型应当输出一行替换,把 epr 补全为 eprintln!("");,并把光标放到空字符串引号内(^ 对准第一个引号后、第二个引号前)。这体现了两点:

  1. 保守性:不猜测要打印的内容,只补全到语法上自洽的最短形式 eprintln!("");
  2. 光标落在预测文本内部:续写完成后光标停在字符串内,用户可以直接键入要打印的内容——这正是文档开头所说 "ability to place the cursor within the predicted output"。

这里的光光标编码方式与 Cursor Position 段不同:在补丁里,光标被编码为新增行(+ 行)内的内联标记。序列化格式中该标记是 <|user_cursor|>,插入到期望补丁的新增行内;expected_patches_with_cursor_positions 会调用 extract_cursor_from_patch 将补丁还原为 (clean_patch, cursor_offset),其中 cursor_offset相对补丁 hunk 起始处、在新文本坐标系中的字节偏移。反向的 encode_cursor_in_patch 则保证幂等(见测试 test_encode_cursor_in_patch_is_idempotent)。

注意评测文件里期望补丁下方也使用了注释风格的 # ... ^[CURSOR_POSITION] 行——这是给人看的可视化表示;机器可读的光标位置最终以内联 <|user_cursor|> 标记形式存在于补丁文本中,打分时以 expected_patches_with_cursor_positions() 的解码结果为准。

5. 评分环节

ep eval / ep score 会对比"模型实际补丁"与"期望补丁",打分逻辑位于 edit_prediction_metrics crate(epCargo.toml 依赖其 tree-sitter feature),并回填到 Example 结构的 score 字段;对光标位置,则使用 ActualCursor 记录模型预测落地后的 path/row/column/offset,与期望光标偏移做对齐比较。其中 ActualCursor::from_editable_region 还专门做了防御性钳位——异常光标偏移只会被收敛到合法字符边界,而不会 panic 中断整批昂贵的评测运行。

如何加载与运行这条评测

ep 的输入接受 .md.json.jsonl 三种格式,.md 文件走 read_example_files 中的 "md" 分支,调用 parse_markdown_example 解析为 Example;若文件内未指定 name,则以**文件名(去扩展名)**作为样本名——因此该评测样本在输出中被记录为 zed--add-eprintln

典型用法(在仓库根目录执行,属于只读查看与运行评测,不修改仓库内容):

# 读取评测样本,输出规范化 JSONL
cargo run -p edit_prediction_cli -- read crates/edit_prediction_cli/evals/zed--add-eprintln.md -o /tmp/ep-example.jsonl

# 为该样本创建 git worktree 并加载文件内容(需要能访问被测仓库)
cargo run -p edit_prediction_cli -- load-project crates/edit_prediction_cli/evals/zed--add-eprintln.md -o /tmp/ep-example.jsonl

# 生成提示词 / 运行预测 / 打分(provider 可选 mercury、zeta1、zeta2:<format>、teacher:<backend> 等)
cargo run -p edit_prediction_cli -- format-prompt --provider=zeta2 /tmp/ep-example.jsonl -o /tmp/ep-prompt.jsonl
cargo run -p edit_prediction_cli -- predict /tmp/ep-prompt.jsonl -o /tmp/ep-predict.jsonl
cargo run -p edit_prediction_cli -- score /tmp/ep-predict.jsonl -o /tmp/ep-score.jsonl

# 一键评估(预测 + 聚合分数)
cargo run -p edit_prediction_cli -- eval crates/edit_prediction_cli/evals/zed--add-eprintln.md

全局参数(EpArgs)包括:--max-parallelism(默认 10)、--limit--offset--name/--repo(按名称/仓库过滤)、--max-duplicates(基于 MinHash 近似 Jaccard 相似度的光标位置去重)、--in-place--failfast--failed(失败样本在输出中保留或跳过)以及 --markdown(把结果写成每样本一个 .md 文件,格式即本文拆解的这套 Markdown 规范——这正是 to_markdown 的逆过程)。provider 字符串的解析规则与可选后端见 PredictionProvider::from_str

小结

zed--add-eprintln.md 虽只有 50 余行,却是理解 Zed 编辑预测评测体系的理想入口:

  • 格式规范+++ TOML front matter(仓库 + revision)→ Edit History diff → Cursor Position(fenced 块 info string 为光标文件路径)→ Expected Patch(可多个),每一段都对应 ExampleSpec 中的一个字段;
  • 光标双编码:代码摘录用 [CURSOR_POSITION] 标记行 + ^/< 列指示符,补丁内用 <|user_cursor|> 内联标记,两套编码在 zeta_prompt/src/udiff.rs 中统一定义;
  • 能力考察点:模型对不完整前缀(epr)应给出保守且唯一确定的补全(eprintln!("");),并把光标精确放置到预测文本内部的语义位置;
  • 可复现性:评测钉死 git revision,ep load-project 据此建 worktree 还原上下文,ep predict/score/eval 构成完整的预测—验证闭环。

如果你在扩展评测集,新增样本时只要遵循同样的四段式结构、保证标记行列对齐规则(可用 cargo test -p edit_prediction example_spec 中的光标摘录测试作为行为参照),ep 工具链即可无缝加载并参与后续预测与打分。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
504
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384