Jev 案例:发票审批门禁与兜底(完整代码)

更新于 适用版本 Jev 1.13 示例数据(example fixture)

TL;DR: 本示例用一道判断题搭建发票审批门禁:Jev 1.13 以 yes/no/unclear 加置信度回答”符合政策是否应该自动批准?“,只有 yes 且置信度不低于 0.8 才自动批准,其余一律兜底转人工。完整 Python 脚本见下文。

场景

我们的应付账款团队每月处理几千张发票。绝大多数毫无悬念——金额低于 500 美元、对得上采购单(PO)、供应商正确。但初级会计还是要把每张发票打开,对着 PO 核三个字段,再点一下批准:每张十秒钟的专业注意力,一个月重复几千次。

政策本身一句话就能说清,于是我们把它变成了一道判断题

这张发票符合政策(金额低于 500 美元且匹配采购单),是否应该自动批准?

再加一条兜底规则——这才是本案例真正想讲的东西:

门禁绝不会在一声耳语上自动批准。一个判断模型说”yes,0.55”,等于在告诉你这张发票处在灰色地带——PO 号缺失、行项目反常、供应商名字对不上。这些恰恰是人应该看的发票,也恰恰说明 Jev——TypeSafe AI 发布的 System One 判断模型(2026 年 9 月)——为什么把置信度作为类型化输出的一等字段返回,而不是埋在一段散文里。调用走 OpenRouter 的 OpenAI 兼容端点。

请求

{
  "model": "typesafe/jev-1.13",
  "messages": [
    {
      "role": "system",
      "content": "Judgment question. Should this invoice be auto-approved under policy (amount under $500, matching a purchase order)? Answer yes, no, or unclear. Reply with JSON only: {\"answer\": <yes|no|unclear>, \"confidence\": <0-1>, \"rationale\": <one sentence>}"
    },
    {
      "role": "user",
      "content": "Invoice INV-2041 from Northwind Office Supply\nAmount: $412.80 | PO: PO-8877 | Terms: Net 30\nLine items: 12 ergonomic chair mats, matching PO-8877 pricing."
    }
  ]
}

响应

示例数据(example fixture)——用于说明格式,不是线上实测抓包:

{
  "answer": "yes",
  "confidence": 0.97,
  "rationale": "Amount is under $500, the invoice references PO-8877, and line items match the purchase order pricing."
}

这个示例刻意选了最平淡的情况:干净的 yes、高置信度、自动批准。门禁真正的价值在两个字段任何一个变差的情形里——见下面的兜底分支。

复现脚本

保存为 gate.py,设置环境变量 OPENROUTER_API_KEY 后运行 python3 gate.py

import json, os, urllib.request

URL = "https://openrouter.ai/api/v1/chat/completions"
MODEL = "typesafe/jev-1.13"  # confirm exact slug on the OpenRouter model page
HUMAN_REVIEW_CONFIDENCE = 0.8

SYSTEM = ('Judgment question. Should this invoice be auto-approved under '
          'policy (amount under $500, matching a purchase order)? '
          'Answer yes, no, or unclear. Reply with JSON only: '
          '{"answer": <yes|no|unclear>, "confidence": <0-1>, "rationale": <one sentence>}')

def gate(invoice_text):
    body = {"model": MODEL, "messages": [
        {"role": "system", "content": SYSTEM},
        {"role": "user", "content": invoice_text}]}
    req = urllib.request.Request(URL, data=json.dumps(body).encode(),
        headers={"Authorization": "Bearer " + os.environ["OPENROUTER_API_KEY"],
                 "Content-Type": "application/json"})
    with urllib.request.urlopen(req) as res:
        payload = json.load(res)
    result = json.loads(payload["choices"][0]["message"]["content"])
    if result["answer"] == "yes" and result["confidence"] >= HUMAN_REVIEW_CONFIDENCE:
        return "auto-approved", result
    return "human-review", result

invoice = """Invoice INV-2041 from Northwind Office Supply
Amount: $412.80 | PO: PO-8877 | Terms: Net 30
Line items: 12 ergonomic chair mats, matching PO-8877 pricing."""

print(gate(invoice))

关键参数

字段取值说明
modeltypesafe/jev-1.13固定版本——审批政策的行为不允许悄悄漂移。准确 slug 请以 OpenRouter 模型页为准。
messages[0](system)判断题 + 完整政策 + JSON 结构政策那句话就是审批规则。政策变了,只需要改这一行。
messages[1](user)发票结构化字段传应付团队本来就抽取好的字段,不需要传 PDF。
answer(响应)yes与置信度一起决定分支:批准 / 拒绝 / 转人工。
confidence(响应)0.97(示例数据)兜底触发器:yes 但低于 0.8 依然转人工。
rationale(响应)一句话随决策一起归档,就是每一次自动批准的审计线索。
价格$0.0462 / 1M input tokens每张发票一次调用;预算前请在 OpenRouter 核对当前价格。

注意事项

继续阅读