)
Flow 代码现代化改造实战用 ReturnType 替换 $Call 工具类型modernize_016_call 评测全解析【免费下载链接】flowAdds static typing to JavaScript to improve developer productivity and code quality.项目地址: https://gitcode.com/gh_mirrors/flow30/flow本文以 Flow 仓库 AI 评测套件中的modernize_016_call任务为核心完整讲解一次代码现代化改造Modernize任务从任务描述、代码差异、评分机制到运行验证的全过程。你将掌握 Flow 中$Call工具类型与ReturnType的等价关系与迁移方法并理解这类改造任务是如何通过 AST 级评分器被自动判定为完成的。文中所有代码与配置均可在 evals/evals/05_code_generation/modernize_016_call 目录下直接查阅。一、任务概览一个最小化的现代化改造评测modernize_016_call位于05_code_generation代码生成评测类别下属于 Flow AI Evals 套件的一部分。它的任务描述文件 prompt.md 全文只有一句话Modernize the code inmain.js.这是一个典型的 SWE-bench 风格评测评测只描述要做什么把main.js中的代码现代化而不透露具体该用哪种 Flow 语法实现真正受测的能力点藏在输入输出文件的差异与评分器里。评测目录结构如下modernize_016_call/ ├── prompt.md # 任务描述模型看到的提示词 ├── config.json # 元数据与专属评分器 ├── input/ # 改造前的起始代码 │ └── main.js └── ideal/ # 参考解法只包含与 input 有差异的文件 └── main.js按照 evals/README.md 的约定input/是模型的起点ideal/是稀疏覆盖层compile_swebench.py会对二者做 diff 生成 gold patch黄金补丁dry-run 模式下用它验证整个评测体系是否自洽。二、改造前与改造后代码逐行解读改造前的input/main.jsinput/main.js 的完整内容如下/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * flow */ type CreateUser (name: string, age: number) { id: number, name: string, age: number, }; type User $CallCreateUser, string, number; export function userSummary(user: User): string { return user.name ( String(user.age) ); }这段代码定义了一个函数类型CreateUser它接收(name: string, age: number)返回一个包含id、name、age三个字段的对象类型。随后用$CallCreateUser, string, number在类型层面调用该函数类型得到其返回类型并赋给User。最后的userSummary函数消费User类型并拼接成字符串。改造后的ideal/main.jsideal/main.js 中唯一的变化在第 16 行type User ReturnTypeCreateUser;一次仅一行的等价替换将两个文件做 diff改造内容完全收敛在User的类型定义上-type User $CallCreateUser, string, number; type User ReturnTypeCreateUser;其余代码CreateUser类型、userSummary函数、flowpragma原封不动。这是现代化改造类评测的典型形态行为完全等价但类型表达方式从旧式工具类型切换为现代语法。三、为什么要从$Call迁移到ReturnType$Call的语义在类型层面调用函数类型$CallF, ...Args是 Flow 历史遗留的函数类型调用工具类型给定一个函数类型F和一组实参类型它返回F被这些实参调用后的返回类型。例如$CallCreateUser, string, number会实例化CreateUser的形参name: string、age: number得到返回的对象类型{ id: number, name: string, age: number }。ReturnType的语义直接取函数类型的返回类型ReturnTypeF是更现代、更直观的等价写法只要F是函数类型就直接取其返回类型。由于CreateUser的参数和调用实参在这里类型一致ReturnTypeCreateUser与$CallCreateUser, string, number的结果完全等价但写法更简洁——不必重复书写实参类型也降低了实参写错导致返回类型被意外特化的风险。评测本身的佐证从 config.json 的元数据标签可以印证这一迁移方向tags: [ flow, modernize, code_generation, removed, returntype, call ],removed标签表明$Call属于计划移除的旧式工具类型returntype与call则点明了本次改造的两个关键角色。也就是说这个评测要考察的是模型能否识别旧式工具类型 → 现代等价工具类型的迁移模式并做出最小化、无副作用的改动。四、评测如何自动判定改造成功AST 级评分器如果只看 prompt 的一句话无法判断改造是否完成。真正的判定逻辑在 config.json 的grading字段里它声明了两个ast_query类型的评分器grading: { graders: [ { type: ast_query, selector: .type \GenericTypeAnnotation\ and .id?.name \ReturnType\ }, { type: ast_query, selector: .type \GenericTypeAnnotation\ and .id?.name \$Call\, negate: true } ] }评分器的执行原理ast_query评分器的实现在 evals/graders/ast_query.sh。它的核心流程见第 13、37-40 行调用 Flow 自带的flow ast file命令把源码解析成 JSON 格式的完整 AST将配置中的 selector 包装进 jq 表达式jq [.. | objects | select(selector)] | length即递归遍历 AST 中的每一个对象节点统计满足条件的节点数量匹配数大于 0 则通过否则失败若带--negate则逻辑反转。对modernize_016_call而言正向断言GenericTypeAnnotation泛型类型注解节点中必须存在名为ReturnType的泛型引用确保模型确实使用了ReturnType语法负向断言AST 中不得出现名为$Call的泛型引用把只删掉$Call却没换成ReturnType之类的半吊子答案一并排除。两个断言同时通过才认定改造完成。这种断言 AST 形状的评分方式比文本正则匹配更稳健——它不在乎代码排版与注释差异只关心类型节点的真实结构能有效防止用字符串拼接等方式作弊。五、隐藏在幕后的基线评分器除了 config.json 里声明的两个 AST 评分器每个评测还会自动获得一组按类别分配的基线评分器。在 evals/compile_swebench.py 中定义了_BASELINE_GRADERS05_code_generation类别使用如下基线05_code_generation: [*_HYGIENE_GRADERS, _NO_EXTRA_STRICT, _NO_TSC],展开后包含评分器作用file_modified目标文件main.js必须被实际修改flow_check修改后的代码必须通过 Flow 类型检查零错误no_flowfixme不得使用$FlowFixMe等压制转义no_any不得引入any类型逃避类型检查no_commonjs不得回退到 CommonJS 语法no_extra_flow_errors阈值 0整个求解过程不允许出现多余 Flow 错误要求模型一次想清楚类型再动手no_tsc这是 Flow 任务调用tsc直接判负其中no_extra_flow_errors的注释compile_swebench.py特意区分了类别策略01_error_fixing允许 1 次初始报错因为要先复现 bug而代码生成类要求 0 次——模型应当一次通过。这些评分器与ast_query一起被generate_grading_script组合成一个 TAPTest Anything Protocol格式的评分脚本。六、如何运行与验证该评测环境准备按 evals/README.md 的说明无需从源码构建 Flow只需npm install该命令会安装flow-bin包提供预编译的flow二进制node_modules/.bin/flow评测默认使用它。如果你想用自己本地构建的 Flow 二进制验证行为可通过FLOW_BIN环境变量或--flow-bin参数指定。验证单个评测dry-run最快的方式是make validate等价于make dry-run它不调用任何模型而是直接应用参考解法gold patch并运行全部评分器确认评测本身自洽。只针对本评测make validate ARGS--eval modernize_016_call也可以通过类别或标签过滤make dry-run ARGS--category 05_code_generation make dry-run ARGS--tag returntype结果会写入build/swebench/results.json。如果打分脚本对改造后的ideal/main.js全部返回ok就证明替换后的代码能通过flow check、AST 中存在ReturnType且不存在$Call。跑真实模型如果你想用模型实际求解这个任务需配置 Anthropic API 的claudeCLImake run ARGS--model claude-sonnet-5 --eval modernize_016_call模型拿到prompt.md后会在临时工作目录中编辑文件随后由同一套评分器判定成败。七、从单个评测看整个 modernize 系列与 Flow AI Evals 体系modernize_016_call并不是孤例它隶属于一个完整的现代化改造评测家族。在 evals/evals/05_code_generation 目录下可以看到modernize_001_property_type到modernize_020_react_element共 20 个任务覆盖了$ElementType、$Keys、$Values、$ReadOnly、$NonMaybeType、$Diff、$Rest、$ObjMap、$TupleMap、$Call、$Checks、$Partial、$Exact等一系列旧式工具类型的现代化改造。这套评测体系的设计原则在 evals/README.md 中有明确说明值得借鉴prompt 只描述行为不透露被测的 Flow 语法——Modernize the code in main.js就是一个极致的例子分支应做真实工作计算、调用而非字面量查询参考解法必须真正使用被测特性——ideal/main.js必须真实使用ReturnType而非只是删掉$Call评分器要能拒绝错误解法又不能过度拟合唯一答案——ast_query的正反双向断言正是这一原则的体现优先真实场景而非教科书示例。小结通过modernize_016_call这个案例可以看到 Flow 仓库如何把一次看似简单的一行代码现代化改造封装成可自动评判的评测任务任务描述刻意保持极简真正的考点藏在input/与ideal/的差异中判定依赖flow ast输出的 AST 结构与 jq 递归选择器正向要求ReturnType出现、反向禁止$Call残留再叠加flow_check、no_any、no_extra_flow_errors等基线评分器从语法正确性与求解过程卫生两个维度把关。对于开发者而言理解这一流程既有助于掌握$Call→ReturnType的类型迁移写法也能举一反三地看懂 Flow AI Evals 中其他 19 个 modernize 任务乃至整套评测体系的运作方式。【免费下载链接】flowAdds static typing to JavaScript to improve developer productivity and code quality.项目地址: https://gitcode.com/gh_mirrors/flow30/flow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考