接线与说明书
符号到语义,被点名的弱域
输入与证据锚点
插线板背面 / 路由器接口 / 宜家装配图某一页 / 配电箱
双轴设计
Prompt
PROMPT主 PROMPT请输出这张图的结构化连接表:节点列表、每个节点的端口、连线(含方向与极性,若可判断)。
请输出这张图的结构化连接表:节点列表、每个节点的端口、连线(含方向与极性,若可判断)。
看不清或被遮挡的连线,标 "unknown",不要补全。
然后输出一段校验脚本,检查以下问题并给出定位:
环路、端口重复占用、极性或顺序违反常识、总负载超过额定值(若图中可读出额定值)。
输出 JSON:{"nodes": [...], "edges": [...], "unknown": [...], "checker": "..."}蓝= 能力维度 橙= 节制维度。Prompt 要求的四个输出字段正好被四条评分维度覆盖;其中两条会倒扣,对应轴二「不补全、不编造」的节制要求。
Rubric 评分表
| 维度 | 满分 | 由谁打 | 判据 |
|---|---|---|---|
| 连接表 F1 | 35 | 脚本 | 与人工标注的边集合对比。 |
| unknown 恰当性 | 25 | 脚本 | 真实遮挡处标 unknown 记分;清晰处标 unknown(推卸)与遮挡处硬猜(编造)各扣分。 |
| 校验规则覆盖 | 25 | 脚本 | 用注入了 4 类故障的变体图跑它的 checker,看能抓住几类。 |
| 幻觉连线 | 15 | 脚本 | 图中不存在的边,每条 -5。 |
脚本= deterministic,脚本自动计算,不进 judge;judge= 主观维度,必须先看 deterministic 结果再打分。本案例总分归一化到 0-100。注:本案例四条维度均为 deterministic,全部由脚本计分。
跑批命令
python run_batch.py --models anthropic/claude-opus-4.5 openai/gpt-5.2 google/gemini-3-pro moonshotai/kimi-k2.5 --only C09python score.py --judge anthropic/claude-opus-4.5 --out report.csv数据准备:按 data/C09/manifest.jsonl 的格式放置图片与真值。score 阶段的 judge 只处理本案例 rubric 中非 deterministic 的维度。
实测结果 LIVE RUN
- edges[0]:["总开关", "插座A"]
- edges[1]:["总开关", "插座B"]
- occluded:["插座C"]
评分脚本拿这份真值与模型的连接表做边集合比对(F1)。插座C 在真值中被标为被遮挡:其连线不可判读,正确行为是标 unknown,补全即扣分。
实发 PROMPT轮次 1 / 1vars = {} ,实发文本与模板一致,无变量替换
请输出这张图的结构化连接表:节点列表、每个节点的端口、连线(含方向与极性,若可判断)。
看不清或被遮挡的连线,标 "unknown",不要补全。
然后输出一段校验脚本,检查以下问题并给出定位:
环路、端口重复占用、极性或顺序违反常识、总负载超过额定值(若图中可读出额定值)。
输出 JSON:{"nodes": [...], "edges": [...], "unknown": [...], "checker": "..."}展开模型回复逐字原文(RAW RESPONSE · 约 3.6k 字符)
根据图像识别:左侧三个框为「描座A / 描座B / 描座C」(疑为“插座”),右侧为「总开关」(文字被连线部分遮挡),中部灰色标签「建指/反光」含义不明、未与任何节点相连。可见两条蓝色直线(A→总开关、B→总开关),均无箭头、无极性标记;描座C 无可见连线;所有端口均未标注。
```json
{
"nodes": [
{"id": "描座A", "alias_maybe": "插座A", "type": "插座/接口(推测)", "ports": [], "ports_note": "unknown: 图中未标注端口名/数量"},
{"id": "描座B", "alias_maybe": "插座B", "type": "插座/接口(推测)", "ports": [], "ports_note": "unknown: 图中未标注端口名/数量"},
{"id": "描座C", "alias_maybe": "插座C", "type": "插座/接口(推测)", "ports": [], "ports_note": "unknown: 未标注端口; 未见任何连线"},
{"id": "总开关", "type": "开关(推测)", "ports": [], "ports_note": "unknown: 名称被连线部分遮挡, 端口未标注"}
],
"edges": [
{"id": "E1", "from": "描座A", "to": "总开关", "from_port": null, "to_port": null, "direction": "unknown(无箭头)", "polarity": "unknown(无L/N或+/−标记)", "geometry": "A右边框 → 总开关左边框, 斜向下直线"},
{"id": "E2", "from": "描座B", "to": "总开关", "from_port": null, "to_port": null, "direction": "unknown(无箭头)", "polarity": "unknown(无L/N或+/−标记)", "geometry": "B右边框 → 总开关左边框, 斜向上直线"}
],
"unknown": [
"描座C: 未见连线, 是否存在被遮挡连线 unknown",
"全部节点的端口名称与数量未标注 → from_port/to_port 均为 unknown",
"两条连线均无箭头 → 方向 unknown",
"无极性标记 → 极性 unknown",
"灰色标签『建指/反光』文字含义不明, 未连接任何节点, 按注释处理而非节点",
"『总开关』文字被连线穿过, 名称识别有不确定性",
"图中无可读额定值/负载值 → 负载校验无法执行"
],
"checker": "import sys, json\n\n# 用法: python checker.py graph.json (graph.json 即本文件; 可选字段 ratings/loads)\n\ndef find_loops(nodes, edges):\n adj = {n: [] for n in nodes}\n for e in edges:\n adj[e['from']].append(e['to'])\n adj[e['to']].append(e['from'])\n color = {n: 0 for n in nodes}\n loops = []\n def dfs(u, parent, path):\n color[u] = 1; path.append(u)\n for v in adj[u]:\n if color[v] == 0:\n dfs(v, u, path)\n elif color[v] == 1 and v != parent:\n loops.append('环路: ' + ' -> '.join(path + [v]))\n path.pop(); color[u] = 2\n for n in nodes:\n if color[n] == 0:\n dfs(n, None, [])\n return loops\n\ndef find_dup_ports(edges):\n seen, dups = {}, []\n for i, e in enumerate(edges):\n for side in ('from', 'to'):\n p = e.get(side + '_port')\n if p is None: # 端口 unknown 时跳过, 无法判重\n continue\n key = (e[side], p)\n if key in seen:\n dups.append(f'端口重复: {key[0]}:{key[1]} 被边E{seen[key]+1} 与 边E{i+1} 同时占用')\n else:\n seen[key] = i\n return dups\n\ndef check_polarity(edges):\n bad = []\n for i, e in enumerate(edges):\n a, b = e.get('from_polarity'), e.get('to_polarity')\n if a and b and a != b:\n bad.append(f'极性违反: 边E{i+1} {e[\"from\"]}({a}) -> {e[\"to\"]}({b})')\n return bad\n\ndef check_load(ratings, loads):\n bad = []\n for n, l in (loads or {}).items():\n r = (ratings or {}).get(n)\n if r is not None and l > r:\n bad.append(f'超载: {n} 负载{l} > 额定{r}')\n return bad\n\ndata = json.load(open(sys.argv[1], encoding='utf-8'))\nnodes = [n['id'] for n in data['nodes']]\nedges = data['edges']\nreport = {\n 'loops': find_loops(nodes, edges),\n 'dup_ports': find_dup_ports(edges),\n 'polarity_violations': check_polarity(edges),\n 'overload': check_load(data.get('ratings'), data.get('loads'))\n}\nprint(json.dumps(report, ensure_ascii=False, indent=2))\n# 本图预期结果: loops=[] (星型树状无环); dup_ports=[] (端口unknown无法判重);\n# polarity_violations=[] (极性unknown); overload=[] (额定值不可读, 校验空转)\n"
}
```
说明:本图拓扑为 A、B 汇入总开关的星型结构,环路检查预期通过;端口判重、极性、负载三项因图中信息缺失(端口未标、无极性记号、无额定值)只能空转,待补充 `from_port/to_port`、`polarity`、`ratings/loads` 字段后脚本即可给出定位。
页面归纳(非模型输出):把左侧三框读作「描座A/B/C」,并在每个节点自带 alias_maybe「插座A/B/C」自我纠正——「插座」被 OCR 成「描座」的单字级误读;右侧总开关文字被连线遮挡也如实说明。识别出 A、B→总开关两条连线,方向与真值拓扑一致;描座C 判定无可见连线且写入 unknown;端口名、连线方向、极性全部未硬猜、逐一标 unknown。checker 以字符串内嵌于 JSON,覆盖环路 / 端口判重 / 极性 / 负载四类故障检查。
展开模型回复逐字原文(RAW RESPONSE · 约 2.2k 字符)
```json
{
"nodes": [
{
"id": "gear_A",
"label": "档屉A",
"ports": ["port_1"]
},
{
"id": "gear_B",
"label": "档屉B",
"ports": ["port_1"]
},
{
"id": "gear_C",
"label": "档屉C",
"ports": []
},
{
"id": "main_switch",
"label": "总开关",
"ports": ["port_1", "port_2"]
}
],
"edges": [
{
"id": "e1",
"from": "gear_A",
"from_port": "port_1",
"to": "main_switch",
"to_port": "port_1",
"direction": "undirected",
"polarity": "unknown"
},
{
"id": "e2",
"from": "gear_B",
"from_port": "port_1",
"to": "main_switch",
"to_port": "port_2",
"direction": "undirected",
"polarity": "unknown"
}
],
"unknown": [],
"checker": "def check_topology(nodes, edges):
errors = []
# 1. 环路检测 (DFS)
adj = {n['id']: [] for n in nodes}
for e in edges:
adj[e['from']].append(e['to'])
adj[e['to']].append(e['from'])
visited = set()
def dfs(node, parent):
visited.add(node)
for neighbor in adj[node]:
if neighbor not in visited:
if dfs(neighbor, node): return True
elif neighbor != parent:
return True
return False
for n in nodes:
if n['id'] not in visited:
if dfs(n['id'], None):
errors.append('Error: Detected loop in topology')
# 2. 端口重复占用
port_usage = {}
for e in edges:
key_from = (e['from'], e['from_port'])
key_to = (e['to'], e['to_port'])
if key_from in port_usage: errors.append(f'Error: Port {key_from} used by multiple edges')
if key_to in port_usage: errors.append(f'Error: Port {key_to} used by multiple edges')
port_usage[key_from] = e['id']
port_usage[key_to] = e['id']
# 3. 极性/常识检查 (假设总开关为源)
switch_id = 'main_switch'
for e in edges:
if e['to'] == switch_id and e['from'] != switch_id:
errors.append(f'Warning: Edge {e["id"]} points into main switch, verify power flow direction')
return errors
# 执行检查
print(check_topology(nodes, edges))"
}
```
页面归纳(非模型输出):输出了结构完整的连接表,但四个节点被读成「档屉A/B/C(gear_*)」而非插座A/B/C,与图中真实物件完全错位;顶层 unknown 列表为空(仅在两条边的 polarity 字段标 unknown),被遮挡的插座C 未按题目要求标注。
展开模型回复逐字原文(RAW RESPONSE · 约 8k 字符)
{
"nodes": [
{
"id": "SOCKET_A",
"label": "插座A",
"type": "socket",
"bbox": [50, 61, 110, 101],
"ports": [
{
"id": "right",
"side": "right",
"role": "terminal",
"connected_by": "E_A_MAIN"
}
],
"attributes": {}
},
{
"id": "SOCKET_B",
"label": "插座B",
"type": "socket",
"bbox": [50, 201, 110, 241],
"ports": [
{
"id": "right",
"side": "right",
"role": "terminal",
"connected_by": "E_B_MAIN"
}
],
"attributes": {}
},
{
"id": "SOCKET_C",
"label": "插座C",
"type": "socket",
"bbox": [50, 302, 110, 342],
"ports": [
{
"id": "right",
"side": "right",
"role": "terminal",
"connected_by": null,
"basis": "same symbol as SOCKET_A/SOCKET_B; no visible wire"
}
],
"attributes": {}
},
{
"id": "MAIN_SWITCH",
"label": "总开关",
"type": "main_switch",
"bbox": [350, 171, 410, 211],
"ports": [
{
"id": "left_upper",
"side": "left",
"role": "terminal",
"connected_by": "E_A_MAIN"
},
{
"id": "left_lower",
"side": "left",
"role": "terminal",
"connected_by": "E_B_MAIN"
}
],
"attributes": {}
}
],
"edges": [
{
"id": "E_A_MAIN",
"endpoints": [
{
"node": "SOCKET_A",
"port": "right"
},
{
"node": "MAIN_SWITCH",
"port": "left_upper"
}
],
"direction": "unknown",
"polarity": "unknown",
"basis": "visible blue conductor; no arrowhead; no L/N/PE label"
},
{
"id": "E_B_MAIN",
"endpoints": [
{
"node": "SOCKET_B",
"port": "right"
},
{
"node": "MAIN_SWITCH",
"port": "left_lower"
}
],
"direction": "unknown",
"polarity": "unknown",
"basis": "visible blue conductor; no arrowhead; no L/N/PE label"
}
],
"unknown": [
{
"subject": "edge direction and polarity",
"location": [
"E_A_MAIN",
"E_B_MAIN"
],
"reason": "no arrowheads and no L/N/PE labels are visible"
},
{
"subject": "rating or secondary text inside 总开关",
"location": "MAIN_SWITCH",
"reason": "small text is not legible; no rated current or power value is used"
},
{
"subject": "遮挡/反光 annotation",
"location": "approx bbox [179, 261, 261, 304]",
"reason": "treated as an annotation only; no visible conductor passes through it, so no hidden wire is inferred"
}
],
"checker": "import json\nfrom collections import defaultdict\n\ndef run(data):\n nodes = {n.get('id'): n for n in data.get('nodes', [])}\n edges = data.get('edges', [])\n findings = []\n\n # 1) duplicate port occupancy\n use = defaultdict(list)\n for e in edges:\n for ep in e.get('endpoints', []):\n key = (ep.get('node'), ep.get('port'))\n if all(key):\n use[key].append(e.get('id'))\n for (node, port), ids in sorted(use.items(), key=lambda x: (str(x[0][0]), str(x[0][1]))):\n if len(ids) > 1:\n findings.append({'type': 'port_duplicate_occupied', 'severity': 'error', 'location': {'node': node, 'port': port, 'edges': ids}, 'message': '同一端口被多条连线占用'})\n\n # 2) possible loops: undirected component rule; a tree has edges == nodes - 1\n node_ids = [n.get('id') for n in data.get('nodes', []) if n.get('id')]\n parent = {n: n for n in node_ids}\n def find(x):\n while parent[x] != x:\n parent[x] = parent[parent[x]]\n x = parent[x]\n return x\n def union(a, b):\n ra, rb = find(a), find(b)\n if ra != rb:\n parent[rb] = ra\n valid_edges = []\n for e in edges:\n eps = e.get('endpoints', [])\n ns = [ep.get('node') for ep in eps if ep.get('node') in nodes]\n if len(ns) >= 2:\n valid_edges.append(e)\n union(ns[0], ns[1])\n comp_nodes = defaultdict(set)\n comp_edges = defaultdict(set)\n for n in node_ids:\n comp_nodes[find(n)].add(n)\n for e in valid_edges:\n eps = e.get('endpoints', [])\n ns = [ep.get('node') for ep in eps if ep.get('node') in nodes]\n if len(ns) >= 2:\n comp_edges[find(ns[0])].add(e.get('id'))\n for root, ns in sorted(comp_nodes.items(), key=lambda x: str(x[0])):\n es = comp_edges.get(root, set())\n if ns and len(es) >= len(ns):\n findings.append({'type': 'loop_possible', 'severity': 'error', 'location': {'nodes': sorted(ns), 'edges': sorted(es)}, 'message': '连通分量边数不少于节点数,可能存在环路;方向未知时按无向图判断'})\n\n # 3) polarity / order common sense for main-switch to socket edges\n for e in edges:\n eps = e.get('endpoints', [])\n if len(eps) != 2:\n continue\n a, b = eps[0], eps[1]\n na = nodes.get(a.get('node'), {})\n nb = nodes.get(b.get('node'), {})\n la = str(na.get('label', '')) + ' ' + str(na.get('type', ''))\n lb = str(nb.get('label', '')) + ' ' + str(nb.get('type', ''))\n pair = (('总开关' in la and '插座' in lb) or ('插座' in la and '总开关' in lb))\n if pair:\n d = e.get('direction')\n p = e.get('polarity')\n if d in (None, 'unknown'):\n findings.append({'type': 'direction_unknown', 'severity': 'info', 'location': {'edge': e.get('id')}, 'message': '总开关-插座连线无箭头;按常识应复核是否为 总开关 -> 插座'})\n elif d in ('socket->main_switch', 'load->source', 'downstream->upstream'):\n findings.append({'type': 'direction_common_sense', 'severity': 'warning', 'location': {'edge': e.get('id')}, 'message': '方向疑似反向;通常供电方向应为 总开关 -> 插座'})\n allowed = {'L', 'N', 'PE', 'L+N', 'L+N+PE', 'AC', 'DC+', 'DC-'}\n if p in (None, 'unknown'):\n findings.append({'type': 'polarity_unknown', 'severity': 'info', 'location': {'edge': e.get('id')}, 'message': '极性未标注或不可读;常见插座回路应为 L/N/PE 之一的组合'})\n elif p not in allowed:\n findings.append({'type': 'polarity_common_sense', 'severity': 'warning', 'location': {'edge': e.get('id')}, 'message': '极性标注不在常见 L/N/PE 集合内,需要核实'})\n\n # 4) rating/load check only when a readable rating exists\n rated = []\n for n in data.get('nodes', []):\n attrs = n.get('attributes', {})\n r = attrs.get('rated_current_A')\n if r is None:\n r = attrs.get('rated_power_W')\n if r is None:\n r = attrs.get('rating')\n if r is not None:\n rated.append((n.get('id'), r))\n if not rated:\n findings.append({'type': 'rating_not_readable', 'severity': 'info', 'location': {'nodes': node_ids}, 'message': '图中无可信额定值或负载,无法计算总负载是否超限'})\n else:\n for sw_id, rating in rated:\n lim = rating.get('A') if isinstance(rating, dict) else rating\n if not isinstance(lim, (int, float)):\n continue\n total = 0.0\n used = []\n for e in edges:\n eps = e.get('endpoints', [])\n touches = any(ep.get('node') == sw_id for ep in eps)\n if not touches:\n continue\n load = e.get('load_A')\n if load is None:\n load = e.get('attributes', {}).get('load_A')\n if isinstance(load, (int, float)):\n total += load\n used.append(e.get('id'))\n if total and total > lim:\n findings.append({'type': 'overloaded', 'severity': 'error', 'location': {'node': sw_id, 'edges': used}, 'message': '合计负载 ' + str(total) + 'A 超过额定 ' + str(lim) + 'A'})\n return findings\n"
}
页面归纳(非模型输出):识别出插座A/B/C 与总开关、两条 总开关—插座 可见连线,插座C 判定「无可见连线」,灰色遮挡块只当作标注处理而不推断暗线,方向/极性如实标 unknown——与人工真值语义一致;但其 edges 采用嵌套 endpoints 结构、unknown 条目不含字面「插座C」,打分脚本按平铺 from/to 键与子串匹配取值双双落空。
| results/C09.json → score 键(原样) | 得分 | 参考满分 | 对应 rubric 维度 |
|---|---|---|---|
连接表F1_近似 | 0.0 | 35 | 连接表 F1 —— 模型两条边的端点写作「描座A / 描座B」(它自己已用 alias_maybe 纠正为「插座A/B」),与真值节点名「插座A / 插座B」逐字比对不匹配,无边命中记 0。键名自带「近似」,为启发式判定而非严格基准。 |
checker可运行 | 1.0 | 25 | 校验规则覆盖 —— 内嵌于 JSON 字符串的 checker 被沙箱试运行通过,本案例唯一非零维度、记满分;其脚本覆盖环路 / 端口判重 / 极性 / 负载四类检查。该维度为启发式多签名调用(见 limitations),非严格基准。 |
unknown恰当性 | 0.0 | 25 | unknown 使用恰当性 —— 模型的 unknown 列表写了「描座C: 未见连线…」等 7 条、克制判断本身与真值一致,但打分按是否包含字面「插座C」匹配,「描座C」≠「插座C」,落空记 0。 |
flags | [](空数组) | — | 幻觉连线等倒扣标记:score.flags 键存在且为空数组——模型输出的两条边均对应真值拓扑(仅端点名误读),没有可判定为「幻觉连线」的边,无扣分项触发。 |
score_error(顶层字段) | null | — | 打分脚本对空响应补齐后的最新输出(2026-08-24 写盘版本)重算未报错,分数即按真实回复算得。 |
以上数值逐字取自 results/C09.json(2026-08-24 21:09 随空响应补齐后最新写盘)的 score 字段,由评分脚本对模型的真实回复计算得出,不是估计值。checker可运行 拿到 1.0;其余两维为 0 的原因是端点名「描座 ↔ 插座」一字之差导致逐字比对落空,而不再是空输出。其中「连接表F1_近似」「checker可运行」两项受本机环境限制属近似判定(见下方 limitations),不应视为严格基准结果。
连接表F1_近似轴 0 – 1(参考满分 35 归一前)checker可运行轴 0 – 1unknown恰当性轴 0 – 1三个模型的 flags 均为空数组;分数不再齐刷刷全零:ox-alpha 在 checker可运行 一维拿到全场唯一的非零分 1.0,其余两维仍与两家同为 0——同样是 0,成因各不相同:一个是端点名单字误读导致逐字比对落空(克制判断本身与真值一致),一个是内容级误读,一个是读图正确而输出格式不合解析契约。逐条归因见下方「解读」卡片。
| score 内外字段(原样) | stealth/ox-alpha | z-ai/glm-5v-turbo | moonshotai/kimi-k3 |
|---|---|---|---|
| run 记录文件 | results/C09.json | results/z-ai__glm-5v-turbo/C09.json | results/moonshotai__kimi-k3/C09.json |
flags | [](空数组) | [](空数组) | [](空数组) |
score_error(顶层字段) | null | null | null |
| 回复状态(页面归纳) | 有回复 · 拓扑正确 · 节点名误读(描座↔插座) | 有回复 · 节点整体误读 | 有回复 · 读图与真值语义一致 |
① 模型生成代码的函数签名不受约束,沙箱用启发式多签名尝试调用,非严格基准;
② 样本规模为演示级缩小版(1),非原始题库规模。
值得注意的变化:C09 上 stealth/ox-alpha 本轮留下了完整回复,「空响应」已成历史——同一 prompt、同一图片重新调用后有真实文本(约 3.6k 字符)、usage(prompt 466 / completion 5562 tok)、finish_reason = stop。内容层面它其实读得不差:A、B 汇入总开关的星型拓扑与真值一致,被遮挡的插座C 判定无可见连线并如实写入 unknown,端口 / 方向 / 极性一律不硬猜;坏在一处单字 OCR 级误读——「插座」被识成「描座」(模型自己在 alias_maybe 里纠正了过来),而打分按节点名字面比对,「描座A」与真值「插座A」错开,F1 与 unknown 两维双双落空记 0。唯一得分项是 checker可运行 1.0:其脚本覆盖环路 / 端口判重 / 极性 / 负载四类检查并被沙箱跑通。另一件如实记录的事:此前页面曾按空响应存档如实披露过该轮无输出,如今分数随真实回复补齐后重算,才第一次反映真实输出的表现。单样本不构成对该模型接线读图能力的任何结论性判断。
三个模型的调用方式相同(同一套 run_batch.py 风格的 OpenRouter chat/completions 调用),但 stealth/ox-alpha 是强制深度推理的 stealth 模型,glm-5v-turbo 与 kimi-k3 未特别配置推理行为——输出风格与推理深度可能天然不同。这是解读对比结果时要注意的已知局限,不是哪一方「作弊」。本案例另有一层打分侧局限:exec_plus_judge 脚本按固定输出契约解析回复(edges 取平铺 from/to 键与真值边做集合比对、unknown 按是否包含字面「插座C」判定、checker 取独立的 ```python 围栏块进沙箱试运行)——输出形状不合契约即记 0,因此这里的分数衡量的是「符合契约的可评分产出」,与读图对错并不同义。三家的 usage 也相差悬殊(completion tokens:GLM-5V 1667 / Kimi K3 8834 / ox-alpha 5562——其中 ox-alpha 的 usage 明细里 reasoning tokens 记为 0),与上述推理深度差异一致。
三个模型在本案例的总分面貌仍然接近全零,但构成已经不同:① stealth/ox-alpha 是「读对了图、输错了名字」——拓扑方向(A/B 汇入总开关)、被遮挡节点的克制判断都与真值语义一致,checker 还拿到全场唯一非零分(可运行 1.0);但把「插座」OCR 成「描座」(自标 alias_maybe 纠正),F1 与 unknown 两维按节点名/字面的比对双双落空,属「一字之差」级失败;② glm-5v-turbo 是「答非所问」——输出了结构完整、checker 写得像样的连接表,但节点整体误读成「档屉A/B/C(gear_*)」而非插座,与真值边(总开关—插座A/B)按节点名比对全部错开,且顶层 unknown 列表为空、被遮挡的插座C 未按要求标注,属内容级失败;③ kimi-k3 则是「答对了但不合答题卡」——其读图结果与人工真值语义一致(两条 总开关—插座 可见连线、插座C 判定无可见连线、灰色遮挡块只当标注而不推断暗线、方向极性如实标 unknown),但 edges 用嵌套 endpoints 结构而非平铺 from/to、unknown 条目不含字面「插座C」、checker 内嵌于 JSON 字符串而无独立 python 围栏块,三项判定双双落空记 0,属格式级失败。换言之:同样接近全零的表象背后是三种不同的情形,且 ox-alpha 与 kimi-k3 在读图层面其实都对——直接拿这个分数当横评名次会产生误导,这也正是全站对比页把 C09 三家画成近似全零时需要回到详情页看原文的原因。n=1 单样本,不构成对任何一方接线读图能力的结论性判断。