展开本页目录
开始前准备什么
- 独立练习目录及Python 3.14;系统与Node依赖以README为准。
- 离线重放无需Key;新请求使用自己的apizt Key,先核对模型权限和当前价格。
- 原创合成材料,不需要登录第三方平台账号。
- 先看文件
- 按步骤操作
- 对照真实结果
- 离线或模型复跑
默认离线重放;包含完整失败尝试与本地检查,不含Key。
1. 核对本例材料与目标文件
参见本批TOPIC-RESEARCH.md同编号新增边界,原生小样与负例均独立交付。
先下载合成材料在独立目录练习。原始文件、模型输入与验收答案分别保留;本地核对答案不发送给模型。
input.json(节选)
{
"fixture": "原创长列表分两块并保留120像素重叠"
}2. 按顺序完成这项具体操作
本次实际使用Python 3.14,依赖版本固定在资料包。需要LibreOffice或Node的案例请先按README安装对应运行时。python run.py读取真实旧响应完成本地处理;只有显式--live才发新请求。
- 1. 生成long-source.jpg原创8行长列表,再裁为tile-1.jpg(高760)和tile-2.jpg(高610);第二块源图起点为640,保留120像素重叠。
- 2. 将两张实际裁片一起交给apizt,要求每行返回id、text和y_norm;y_norm限定0—1000归一坐标,不能当像素使用。
- 3. 分别按source_y=offset+y_norm×actual_height/1000换算源坐标,图1用offset=0、高760,图2用offset=640、高610。
- 4. 按源坐标排序,并对重叠R05比较文字及坐标容差后去重;相同ID若文字冲突或位置超差,保留冲突而非静默覆盖。
- 5. 检查最终R01—R08恰好8行,导出merged-rows.csv和merge-audit.json,展示原始行、合并行与坐标契约。
- 6. 保留第一次坐标理解失败的request-1.json/receipt-1.json/output-1.json,以及澄清y_norm后第二次真实请求的对应文件;不能只留下成功截图。
独立练习目录 · 默认仅离线复核
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
python run.py3. 对照真正发送的请求
只输出JSON:tiles数组,每项tile为1或2、rows数组。每行含id(如R01)、text(货品文字)、y_norm(该裁片内行首纵坐标,0到1000归一化,0是顶部1000是底部;不是像素)。图1真实宽1000高760,图2真实宽1000高610。同一行在两张图中出现时分别保留,由程序按源坐标合并。不要输出不存在的行。
网页实验台只执行这一步模型字段检查。原生文件写入、坐标/公式/格式回读及负例验收由下载包负责。
request-2.json(图片Base64省略,原文件在下载包)
{
"model": "gemini-2.5-flash-lite",
"messages": [
{
"role": "system",
"content": "严格只输出单个JSON对象,不要Markdown代码围栏,不要解释。只输出JSON:tiles数组,每项tile为1或2、rows数组。每行含id(如R01)、text(货品文字)、y_norm(该裁片内行首纵坐标,0到1000归一化,0是顶部1000是底部;不是像素)。图1真实宽1000高760,图2真实宽1000高610。同一行在两张图中出现时分别保留,由程序按源坐标合并。不要输出不存在的行。"
},
{
"role": "user",
"content": [
{
"type": "text",
"text": "严格只输出单个JSON对象,不用代码围栏。只输出JSON:tiles数组,每项tile为1或2、rows数组。每行含id(如R01)、text(货品文字)、y_norm(该裁片内行首纵坐标,0到1000归一化,0是顶部1000是底部;不是像素)。图1真实宽1000高760,图2真实宽1000高610。同一行在两张图中出现时分别保留,由程序按源坐标合并。不要输出不存在的行。\n只输出JSON:tiles数组,每项tile为1或2、rows数组。每行含id(如R01)、text(货品文字)、y_norm(该裁片内行首纵坐标,0到1000归一化,0是顶部1000是底部;不是像素)。图1真实宽1000高760,图2真实宽1000高610。同一行在两张图中出现时分别保留,由程序按源坐标合并。不要输出不存在的行。"
},
{
"type": "image_url",
"image_url": {
"url": "[实际图片Base64;完整原始请求在资料包]",
"detail": "high"
}
},
{
"type": "image_url",
"image_url": {
"url": "[实际图片Base64;完整原始请求在资料包]",
"detail": "high"
}
}
]
}
],
"temperature": 0,
"max_tokens": 1536,
"provider": {
"sort": "success_rate"
},
"response_format": {
"type": "json_object"
}
}4. 查看原生处理代码与实际文件
下面节选来自本次实际执行的workflow.py分支,需要结合完整脚本运行。模型输出不能代替文件解析器或业务验算。
具体产物:merged-rows.csv、merge-audit.json。
workflow.py · 本例分支节选
rows = output.get('tiles', [])
offset = {1: 0, 2: 640}
tile_heights = {1: 760, 2: 610}
allrows = []
for tile in rows:
tile_no = tile.get('tile')
check('裁片编号合法', tile_no in offset)
if tile_no not in offset:
continue
for r in tile.get('rows', []):
y = r.get('y_norm')
allrows.append({'tile': tile_no, 'id': r.get('id'), 'text': r.get('text', ''), 'source_y': offset[tile_no] + y * tile_heights[tile_no] / 1000 if isinstance(y, (float, int)) and 0 <= y <= 1000 else None})
merged = {}
collisions = []
for r in sorted(allrows, key=lambda r: r['source_y'] if r['source_y'] is not None else 100000):
key = r['id']
if key in merged:
a = merged[key]
if a['text'] != r['text'] or a['source_y'] is None or r['source_y'] is None or (abs(a['source_y'] - r['source_y']) > 65):
collisions.append({'before': a, 'after': r})
else:
merged[key] = r
golden = [f'R{n:02}' for n in range(1, 9)]
check('两裁片共同覆盖8行且无新行', set(merged) == set(golden))
check('源坐标合并后排序正确', [r['id'] for r in merged.values()] == golden)
check('重叠R05实际重复出现再去重', sum((r['id'] == 'R05' for r in allrows)) == 2 and len(merged) == 8)
check('重叠内容与源坐标一致', not collisions)
write_csv(artifact('merged-rows.csv'), merged.values(), ['tile', 'id', 'text', 'source_y'])
result = {'rawRows': allrows, 'merged': list(merged.values()), 'collisions': collisions, 'tileOffsets': offset, 'coordinateContract': 'y_norm 0..1000; source_y = offset + y_norm * actual_height / 1000'}
dump(artifact('merge-audit.json'), result)5. 对照真实结果和检查表
实测2026-10-25T07:57:40.798288+00:00,HTTP200;请求gemini-2.5-flash-lite,返回gemini-2.5-flash-lite。本次8/8项检查通过,指本例执行及验收机制通过,不代表所有模型字段零误差。
最后一次返回用量3046tokens;2份尝试记录的已知用量合计5904。失败记录保留,用量缺失不按0计,本文不推算实际金额。
| 实际检查 | 结果 |
|---|---|
| 真实apizt API响应HTTP200 | 通过 |
| 裁片编号合法 | 通过 |
| 裁片编号合法 | 通过 |
| 两裁片共同覆盖8行且无新行 | 通过 |
| 源坐标合并后排序正确 | 通过 |
| 重叠R05实际重复出现再去重 | 通过 |
| 重叠内容与源坐标一致 | 通过 |
| 列出的原生产物实际存在 | 通过 |
- 实际检查
- 真实apizt API响应HTTP200
- 结果
- 通过
- 实际检查
- 裁片编号合法
- 结果
- 通过
- 实际检查
- 裁片编号合法
- 结果
- 通过
- 实际检查
- 两裁片共同覆盖8行且无新行
- 结果
- 通过
- 实际检查
- 源坐标合并后排序正确
- 结果
- 通过
- 实际检查
- 重叠R05实际重复出现再去重
- 结果
- 通过
- 实际检查
- 重叠内容与源坐标一致
- 结果
- 通过
- 实际检查
- 列出的原生产物实际存在
- 结果
- 通过
result.json · 原生处理后实际结果
{
"rawRows": [
{
"tile": 1,
"id": "R01",
"text": "R01 ITEM-01 QTY 2",
"source_y": 142.88
},
{
"tile": 1,
"id": "R02",
"text": "R02 ITEM-02 QTY 3",
"source_y": 285.76
},
{
"tile": 1,
"id": "R03",
"text": "R03 ITEM-03 QTY 4",
"source_y": 427.12
},
{
"tile": 1,
"id": "R04",
"text": "R04 ITEM-04 QTY 5",
"source_y": 567.72
},
{
"tile": 1,
"id": "R05",
"text": "R05 ITEM-05 QTY 6",
"source_y": 708.32
},
{
"tile": 2,
"id": "R05",
"text": "R05 ITEM-05 QTY 6",
"source_y": 699.78
},
{
"tile": 2,
"id": "R06",
"text": "R06 ITEM-06 QTY 7",
"source_y": 841.91
},
{
"tile": 2,
"id": "R07",
"text": "R07 ITEM-07 QTY 8",
"source_y": 982.8199999999999
},
{
"tile": 2,
"id": "R08",
"text": "R08 ITEM-08 QTY 9",
"source_y": 1123.73
}
],
"merged": [
{
"tile": 1,
"id": "R01",
"text": "R01 ITEM-01 QTY 2",
"source_y": 142.88
},
{
"tile": 1,
"id": "R02",
"text": "R02 ITEM-02 QTY 3",
"source_y": 285.76
},
{
"tile": 1,
"id": "R03",
"text": "R03 ITEM-03 QTY 4",
"source_y": 427.12
},
{
"tile": 1,
"id": "R04",
"text": "R04 ITEM-04 QTY 5",
"source_y": 567.72
},
{
"tile": 2,
"id": "R05",
"text": "R05 ITEM-05 QTY 6",
"source_y": 699.78
},
{
"tile": 2,
"id": "R06",
"text": "R06 ITEM-06 QTY 7",
"source_y": 841.91
},
{
"tile": 2,
"id": "R07",
"text": "R07 ITEM-07 QTY 8",
"source_y": 982.8199999999999
},
{
"tile": 2,
"id": "R08",
"text": "R08 ITEM-08 QTY 9",
"source_y": 1123.73
}
],
"collisions": [],
"tileOffsets": {
"1": 0,
"2": 640
},
"coordinateContract": "y_norm 0..1000; source_y = offset + y_norm * actual_height / 1000"
}6. 替换输入前,先确认这些边界
坐标只在原创8行裁片上验证,近似y允许65像素容差;跨栏或更复杂版面需另验。
修改材料后应重新制定事实断言和反例。识别错误率、混淆矩阵或拒答类教程允许保留模型实际错误;检查通过指计算和处理正确。没有调用视频模型。
怎样确认已经完成
- 真实apizt API响应HTTP200
- 裁片编号合法
- 裁片编号合法
- 两裁片共同覆盖8行且无新行
- 源坐标合并后排序正确
- 重叠R05实际重复出现再去重
- 重叠内容与源坐标一致
- 列出的原生产物实际存在
常见问题
AI 长截图 OCR 分块怎么开始?
生成long-source.jpg原创8行长列表,再裁为tile-1.jpg(高760)和tile-2.jpg(高610);第二块源图起点为640,保留120像素重叠。按本页顺序继续,先用下载包离线重放,再替换自己的材料。
网页试跑和下载包有什么区别?
网页只复跑模型字段,不生成全部原生文件;资料包包含实际原生处理和本地验收。
这次通过结果适用于其他材料吗?
坐标只在原创8行裁片上验证,近似y允许65像素容差;跨栏或更复杂版面需另验。


