多模态模型读取发票图片时如何保留字段证据
多模态模型能从发票图片中读出发票号码、金额和日期,但如果系统只保存一段模型文本,财务人员很难回答“这个值在原图哪里”“为什么相信它”。更稳妥的做法是把每个字段设计成一个证据对象:值、原图归一化坐标、证据描述、置信说明和复核状态一起保存。
官方地址:https://platform.openai.com/docs/
- 用 JSON Schema 固定每个字段的证据结构,避免模型只返回自由文本。
- 坐标保存为 0 到 1 的比例值,并与原图宽高、哈希绑定。
- 置信度只代表抽取判断的把握,缺证据或低置信字段仍要人工复核。
一、先定义字段证据模型
字段证据的核心不是给结果再加一个 confidence,而是让值和它的来源区域成为一条不可拆开的记录。下面的结构以发票号码、价税合计为例;box 使用左上角和右下角的归一化坐标,范围固定在 0 到 1。
# 用同一种结构保存字段值、原图位置和复核状态
FIELD_SCHEMA = {
"type": "object",
"properties": {
"value": {"type": "string"},
"box": {
"type": "object",
"properties": {
"x1": {"type": "number", "minimum": 0, "maximum": 1},
"y1": {"type": "number", "minimum": 0, "maximum": 1},
"x2": {"type": "number", "minimum": 0, "maximum": 1},
"y2": {"type": "number", "minimum": 0, "maximum": 1}
},
"required": ["x1", "y1", "x2", "y2"],
"additionalProperties": False
},
"evidence": {"type": "string"},
"confidence_note": {"type": "string"},
"needs_review": {"type": "boolean"}
},
"required": ["value", "box", "evidence", "confidence_note", "needs_review"],
"additionalProperties": False
}
这里的 evidence 应该是“字段出现在发票右上区域的黑色印刷文字”这类可读说明,而不是再次复制整张发票。confidence_note 也要描述不确定性来源,例如“数字 8 的边缘略模糊”,不要把模型置信度写成税务真实性结论。

二、把发票图片和抽取规则一起提交
图像输入和抽取规则要在一次请求中表达清楚。官方 Responses API 支持把图片作为 input_image 传入;实际项目还应在提示中声明:看不清时返回空值并标记复核,不要猜测号码。
import base64
import json
from openai import OpenAI
# 图片只作为本次请求输入;密钥应从服务端环境变量读取
client = OpenAI()
with open("invoice.jpg", "rb") as image_file:
image_data = base64.b64encode(image_file.read()).decode("ascii")
prompt = """
# 只抽取发票号码和价税合计,并为每个字段返回原图归一化坐标。
# 无法确认的字段 value 返回空字符串,needs_review 必须为 true;不要猜测。
"""
response = client.responses.create(
model="gpt-5",
input=[{
"role": "user",
"content": [
{"type": "input_text", "text": prompt},
{"type": "input_image", "image_url": f"data:image/jpeg;base64,{image_data}"}
]
}],
text={
"format": {
"type": "json_schema",
"name": "invoice_evidence",
"strict": True,
"schema": {
"type": "object",
"properties": {
"invoice_number": FIELD_SCHEMA,
"total_amount": FIELD_SCHEMA
},
"required": ["invoice_number", "total_amount"],
"additionalProperties": False
}
}
}
)
result = json.loads(response.output_text) # 结构固定后再交给业务层处理
Schema 的价值是让缺失字段也有稳定形状,便于后续审计和数据库入库。不要把图片压缩、裁剪后的坐标和原图坐标混在一起;如果为了识别做了裁剪,要同时记录裁剪框。

