Skip to main content
Orux AIOruxAI

Orux AI / 模型观察

交给DeepSeek写文案前,先核对发票行金额

发票合计对上也可能有错。本文用一份虚构的会议支出CSV,实际运行Python整数美分检查器,定位234美元报价与244美元重算结果之间的差异,展示逐行报告、修正样本和七个被拒绝的格式反例。核对通过后才允许创建精简文案资料,并附DeepSeek V4.1 Flash当前两档Credits预算,不把算术核对当成付款批准。

Orux AI发布于 9 分钟阅读
交给DeepSeek写文案前,先核对发票行金额 — 发票合计对上也可能有错。
文章目录

请 DeepSeek 说明发票之前,先独立核算每一行

活动供应商的发票,即使合计完全对得上,也可能算错。下面的示例中,三行报价之和是 234.00 美元,与发票声明的总额一致。但其中一行写的是单价 45.00 美元、数量 2,行金额却是 80.00 美元。独立相乘应为 90.00 美元,重新计算的总额因此是 244.00 美元。两个照抄而来的合计相同,不等于完成了独立核算。

本文为活动协调人员提供一份可运行的 Python 检查器,在准备交给 DeepSeek V4.1 Flash 的请求之前,先定位这种矛盾。交付物是逐行异常报告,以及只有算术检查通过后才允许创建的精简文案资料。案例费用均为虚构的会议支出,结果来自实际执行本地程序;这里没有让模型生成或批准发票。

由负责人解决差异后,DeepSeek 可以作为可选的文案环节。它不应决定双方约定的价格、批准付款,或悄悄改掉发票。决定应依据原始单据、合同和澄清记录。乘法正确,只能证明一种算术关系,不能证明服务已交付、费用已获授权。

虚构发票的本地核算:报价与声明总额均为234美元,独立计算为244美元
虚构发票的本地核算:报价与声明总额均为234美元,独立计算为244美元

总额一致,仍然藏着 10 美元的差异

这份合成导出包含姓名牌、会场标识和字幕服务,数量均指完整的服务单位。每行采用相同的五列结构,另外单独提供发票总额。这个独立值很重要:如果只是拿求和结果与它自己比较,会再次得到一个令人安心、却没有意义的检查。

行数量单价报价行金额独立计算
L1:姓名牌40USD 2.50USD 100.00USD 100.00
L2:会场标识3USD 18.00USD 54.00USD 54.00
L3:字幕服务2USD 45.00USD 80.00USD 90.00
合计——USD 234.00USD 244.00

左右滑动查看完整表格。

这不意味着应自动认定少付了 10 美元。供应商可能本来想报一个折后行金额,也可能写错了数量或单价。程序无法选择哪一种解释。它能确认的范围更明确,也更实用:L3 不符合声明的“数量乘以单价”规则,因此在本流程创建常规文案资料之前,需要先澄清。

供应商更正导出文件时,应保留前后两个版本。本文后面的修正测试会同时把 L3 改为 USD 90.00,把总额改为 USD 244.00。这只是为测试构造的明确修正,不代表真实供应商的意图。实际发票仍须采用负责人批准的真实更正。

明确金额格式,不猜测地区约定

程序接受非负、恰有两位小数的美元金额,以及正整数数量。它把金额字符串转换为整数美分,再进行整数乘法和加法;不做二进制浮点数比较,也不设置可能掩盖一美分差异的容差。这是刻意限定的小型输入协议,不是通用发票解析器。

2.500、-2.50、234,00 和科学计数法会被拒绝,数值字段首尾的空格同样会被拒绝。欧洲导出采用其他约定,并不意味着原文件错误,而是进入这个检查器前需要单独、经过审核的格式归一化。不要猜测分隔符到底表示小数点还是千位分组。

Python CSV 文档说明,分隔符和引号规则可能不同。程序使用 CSV 解析器,而不是按逗号直接切行;内存文本流也采用文档所示的换行处理。带引号且包含逗号的描述可以保持为一个字段。多余的列和重复行标识会被拒绝,不会静默忽略。

小数数量、税额、折扣、运费、多币种和贷项通知单不在本协议之内。如果发票涉及这些内容,应先停下来,设计对应的算术规则。为了得到“通过”状态而删掉不支持的行,会破坏核对本身的意义。

在本地运行完整检查器

保存为 check_invoice.py,执行 python3 check_invoice.py。程序只用 Python 标准库,不需要 API Key,也不发起网络请求。内置样本与断言属于交付物的一部分:读者不购买模型调用,就可以复现隐藏的差异和更正后的结果。

Python
"""Offline synthetic invoice check. No model/API request; USD integer cents only."""
import csv
import io
import json
import re

HEADER = ['line_id', 'description', 'qty', 'unit_usd', 'line_usd']
CSV = '''line_id,description,qty,unit_usd,line_usd
L1,Name badges,40,2.50,100.00
L2,Room signage,3,18.00,54.00
L3,Captioning service,2,45.00,80.00
'''

def cents(value):
    if not isinstance(value, str) or not re.fullmatch(r'[0-9]+\.[0-9]{2}', value):
        raise ValueError('Use unsigned USD amounts with exactly two decimals')
    whole, fraction = value.split('.')
    return int(whole) * 100 + int(fraction)

