凭证自动审核:规则加模型的两道关
财务审凭证,是个月月都逃不掉的细活。我们部门二十来人,每月经手凭证上千张,逐张看摘要对不对、科目用没用错、金额合不合规、附件齐不齐。审得慢,月底堆成山;审得快,漏一张错的月底就得多半天排查。今年我们把凭证审核改成了机器初审、人工终审的两道关模式:规则引擎过一遍,模型再过一遍,人只看机器筛出来的存疑件。
跑了小半年,效果说三个数:机器初审覆盖率百分之百,人工终审工作量降到原来的两成,错弊检出率是人工全审时代的两倍半。最后那个数最反直觉也最提气——机器加人一起,比纯人眼审得又快又准。这篇讲讲两道关是怎么设计的,中间的坑在哪。
一、为什么一道关不够
1.1 纯规则的天花板
规则审核是财务自动化的老朋友:金额超五千必须附合同、招待费必须事前审批、差旅住宿按城市档位限额——这些白纸黑字的制度,写成一串条件判断,机器执行又快又稳,永不疲倦。我们规则引擎先跑起来,覆盖了全部凭证的三类硬性检查:合规性(制度红线)、勾稽性(金额计算关系)、完整性(附件和要素齐全)。上线头一个月就发现:它能逮住的错误占历史错弊的七成。
但天花板也很快摸到:剩下三成,规则够不着。摘要写购买办公用品,附件是一张餐饮发票——写和贴对不上,规则看不出(它不读附件内容,只看有没有附件)。科目挂在差旅费下的招待宴请——差旅科目本身合规,只有理解了业务实质才觉得别扭。同一供应商当月开票异常密集——单张都合规,放在一起才有问题。这些需要理解和联想的判断,是规则的盲区。
1.2 纯模型的坑
于是我们试着全上模型:让大模型读凭证全要素做综合判断。坑立刻出现:模型会联想过度。一张正常的培训费发票,它联想出该培训是否有预算、讲师是否有资质、课程是否与岗位相关——联想都对,但全都超出了凭证审核的范围,按它的提示单核实,审核量不降反增。更麻烦的是尺度漂移:同样的凭证这周说过关下周说存疑,问它为什么,它给的理由都挺有道理。财务审核要的是尺度如一,模型天生爱思考,这两个脾气合不来。
1.3 两道关的分工
所以最终定型是分工而不是替代:规则管死规矩——写进制度的、有明确数字线的、不需要理解业务背景的,规则说了算,机器判定具有终审效力;模型管活线索——需要读内容的、需要跨凭证联想的、给人提供线索的,模型只出提示不出结论,存疑的流转人工。一句话:规则是法官,模型是侦探,人工是陪审团。各安其位,谁都别抢别人的戏。
二、规则关:怎么把制度写成代码
2.1 规则的分层
我们的规则库分三层,全部从制度文件翻译而来:红线层(违反即退回):无审批的采购、超限额的招待、假发票号码特征;校验层(不符即标记):金额与合同不一致、税率与业务类型不匹配、附件张数与制度要求不符;提示层(仅提示不拦):摘要过于简单、临近科目边界、该供应商本月开票频繁。三层的设计思想是力度递减——红线直接拦,校验标记后人工确认,提示仅作为模型关的输入参考。
RULES = [
{"id": "R001", "level": "block",
"cond": "expense.type=='招待' and approval.prior is None",
"msg": "招待费无事前审批单,退回"},
{"id": "R002", "level": "block",
"cond": "invoice.tax_code_invalid or invoice.duplicate_no",
"msg": "发票税号异常或号码重复,退回"},
{"id": "R014", "level": "flag",
"cond": "abs(invoice.amount - contract.amount) > 100",
"msg": "发票金额与合同差额超百元,请核实"},
{"id": "R021", "level": "hint",
"cond": "vendor.monthly_invoice_count > 20",
"msg": "该供应商本月开票异常频繁"},
]
def rule_check(voucher):
hits = []
for r in RULES:
if eval_rule(r["cond"], voucher):
hits.append(r)
blocks = [h for h in hits if h["level"] == "block"]
return {"pass": not blocks, "hits": hits}
2.2 制度翻译的坑
把制度写成规则,最大的坑不是技术,是制度本身含糊。写规则时才发现,有些制度条款是原则式表述:合理、适度、必要——这些词没法进规则。我们的处理:每碰到一处含糊,记录下来,季度汇总推给管理层把制度条款数字化(多少算合理?给出数)。一年下来推了十来条,制度越写越像参数表。这个副产品很值钱:制度的可执行化,本身就是管理水平的提升——写不出数字的制度,多半从来没被执行过。
三、模型关:给侦探立规矩
3.1 模型审什么
过了规则关的凭证,进入模型关。模型拿到的是凭证全要素:摘要、科目、金额、发票 OCR 内容、关联审批信息、供应商历史行为摘要。它的任务清单:摘要与附件内容一致性(写的是办公用品,附件读出来是不是办公用品);业务实质与科目的匹配度(餐饮发票挂差旅科,实质对不对);跨凭证的异常联想(同人多报、拆分报销、供应商集中度)。
3.2 输出必须是结构化的
前面说了模型爱自由发挥,治它的办法是输出格式锁死:
MODEL_PROMPT = """你是财务凭证审核助手。根据以下凭证信息给出判断。
只输出 JSON,字段如下:
{"risk": "高/中/低",
"risk_points": ["具体风险点,逐条列出"],
"suggest_action": "建议人工重点核实的内容",
"confidence": 0-1}
判断标准:
- 摘要与附件矛盾 → risk=高
- 科目与业务实质疑似不符 → risk=中
- 供应商或报销人行为异常 → risk=中
- 无明确异常 → risk=低
不确定时如实降低 confidence,禁止编造附件中不存在的内容。"""
risk 为低的直接通过(机器放行),中和高的进人工终审队列,按风险值排序——人先看最可疑的。模型只有建议权没有处置权:它说高,人核实后该过还是过;它说低,抽检发现错了,下月调它的判断标准。权力永远在人这一层。
3.3 抽检:给侦探也装个探头
机器放行的凭证不是免检金牌:每月按比例随机抽检一批 risk=低的,人工复核实情。这个抽检是体系的保险丝——上个月抽检逮住一例:摘要、科目、金额全部合规,附件发票也真,但抽检的同事认出那家供应商是上季度已预警的高风险供应商(模型没拿到黑名单的最新版本)。这事之后我们给模型关加了黑名单实时同步。抽检的意义就在这:你不检查机器,机器的错就会以你不检查的方式积累。
四、半年账目:值不值
投入端:规则库建设两个月(含制度翻译梳理),模型关调优一个月,日常维护每周两小时。产出端:人工审核工作量降八成,月底审核不再加班;错弊检出率翻倍半——上半年逮住的问题:重复报销三例、摘要附件不符七例、科目挪用四例、拆分报销两例,其中拆分报销那两例是纯人工时代从没逮住过的类型(跨三个月把一笔超限支出拆成三笔),模型靠跨凭证联想抓的。
还有一笔隐性收益:审核标准终于统一了。以前三个审核员对同一张灰色凭证能给出三个结论,部门内部吵、业务部门也抱怨尺度不一。现在规则和模型的尺度是明文写死的,人工终审只处理规则和模型都说不清的硬骨头,附上判断理由存档。尺度统一之后,业务部门反馈报销被退回时终于有据可查,扯皮少了一大半。
常见问题
问:模型误报太多,人工看不过来怎么办?
答:调两个参数:风险阈值的分层线(我们的中和高分占三成左右,人工看得过来;早期调得严,半数都存疑,等于把全审的活换了个地方干)和提示词里的判断标准(标准越具体,模型越少自由发挥)。另一个减负技巧:让模型输出风险点时必须引用凭证原文——引用不出来的风险点删掉。误报是模型关里最费钱的成本,这两个月我们基本把误报率压到了可忽略的水平,靠的就是把判断标准一条条写实。
问:业务部门会不会觉得被机器盯上,抵触?
答:我们的经验:公开规则,一切审核依据对业务可见。规则库发布在内部网,模型提示的处置都引用具体标准。抵触的根源不是严格而是黑箱——人怕的是说不清为什么被退。规则透明后,业务部门反而拿规则库当报销指南用,退单率都降了:按规矩填,一次过。机器审核最好的状态,是让守规矩的人感觉不到它存在。
问:中小公司凭证量不大,值得上这套吗?
答:量小的话降配:规则关用表格软件的条件格式加数据验证就能做雏形,覆盖最常见的红线和勾稽;模型关用通用助手人工问答实现——存疑凭证整批丢给它,按固定问题清单(摘要附件一致吗、科目合理吗)让它过一遍。核心思路不变:死规矩自动化、活线索给模型、最终判断留给人。工具可以土,结构不能省。
问:审核全自动的那天,财务审核岗还有意义吗?
答:这个我认真想过。真到那天,审核岗的残余价值有两块永远在:一是判断标准的设计权——规则库和模型标准怎么定,这是专业判断,机器替代不了;二是疑难件的裁决——灰色地带的定夺,责任必须有人背。所以审核岗不是消失,是从流水线工人变成质检工程师:定标准、管机器、裁疑难。这个转变早开始早主动,我们的审核同事现在已经把规则库当成自己的作品了——这种心态的人,不怕任何自动化。
更多推荐


所有评论(0)