Java for You AI Python Responses API视觉输入与本地金额校验最小实现

Python Responses API视觉输入与本地金额校验最小实现

工作台上的笔记本

把发票图片交给视觉模型,确实能省掉手输;但“模型说是 128.00 元”不等于系统该付款。更稳妥的做法是:模型只产生候选字段,本地程序以 Decimal 重算含税金额、检查币种和上限,再把通过或拒绝的理由交给界面。你将得到一个可以复制的最小链路,也能把同样的门禁迁移到合同、收据和质检单。

OpenAI 的 Images and vision 文档说明 Responses API 可接收图像输入。本文用 REST 而非 SDK,目的是让请求、超时和错误分支对初学者可见。模型 ID 请以目标账号的 Models 页面为准;代码中的 gpt-6 是示例占位,调用前替换为你账户可用模型。

mermaid diagram

环境准备与完整代码

Python 3.10+,安装 pip install requests,设置 export OPENAI_API_KEY='...',再运行 python receipt_gate.py receipt.jpg。示例未在本次任务中实际调用线上 API;已在本机完成语法检查。

import base64, json, os, sys
from decimal import Decimal, InvalidOperation
import requests

API = "https://api.openai.com/v1/responses"
def gate(data: dict) -> tuple[bool, str]:
    try:
        subtotal = Decimal(str(data["subtotal"]))
        tax = Decimal(str(data["tax"]))
        total = Decimal(str(data["total"]))
    except (KeyError, InvalidOperation):
        return False, "字段缺失或金额不是数字"
    if data.get("currency") != "CNY": return False, "仅接受CNY票据"
    if total > Decimal("2000"): return False, "超过自动处理上限"
    if abs(subtotal + tax - total) > Decimal("0.01"):
        return False, "小计、税额与总额不一致"
    return True, "允许进入人工确认"

def main(path: str) -> None:
    key = os.environ.get("OPENAI_API_KEY")
    if not key: raise SystemExit("请设置OPENAI_API_KEY")
    image = base64.b64encode(open(path, "rb").read()).decode()
    prompt = "识别票据,严格只返回JSON:subtotal,tax,total,currency"
    body = {"model":"gpt-6", "input":[{"role":"user","content":[
        {"type":"input_text","text":prompt},
        {"type":"input_image","image_url":"data:image/jpeg;base64,"+image}]}]}
    try:
        r = requests.post(API, headers={"Authorization":f"Bearer {key}","Content-Type":"application/json"}, json=body, timeout=30)
        r.raise_for_status()
        text = r.json()["output"][0]["content"][0]["text"]
        ok, reason = gate(json.loads(text)); print({"approved": ok, "reason": reason})
    except (requests.RequestException, KeyError, json.JSONDecodeError) as e:
        print({"approved": False, "reason": f"调用或解析失败: {e}"})

if __name__ == "__main__":
    if len(sys.argv) != 2: raise SystemExit("用法: python receipt_gate.py receipt.jpg")
    main(sys.argv[1])

关键点有三个:不要用浮点数算钱;不要允许模型决定“批准”;不要把原始票据和密钥写进日志。成功时预期输出 {'approved': True, 'reason': '允许进入人工确认'},仍不是自动付款。

常见失败:一是图片太大或格式不被账户支持,先压缩并核对视觉文档;二是模型返回 Markdown 围栏而非 JSON,应在生产中启用结构化输出或做更严格解析;三是网络超时,代码已设 30 秒,生产环境还应重试并加幂等键;四是发票有多税率,不能沿用单一小计公式。

它适合低风险预录入和人工前置核验,不适合绕过财务审批、税务判断或未获授权的证件处理。下一步可把字段置信度、供应商白名单和审计 ID 写入数据库。5分钟练习:把 2000 改成你的团队阈值,并给 gate 增加“日期不得晚于今天”的规则。

把它接进真实页面

页面至少应该同时展示原图缩略图、模型原始候选、本地复算值和拒绝原因。不要只用一枚绿色“已通过”徽标:使用者需要能看出是“识别到 128.00”“规则算出 128.00”,还是“金额相差 0.02”。若模型无法读取图片,保留上传记录并让用户补图;若规则不通过,允许修正字段但要求说明原因。对发票号、身份证号等敏感字段,日志只保留哈希或局部掩码,原图按组织保留期自动删除。批量场景可先排队、限制单用户并发,并把同一文件的 SHA-256 作为幂等键,避免重试造成重复报销草稿。

官方文档:Images and vision。你的业务里,哪一个AI提取字段必须由本地规则二次确认?

关注「蜗牛聊AI」,一起看懂技术变化背后的真正机会。


本文首发于 java4u.cn,转载请注明出处。

本文由 java4u.cn 发布,可自由转载、引用,但需署名作者且注明文章出处(作者:白色蜗牛,出处:java4u.cn)。如转载至微信公众号,请在文末添加作者公众号二维码。 https://java4u.cn/ai/3088.html

作者: 蜗牛

下一篇

已经没有了

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

联系我们

公众号:蜗牛互联网

在线咨询: QQ交谈

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部