def check(text, invoice_total):
    reader = csv.reader(io.StringIO(text, newline=''), strict=True)
    if next(reader, None) != HEADER:
        raise ValueError('Unexpected CSV header')
    seen, rows, issues = set(), [], []
    for fields in reader:
        if len(fields) != len(HEADER):
            raise ValueError('Unexpected column count')
        ident, description, quantity, unit, quoted = fields
        if not ident or ident in seen or not description.strip():
            raise ValueError('Missing or duplicate line identity')
        if not re.fullmatch(r'[0-9]+', quantity) or int(quantity) < 1:
            raise ValueError('Quantity must be a positive whole number')
        seen.add(ident)
        expected, stated = int(quantity) * cents(unit), cents(quoted)
        rows.append(dict(line_id=ident, expected_cents=expected, stated_cents=stated))
        if expected != stated:
            issues.append(dict(line_id=ident, expected_cents=expected, stated_cents=stated))
    if not rows:
        raise ValueError('No invoice lines')
    declared = cents(invoice_total)
    expected_total = sum(x['expected_cents'] for x in rows)
    stated_sum = sum(x['stated_cents'] for x in rows)
    return dict(currency='USD', line_count=len(rows), line_issues=issues,
                expected_total_cents=expected_total, stated_line_sum_cents=stated_sum,
                declared_total_cents=declared, declared_matches_lines=declared == stated_sum,
                eligible_for_draft=not issues and declared == expected_total)

def draft_brief(report):
    if not report['eligible_for_draft']:
        raise ValueError('Resolve arithmetic before creating a drafting brief')
    return {k: report[k] for k in ['currency', 'line_count', 'expected_total_cents']}

def planned_microcredits(inputs, outputs, rate_in, rate_out):
    if any(type(x) is not int or x < 0 for x in [inputs, outputs, rate_in, rate_out]):
        raise ValueError('Planning quantities and rates must be nonnegative integers')
    numerator = inputs * rate_in + outputs * rate_out
    return (numerator + 999999) // 1000000

if __name__ == '__main__':
    bad = check(CSV, '234.00')
    assert bad['declared_matches_lines'] and not bad['eligible_for_draft']
    assert bad['expected_total_cents'] - bad['declared_total_cents'] == 1000
    try:
        draft_brief(bad)
    except ValueError:
        pass
    else:
        raise AssertionError('Bad invoice became a drafting brief')
    fixed = check(CSV.replace('45.00,80.00', '45.00,90.00'), '244.00')
    assert draft_brief(fixed) == dict(currency='USD', line_count=3, expected_total_cents=24400)
    rejected = 0
    for text, total in [
        (CSV.replace('L2,', 'L1,'), '234.00'),
        (CSV.replace(',40,', ',0,'), '234.00'),
        (CSV.replace(',40,', ',1e2,'), '234.00'),
        (CSV.replace('2.50', '2.500'), '234.00'),
        (CSV.replace('2.50', '-2.50'), '234.00'),
        (CSV.replace('L1,Name badges,', 'L1,Name badges,EXTRA,'), '234.00'),
        (CSV, '234,00'),
    ]:
        try:
            check(text, total)
        except ValueError:
            rejected += 1
        else:
            raise AssertionError('Invalid fixture accepted')
    rates = {'catalog_low': (18333360, 73333440), 'catalog_high': (36666720, 146666880)}
    plans = {key: planned_microcredits(1000, 300, *value) for key, value in rates.items()}
    assert plans == {'catalog_low': 40334, 'catalog_high': 80667}
    print(json.dumps(dict(bad=bad, corrected_brief=draft_brief(fixed),
                         negative_fixtures_rejected=rejected, planned_microcredits=plans), indent=2))

程序对金额不一致返回报告,对结构或格式无效的输入抛出错误。这是两种不同情况:一张可解释的发票可能存在值得调查的分歧,而不符合协议的数据则无法可靠地解释。生产导入还需要适合实际环境的文件大小限制、访问控制、会计规则和业务审核。

正确理解报告,不把它当付款决定

实际执行结果包含 declared_matches_lines: true 和 eligible_for_draft: false。独立计算总额为 24,400 美分,而声明总额与报价行之和都是 23,400 美分。异常指向 L3:声明值 8,000 美分,应算值 9,000 美分。正是这些具体数字,而不是一个笼统警告,解释了为什么表面一致的总额被拦截。

程序还实际尝试为错误报告创建文案资料,确认函数会拒绝。对明确修正后的测试样本,它返回 {"currency":"USD","line_count":3,"expected_total_cents":24400}。这个小对象才是本地流程成功交付的结果。它不是模型回答,也不是税务合规证明,更不是支付 USD 244.00 的授权。

本地测试结果:原发票被拦截,修正样本获准创建资料,七个格式反例均被拒绝
本地测试结果:原发票被拦截,修正样本获准创建资料,七个格式反例均被拒绝

