多模态模型读取发票图片时如何保留字段证据
来源:17golang原创
时间:2026-09-12 16:12:00 446浏览 收藏
多模态模型能从发票图片中读出发票号码、金额和日期,但如果系统只保存一段模型文本,财务人员很难回答“这个值在原图哪里”“为什么相信它”。更稳妥的做法是把每个字段设计成一个证据对象:值、原图归一化坐标、证据描述、置信说明和复核状态一起保存。
官方地址: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 文本?
纯文本缺少字段与原图的对应关系,后续很难复核。把文本、坐标和说明放在同一字段对象里,前端才能点击字段回看原图。
置信度低于多少才需要人工复核?
不要只设一个脱离业务的通用阈值。先按字段风险、金额范围、图像清晰度和历史误差制定规则,并把阈值命中原因写入复核记录。
-
273 收藏
-
科技周边 · 人工智能 | 3星期前 | ai · claude · Anthropic API · 文档问答 · 可追溯回答 · Claude 引用 Anthropic Messages API citations document block295 收藏
-
195 收藏
-
482 收藏
-
229 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习