ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Zed 编辑预测评测体系剖析:tuple-to-struct-literal 评测样例与 Edit Prediction 数据格式

Zed 编辑预测评测体系剖析:tuple-to-struct-literal 评测样例与 Edit Prediction 数据格式 Zed 编辑预测评测体系剖析tuple-to-struct-literal 评测样例与 Edit Prediction 数据格式【免费下载链接】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/zedZed 的编辑预测Zeta/edit prediction功能依赖一套评测样例体系来持续验证模型在真实代码重构场景下的表现。本文以仓库中的评测样例 tree-sitter--tuple-to-struct-literal.md 为主线完整解读这类样例的三段式结构编辑历史、光标位置、期望补丁、Rust 重构的具体技术细节以及该样例如何被edit_prediction_cli工具链读取、加载、预测与打分。读完后你可以独立看懂、编写并运行这类评测样例。评测样例在 Zed 工程中的位置该文件位于crates/edit_prediction_cli/evals/目录与多个同构样例并列存放例如tree-sitter--tuple-to-struct-definition.mdtree-sitter--tuple-to-struct-destructuring.mdtree-sitter--tuple-to-struct-for-loop.mdflask--add-test-function.md、vscode--add-async-and-await.md 等。文件名遵循仓库名--重构场景描述的命名约定双横线分隔与解析逻辑一致example.rs 中的read_example_files会按扩展名分发——.md走parse_markdown_example即ExampleSpec::from_markdown.json反序列化为单个Example.jsonl按行反序列化且当ExampleSpec的name为空时默认以文件名为样例名。驱动这些样例的工具是名为ep的命令行程序其子命令定义在 main.rsread读取样例、load-project为每个样例创建 git worktree 并加载文件、context检索上下文、format-prompt生成模型提示词、predict执行编辑预测、parse-output把模型输出解析为统一 diff、score/eval按实际补丁与期望补丁计算得分等。仓库还提供入口脚本 script/run-unit-evals其核心是GPUI_TEST_TIMEOUT1500 cargo nextest run --workspace --no-fail-fast \ --features unit-eval --no-capture -E test(::eval_)即通过unit-evalfeature 编译并以::eval_前缀筛选测试用例把评测样例跑成集成测试。样例文件的通用格式规范从 example_spec.rs 中定义的分节标题常量可以看出一个 Markdown 评测样例由以下可选分节构成标题匹配不区分大小写分节标题内容对应字段front matter ... 包裹的 TOMLrepository_url、revision等指定样例所基于的外部仓库及精确提交## Uncommitted Diff可选光标时刻的未提交改动uncommitted_diff## Edit History之前若干次编辑构成的 diff 序列edit_history## Cursor Position光标所在文件的摘录片段用标记注释标出光标列cursor_pathcursor_position## Expected Patch一个或多个期望的统一 diff多个即代表多个可接受答案expected_patches## Rejected Patch可选被拒绝的预测用于 DPO 训练rejected_patch解析实现from_markdownexample_spec.rs用 pulldown-cmark 遍历事件## Cursor Position代码块围栏后的 info string 就是文件路径如tree-sitter/crates/loader/src/loader.rs块内文本是光标摘录## Expected Patch下的每个diff代码块都追加为一个期望补丁缺少光标位置代码块会直接报错 Missing cursor position codeblock。光标列的标注格式由 example_spec.rs 的cursor_excerpt文档注释规定光标所在行的下一行写一条注释包含[CURSOR_POSITION]字符串注释中用一个箭头指明列号——^表示光标列就是^字符所在位置表示光标位于该行第一个非空白字符处。此外还支持行内标记|user_cursor|INLINE_CURSOR_MARKER直接嵌在代码中常见于期望补丁的 added 行里用来同时表达预测出的代码与预测后光标应落在何处。本样例详解从元组到结构体字面量的重构front matter锁定外部仓库与提交 repository_url gitgithub.com:tree-sitter/tree-sitter revision 24007727d42b4caceda3095ac685c463fae1ba1a 样例并不针对 Zed 自身代码而是引用 tree-sitter 仓库在指定 revision 处的状态。ep load-project阶段会按 example.rs 的repo_name/worktree_path逻辑解析出 owner/repo支持gitgithub.com:owner/repo.git与 http 两种 URL 形式并在 worktree 目录中 checkout 到该 revision从而让编辑历史与光标摘录中的代码路径可被真实解析。Edit History此前已完成的编辑编辑历史是喂给模型的核心上下文信号本样例记录了在tree-sitter/crates/loader/src/loader.rs中把匿名元组类型逐步重构为具名结构体LanguageEntry的过程--- a/tree-sitter/crates/loader/src/loader.rs b/tree-sitter/crates/loader/src/loader.rs -604,7 604,7 pub struct Loader { pub parser_lib_path: PathBuf, - languages_by_id: Vec(PathBuf, OnceCellLanguage, OptionVecPathBuf), languages_by_id: VecLanguageEntry, language_configurations: VecLanguageConfigurationstatic, language_configuration_ids_by_file_type: HashMapString, Vecusize, language_configuration_in_current_path: Optionusize, -619,6 619,12 #[cfg(feature wasm)] wasm_store: MutexOptiontree_sitter::WasmStore, } struct LanguageEntry { path: PathBuf, language: OnceCellLanguage, external_files: OptionVecPathBuf, } pub struct CompileConfiga { -767,7 773,7 pub fn get_all_language_configurations(self) - Vec(LanguageConfiguration, Path) { self.language_configurations .iter() - .map(|c| (c, self.languages_by_id[c.language_id].0.as_ref())) .map(|c| (c, self.languages_by_id[c.language_id].path.as_ref())) .collect() } -920,13 926,17 } fn language_for_id(self, id: usize) - LoaderResultLanguage { - let (path, language, externals) self.languages_by_id[id]; let LanguageEntry { path, language, external_files, } self.languages_by_id[id]; language .get_or_try_init(|| { let src_path path.join(src); self.load_language_at_path(CompileConfig::new( src_path, - externals.as_deref(), external_files.as_deref(), None, )) }) -1532,10 1542,9 // Determine if a previous language configuration in this package.json file // already uses the same language. let mut language_id None; - for (id, (path, _, _)) in - self.languages_by_id.iter().enumerate().skip(language_count) for (id, entry) in self.languages_by_id.iter().enumerate().skip(language_count) { - if language_path *path { if language_path entry.path { language_id Some(id); } } --- a/tree-sitter/crates/loader/src/loader.rs b/tree-sitter/crates/loader/src/loader.rs -1553,10 1553,10 let language_id if let Some(language_id) language_id { language_id } else { - self.languages_by_id.push(( - language_path, - OnceCell::new(), - grammar self.languages_by_id.push(LanguageEntry { path: language_path, language: OnceCell::new(), external_files: grammar .external_files .clone() .into_vec()这段历史覆盖了五处改动点字段类型替换、新结构体定义、按位置索引.0的访问改为命名字段访问、解构从元组模式改为结构体模式、循环中的元组迭代改为按entry字段访问最后一段则是把push((...))元组构造改写为push(LanguageEntry { ... })字面量——注意最后一个 diff 块在into_vec()处被截断说明用户此刻正写到一半。Cursor Position光标正在编辑的结构体字面量let language_id if let Some(language_id) language_id { language_id } else { self.languages_by_id.push(LanguageEntry { path: language_path, language: OnceCell::new(), external_files: grammar .external_files .clone() .into_vec() .map(|files| { files .into_iter() .map(|path| { let path parser_path.join(path); // prevent p being above/outside of parser_path if path.starts_with(parser_path) { Ok(path) } else { Err(LoaderError::ExternalFile( path.to_string_lossy().to_string(), parser_path.to_string_lossy().to_string(), )) } }) .collect::LoaderResultVec_() }) .transpose()?, // ^[CURSOR_POSITION] )); self.languages_by_id.len() - 1 };按前述格式规范解读围栏 info string 给出文件路径tree-sitter/crates/loader/src/loader.rs标记行// ^[CURSOR_POSITION]中的^指向上方//前第 12 列处即transpose()?,之后、));之前的位置——用户刚写完字段值的.transpose()?表达式正准备敲结构体字面量的收尾括号。Expected Patch一行括号修复--- a/tree-sitter/crates/loader/src/loader.rs b/tree-sitter/crates/loader/src/loader.rs -1578,7 1578,7 .collect::LoaderResultVec_() }) .transpose()?, - )); }); self.languages_by_id.len() - 1 };期望补丁只有一行把收尾的));改成});。这正是编辑历史所引出的陷阱——上一段历史编辑把self.languages_by_id.push((元组构造改成了self.languages_by_id.push(LanguageEntry {结构体字面量构造但用户尚未同步修改与之配对的右括号。模型必须从编辑历史中理解元组构造 → 结构体字面量构造这一语义转变而不是机械地补一个右圆括号。这个用例考察的正是编辑预测模型对跨 hunk 配对语法开括号与闭括号类型一致的敏感度也是tuple-to-struct系列用例definition / destructuring / field-access / for-loop / literal中字面量构造这一环。运行与扩展这个评测样例运行方式上ep的输入参数支持本地.md文件路径也支持-表示 stdin 的 JSONL以及captured-after:、rejected-after:等远端数据源标记说明见 main.rs 的INPUTS_HELP。一条典型的评测链路为# 1. 读取并规范化样例md - jsonl ep read crates/edit_prediction_cli/evals/tree-sitter--tuple-to-struct-literal.md -o out.jsonl # 2. 按 repository_url/revision 建立 git worktree 并载入光标文件 ep load-project out.jsonl # 3. 采集上下文默认 LSP 类型可用 --type 指定 ep context out.jsonl # 4. 生成提示词 - 预测 - 解析输出 - 打分 ep format-prompt out.jsonl ep predict out.jsonl --providerprovider ep parse-output out.jsonl ep score out.jsonl全局参数还包括--limit、--offset、--name、--repo按样例名或仓库过滤、--markdown把结果按每样例一个.md文件写回等见 main.rs。若要以集成测试形式跑全量评测则使用 script/run-unit-evals设置UNIT_EVAL_COMMIT可先固定到指定提交然后以--features unit-eval编译并用 nextest 过滤::eval_前缀的测试。若要为这条流水线新增用例按 example_spec.rs 的解析约束编写即可front matter 中repository_url与revision必填解析时FrontMatter要求这两个字段## Cursor Position代码块必须存在且围栏 info string 写文件路径## Expected Patch下可放多个diff块表示多个可接受答案若期望预测后光标移动可在 added 行内嵌|user_cursor|标记序列化时通过encode_cursor_in_patch编入补丁、extract_cursor_from_patch取出example_spec.rs。小结tuple-to-struct-literal 样例 是 Zed 编辑预测评测体系的一个缩影front matter 把样例锚定到外部仓库的精确 revisionEdit History 提供用户正在做什么重构的语义线索Cursor Position 用标准化的^[CURSOR_POSITION]/|user_cursor|标记精确描述编辑点Expected Patch 给出唯一的正确修复));改});。整套格式由edit_prediction的ExampleSpec定义、由edit_prediction_cli的ep工具链消费配合unit-evalfeature 的集成测试形成闭环。理解并遵循这一格式就能为编辑预测模型贡献可复现、可打分的回归用例。【免费下载链接】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),仅供参考
返回列表