程序实际拒绝了七个反例:重复标识、数量为零、指数形式的数量、金额精度超限、负单价、多出一列,以及逗号小数格式的总额。这些测试针对本文协议,不证明所有供应商导出都安全。CSV 语法错误也可能中止解析;程序并未宣称可以自动修复任意损坏文件。

给 DeepSeek 一个已解决问题的任务边界

当供应商或负责审核的人解决差异后,协调人员可以选择请 DeepSeek 只依据批准的事实,起草一份中性的收件确认。例如,可以提出以下要求:“简短确认已收到更正后的三行美元发票,核算总额为 244.00。不要声称付款已获批准或已经安排。请审核人确认单据编号后再发送。”这个请求在本文中没有实际调用。

当前 Orux 的 deepseek-v4.1-flash 表单提供 messages、max_tokens 和 JSON 对象输出选项。这只核实了可用控件,不等于已成功执行本文的发票文案任务。请使用模型页上的准确 Orux alias。DeepSeek 自有服务上的模型名属于另一套服务标识,不能未经核对就当成 Orux alias 使用。

DeepSeek Chat Completions 参考介绍了用量返回。真正执行请求后,应记录实际返回的用量;CSV 字符数和发票行数都不能确定 token 用量。如果需要 JSON 返回值,事后仍要校验字段和值。表单选项或者一段看起来礼貌的回答,都不能替代这个步骤。

延伸阅读中,博物馆 JSON 案例讨论输出校验,客服摘要指南则准备另一类受约束输入。本文新增的是发票算术核对,而不是重复其中的抽取或隐私检查。

比较公开目录中的两档 Orux 费率

2026 年 11 月 2 日,该 alias 的公开目录有两条 dailytimeband 费率。下表只采用未命中缓存的输入和输出费率;不假设重复发票一定享受缓存价,也不根据时钟推断账户适用哪一档。授权请求前,请确认当前报价和适用条件。

公开条件输入 Credits / 1M tokens输出 Credits / 1M tokens计划1000输入+300输出
dailytimeband=offpeak18.3333673.333440.040334 Credits
dailytimeband=peak36.66672146.666880.080667 Credits

左右滑动查看完整表格。

最后一列是预算计算,不是实测 token 用量或承诺账单。程序会把每个计划请求的估算向上取整到一个完整 micro-Credit。若 1000 个请求恰好都采用上述计划用量,按此规则,预算分别为 40.334 或 80.667 Credits。实际用量、适用条件或追加尝试会改变结果。本文没有测量账户扣费。

厂商价格页描述的是其自身的模型版本与时段规则,不能用来确定 Orux 的时段或账户报价。本文不声称本流程在发票准确性上胜过其他模型,也不声称某个服务在所有条件下都更便宜。计算器的用途是在任何可选请求前,把明确的计划展示出来供核查。

分开保存核对、文案和批准记录

保留原 CSV、声明总额、异常报告和批准后的修正。用更正后的数据重新运行检查器,再记录可选模型环节实际收到的资料。这样可以区分供应商写了什么、程序算出什么,以及人工批准了什么。生成的确认文案不应覆盖其中任何一份记录。

如果文案环节加入未经授权的付款日期、银行信息、单据编号或批准结论,应拒绝这些新增内容,并交由负责人解决。本文没有展示模型生成案例,也没有声称某种提示词能避免这些添加。已完成的贡献是本地算术门禁和可复现证据,后面的通信环节仍须单独审核。

价格与表单核对日期:2026-11-02。来源:Orux 模型页、公开目录、Python CSV、Python 数字类型、DeepSeek 接口参考、DeepSeek 价格。

FAQ

发票总额能对上,是否说明每一行都正确?

不能。示例总额与报价行相符,但 L3 不满足数量乘以单价的关系。除了核对总额,也要独立计算行金额。程序找出的是这个具体矛盾;接下来仍由人工判断到底应当更正哪一个来源值。

这10美元的差异是DeepSeek发现的吗?

不是,是本地 Python 程序发现的,本文没有调用模型。DeepSeek 是后续可选的文案环节,本文核实了当前 Orux 控件与注明日期的预算费率,但没有评测其发票准确性、质量、延迟或可靠性。

能直接用于税额或多币种吗?

不能按当前协议直接使用。它只覆盖正整数数量、非负两位小数的美元金额,不含税额、折扣和汇率逻辑。应根据批准的会计规则明确扩展并测试,而不是删掉不方便的行,或猜测地区格式。

表中的Credits是检查这个CSV的费用吗?

不是。本地检查器不发起 Orux 请求,不消耗站内 Credits。表格估算的是后续可选请求,采用假设的 token 数量。实际模型用量和适用的当前报价决定该请求费用,CSV 行数不能决定费用。

发送生成的确认文案前需要审核什么?

要对照批准后的修正和真实的通信授权来审核。总额核对通过,不代表付款或付款日期获得授权。应单独保留源报告,拒绝没有依据的细节,并在发送前确认单据编号和收件人。

在 Orux AI 试用 DeepSeek V4.1 Flash在模型页在线试用,并查看价格与 API 示例。打开模型

用一个 API 调用这些模型

一个 OpenAI 兼容 API,覆盖对话、图像、视频与音频模型,按积分计费。