# focus hint 效果评测 — 设计与预注册

2026-08-04 · 小规模 pilot

本文在**看到任何结果之前**写完并提交。预测写在下面，跑完不改。
目的是让「hint 有效」这句话第一次有可证伪的形式。

> 同日修订一次：初稿描述的是一套另起炉灶的 n=36 题库，而实际要跑的是既有的
> 130 题评测框架。修订把条件、题库、指标全部对齐到真正会执行的那套代码，
> 并据此重写了分类预测。修订发生在五条件实验产出**第一行数据之前**——
> 当时实验处于停止状态。此后不再改预测。

## 要回答的问题

README 现在的主张是：hint 让描述「贴合当前任务」。这只是对机制的描述，
没有任何数字支持「所以答得更准」。本次要给出的是：

1. 端到端问答准确率，hint 组 vs 无 hint 组，差多少。
2. 这个差是不是来自 hint 本身，而不是来自我们 prompt 里其它部分。
3. 离「直接用多模态模型」还差多远。
4. **hint 组的描述是不是在替主模型作答**——README_CN 亮点里写了
   「视觉模型只负责看，不替你推理」，这条要么被验证，要么被推翻。

## 这套评测测的是哪一层

单图问答测的是**描述通道的保真度**，不是产品的端到端能力。真实用法是多轮的：
主模型看完首轮描述，发现不够，再用 `glance -q` / `ground --region` 回头追问。
这里没有追问的机会，所以本文的所有数字只回答一个问题——
**同一张图、同一个问题下，换 prompt 能让描述好多少**。

放在这一层是故意的：agent 循环里的随机性会淹没一句 prompt 的差异，
单变量归因只能在低噪音环境里做。代价是它测不到追问依从性、
测不到 `view_image` 场景下以 assistant 意图作 hint 的那条路径、也测不到任务成败。
这三项归任务级评测，另行设计，**本文结论不得外推到那一层**。

定位参照：VisualWebArena（ICLR 2024）的 baseline 里有一档 caption-augmented ——
纯文本 LLM 拿不到图，由一个现成 captioner 把页面图片转成文字，与本项目形态相同。
它报告 GPT-4 从 7.25%（纯文本）升到 12.75%（加描述），GPT-4V 原生为 15.05%，
即描述通道挽回了约七成的多模态差距。模型与年代都不同，**不能与本文数字同表比较**，
只用来说明「描述通道能挽回多少」这个问题本身是有先例、可量化的。

## 五个条件

prompt 一律从生产代码现取（`git show main:codex-vision-proxy.py`），不在评测里手抄副本——
上一版实验正是因为手抄，「生产条件」漏掉了 `_DESCRIBE_PROMPT` 整段而无人察觉。

| 条件 | 视觉侧 prompt | 代表什么 |
|---|---|---|
| `naive` | `DEFAULT_PROMPT`（"Please describe the contents of this image in detail."） | 普通转接方案 |
| `contract` | `_ROLE_PROMPT` + `_DESCRIBE_PROMPT`（无 hint） | 本项目的 prompt，但摘掉 hint |
| `hint` | `_ROLE_PROMPT` + hint + `_DESCRIBE_PROMPT` | **本项目实际行为** |
| `template` | 上一条再加已删除的场景模板（error/ui/chart） | 模板该不该加回来 |
| `native` | 视觉模型直接看图作答，无描述环节 | 多模态上限（Prism 式对照） |

`naive → contract` 分离出 prompt 契约的贡献；`contract → hint` 分离出 **hint 本身**的贡献。
只跑两条会把两者混在一起，得出的数字无法归因。

`template` 只在问题措辞触发场景关键词时才与 `hint` 不同——全 130 题里只有 19 题
（chart 10 + error 9，实测逐字比对得出）。其余 111 题两者字节相同，跑了只是花钱买必然打平，
因此 `template` 只在这 19 题上计分，且**不参与其它条件的配对集**。

五个条件共用同一 `max_tokens`。描述长度不设限也不设下限——
如果 hint 组靠更长的描述取胜，那是它的成本，要在结果里如实报出。

## 两级指标

- **端到端准确率（主指标，本轮实现）**：描述交给 `deepseek-v4-flash`（用户 Codex 里实际在用的
  纯文本模型），只给描述和问题，不给图，答案与标准答案比对。
- **关键事实覆盖率（机制指标，本轮不实现）**：每题预先写死一条「答对它必须包含的事实」，
  判定描述里有没有。准确率告诉我们有没有提升，覆盖率告诉我们提升从哪来。
  现有题库没有这个字段，补齐要逐题手写 130 条；先出主指标，覆盖率留到主指标显示有信号之后再补。

