oh-my-pi snapcompact 实验 exp08:中央凹式两级读取协议与 ZOOM 放大回合提示词设计
【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi
导读
本文深入剖析 oh-my-pi 仓库中 snapcompact 的 SQuAD 召回实验 08(exp08_foveate,中央凹式两级读取):系统先把长文本以 5×8 像素字体压进 1568×1568 的位图"档案图",让视觉模型第一轮尽可能作答,再对读不清的区域按行带切片放大重渲染,进入第二轮精确作答。核心是 exp08-zoom.md 这份放大回合提示词——它定义了标签、行带、提取式回答、UNREADABLE 与编号输出这一整套协议。读完本文,你将掌握该两级协议的完整数据流、三种提示词变体(rows/phrase 定位)的差异、行带合并与放大的实现细节,以及如何复跑这套实验并解读其成本/精度指标。
背景:snapcompact 与"位图帧上下文压缩"
snapcompact 的核心理念是:与其让 LLM 去总结被丢弃的对话历史,不如把历史序列化成紧凑文本,再用像素字体渲染成密集 PNG 帧,让视觉模型直接"读回"这些位图。整个过程本地化、确定性执行,不消耗 LLM token 也不产生延迟(README 明确:Rasterization and PNG encoding happen in native code)。
在 research/ 目录下,这一理念被系统化评测:以 SQuAD v1.1 dev 全集(约 150 万字符,见 run.py)为语料,比较 text、compact、handoff、img-<字体>-<变体> 等条件的 QA 召回率。实验 08 就是其中一条重要的压缩路线:不再追求"一张图装进所有内容",而是主动接受第一轮读不清,用第二轮按需放大来补齐。
exp08 协议总览:一图两读,按行放大
exp08_foveate.py 的模块 docstring 给出了实验全貌:
- 第一轮(档案图):用 5×8 字体渲染档案图。在 1568×1568 画布上,
capacity计算得到 313 列 × 196 行 = 61348 字符/页,比此前 6×10 最优解(40716 字符/页,见 run.py)密 1.5 倍。模型先读这张"尽力而为"的图并回答问题。 - 放大请求:对读不清的区域,模型在答案中回复
ZOOM rows A-B这样的命令(或带锚点短语的变体)。 - 第二轮(放大回合):harness 从块文本中按行带切片——行 r 覆盖字符区间
[(r-1)*cols, r*cols)——用 8×13 舒适字体重新渲染为放大图,把放大图 + 待答问题继续发给模型。 - 合并评分:两轮答案合并,用官方 SQuAD EM/F1 与成本,对比
img-6x10-sent基线。
整体流程见run_cell_chunk(exp08_foveate.py):qa1存档回合 → 解析zoom请求 →merge_bands合并行带 →zoom_renders渲染放大图 →qa2放大回合 → 合并final答案。
exp08-zoom.md:放大回合的提示词逐条解读
exp08-zoom.md 全文六行,构成放大回合的全部指令,逐条拆解如下。
1. 内容定位与标签协议
Below are high-resolution re-renderings of the archive row bands you requested. Each image is preceded by a label giving the archive row range it covers; the text inside is identical to those rows, re-flowed to the new line width.
要点有二:
- 明确告知模型:图中的文字与档案图中对应行的文字完全一致,只是按新行宽重新排版(
re-flowed to the new line width)。这消除了"放大图是不是新内容"的歧义,也提示模型文本是连续重排的,不必按原行号对应回去。 - 标签协议:每张放大图前都有一行标签,说明该图覆盖的档案行范围。对应到代码里,是
z_content中的f"Zoom of archive rows {a}-{b}:"文本块(exp08_foveate.py)。标签是模型把放大内容与"我到底在问哪块"对齐的锚点。
2. 回答范围指令
Answer your remaining questions, listed after the images, using the zoomed images plus anything you already read. Keep the same question numbers as before.
这是多轮对话语义的关键:放大回合不重发所有问题,只重发待解决(pending)的问题(代码中pending列表,exp08_foveate.py),且必须保持原有编号。同时允许结合第一轮已读到的内容(plus anything you already read),因为放大图可能只覆盖了问题答案所在的一小条带,上下文仍需要第一轮的全局信息。
3. 提取式答案
Give short extractive answers: a word or phrase copied from the text.
与第一轮提示词一致(exp08-archive.md),要求答案是从原文中逐字抄录的词或短语,便于squad.parse_numbered提取后与 golden answer 做字符串级 EM/F1 匹配。
4. 兜底协议:UNREADABLE
If you still cannot read the answer, reply exactly UNREADABLE.
即使放大也读不出来,就精确回复UNREADABLE。代码在合并阶段用answers2[i] or "UNREADABLE"兜底(exp08_foveate.py),并在指标中统计abstained数量。这套"弃权"机制让模型宁可弃权也不猜,把"看不清"和"答错"分开计量。
5. 输出格式
Output a numbered list (original numbering), one answer per line, no commentary.
要求按原编号输出、每行一条、不加注释,正是为了配合 squad.py 中parse_numbered的正则解析:r"\s*(\d+)[.):]\s*(.*\S)?\s*$"逐行提取1. 答案形式的条目,未命中则留空。
三种协议变体:fov / fov2 / fov3 与 zoom 请求格式
exp08_foveate.py 中PROTO字典定义了三种提示词组合,其差异决定了模型如何表达"我要放大哪里":
| 变体 | 档案回合提示词 | 放大 padding | 定位方式 | 特征 |
|---|---|---|---|---|
fov | exp08-archive.md | 2 行 | 行号(rows) | 保守策略:只有太小/太糊才申请放大,紧凑 padding |
fov2 | exp08-archive-eager.md | 12 行 | 行号(rows) | 激进策略:不完全确定就申请放大,宽 padding |
fov3 | exp08-archive-phrase.md | 12 行 | 短语(phrase) | 激进策略 + 模型引用半读出的锚点词,harness 模糊定位后放大该行带 |
行号定位(rows)与解析
fov/fov2用行号。第一轮提示词要求:reply exactly ZOOM rows A-B(如ZOOM rows 41-47)。解析由三个正则完成(exp08_foveate.py):
_ZOOM_RANGE:ZOOM rows 41-47、41–47、41 to 47均命中,且自动把A>B的情况交换为有序区间;_ZOOM_SINGLE:ZOOM rows 41这样的单行请求,解析为(41, 41);_ZOOM_PHRASE:ZOOM "anchor words"形式的短语请求。
短语定位(phrase)与模糊匹配
fov3走锚点短语路线:提示词要求模型引用"在区域内或紧邻区域能部分辨认出的 3~8 个连续单词",harness用 locate_phrase 在块文本里模糊定位:
- 先把 chunk 与短语都归一化(只留字母数字、以空格连接),长度保持对齐;
- 先尝试精确子串匹配;
- 失败则滑窗打分——窗口大小
k = max(2*len(p), 8)个词,统计与短语词集的命中数; - 分数达到
max(2, (len(p)+1)//2)才接受,命中位置换算回行号:span[0] // cols + 1。
这套设计允许模型"读错几个字符"(提示词明说a few wrong characters are fine),把模糊的视觉感知容错地映射到精确的行带。
三种变体的完整字面量差异体现在提示词语气上:fov是"大部分能读,个别区域不行"的中性描述;fov2/fov3则警告this font is rendered BELOW the size you can read reliably... Be skeptical of your own reading,并强调Zooming is cheap and encouraged; guessing is penalized(exp08-archive-eager.md)。注意:所有第一轮提示词都禁止猜测——读不清要么ZOOM,要么UNREADABLE。
放大回合的工程实现:行带合并、切片与重渲染
行带合并与 padding
模型可能对多个问题分别请求放大,这些行带需要合并。merge_bands(exp08_foveate.py)做三件事:
- 每个 band 向外扩
pad行(fov 为 2 行,fov2/fov3 为 12 行),并 clamp 到[1, max_row]——因为模型给的行号是估计值,需要余量兜住; - 排序后合并重叠或相邻(间隔 ≤1 行)的 band,避免同一区域渲染两张图;
- 输出互不相交的有序区间列表。
按字符切片与分页
每个 band 在 chunk 文本中的字符区间是[(pa-1)*arch_cols : pb*arch_cols](exp08_foveate.py),随后zoom_renders判断:若 band 超过一张放大图能容纳的行数(由capacity(zcfg, ZOOM_SIZES[-1])[2] // arch_cols计算,exp08_foveate.py),自动拆成多页。
放大尺寸自适应
ZOOM_SIZES = (520, 784, 1040, 1568) # smallest square that fits the band winsexp08_foveate.py 用 4 档画布尺寸,按"能容纳这段文本的最小正方形"选取,避免小 band 也渲染大图造成浪费。渲染函数bdf.render(txt, zcfg, CACHE, size, "bw")复用 bdf.py 的位图渲染管线(黑白变体,8×13 字距)。
磁盘缓存与原子写
放大图以内容哈希命名:f"exp08-zoom-{ZOOM_FONT}-{size}-{sha8(txt)}.png"(exp08_foveate.py),命中直接复用;写文件走atomic_png——先写临时文件再 rename,避免并发任务读到半成品(exp08_foveate.py)。
双轮问答的完整数据流
以run_cell_chunk为主线,一次 chunk 的完整生命周期如下(exp08_foveate.py):
- 采样:
squad.sample_chunk_questions从完全落在 chunk 内的段落中均匀采样至多--qpc(默认 30)个问题,并记录pos_rel(段落起点在 chunk 中的相对位置 0~1),便于后续按位置四分位分析。 - 渲染档案图:
render(chunk_text, FONTS["5x8"], CACHE, args.size, variant),variant 为bw或sent(对应 conditionsfov-5x8-bw、fov-5x8-sent)。 - 第一轮 QA:消息 = 档案提示词(含
{cols}/{rows}格式化) + 档案图 + 编号问题块,经llm_complete调用(providers.py 按模型名自动分派 OpenAI / OpenRouter / Anthropic 三家)。结果按 payload 哈希缓存,截断(stop == "max_tokens")响应不缓存不重放(exp08_foveate.py)。 - 解析 zoom 请求:对每个答案检查是否含
zoom;fov3优先短语定位,失败则回退行号解析。请求了 zoom 但 band 无法解析的,该题直接置为UNREADABLE(宁可弃权也不猜)。 - 放大回合:
pending问题 + 放大图组装z_content(提示词 exp08-zoom.md + 逐图标签 + 编号问题块),作为第二轮 user 消息追加在qa1之后形成完整对话历史。 - 合并与评分:
answers2覆盖pending项,squad.parse_numbered解析,exact_match/f1按官方 SQuAD 归一化(去标点、去 a/an/the)逐题打分(squad.py),每条记录写入records.jsonl。
成本建模与基线对比
成本核算在aggregate与_phase_cost(exp08_foveate.py):
- token 分
in/out/cache_w/cache_r统计,其中缓存写按 1.25×、缓存读按 0.1× 输入单价折算(与 run.py 的 Anthropic 定价口径一致); - 放大回合(
qa2阶段)的增量成本单独统计为cost_zoom_usd,用于回答"按需放大到底贵不贵"; zoom_rate= 申请过放大的问题占比,zoom_chunks= 实际发生放大回合的 chunk 数。
基线定义在 exp08_foveate.py:img-6x10-sent最优配置的 (f1, se, cost$)。例如gpt-5.5长度 150 的基线是 f1=0.8218、$0.2452。汇总时每个 cell 输出d_f1、d_cost_usd,直接对比两级协议相对单图基线的精度差与成本差。
复跑实验:CLI 与参数速查
实验依赖 uv 与 pillow(# /// script头声明requires-python >= 3.10、dependencies = ["pillow"]),在packages/snapcompact/research/目录下运行:
uv run exp08_foveate.pymain暴露的关键参数(exp08_foveate.py):
| 参数 | 默认值 | 说明 |
|---|---|---|
--models | gpt-5.5,google/gemini-3.5-flash | 逗号分隔的模型列表;OpenAI 模型名以gpt-开头、OpenRouter 模型名含/(见 providers.py) |
--lengths | 50,150 | 使用的语料段落数(corpus 前缀) |
--conditions | fov-5x8-bw,fov-5x8-sent | 实验条件,格式为<proto>-<font>-<variant> |
--qpc | 30 | 每个 chunk 采样的问题数 |
--seed | 42 | 采样随机种子(可复现) |
--size | 1568 | 档案图边长像素 |
--workers | 3 | 并发线程数 |
--max-tokens | 32768 | 每轮 QA 输出预算 |
--effort | 无 | 思考力度(low/medium/high/xhigh/max等) |
--fresh | 关闭 | 忽略缓存强制重跑 |
--env | ~/.env | 存放OPENAI_API_KEY/OPENROUTER_API_KEY的环境文件(最后赋值生效,见 providers.py) |
--out | exp08-foveate | 结果子目录名 |
输出三份产物到research/results/<out>/:records.jsonl(逐题记录,含zoomed、zoom_band、anchor、abstained等字段)、summary.json(按模型×长度×条件聚合)、matrix.csv。模型的输入/输出单价在MODELS字典中显式配置(如gpt-5.5: (2.0, 16.0)美元/百万 token,exp08_foveate.py)。所有响应按 (model, tag, payload) 哈希缓存于research/.cache/qa/,中断重跑免费续传。
从实验到产品:位图帧形状的选取依据
exp08 这类 SQuAD 召回实验的结论直接指导了 snapcompact 的产品参数。README 明确"Frame shapes are provider-aware, chosen by SQuAD recall evals (seeresearch/) against real provider billing"(README),并给出各 reader 的默认形状:Anthropic11on16-bw(X.org 8x13 字形、11px 步进)、Google8on22-bw@2048、OpenAI8on22-bw(detail: "original")。也就是说,"档案 + 按需放大"的实验框架并非孤立研究,而是 oh-my-pi 压缩管线(compactAPI 的preserveData中持久化图像帧,见 README)中帧几何选择的方法论来源。
相关文件索引
- 放大回合提示词:exp08-zoom.md
- 档案回合提示词三变体:exp08-archive.md、exp08-archive-eager.md、exp08-archive-phrase.md
- 实验主程序:exp08_foveate.py
- 位图渲染基础设施(BDF/HEX 解析、capacity、render、variant):bdf.py
- 语料与评分(SQuAD v1.1 dev、EM/F1、编号解析):squad.py
- 模型分派与用量归一化:providers.py
- 通用评测框架与字体表:run.py
- 产品侧形态选择:README
结语
exp08-zoom.md虽只有六行,却是整个中央凹式两级读取协议承上启下的关键一环:它用"标签对齐 + 保持原编号 + 提取式答案 + UNREADABLE 兜底 + 严格输出格式"五条指令,把第一轮档案图的模糊感知与第二轮放大图的精确阅读无缝衔接。配合 harness 侧的行带合并、自适应分页、模糊短语定位与内容寻址缓存,这一协议实现了"档案图极致压缩、放大成本按需支付"的工程闭环——这也是 oh-my-pi 为视觉上下文压缩寻找最优帧几何时,被实际采用的实验方法论。
【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考