Qwen Validation Debugger 合成数据 E2E 合约
编写日期:2026年 7月 15日
文档目的
Qwen Validation Debugger 是在运营用 Retriever 和验证器完成之前,用合成数据测试整体流程的工具。
针对一个测试主题,生成 Godot 3 代码和 Godot 4 代码,并为这些代码生成匹配的 JSONL 和不匹配的 JSONL。随后将相同的 JSONL 代入各版本代码,检查最终判定是否正确为 是 或 否。
未更改已有的响应模式和判定类型。
- 语法范围:
common、separate - JSONL 表格:
docs_chunks、api_mapping、label_prototypes - 槽位:
positive、negative - 最终判定:
是、否
未创建第三方判定值、分数、额外原因字段。
整体流程
TEST_ITEM
-> common / separate 分类
-> 保存分类结果
-> 生成目标版本代码
-> 实际检查 Godot 引擎解析器
-> Qwen 是/否 代码检查
-> 仅使用通过的代码生成 JSONL
-> 检查现有 JSON Schema
-> 检查当前代码与直接证据
-> JSONL 与代码交叉验证separate 项首先生成 Godot 3 代码。Godot 4 代码则将该 Godot 3 代码作为 REFERENCE_GODOT3_CODE,生成保持相同功能和执行流程的对应代码。
分类与代码生成输入分离
分类响应保持原有的五个字段。
{
"syntax_scope": "common 또는 separate",
"label": "짧은 한국어 라벨",
"reason": "분류 근거",
"godot3_focus": "Godot 3 코드 생성 포인트",
"godot4_focus": "Godot 4 코드 생성 포인트"
}reason、godot3_focus、godot4_focus会保留在屏幕显示和记录中,但不会传递给代码生成提示。这是为了即使分类阶段解释了错误的版本语法,也不让该句子成为后续代码生成的事实依据。
代码生成仅使用以下输入。
- 测试项目
common或separate- 生成目标版本
separate生成 Godot 4 时先前通过的 Godot 3 代码- 重试时最近一次被拒绝的代码和实际检查诊断
合成代码合同
生成的代码必须是引擎能够解析的单个 GDScript 文件,而不是看起来像代码片段的字符串。
- 第一行必须是
extends声明。 - 使用实际拥有测试 API 的类。
- 普通函数不要嵌套在其他函数内部。
- 使用测试项目的实际运行 API。
- 不要用
pass、注释或本地call来模拟目标行为。 - 不要在注释或代码中混入针对其他版本的专用语法。
- Godot 4 代码必须保持先前通过的 Godot 3 代码的功能、输入、目标和结果。
对于像 RPC 这样版本间语法明显不同的项目,会在提示中提供官方语法合同。这不是对生成结果的词语进行事后替换的逻辑。生成的源字符串不做任何修改,直接交给引擎解析器。
实际 Godot 引擎检查
仅凭 Qwen 自己重新评判其代码,就曾让错误的语法通过。实际测试中,Godot 3 代码中出现了 Godot 4 的 @rpc,但 Qwen 检查器仍回答 “是”。
现在会在代码生成后立即运行实际引擎进行检查。
Godot 3: --no-window --check-only --script
Godot 4: --headless --check-only --script
common: Godot 3和 Godot 4 双方检查执行文件可以指定为 GODOT3_BIN、GODOT4_BIN。本地默认安装版放在仓库外的用户数据目录中。要检查的代码仅以临时文件形式创建,检查后删除。在诊断日志中会移除临时路径和用户主目录路径。
代码生成和检查最多执行三次。失败时更换 seed 以避免重复相同的响应,并将上一次的代码和实际引擎诊断放入下一次的生成提示中。
保持 JSONL 架构
顶层字段与现有的三个表定义相同。
docs_chunks
chunk_id, doc_version, source_url, source_file, source_sha256,
doc_type, symbol, section_path, heading, content, code_blocks,
language_tags, godot_version_tags, api_symbols, token_count, metadataapi_mapping
mapping_id, source_api, target_api, change_type, godot_from,
godot_to, confidence, evidence_chunk_ids, match_terms, notes,
negative_patternslabel_prototypes
prototype_id, label, task_type, input_pattern, expected_finding,
recommended_action, evidence_mapping_ids, evidence_chunk_ids,
severity, validator_rulesvalidator_rules也只使用现有的四个字段。
{
"required_when_seen_in_code": [],
"before_code": "",
"after_code": "",
"reject_when_seen_in_code": []
}收到响应后,使用现有的 JSON Schema 检查必填字段、类型、enum、是否有额外字段。如果模型将 confidence 写成数字或将 section_path 写成字符串,则拒绝,并最多重新生成三次。
正向和负向生成
positive JSONL 是使用当前合成代码的直接证据。
docs_chunks:直接说明代码的目的、对象、输入流程、结果。api_mapping:Godot 3 的source_api与 Godot 4 的target_api必须各自出现在实际代码中。label_prototypes:before 依据必须在 Godot 3 代码中,after 依据必须在 Godot 4 代码中。- positive 的
negative_patterns和reject_when_seen_in_code为空数组。
negative JSONL 生成时不提供当前代码和当前条目。动态地将当前条目之后的示例条目选为 NEGATIVE_TEST_ITEM,仅使用该其他条目生成 JSONL。生成后服务器会将其与当前代码直接比较,若 source/before 证据重叠则拒绝。
此过程不对特定 API 名称或句子进行一对一替换,只使用样本顺序选择和实际生成结果的字符串比较。
验证顺序
验证按以下顺序处理。
- 若结果已通过版本槽结构确定,则不调用模型,直接判定为 “否”。
- 若迁移前的直接依据在当前代码中完全不存在,则判定为 “否”。
- 仅在上述两种情况均未确定时,Qwen 才比较意义和使用方式。
确定性门不会创建新状态。返回值仍为 “是” 或 “否”。
| JSONL | 验证对象 | 期望响应 |
|---|---|---|
同版本 docs_chunks positive |
生成基准代码 | 是 |
不同版本 docs_chunks positive |
跨版本代码 | 否 |
docs_chunks negative |
任意代码 | 否 |
3 -> 4 migration positive |
Godot 3 代码 | 是 |
3 -> 4 migration positive |
Godot 4 代码 | 否 |
3 -> 4 migration negative |
任意代码 | 否 |
API 请求可靠性
- 禁用 thinking 输出。
- 分类、代码、JSONL 仅请求包含已有字段的 JSON Schema 响应。
- 最终判定仅允许使用 grammar 返回 “是” 或 “否”。
- 代码和 JSONL 重新生成时更换 seed。
- 对 HTTP 429、502、503、504、连接中止、请求超时最多重试三次。
API key 仅在浏览器内存的当前输入值中包含于请求,不记录在存储库、文档、日志或提交中。
2026 年 7 月 15 日测试结果
单元合约测试通过了 27 项。
在实际的 Godot 引擎检查中发现:
- Godot 3 的
remote func代码通过了 Godot 3 解析器。 - 在 Godot 3 代码中加入
@rpc会因 “Unexpected '@'” 被拒绝。 - Godot 4 的
@rpc代码通过了 Godot 4 解析器。
实际 RunPod Qwen 测试的进展如下:
- 初始整体 E2E:5/12 通过。发现了错误的 Godot 3 合成代码以及宽泛的相关性判定。
- 引擎检查和生成合约应用后整体 E2E:10/12 通过。
- 动态 negative 条目和直接字符串门应用后 migration negative:4/4 通过。
- 剩余 2 项是模型忽视了在 Godot 4 上无法再次应用 migration positive 的槽合约。该条件已移至确定性版本门,单元测试通过。
- 开始最终整体复测时,RunPod 服务对
/v1/models与生成请求返回 HTTP 502,导致中止。这不是代码或 JSONL 被拒,而是远程服务无响应。
远程服务恢复响应后,需要从头重新执行这 12 项 E2E。