## 题目分类与预注册预测

题库不是为本文新写的，是既有的 130 题：100 道 CaptionQA（公开数据集，
`fetch_captionqa.py` seed=42 可确定性重取，四选一）+ 30 道合成题（标准答案来自
生成图片的 HTML 源码，开放式，带数值容差）。**标准答案不来自任何模型输出。**

CaptionQA 自带的 `category` 有 48 种、多数每类不足 3 题，太稀疏；分组按 `domain`：

| 数据集 / domain | n | 问的是 | 预测 |
|---|---|---|---|
| captionqa/document | 25 | 图表、表格、流程图里的具体标签与取值 | **hint 明显胜出** |
| captionqa/ecommerce | 25 | 品牌、包装、商品属性 | **hint 小幅胜出** |
| captionqa/natural | 25 | 物体有无、空间关系、幻觉检验 | **打平；幻觉类可能反而落后** |
| captionqa/embodiedai | 25 | 机器人视角的感知与可供性 | **打平** |
| synthetic/error,chart,ui | 30 | 报错原文、数据点、界面元素的精确值 | **hint 明显胜出，但大概率测不出来（见下）** |

两处故意留的反向/不利预测：

- **幻觉类可能落后。** hint 把问题里的名词送进视觉侧，弱视觉模型在指令压力下
  可能顺着把并不存在的东西写进描述。这是证据库里已经点名的唯一真实误导通道。
  如果 `natural` 域 hint 输给 `contract`，那不是噪音，是这条通道被证实。
- **合成题大概率已经饱和。** 旧数据（换答题模型前）三条件是 96.7% / 100% / 96.7%，
  没有区分度。若本轮仍然饱和，那么**`template` 的裁决同时失效**——因为
  `template` 与 `hint` 有差异的那 19 题**全部**落在合成集内。这一点必须在结果里明说，
  不能拿一个无区分度的子集去宣布「模板不必加回来」。

**一个哪里都赢的评测是设计失败，不是好消息。**

## 诚实性检查：描述是否在替主模型作答（本轮不实现）

hint 组的描述里带着问题本身，视觉模型有可能直接把答案写进描述，
主模型只是复述。这样端到端准确率会好看，但 README 那条
「视觉模型只负责看，不替你推理」就是错的（`_ROLE_PROMPT` 明确禁止代答）。

需要对每条描述额外判一次：**它是给出了推导所需的事实，还是直接给出了结论。**
本轮先不做——它要再跑一遍全部描述的判定，成本与主实验同量级。
但**只要 hint 组赢了，这一检查就必须在把数字写进 README 之前补上**，
否则无法排除「赢在代答」。

## 统计

n=130（配对集以实际跑完的题数为准），pilot 量级，只够看有没有信号，不够定精确效应量。

- 配对设计（同题同图跑各条件），用 **McNemar 精确检验**比较配对的对/错翻转。
- 效应量报 **bootstrap 95% CI**（10000 次重采样，固定随机种子，数字可复现）。
- 分 domain 的 n=25，**只看方向，不做单 domain 显著性**。

## 已知局限（写在前面，不等审稿人问）

- 一个视觉模型、一个主模型（均与线上一致，型号以结果文件里 stamp 的为准）。换模型结论可能变。
- 合成图的标准答案精确，但比真实截图简单，且旧数据显示已饱和。
- CaptionQA 的题不是我出的，避免了选题偏好，代价是它偏通用图像理解，
  与本项目的真实场景（代码、终端、界面截图）不完全重合。
- 判分先用字符串/数值匹配，失败才回退 LLM 判定，与视觉模型、主模型都不同家族；
  回退判定的行在结果文件里带 `judge_used` 标记，**报数前必须人工过目**。
- 本文只覆盖机制层。追问依从性、多轮 hint 来源、任务成败均不在此列。

## 产物

代码与数据在 worktree `~/cdv-eval`（分支 `eval-pipeline`），不在 main 上——
`template` 条件依赖 main 已删除的旧版模板代码，**把 main merge 进该分支会毁掉它的可复现性**。

- `eval/data/{captionqa,synthetic}/questions.json` — 题库与标准答案
- `eval/common.py` — 条件定义（prompt 全部从 main 现取）、缓存、判分
- `eval/run_eval.py` — 按题横跨条件跑，JSONL 断点续跑
- `eval/make_results_md.py` — 配对统计、McNemar、bootstrap CI → `eval/RESULTS.md`
- `research/2026-08-04-focus-hint-eval.md` — 结果（写在 main 上）