三、把坐标和原图绑定到审计记录
归一化坐标的计算很简单:原图宽度为 W、高度为 H 时,像素点 (px, py) 保存为 (px / W, py / H)。入库时建议额外保存原图 SHA-256、宽高和处理时间,这样同一张发票被重新识别时仍能对比证据。
import hashlib
from pathlib import Path
# 生成可复核的原图指纹,并把比例坐标恢复为像素框
image_path = Path("invoice.jpg")
image_hash = hashlib.sha256(image_path.read_bytes()).hexdigest()
def to_pixels(box, width, height):
# 乘回原图尺寸,方便前端在原图上画定位框
return {
"x1": round(box["x1"] * width),
"y1": round(box["y1"] * height),
"x2": round(box["x2"] * width),
"y2": round(box["y2"] * height),
}
audit_record = {
"image_sha256": image_hash,
"image_width": 2480,
"image_height": 3508,
"fields": result,
}
如果模型返回的框越界、x1 > x2 或没有覆盖字段文字,不要静默修正后当成可信结果;应保留原始响应并把该字段设为待复核。坐标只回答“模型指向哪里”,不能代替发票验真、税率核验或业务规则。
四、用证据完整度决定是否人工复核
自动入账前至少检查四件事:字段值非空、坐标在范围内、证据说明非空、needs_review 为 false。金额还要和业务侧的数值解析、币种及合计规则独立核对。只要一项不满足,就把整张发票送入人工队列,并保留模型原始响应。
| 检查项 | 通过条件 | 不通过处理 |
|---|---|---|
| 字段值 | 非空且符合字段格式 | 标记缺失字段 |
| 图像定位 | 四个坐标在 0 到 1 之间 | 保留原始 JSON,人工查看原图 |
| 证据说明 | 能说明文字所在区域或可见特征 | 禁止自动入账 |
| 复核标记 | needs_review=false | 进入人工复核队列 |
最后要强调:证据链提升的是可追溯性,不是模型的绝对正确率。发票识别涉及财务和合规场景时,仍应结合原图、业务规则和人工抽查;不要因为 JSON 格式正确,就把抽取结果当作已经验证的事实。
相关问题
为什么不直接保存 OCR 文本?
纯文本缺少字段与原图的对应关系,后续很难复核。把文本、坐标和说明放在同一字段对象里,前端才能点击字段回看原图。
置信度低于多少才需要人工复核?
不要只设一个脱离业务的通用阈值。先按字段风险、金额范围、图像清晰度和历史误差制定规则,并把阈值命中原因写入复核记录。
Go race detector 没报错但数据仍不一致该查什么
- 上一篇
- Go race detector 没报错但数据仍不一致该查什么
- 下一篇
- Go 泛型约束如何同时支持整数别名与自定义方法
-
- 科技周边 · 人工智能 | 4小时前 | API · 错误处理 · 人工智能 · 工程实践 · 函数调用 · 参数校验 工具调用 Function Calling 幂等重试 strict Schema
- 工具调用参数校验失败后怎样安全重试
- 215浏览 收藏
-
- 科技周边 · 人工智能 | 5小时前 | API · 人工智能 · json schema · 结构化输出 · 排错 · enum 结构化输出 JSON Schema 模型API 响应校验
- 结构化输出如何处理模型返回的枚举值错误
- 345浏览 收藏
-
- 科技周边 · 人工智能 | 1天前 |
- 本地模型量化时怎么比较 4-bit 与 8-bit 代价
- 481浏览 收藏
-
- 科技周边 · 人工智能 | 1天前 |
- 语音转写带说话人分离时如何处理重叠发言
- 115浏览 收藏
-
- 科技周边 · 人工智能 | 1天前 |
- 扩散模型固定 seed 后为什么仍有细节差异
- 457浏览 收藏
-
- 科技周边 · 人工智能 | 1天前 | JSON · 人工智能 · schema · 工程实践 · 大模型 · Python LLM JSONSchema 结构化输出 JSON Schema 有限重试
- LLM 输出 JSON Schema 不稳定时怎么设计重试
- 480浏览 收藏
-
- 科技周边 · 人工智能 | 2天前 | 人工智能 · OCR · 文档理解 · OCR 表格识别 行列关系 Table Transformer
- OCR 识别表格时如何保留行列关系
- 147浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 102次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 16次使用
-
- OpenCompass
- OpenCompass是上海AI实验室推出的开源大模型评测平台,提供CompassKit、CompassHub和CompassRank三大核心组件,支持LLM及多模态模型的一站式标准化评估与排行榜查询。
- 29次使用
-
- AGI-Eval
- AGI-Eval是由上海交大等高校联合发布的大模型评测社区,提供公正透明的LLM能力榜单、多领域评测集及Data Studio数据服务,助力AI模型性能评估与NLP科研开发。
- 17次使用
-
- SuperCLUE
- SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
- 257次使用
-
- 纸质档案扫描选 300dpi 还是 600dpi
- 2026-09-06 273浏览
-
- Claude Messages API citations 怎么核对:document blocks、source 与引用位置
- 2026-08-21 295浏览
-
- AI 推理过程怎么给用户看摘要:Responses API reasoning summary 与隐私边界
- 2026-08-23 195浏览
-
- AI 接口超时后怎么安全重试:请求标识、指数退避与结果去重
- 2026-08-24 482浏览
-
- AI 接口 504 后要不要重发:请求标识、退避与幂等核对
- 2026-08-24 229浏览

