大模型工程化实战(十七):金融级 AI 落地——决策可追溯/可复现/可追责/不可抵赖这四件事怎么做

目录

  • 前言
  • 一、问题定义:为什么"五关全过"不等于"金融级过"
  • 二、核心方案:五关之上,再叠一层"决策级举证"
    • [2.1 四可核对表(本篇的骨架)](#2.1 四可核对表(本篇的骨架))
    • [2.2 四可逐个说清"它会怎么卡你 + 你该拿什么去核"](#2.2 四可逐个说清“它会怎么卡你 + 你该拿什么去核”)
    • [2.3 判据复用表:三可的判据前篇全立过,第四可(不可抵赖)是金融级新增、心智接第 12 篇](#2.3 判据复用表:三可的判据前篇全立过,第四可(不可抵赖)是金融级新增、心智接第 12 篇)
    • [2.4 外层监管层:只给边界,不重建立五关](#2.4 外层监管层:只给边界,不重建立五关)
    • [2.5 三个取舍点(每个都有代价)](#2.5 三个取舍点(每个都有代价))
    • [2.6 边界:这篇不是什么](#2.6 边界:这篇不是什么)
  • 三、代码实战:一个纯标准库的金融级决策审计链核对器
    • [3.1 数据结构:决策是数据,不是一行日志](#3.1 数据结构:决策是数据,不是一行日志)
    • [3.2 哈希链那一刀:一改就断链、一断全废](#3.2 哈希链那一刀:一改就断链、一断全废)
    • [3.3 可复现是"版本对得上",不是"逐字一致"](#3.3 可复现是“版本对得上”,不是“逐字一致”)
    • [3.4 主核对:先验链、再逐笔核四可](#3.4 主核对:先验链、再逐笔核四可)
    • [3.5 9 个断言怎么把这些结论钉死](#3.5 9 个断言怎么把这些结论钉死)
  • 四、踩坑记录:这三个坑,每个都真付过费
    • [4.1 我以为"记了日志"就=可审计,结果审计员一句"这日志能改吗"把我问住](#4.1 我以为“记了日志”就=可审计,结果审计员一句“这日志能改吗”把我问住)
    • [4.2 客户投诉要我复现三个月前那笔拒绝决策,我复现不出来](#4.2 客户投诉要我复现三个月前那笔拒绝决策,我复现不出来)
    • [4.3 出了事要追责,我发现"申请人"和"审批人"是同一个人](#4.3 出了事要追责,我发现“申请人”和“审批人”是同一个人)
  • 五、选型对比:三种做法,你该抄哪一种
    • [5.1 大表:金融级"决策可举证"这条路的三种做法](#5.1 大表:金融级“决策可举证”这条路的三种做法)
    • [5.2 副表:金融级决策可举证的监管口径现状(2026,口径与期限待核实)](#5.2 副表:金融级决策可举证的监管口径现状(2026,口径与期限待核实))
    • [5.3 可复用 checklist:金融级 AI 决策可举证 8 问](#5.3 可复用 checklist:金融级 AI 决策可举证 8 问)
  • [六、总结 + 下一篇预告](#六、总结 + 下一篇预告)
  • [附录 A:四可 → 判据 → 依据出处 → 对应前篇](#附录 A:四可 → 判据 → 依据出处 → 对应前篇)
  • [附录 B:金融级决策可举证的监管口径现状表(2026,全标"待核实")](#附录 B:金融级决策可举证的监管口径现状表(2026,全标“待核实”))
  • [附录 C:可引用公开口径清单(口径与条文以官方原文为准)](#附录 C:可引用公开口径清单(口径与条文以官方原文为准))
  • [附录 D:审计链算法说明](#附录 D:审计链算法说明)

前言

上一篇《政企国产化避坑》结尾我留了一句话:"政企国产化讲的是'东西能不能进来、谁来扛';金融级讲的是'每个决策能不能被审计、能不能被追责'------同一套工程纪律,在金融行业要被逼到什么程度。"今天来还这笔账。

先说个让我脸上挂不住的事。我交付过一个金融客户的 AI 审批项目,政企那五关我全按第 16 篇的核对器过了一遍------合规过了、信创逐家核了、运维排了人、原厂维保也签了,我自认为交得漂亮。结果有一天,客户一笔 AI"拒绝放款"的决策被投诉到了监管,监管来函,要我把那笔决策复现一遍:当时是谁调的、命中了哪条规则、模型是哪一版、谁批的、这条记录有没有被改过。

我打开日志,只有一行"审核未通过"。 那一刻我才知道:政企那五关,问的是"这套系统能不能上线";金融 AI 落地问的是另一件事------"这套系统做的每一笔决策,能不能拿出来举证" 。这一篇就把这一层补上。

一、问题定义:为什么"五关全过"不等于"金融级过"

第 16 篇那五道关,我核得很认真。可它核的全是"系统级"的东西:这套系统能不能进来、谁来扛它------上线前和交付时的事。金融级问的是"决策级":这套系统上线之后,它做的每一笔放行、每一笔拒绝,事后能不能自证。 这两个问题之间隔着一整层,我原来把它们混成了一件。三个误区,一个比一个贵。

误区一:把审计当成"日志"。 我当时的想法很朴素:每次决策我都记了日志------谁调的、什么时候、结果是什么,一应俱全,这不就是可审计吗?后来内部审计的人只问了我一句:你这日志存在哪、谁能改、你怎么证明现在给我看的这条就是当时那条?我一下哑了。日志就在业务库里,运维能改、开发能删,我拿不出任何"这条记录没被动过"的证明。能被改的日志,不叫证据。

误区二:把合规当成"系统过等保就行"。 我一开始觉得系统过了等保、过了密评,合规这块就齐了。错。系统级合规 ≠ 决策级举证------系统过了等保,不代表它做的某一笔决策说得清"是谁、凭什么"。等保管的是这台机器安不安全,管不了"这一笔放款为什么批"。

误区三:把可复现当成"重跑一遍"。 我一度以为复现就是拿今天的数据再跑一遍。真去复现才发现:模型升级过、Prompt 改过好几轮,我用今天的版本怎么跑都对不上当时那笔;就算版本没换,LLM 本身也有随机性。重跑 ≠ 复现------复现的标准要提前定义,金融里通常是"关键依据一致",不是"逐字一致"。

先把结论撂这儿:金融级 AI 落地 = 政企五关(系统级)之上,再叠一层"决策级举证"的四可------① 可追溯(谁调的/谁批的/走了哪条路)→ ② 可复现(用当时那一版三元组,能证明当时凭什么这么判)→ ③ 可追责(追到具体责任人,且申请人 ≠ 审批人)→ ④ 不可抵赖(记录防篡改,一改就断链、一断全废)。四可缺一件,你那堆日志就只是一堆能被改的字符串,举不了证。 落点是一个纯标准库、离线可跑、可断言的"金融级决策审计链核对器"。

举个最具体的例子,把"系统级"和"决策级"这一刀切干净。 我这套信贷审批系统,等保过了、密评过了、日志也打了------从"系统"这一层看,它是一套合规的系统,第 16 篇那五关我核得挑不出毛病。可监管来函要的是那一笔 拒绝的答案:命中了哪条规则、模型是哪一版、谁批的、这条记录有没有被动过。这两件事隔着整整一层:系统级通过,回答的是"这台机器安不安全、能不能上线";决策级通过,回答的是"它做的这一笔 决定站不站得住"。我原来拿前者的答案去回后者的问,所以才在监管来函面前一句话都答不上来------这也是本篇跟第 16 篇最大的不同:那五关是上线前和交付时的系统级准入,这四可是上线后每一笔决策的决策级举证。

二、核心方案:五关之上,再叠一层"决策级举证"

整篇的主线就一句:第 16 篇给了我一套政企五关、一个能核的核对器------可那五关全是"系统级"的,管的是这套系统能不能上线、谁来养它。金融级管的是另一层:"决策级"------这套系统做的每一笔决策,事后能不能自证。这一篇在五关之上叠一层"四可",每一可的判据全是前几篇在真实场景里立过的,我一个不新造。

复制代码
第 16 篇政企五关(系统级:这套系统能不能进来、谁来扛)
  ① 合规关 ② 信创关 ③ 运维关 ④ 适配关 ⑤ 支持关 ------ 管的是"上线前 + 交付时"
   │
   ▼  金融级在它之上再加一层(本篇):这套系统做的每一笔决策,能不能自证
   │
金融级增量 = "决策级举证"的四可(每一笔放行/拒绝,都要过这四关)
  ① 可追溯 ------ 谁调的、谁批的、走了哪条路           ← 接第 8 篇 Trace(可观测 → 可举证)
  ② 可复现 ------ 用当时那一版三元组,能证明当时凭什么 ← 接第 12 篇版本不可变 + 第 13 篇模型是耗材的正面冲突
  ③ 可追责 ------ 追到具体责任人,且申请人 ≠ 审批人      ← 接第 10 篇"放行/拒绝都可追到是谁"
  ④ 不可抵赖 ------ 记录防篡改,一改就断链、一断全废     ← 金融级增量核心(接第 12 篇指纹心智)
   │
   ▼  每一可的判据,全部复用前几篇立过的(不新造)
   │
落点:一个能核对的东西(这是本篇区别于"金融 AI 软文"的关键)
  决策记录数据(DecisionRecord:决策 id + 输入指纹 + 三元组版本 + 依据 + 操作人/审批人/责任人 + 前序链哈希)
        ├──► render_audit_table():把决策链渲染成人看的「决策审计表」(表给人看)
        └──► audit_all(records):逐笔核对 → PASS/FAIL/PENDING/NEEDS_HUMAN + 断链点
                               → 确定性吐出「这一笔能不能上法庭 + 断链在哪 + 待人工确认清单」
  一句话:表给人看,程序给人核;两者共用同一份数据,所以不会打架。

先点破这一刀:系统级通过 ≠ 决策级通过。 我把政企五关全过了一遍,不等于金融级过了------它们问的是两个问题。五关问"这东西能不能进我的网、谁来养",四可问"它做的那一笔决定,出了事我能不能自证清白"。顺序也不能反:先过五关、再叠四可 ------系统都进不来,谈决策级举证是空的。这是第 16 篇"先过边界、再谈性能"在金融语境里的续写:先能举证、再谈性能。

2.1 四可核对表(本篇的骨架)

整篇里这张表最实用,你可以直接抄走。每一可的判据都标了出处,坐实"判据复用、不新造"。

四可(金融问的第一个问题) 它会怎么卡你 你该拿什么去核 判据来源(前篇立过的)
① 可追溯 只有结果没过程 → 说不清"谁做的、凭什么做的" 决策留痕:接入链路 + 操作人 + 审批人 + 命中规则 第 8 篇《OTel + LangFuse 全链路 Trace》"Trace = 谁调的、谁批的、走了哪条路可回溯"+ 第 2 篇《Golden Set 评测》评测记录
② 可复现 模型/Prompt/数据版本漂了 → 用当时的版也证明不了 三元组版本指纹 + 依据快照(冻结、可归档,不要求逐字一致) 第 12 篇《数据工程底座》"版本不可变"+ 第 13 篇《LLMOps 不完全指南》"模型是耗材 / 指针级回滚的正面冲突"
③ 可追责 申请人=审批人 / 责任人字段缺失 → 追不到具体的人 责任人字段 + 职责分离(申请人≠审批人)+ 审批留痕 第 10 篇《Human-in-the-Loop 反馈闭环》"放行/拒绝都能追到是谁、凭什么"
④ 不可抵赖 日志能被改/删/补 → 拿出去举不了证 哈希链:记录防篡改------改一处,后面整段对不上(防篡改 + 可验证) 金融级新增(增量核心;指纹心智接第 12 篇《数据工程底座》"版本不可变")

2.2 四可逐个说清"它会怎么卡你 + 你该拿什么去核"

① 可追溯:不是"有没有记",是"记下来能不能说清是谁、凭什么"。 这一可的判据最直接------第 8 篇立过的全链路 Trace:"谁调的、谁批的、走了哪条路可回溯"。金融级只是把它从"可观测"推成"可举证":Trace 过去是给你自己排查问题看的,现在要能原样交出去当证据。所以一条决策记录里,必须有操作人、有命中的规则/引用的条款(我叫它 grounds)、有输入指纹。少了"凭什么",审计员问一句你就哑。这一可有强监管锚 :信贷场景的《商业银行互联网贷款管理暂行办法》要求风险模型全过程文档化归档、供本行和监管随时查阅;2025 年底的《银行业保险业数字金融高质量发展实施方案》又把"提升算法透明度和可解释性"统一提了一遍。但要说清楚------它是"原则性表述 + 分场景强制留痕",没有一条专门叫"AI 决策可追溯"的技术标准。

② 可复现:弱锚,只有框架的原则性要求------所以我把标准定成"关键依据一致"。 这一可跟第 13 篇"模型是耗材、随时换"天生打架,我在取舍点③展开。这里先说判据:第 12 篇的"版本不可变"给了它心智------用当时那一版三元组(模型/Prompt/数据),能证明当时凭什么这么判。注意"证明"两个字:可复现不是要你把老模型养一辈子真跑,是要你留一条"能证明当时凭什么这么判"的最小链。 监管侧这一可最弱------只有模型风险管理框架的原则性要求(验证、监控、文档化),没有"必须逐字复现 AI 决策"的强制条款。所以我照取舍点③写:分层、关键依据一致,不苛求逐字。

③ 可追责:有强监管锚,而且"申请人 ≠ 审批人"这条能直接挂上去。 第 10 篇立过"每一次放行/拒绝都能追到是谁、凭什么";金融把它推成硬约束:不仅"能追到",还要"追到的是被分开的两个角色"。《商业银行内部控制指引》要求不相容岗位分离、重要岗位轮岗------"申请人 ≠ 审批人"这条,直接挂"不相容岗位分离"(条文编号进附录)。再加金融监管总局"谁使用谁负责"的原则:AI 不背锅,人和机构是最终责任主体。所以可追责就是三件事:责任人字段必填、有独立的人工审批留痕、申请人 ≠ 审批人。这三件缺一件,出了事你就追不到具体的人。

④ 不可抵赖:这条得正面说清楚------它是"工程自保",不是"监管强制"。 这是全篇最容易得罪人、也最容易被审稿盯的一刀,我不绕:目前没有"金融 AI 决策日志必须防篡改/哈希链"的强制技术标准。 我翻了一圈公开口径,能挂上的只有"密码学手段"的技术参照------区块链存证、可信时间戳、金融分布式账本安全这一类国标/行标,它们定义的是"怎么用哈希/时间戳做存证、防篡改、可核验",但都不是"金融 AI 决策日志"的强制要求 。所以这一可的定位是:我做哈希链,是为了让记录"改了你验得出来",是工程上的自保,不是满足某个必须过的监管条款。 你被审计员问"这日志能改吗"的时候,能当场自己验一遍------这就够了。别把工程自保吹成监管强制,这是这一篇最要紧的诚实。

2.3 判据复用表:三可的判据前篇全立过,第四可(不可抵赖)是金融级新增、心智接第 12 篇

这张表的信任来源就在这儿:上面每一可的判据,都是前面某一篇在真实场景里立过的,我不是临时编一套标准来评金融。

可 判据来源(前篇立过的) 一句话
可追溯 第 8 篇《OTel + LangFuse 全链路 Trace》 Trace = 谁调的、谁批的、走了哪条路可回溯(可观测 → 可举证)
可追溯 第 2 篇《Golden Set 评测》 "当时那版凭什么被评过",评测记录也是决策链的一部分
可复现 第 12 篇《数据工程底座》 版本不可变:用当时那一版能证明当时凭什么这么判
可复现 第 13 篇《LLMOps 不完全指南》 模型是耗材 → 与"能复现"正面冲突,解法是分层留最小举证集
可追责 第 10 篇《Human-in-the-Loop 反馈闭环》 放行/拒绝都能追到是谁、凭什么 → 推成"责任人 + 职责分离"
不可抵赖 第 12 篇《数据工程底座》 内容指纹当身份:能被验证的才是真的 → 哈希链
增量边界 第 16 篇《政企国产化避坑》 五关是系统级、四可是决策级;系统级通过 ≠ 决策级通过
全局映射 开篇《四大支柱》 金融级不是新框架,是四大支柱被监管逼到举证级

2.4 外层监管层:只给边界,不重建立五关

四可外面还压着一层监管约束:留痕期限、双录、报送、等保密评更严、数据分级、容灾高可用、职责分离。这些我一个都不展开------它们是第 16 篇和附录的活,本篇只点边界,且口径全标待核实:

  • 留痕期限 :没有统一数字,取决于留的是什么------双录、反洗钱交易记录、生成式 AI 日志各是一档,"AI 决策留痕"本身没有专属统一期限。
  • 双录:强制要求锚在"销售行为"上,"AI 决策要不要双录"核不到统一强制口径,目前是团体标准和厂商方案。
  • 报送:对外/有舆论属性的 AI 可能触发算法备案、仅内部使用一般豁免,"金融 AI 是否必然触发"口径未统一(待核实)。
  • 等保/密评:金融系统等保、密评要求更严,具体等级按机构与系统定(口径统一、等级按系统,待核实)。
  • 数据分级:有明确标准(标准侧五级、监管侧三级四类两套颗粒度),敏感级数据进测试环境要脱敏、到期限要删到不可恢复。
  • 容灾:金融核心系统有公开的灾难恢复等级口径,两地三中心是优选架构(厂商口径,待核实);AI 决策审计链是信息系统的一部分,套同一套口径,不因是大模型单独给个标准。RTO/RPO 具体数值只给量级、一律待核实。
  • 职责分离:有明文依据(不相容岗位分离),已落到四可③里。

这张清单的生产化,就一句话:一张"监管维度 × 依据 × 口径 × 核实日期"的数据表 + 一个核对器。 本篇 demo 的两张数据表(决策记录 DecisionRecord + 审计要求 Policy)就是它的最小 schema------换成你们机构真实的口径数据,加个前端,它就是你们机构的"决策审计平台"。

还有一件事得单独说:判定是四态 ,不是两态。金融的现实是"很多事你核不到确定答案"------留痕期限到底留几年、AI 决策要不要双录,这些都没有统一口径。只给 PASS/FAIL 的核对器会逼你替监管编一个答案;四态让"我不知道"成为合法结论,并把这些"我不知道"单独收进一张待人工确认清单 ,交接给合规口和法务去补。一个诚实的审计链,不只告诉你哪些笔能自证,还要把"我不确定的那部分"原样交出来------少了这一条,"金融级"三个字就站不住。

再说清"四可"这个词:它是我为了"能对着核"做的工程化归纳,不是某个监管文件的官方分类。 但它不悬空------可追溯/可复现能挂到算法金融应用评价规范的评价判据上,可追责挂不相容岗位分离,不可抵赖挂区块链存证/可信时间戳的国标参照,整体还能对到模型风险管理的"验证---监控---文档化"框架。我不发明官方口径,我只是把"金融落地时你每一笔决策都得挨个核的那四件事"编成一张能核的表。

2.5 三个取舍点(每个都有代价)

取舍一:"能举证 > 跑得动"------金融级的第一性是"事后能自证",不是"事前跑得快"。 互联网/政企通用场景,第一性是"能不能用、快不快、谁来扛";金融级要把它翻过来------一笔决策哪怕被判"拒绝",也必须是可举证的拒绝 (凭什么拒、依据哪条规则、谁批的)。所以系统要在正常业务链路上额外挂一条"举证链"(决策留痕 + 防篡改 + 可复现),这条链会在延迟、吞吐、成本上收税。代价我认三条 :① 每条决策都要落审计记录 + 算链哈希,写放大、延迟增加(量级随实现浮动,本行只定性、不编数字);② 为了可复现,三元组版本得冻结、不能随便热更,发布自由度下降(跟第 13 篇"模型是耗材"直接顶牛);③ 职责分离强制多加一道人工审批,业务流程变长、人效下降。我认,因为在金融,一笔"说不清凭什么"的放行,比一笔慢 200ms 的放行危险不在一个量级------前者出事你举不了证,责任就落你自己头上。

取舍二:"不可抵赖"要靠密码学,不是靠"我日志里写了"------但它是工程自保、不是监管强制。 很多团队以为"我记了日志 = 可审计",可日志能被改、能被删、能对不上。金融级要的是不可抵赖 :决策记录必须防篡改(哈希链/签名),一改就断链、一断就全废,还得能证明"这条记录就是当时那条"。第 12 篇那句"能被验证的才是真的",搬到日志上就是哈希链:记录不是写下来就算数,是能被验证才算数。 但必须说清------金融对"AI 决策日志必须防篡改"没有统一强制技术标准,只有密码学手段的国标/行标当技术参照,所以这条是工程自保。你的哈希链做的是让记录"改了你验得出来",不是满足某个必须过的监管条款。代价: ① 哈希链/签名带来额外计算和存储(每次决策一次哈希、密钥得管);② 密钥管理本身是个大活(丢了/轮换了,历史链怎么验,得提前设计);③ 链一旦定死就难回改------记录顺序、字段口径得一次定对,事后补一条或改一个字段,从断点往后全链重算。我认,因为谁都能改的日志是自说自话------对方一句"这日志是不是事后补的"就把你问住。**

取舍三:"可复现"跟"模型是耗材"天然打架------你得在"换模型"和"能举证"之间做取舍。 第 13 篇我立过"模型是耗材、可迁移性第一天设计",鼓励你随时换模型;可金融级又要求"用当时的版本能证明当时的决策"。这两件事是矛盾的:模型换得越勤,历史决策的复现成本越高。所以金融级的做法是分层 :不是要你留着所有老模型能真跑,而是留"可举证的最小集"------决策当时的三元组版本指纹 + 依据快照 + 输出摘要;能不能真重放出逐字一致反而次要(LLM 有随机性、有温度、甚至供应商静默更新),关键是"当时的依据链没断"。代价: ① "复现"的"一致标准"要提前定义(逐字一致 vs 关键依据一致------金融里通常是后者);② 老版本组件要归档、不能删,存储和维护成本上升;③ LLM 的固有随机性让"逐字复现"在很多情况下根本做不到,只能退到"依据可复现"。我认,因为可复现不是要你把老模型养一辈子,是要你留一条"能证明当时凭什么这么判"的链------链在,就举得了证。

2.6 边界:这篇不是什么

三层边界,缺一层就滑向软文或政策文:不是"金融 AI 落地案例秀"的软文 (不吹任何一家机构/厂商、不写"某银行上线后效率提升 X%"------本篇给的是"每一笔决策怎么变成可举证的记录 + 一个能核的落点");不是金融监管政策解读/条文复述 (不复述政策原文、不假装我有一份权威的"金融 AI 合规清单"------恰恰相反,本篇点破"监管口径又多又碎、很多没有统一技术标准,别把一篇营销号的'金融 AI 合规要点'当依据");不是风控模型测评 (一句不比"哪个风控模型准"------准确率是模型评测的事,可举证是工程纪律的事,两件事)。另外两条:不重讲前十六篇的细节 (四可判据只引用、各一句);不抢下一篇的活(把全专栏拼成一张总图那件事,推给收官篇)。

三、代码实战:一个纯标准库的金融级决策审计链核对器

"每一笔决策能自证"正是本篇区别于"金融 AI 软文"的唯一硬落点。所以这一篇的落点是一个离线可跑、纯标准库、无 API key、无第三方依赖的核对器:把每一笔决策编码成一条带链哈希的可举证记录,跑通"先验哈希链完整性 → 逐笔核四可 → 汇总结论 + 断链点 + 待人工确认清单 → 渲染成人看的决策审计表"。一篇案例秀不用跑也能看,一条能验的审计链不跑就不知道断在哪。

文件结构跟前几篇的 govcheck/、toolmap/、release/ 同级:

复制代码
auditchain/
├── mini_auditchain.py        # 主代码:Triplet / DecisionRecord / Policy / VerdictItem / ChainReport
│                             #         + chain_hash / verify_chain / build_chain / replay
│                             #         + audit_decision / audit_all / explain / render_audit_table
│                             #         + load_policies / load_registry / build_demo(纯标准库 hashlib,离线可跑)
└── test_mini_auditchain.py   # 9 个断言,锁"链一断全废 / 四可缺一不予放行 / 申请人≠审批人 /
                              #   版本对不上不可复现 / 放行拒绝对称留痕 / 核不到标 pending /
                              #   结论可对账 / 待人工确认清单完整 / 审计要求一改结论就改"

正文只贴关键节选、为便于阅读对 docstring 做了略精简、对函数体用了 ... 占位 (不是逐字原样)。没露面的辅助函数 ------load_registry(在册版本集数据源)、_judge(按规则名分派判定)、_overall_of(逐笔整体判定)、_verify_mark(核实标记)、_action_cn(动作中文名)、_demo_records(构造示意决策链)、_print_chain(打印链核对),以及各条判定规则(rule_accountable 等 rule_*)与规则表 RULES / DIM_CN------都在 auditchain/mini_auditchain.py 里。别照抄正文片段去拼,直接跑整个文件 (python auditchain/mini_auditchain.py)。

3.1 数据结构:决策是数据,不是一行日志

这是整份代码存在的前提------把"举证要哪些字段"焊进 schema。每个字段的"为什么"都写在 docstring 里:

python 复制代码
@dataclass
class DecisionRecord:
    """一条决策记录 = 一份可举证的证据(不是一行日志)。

    为什么决策要做成「数据」而不是「一行日志」:
    "谁、凭什么、依据哪版"这三件事,一条记录里没有,后面再补就补不回来------把「举证要哪些字段」
    焊进 schema,比事后补日志靠谱得多。
      action       动作:放行 / 拒绝 ------ 一视同仁,都要留痕
      triplet      三元组版本(模型/Prompt/数据指纹)------ 可复现的锚
      grounds      依据(命中规则 / 引用条款)------ 可追溯的锚
      operator     操作人(谁调的)    approver 审批人(谁批的,必须 ≠ operator)    owner 责任人(出事追到谁)
      prev_hash    前序链哈希          chain_hash 本条链哈希 ------ 不可抵赖的锚
    """
    decision_id: str
    ts: str
    scenario: str
    action: str
    input_fp: str
    triplet: Triplet
    grounds: list[str] = field(default_factory=list)
    operator: str = ""
    approver: str = ""
    owner: str = ""
    prev_hash: str = ""
    chain_hash: str = ""

审计要求也做成数据------这是"口径会烂、审计链得跟着变"的落点:

python 复制代码
@dataclass
class Policy:
    """一条审计要求 = 一行数据(不是一段写死的 if-else)。

    为什么审计要求要做成数据:
    "监管口径是一张会烂的活"------口径会更新、会新增、会有冲突。做成数据,要求变了你改数据就行;
    写成 if-else,明天多一条口径你就得重构。
      dimension   维度(四可之一,或外层监管维度如留痕期限/数据分级/双录)
      clause      依据(这条要求管什么)------"凭什么这么判"
      rule        判定规则名(RULES 里的键)------判定逻辑本身也是数据引用,不是散落的 if
      verified_at 核实日期;None 表示没核过(输出里显式标 pending)
    """
    item_id: str
    dimension: str
    clause: str
    applies_when: object          # callable(DecisionRecord) -> bool
    rule: str
    source: str
    verified_at: str | None = None

判定是四态不是两态------金融监管口径又多又碎,四态是为了让"我不知道"成为合法结论:

python 复制代码
PASS = "PASS"                # 过(且在核实的口径内)
FAIL = "FAIL"                # 卡住(四可里任一 FAIL,这一笔就举不了证)
PENDING = "PENDING"          # 核不到权威口径(如留痕期限没统一标准),只能标待核实
NEEDS_HUMAN = "NEEDS_HUMAN"  # 口径冲突/边界模糊,需人工判断
VERDICTS = (PASS, FAIL, PENDING, NEEDS_HUMAN)

3.2 哈希链那一刀:一改就断链、一断全废

这是本篇最硬的一条纪律,也是最容易被审稿盯的一条。核心就两句:算哈希、从头重算:

python 复制代码
def chain_hash(record: DecisionRecord) -> str:
    """算一条记录的链哈希 = H(prev_hash + 本条规范化内容),标准库 hashlib.sha256。

    为什么用哈希链而不是「存条日志 + 加个 id」:
    日志能被改、能被删、能对不上------哈希链让「改一条」必然导致「它的链哈希对不上」,
    而它的链哈希又是下一条 prev_hash 的一部分,于是一改就断链、一断全废。
    字段之间用 \x1f(不可见分隔符)拼,避免「ab|c」和「a|bc」拼出同一个字符串这种拼接歧义。
    """
    t = record.triplet
    parts = [
        record.prev_hash or GENESIS, record.decision_id, record.ts, record.scenario,
        record.action, record.input_fp, t.model_fp, t.prompt_fp, t.data_fp,
        "\x1e".join(record.grounds or []), record.operator, record.approver, record.owner,
    ]
    payload = "\x1f".join(parts)
    return hashlib.sha256(payload.encode("utf-8")).hexdigest()
python 复制代码
def verify_chain(records: list[DecisionRecord]) -> tuple[bool, int | None]:
    """链完整性核对:返回(是否完整,第一个断点的下标)。这是「不可抵赖」的落点。

    为什么要「从头发到尾重算」而不是「比对一下存的值」:存的值本身可能就是被改过的------
    只有重算才能发现「内容被动过」;而一旦动过,它之后的每一条都建在一条假链上,所以断点及其之后全废。
    """
    prev = GENESIS
    for i, r in enumerate(records):
        if r.prev_hash != prev:
            return False, i
        if r.chain_hash != chain_hash(r):
            return False, i
        prev = r.chain_hash
    return True, None

3.3 可复现是"版本对得上",不是"逐字一致"

这一条是取舍点③的代码落点,也是跟第 13 篇"模型是耗材"顶牛的地方。核对器不假装能重放 LLM 的逐字输出------它核的是"当时那一版还在不在、依据链还在不在":

python 复制代码
def replay(record: DecisionRecord, registry: set[str]) -> tuple[bool, str]:
    """可复现核对:record.triplet 的三版在不在册(registry = 在册版本集)。

    为什么核的是版本在不在、不是逐字一致:
    LLM 有随机性、供应商会静默更新(换权重不换名)、数值舍入和专家路由都会让输出飘------
    「逐字复现」在很多场景根本做不到。金融级要的是「关键依据可复现」:当时那一版还在册、
    依据链没断,就足以证明「当时凭什么这么判」。
    """
    t = record.triplet
    missing = [name for name, fp in
               (("模型", t.model_fp), ("Prompt", t.prompt_fp), ("数据", t.data_fp))
               if fp not in registry]
    if missing:
        return False, (f"三元组版本不在册:{'、'.join(missing)}------版本漂了、组件下架了,"
                       f"用今天的版重放不出当时那笔(核的是版本在不在,不是逐字一致)")
    return True, (f"三元组三版均在册[{t.model_fp} / {t.prompt_fp} / {t.data_fp}]:依据链未断"
                  f"(只核版本对得上,不假装重放 LLM 逐字输出)")

3.4 主核对:先验链、再逐笔核四可

python 复制代码
def audit_all(records, policies=None, registry=None) -> ChainReport:
    """主核对:先验链完整性(断链则断点及其之后全标记链不可信)→ 逐笔核四可 → 汇总。

    为什么先验链、再逐笔核:链一断,断点之后的记录全建在假链上,先给它们盖个「链不可信」的戳,
    再逐笔核才有意义------否则你会对着一条被改过的记录认真核「依据全不全」。
    为什么放行和拒绝走完全一样的核对:audit_all() 对 action 不做任何区分------
    一笔「说得清凭什么」的拒绝,和一笔「说得清凭什么」的放行,价值一样高。
    manual_review = 所有 PENDING/NEEDS_HUMAN 的条目(一个诚实的审计链要把「我不确定的那部分」
    单独交出来,而不是混在结论里蒙混过去)。
    """
    policies = list(load_policies() if policies is None else policies)
    registry = set(load_registry() if registry is None else registry)
    ok, broken_at = verify_chain(records)

    verdicts: list[VerdictItem] = []
    for i, r in enumerate(records):
        # 断点之前的笔不受影响;断点及其之后的所有笔一律标记「链不可信」(一断全废)。
        chain_ok = (broken_at is None) or (i < broken_at)
        verdicts.extend(audit_decision(r, policies, registry, chain_ok))
    ...

跑 python auditchain/mini_auditchain.py(build_demo())会打印 7 个确定性场景(并给出 9 条确定性结论)。注意:这里的数据全是【示意,待核实】,下面贴的是跑出来的输出,它是对示意数据的确定性结论,不是对真实监管/机构的评价:

复制代码
==============================================================================
金融级决策审计链核对器 demo(数据全部为【示意,待核实】)
==============================================================================
四可(每一笔放行/拒绝都要过的四关):① 可追溯  ② 可复现  ③ 可追责  ④ 不可抵赖
外层监管维度(只给边界、只标待核实):留痕期限 · 数据分级 · 双录
一句话:政企五关管的是「这套系统能不能进来」(系统级);
        这四可管的是「它做的每一笔决策能不能上法庭」(决策级)------系统级通过 ≠ 决策级通过。

==============================================================================
[表给人看] render_audit_table()(表与 audit_all 共用同一份决策数据):
| 决策 id | 场景 | 动作 | 操作人 | 审批人 | 三元组版本 | 判定 |
|---|---|---|---|---|---|---|
| D-001 | 信贷审批 | 放行 | op-01 | ap-01 | model:v3.2/prompt:p17/data:ds-2026q1 | 可举证 |
| D-002 | 风控辅助 | 拒绝 | op-02 | ap-01 | model:v3.2/prompt:p17/data:ds-2026q1 | 可举证 |
| D-003 | 信贷审批 | 放行 | op-03 | ap-02 | model:v3.1/prompt:p16/data:ds-2026q1 | 可举证 |
| D-004 | 信贷审批 | 拒绝 | op-04 | ap-02 | model:v3.2/prompt:p17/data:ds-2026q1 | 可举证 |
| D-005 | 风控辅助 | 放行 | op-05 | ap-03 | model:v3.2/prompt:p17/data:ds-2025q4 | 可举证 |

==============================================================================
[场景 1] 干净链:逐笔核四可(放行和拒绝走完全一样的核对)
  D-001 [放行] -> 可举证   FAIL[无]   非决定性[留痕期限、数据分级、双录]
  D-002 [拒绝] -> 可举证   FAIL[无]   非决定性[留痕期限、数据分级、双录]
  D-003 [放行] -> 可举证   FAIL[无]   非决定性[留痕期限、数据分级、双录]
  D-004 [拒绝] -> 可举证   FAIL[无]   非决定性[留痕期限、数据分级、双录]
  D-005 [放行] -> 可举证   FAIL[无]   非决定性[留痕期限、数据分级、双录]
  -> 决策审计链:5 笔决策;链完整性[完整];可举证 5 笔 / 不可举证 0 笔 / 待人工 0 笔;待人工确认 15 项(对示意数据的确定性结论,非对真实监管/机构的评价)

==============================================================================
[场景 2] 篡改第 3 笔(D-003)的 grounds------不可抵赖:一改就断链、一断全废
  verify_chain() -> 链完整[False];第一个断点下标[2](= D-003)
  断链后重核:断点(含)之后全标记「链不可信」,断点之前不受影响
  D-001 [放行] -> 可举证   FAIL[无]   非决定性[留痕期限、数据分级、双录]
  D-002 [拒绝] -> 可举证   FAIL[无]   非决定性[留痕期限、数据分级、双录]
  D-003 [放行] -> 不可举证   FAIL[不可抵赖]   非决定性[留痕期限、数据分级、双录]
  D-004 [拒绝] -> 不可举证   FAIL[不可抵赖]   非决定性[留痕期限、数据分级、双录]
  D-005 [放行] -> 不可举证   FAIL[不可抵赖]   非决定性[留痕期限、数据分级、双录]
  -> 决策审计链:5 笔决策;链完整性[断链@D-003(下标 2)];可举证 2 笔 / 不可举证 3 笔 / 待人工 0 笔;待人工确认 15 项(对示意数据的确定性结论,非对真实监管/机构的评价)

==============================================================================
[场景 3] 申请人 = 审批人(职责分离违规)------可追责 FAIL
  D-002 可追责 -> FAIL
  理由:职责分离违规:申请人=审批人(operator==approver)------出事追不到具体责任人(银监发〔2014〕40 号第 18 条不相容岗位分离)

==============================================================================
[场景 4] 三元组版本不在册------可复现 FAIL(核的是版本在不在,不是逐字一致)
  D-004 可复现 -> FAIL
  理由:三元组版本不在册:模型------版本漂了、组件下架了,用今天的版重放不出当时那笔(核的是版本在不在,不是逐字一致)

==============================================================================
[场景 5] 每条结论可对账:explain() 逐条给维度/依据/出处/核实日期
  维度[不可抵赖] 判定[PASS] 决策[D-001]
  依据[不可抵赖:记录防篡改(哈希链),一改就断链、一断全废------工程自保,非监管强制]
  出处[第 12 篇内容指纹心智;密码学手段技术参照 GB/T 43580-2023 区块链存证 / GB/T 20520 时间戳 / JR/T 0184-2020 金融分布式账本]
  核实[2026-09(技术参照,非强制)]
  理由:链哈希匹配且本笔在链完整段内:这条记录改了你验得出来(一改就断链)
  维度[留痕期限] 判定[PENDING] 决策[D-001]
  依据[留痕期限:AI 决策留痕本身无专属统一期限,落到具体数据类型上]
  出处[双录/反洗钱/生成式日志多档并存,口径未统一(待核实)]
  核实[pending]
  理由:留痕期限口径未统一(双录 / 反洗钱 / 生成式日志各是一档),「AI 决策留痕」无专属统一期限------需人工确认,不硬给数字

==============================================================================
[场景 6] 审计要求是数据:加一条「双人复核」要求 → 结论随之变化,audit_all 一行不改
  加之前:待人工确认 15 项
  加之后:待人工确认 20 项(多出的就是新增维度「双人复核」)
  -> 数据改了结论就改,不用动 audit_all() / _judge() 一行代码。

==============================================================================
[场景 7] 待人工确认清单 = 所有非决定性判定的集合(不多不少)
  · D-001 [留痕期限] PENDING:留痕期限口径未统一(双录 / 反洗钱 / 生成式日志各是一档),「AI 决策留痕」无专属统一期限------需人工确认,不硬给数字
  · D-001 [数据分级] PENDING:数据分级口径未统一(标准侧五级 vs 监管侧三级四类),涉敏感级决策的脱敏/加密到什么程度无统一强制------需人工确认,按机构数据分级细则落地
  · D-001 [双录] NEEDS_HUMAN:「AI 决策要不要双录」无统一强制口径(现有双录锚在销售行为上,AI 双录是团体标准/厂商方案)------口径冲突,需人工判断(不硬给 PASS,也不硬给 FAIL)
  · ...共 15 项(= 所有 PENDING / NEEDS_HUMAN 的条目)

==============================================================================
九条确定性结论(对示意数据的确定性结论,不是对真实监管/机构的评价):
  1. 链一断,整条链全废------改第 3 笔,断点(含)之后全标记链不可信,断点之前不受影响。
  2. 四可缺一,这一笔就不予放行------可追溯/可复现/可追责/不可抵赖,任一 FAIL 即不可举证。
  3. 申请人 = 审批人 → 可追责 FAIL------职责分离是金融内控硬要求(不相容岗位分离)。
  4. 可复现 = 三元组版本对得上,不是逐字一致------版本不在册就判不可复现。
  5. 放行和拒绝一视同仁------action 不改变要核什么,拒绝笔走和放行笔一样的核对。
  6. 核不到口径的老实标 PENDING(如留痕期限),不编一个数字。
  7. 每条结论能对账到依据------explain() 给维度/依据/出处/核实日期。
  8. 待人工确认清单 = 所有 PENDING/NEEDS_HUMAN 的集合,不多不少。
  9. 审计要求是可增删的数据------加一条 Policy,结论随之变,核对逻辑一行不改。

读一遍这个输出,主线就出来了:同一批决策 ,一改第 3 笔,断链点之后三笔全废、断链之前两笔不受影响------"一改就断链、一断全废"不是口号,是跑出来的;把某个业务员的"申请人"和"审批人"设成同一个账号,可追责当场 FAIL;把模型版本换成一个不在册的,可复现当场 FAIL;放行笔和拒绝笔走的是完全一样的核对(你看场景 1 里两列维度一模一样);核不到的口径(留痕期限)老实标 PENDING,单列一张"待人工确认清单",不混进结论里蒙混过去。

3.5 9 个断言怎么把这些结论钉死

test_mini_auditchain.py 用纯标准库 unittest,两种跑法都行:

bash 复制代码
python auditchain/test_mini_auditchain.py     # 在仓库根目录下
python -m unittest test_mini_auditchain        # 在 auditchain/ 目录下

九个断言,对应本篇的九个命题句。挑三条说透:

断言①"链一断,整条链全废"是本篇的命题句。 它构造一条 5 笔的链,改中间第 3 笔的 grounds,断言 verify_chain() 返回 (False, 2),且断点及其之后的每一笔"不可抵赖"都 FAIL、断点之前不受影响:

python 复制代码
def test_01_break_chain_discards_all_after(self):
    recs = build_chain([_valid_record(i) for i in range(1, 6)])   # 5 笔
    ok, idx = verify_chain(recs)
    self.assertTrue(ok)
    self.assertIsNone(idx)

    recs[2].grounds = ["被改过的依据(事后补的)"]                 # 篡改第 3 笔(下标 2)
    ok, idx = verify_chain(recs)
    self.assertFalse(ok)
    self.assertEqual(idx, 2)                                     # 断点就是第 3 笔

    rep = audit_all(recs)
    # 断点(含)及其之后的所有笔:不可抵赖 FAIL(链不可信)
    for r in recs[2:]:
        v = _find(rep, r.decision_id, NON_REPUDIABLE)
        self.assertEqual(v.verdict, FAIL)
        self.assertIn("链不可信", " ".join(v.reasons))
    # 断点之前的笔不受影响
    for r in recs[:2]:
        self.assertEqual(_find(rep, r.decision_id, NON_REPUDIABLE).verdict, PASS)

断言③"申请人 ≠ 审批人"是金融级最硬的一条。 它不只断判定是 FAIL,还断理由里点名"职责分离"和"申请人=审批人"------把这条纪律的措辞也钉进测试。想亲手验证这刀很容易:把 rule_accountable 里那句 operator == approver 的判断删掉再跑,断言③当场就红。

断言⑧"待人工确认清单不多不少"是核对器诚实度的落点。 它断言 manual_review 的条目集合恰好等于所有 PENDING/NEEDS_HUMAN 的集合------一个诚实的审计链不只告诉你"哪些笔能自证、哪些不能",还要把"我不确定的那部分"单独交出来,交接给合规口/法务去补口径。其余六条------②四可缺一不予放行、④可复现=版本对得上、⑤放行拒绝对称留痕、⑥核不到标 pending、⑦每条结论可对账、⑨审计要求一改结论就改------都在 test_mini_auditchain.py 里,命名和命题句一一对应,就不逐个展开了。

四、踩坑记录:这三个坑,每个都真付过费

4.1 我以为"记了日志"就=可审计,结果审计员一句"这日志能改吗"把我问住

症状:可追溯这块我以为最简单------每次决策我都记了日志,谁调的、什么时候、结果是什么,一应俱全,我自认为可审计。结果有一次内部审计,审计员问了一句:你这日志存在哪、谁能改、怎么证明你现在给我看的这条就是当时那条?我一下哑了------日志就在业务库里,运维能改、开发能删,我拿不出任何"这条记录没被动过"的证明。

排查:根因是我把"可审计"简化成了"有没有记",其实金融级要的是不可抵赖 ------记下来只是一半,能不能证明它没被改过是另一半。

修复:给决策记录加哈希链(每条记录的链哈希 = 上一条链哈希 + 本条内容的哈希),一改就断链、一断全废;审计员随时能自己验一遍。教训:能被改的日志,不叫证据------你要证明的不是"我记了",是"这条记录没被动过"。 但也别把这一刀说歪:金融对"日志必须防篡改"没有统一强制技术标准,这是工程自保,不是监管强制------我事后专门跟客户合规口对齐过这件事,免得被当成"我们满足某条强制要求"去汇报。

4.2 客户投诉要我复现三个月前那笔拒绝决策,我复现不出来

症状:客户对一笔三个月前的 AI 拒绝不满、投诉到监管,监管要我把那笔决策复现一遍。我去复现,才发现那笔决策只留了结果("审核未通过"),没留当时的依据(命中了哪条规则、引用了哪份知识)、没留当时的版本(模型是哪一版、Prompt 是哪一版)------而这三个月里模型升级过、Prompt 改过好几轮,我用今天的版本怎么跑都对不上当时那笔。

排查:根因是我把"可复现"理解成了"系统能重跑",可重跑 ≠ 复现------复现要的是"用当时那一版、当时那份依据,能证明当时为什么这么判",我什么都没留。

修复:决策时就把三元组版本指纹(模型/Prompt/数据)+ 依据快照 + 输出摘要冻结留存,能归档、能对账;复现的标准定成"关键依据一致",不苛求逐字一致(LLM 有随机性,逐字一致在很多场景做不到)。教训:可复现不是要你把老模型养一辈子,是要你留一条"能证明当时凭什么这么判"的链------留痕留到能举证为止,不是留到"记过"为止。(这一坑跟第 13 篇"模型是耗材"正面顶牛,我上面取舍点③如实写了这对矛盾。)

4.3 出了事要追责,我发现"申请人"和"审批人"是同一个人

症状:一笔由 AI 建议、人工确认的信贷放款后来成了坏账,要追责。我调记录一看------系统里"提交申请"和"审批确认"两步是同一个账号操作的(因为图省事,让业务员一个人点到底),AI 给了建议、同一个业务员点了"同意",流程就过了。真要追责时,追谁?追业务员"你不该信 AI"?追开发者"你不该让 AI 这么判"?追不到一个清晰的责任人。

排查:根因是我从没把职责分离当成硬约束------金融内控里"不相容岗位要分离"是基本要求,而我的系统把申请人、审批人合成了一个角色。

修复:审计链强制核"申请人 ≠ 审批人",相等就判 FAIL;责任人字段必填,缺了不许放行;AI 建议和人工确认各自留独立的操作人。教训:可追责的前提是"责任被分清了"------申请人=审批人的系统,出了事谁都追不到,等于没有责任人。

五、选型对比:三种做法,你该抄哪一种

5.1 大表:金融级"决策可举证"这条路的三种做法

做法 组织的维度 覆盖几可 结论能不能对账到依据 核不到的口径怎么处理 时效性怎么管 推荐指数
① 只记业务日志 按业务动作 看着有痕,实际不可举证 不能------日志没带依据链 没有"核不到"的概念,一律当"记过了" 无 ⭐⭐
② 上商业审计/合规平台 按平台定的口径 平台覆盖到哪算哪,LLM 决策链常不在范围 答案随平台口径走,带不走 平台怎么说就怎么说 平台升级才更新 ⭐⭐⭐
③ 按"四可"建自己的决策审计链(本篇 demo 就是最小实现) 按你的监管场景 四可 + 外层维度可逐项加 能------每条结论带维度/依据/出处/核实日期 核不到的条目老实进"待人工确认清单" 每条标核实日期 ⭐⭐⭐⭐⭐

结论:做法①是"记了但举不了证"(能被改、没依据链);做法②是"买了个别人的答案"(上手快,但口径未必适配你的监管场景、LLM 决策链常常不在它覆盖范围、数据还可能出域);做法③是"可复用、可对账、能自证",输入你的决策流水就给结论 + 依据 + 断链点,核不到的条目老实进"待人工确认清单"。 小团队不用一上来就把四可全填满,先把你自己监管场景真实要核的那几件填上(每可给判据 + 依据出处),审计链就比任何"合规平台"都实在;后面按需加项。

5.2 副表:金融级决策可举证的监管口径现状(2026,口径与期限待核实)

正文只给结论(完整版维度逐行、全标"待核实"的表格在附录 B):"不可抵赖"这一格,监管口径栏写的是"无统一强制技术标准,只有密码学手段的国标/行标技术参照"------它是工程自保。

5.3 可复用 checklist:金融级 AI 决策可举证 8 问

这八问是你落地时要挨个核的清单;本篇 demo 覆盖了其中可判定的几项(可追溯/可复现/可追责/职责分离/不可抵赖/留痕期限/数据分级),容灾这类只给边界的维度不在 demo 内、按机构口径自核------也是你能直接抄走的落地清单:

  1. 这一笔决策,谁调的、谁批的、走了哪条路,留全了吗(可追溯)?
  2. 当时那一版的模型/Prompt/数据,指纹留了吗,能对得上吗(可复现)?
  3. 出了事追到哪个具体的人,责任人字段填了吗(可追责)?
  4. 申请人 ≠ 审批人吗(职责分离)?
  5. 这条记录能被改吗,改了你验得出来吗(不可抵赖)?
  6. 你们的留痕要留多久、口径是哪来的(监管留痕)?
  7. 这套审计链自己扛不扛得住故障,灾备下审计不断吗(容灾)?
  8. 涉及敏感/涉密数据的决策,分级和脱敏做了吗(数据分级)?

六、总结 + 下一篇预告

回到开篇那个场景------监管来函要我把那笔拒绝决策复现一遍,我拿不出来。问题不在"系统跑不跑得动",在"每一笔决策能不能自证"。

一句话收口:金融级 AI 的第一性不是"跑得动",是"能举证"------政企五关问的是"这套系统能不能进来、谁来扛"(系统级),金融级问的是"它做的每一笔决策能不能上法庭"(决策级);可追溯、可复现、可追责、不可抵赖,四可缺一,日志就只是能被改的字符串。 顺序还是不能反:先过政企五关,再叠决策四可。

再说句大实话,也是本篇的信任来源:金融项目我只写实打实跑过的------我跑过信贷审批和一条风控辅助的 AI 落地;投顾、反洗钱这些我没真做过的,一律只给公开口径,不假装我懂每一类金融业务的风控模型。 一个把信贷/风控/投顾都说得像亲历过的人,你反而不敢信。

话说回来,行业纵深的两站------政企、金融------都讲完了;可这十七篇里立过的判据散在各处(评测门、Trace、版本不可变、五道关、四可......),你手里拿着一堆零件,还缺一张"我处在这个处境,该先上哪套纪律、该看哪个落点"的总图。下一篇(专栏收官)《全息地图》:把全专栏的四大支柱、三底座、行业落地,拼成一张"你的处境 → 该用哪套纪律 + 该落哪个核对器"的全息图------前面十七篇的判据在这张图上各就各位,你拿自己的处境一查,就知道从哪一篇开始读、该落哪个 demo。


附录 A:四可 → 判据 → 依据出处 → 对应前篇

可 判据(要核什么) 依据出处(口径/标准) 锚强度 对应前篇
① 可追溯 操作人 + 命中规则/引用条款 + 输入指纹 + 三元组字段齐 《商业银行互联网贷款管理暂行办法》(银保监会令 2020 年第 9 号)第 42 条风险模型全过程文档化归档;《银行业保险业数字金融高质量发展实施方案》(金办发〔2025〕95 号)"提升算法透明度和可解释性";JR/T 0221-2021 算法可追溯性 强(原则性表述 + 分场景强制留痕;无单一"AI 决策可追溯"技术标准) 第 8 篇、第 2 篇
② 可复现 三元组版本指纹在册 + 依据快照(关键依据一致,不苛求逐字) 模型风险管理框架的原则性要求(验证/监控/文档化);SR 11-7 三支柱;无"必须逐字复现 AI 决策"的强制条款 弱(框架参照 + 行业惯例) 第 12 篇、第 13 篇
③ 可追责 责任人字段 + 申请人 ≠ 审批人 + 人工审批留痕 《商业银行内部控制指引》(银监发〔2014〕40 号)第 18 条不相容岗位分离;金融监管总局"谁使用谁负责" 强(明文内控要求 + 原则性责任归属) 第 10 篇
④ 不可抵赖 哈希链:一改就断链、一断全废 无强制技术标准;技术参照:GB/T 43580-2023(区块链存证)、GB/T 20520(时间戳)、JR/T 0184-2020(金融分布式账本安全) 无监管强制锚------工程自保 第 12 篇

附录 B:金融级决策可举证的监管口径现状表(2026,全标"待核实")

正文一个口径都不编死,这张表才是"会烂的那部分"。每一行的"依据出处 / 口径 / 是否统一 / 核实日期"都标"待核实"------真实能不能过,取决于你机构适用的具体口径和你自己的落地。

监管维度 依据出处(待核实) 口径(待核实) 是否统一 核实日期
AI 决策可追溯/可解释 互联网贷款办法 + 金办发〔2025〕95 号 + JR/T 0221-2021 原则性表述 + 分场景强制留痕 + 评价规范;无"AI 决策可追溯"技术标准 不统一 2026-09(待核实)
可复现 / 模型可审计 模型风险管理框架(SR 11-7 参照 + 国内风险模型全流程) 原则性要求(验证/监控/文档化);无"逐字复现"强制条款 不统一 2026-09(待核实)
留痕期限 双录规定 / 反洗钱法 / 生成式 AI 日志口径 / 《人工智能示范法 3.0》草案(模型研发记录 ≥5 年,草案非现行法) 6 个月 / 3 年 / 5 年 / 10 年多档并存,取决于数据类型;"AI 决策留痕"无专属统一期限 不统一 2026-09(待核实)
双录是否延伸 AI 决策 银监办发〔2017〕110 号(销售行为双录) 现有双录锚在销售行为;"AI 决策要不要双录"核不到统一强制口径(AI 双录是团体标准/厂商方案) 核不到 2026-09(核不到)
报送要求 算法备案/生成式 AI 备案相关法规 对外/有舆论属性可能触发备案;仅内部使用一般豁免;"金融 AI 是否必然触发"口径未统一 口径未统一 2026-09(待核实)
数据分级 JR/T 0197-2020(分级指南)+ 金规〔2024〕24 号 标准侧五级 vs 监管侧"三级四类"两套颗粒度;敏感级进测试环境须脱敏 统一(但两套口径) 2026-09(待核实)
等保/密评 等保 2.0 + 密码应用基本要求(金融口径更严) 金融系统等保/密评要求更严;具体等级按机构与系统定 统一(等级按系统定) 2026-09(待核实)
容灾 银行业信息系统灾难恢复管理规范 公开灾难恢复等级口径,核心系统要求较高;两地三中心为优选;RTO/RPO 具体数值只给量级 统一 2026-09(待核实)
职责分离 银监发〔2014〕40 号第 18 条 不相容岗位分离、重要岗位轮岗,明文要求 统一 2026-09(待核实)
不可抵赖/防篡改 无强制标准;技术参照 GB/T 43580-2023 / GB/T 20520 / JR/T 0184-2020 无"金融 AI 决策日志必须防篡改"的强制技术标准;只有密码学手段的国标/行标可参照 无统一强制口径------工程自保,非监管强制 2026-09(技术参照,非强制)

附录 C:可引用公开口径清单(口径与条文以官方原文为准)

  • 《商业银行互联网贷款管理暂行办法》(银保监会令 2020 年第 9 号)第 42 条------风险模型全过程文档化归档、供本行和监管随时查阅(可追溯的强锚,信贷场景)
  • 《银行业保险业数字金融高质量发展实施方案》(金融监管总局办公厅,金办发〔2025〕95 号,2025-12)------算法模型全周期管理、提升算法透明度和可解释性、关键节点人工干预、防止模型漂移
  • 《商业银行内部控制指引》(银监发〔2014〕40 号)第 18 条------不相容岗位分离("申请人≠审批人"的直接依据)
  • 金融监管总局《关于银行业保险业人工智能安全开发应用的指导意见》------"谁使用谁负责"、压实金融机构主体责任、关键环节人工监督干预
  • JR/T 0221-2021《人工智能算法金融应用评价规范》(央行)------安全/可解释/精准/性能四维评价(可追溯性、可解释性判据的权威对照物;是评价规范,不是准入强制)
  • JR/T 0197-2020《金融数据安全 数据安全分级指南》、JR/T 0171-2020《个人金融信息保护技术规范》、《银行保险机构数据安全管理办法》(金规〔2024〕24 号)
  • 《中华人民共和国反洗钱法》(2024 修订)第 34 条------客户身份资料和交易记录至少保存十年
  • 《银行业金融机构销售专区录音录像管理暂行规定》(银监办发〔2017〕110 号)------双录锚在销售行为
  • JR/T 0044-2008《银行业信息系统灾难恢复管理规范》、GB/T 20988(信息系统灾难恢复规范)------容灾等级(RTO/RPO 数值待核实)
  • 密码学手段技术参照 :GB/T 43580-2023(区块链存证通用服务指南)、GB/T 43572-2023(区块链术语)、GB/T 20520(时间戳规范)、JR/T 0184-2020(金融分布式账本技术安全规范)------技术参照,非"金融 AI 决策日志"强制要求
  • 框架参照:SR 11-7(美联储/OCC,模型风险管理三支柱)、BCBS 239(风险数据聚合原则)、中国银行业协会《人工智能模型风险管理框架》

说明(口径统一性) :上表中"不相容岗位分离""数据分级标准号""容灾等级表""等保密评"有相对权威统一口径;而"AI 决策留痕留存期限""AI 决策是否要双录""算法备案是否必然触发(金融 AI)""可复现/可审计的强制技术条款""金融 AI 决策日志必须防篡改"口径不统一或核不到统一口径 ------这几类正文一律写成"核不到/待核实",不编死。"四可"这个说法是本篇为了可核对做的工程化归纳,不是某个监管文件的官方分类。

附录 D:审计链算法说明

demo 是纯标准库的确定性近似,不是真实合规审查、不是真实监管报送。

  • 为什么决策是数据不是一行日志 :DecisionRecord 把一笔决策拆成 (decision_id, ts, scenario, action, input_fp, triplet, grounds, operator, approver, owner, prev_hash, chain_hash)。为什么这么拆:"谁、凭什么、依据哪版"三件事,一条记录里没有,后面再补就补不回来------把举证要哪些字段焊进 schema,比事后补日志靠谱(踩坑②的代码落点)。
  • 为什么哈希链能"一改就断链" :chain_hash(r) = H(prev_hash + 规范化内容),verify_chain() 从头发到尾重算,任一条对不上就在那一条断链。为什么不是比对存量:存量本身可能就是被改过的,只有重算才能发现内容被动过;而它的链哈希又是下一条的 prev_hash,所以断点及其之后全废(断言①、取舍点②)。
  • 为什么四可是"逐笔核、缺一不予放行" :audit_decision() 把四可逐条核一遍,_overall_of() 里任一 FAIL 即"不可举证"。为什么不是"平均分够高":四可缺一,这一笔就举不了证------是"每一笔都要过"(断言②、取舍点①)。
  • 为什么"申请人≠审批人"判 FAIL :rule_accountable 里 operator == approver 直接 FAIL(断言③、踩坑③,依据不相容岗位分离)。
  • 为什么"可复现"只核版本在不在 :replay() 只查 triplet 三版在不在册,绝不假装重放 LLM 逐字输出------LLM 有随机性、供应商会静默更新,"逐字一致"很多场景做不到(断言④、取舍点③)。
  • 为什么放行和拒绝走一样的核对 :audit_all() 对 action 不做区分------一笔"说得清凭什么"的拒绝和一笔"说得清凭什么"的放行,价值一样高(断言⑤)。
  • 为什么判定是四态 :PASS/FAIL/PENDING/NEEDS_HUMAN。只给两态会逼你对"核不到的东西"编一个答案;四态让"我不知道"成为合法结论,并让 manual_review 从非决定性判定里自然长出来(断言⑥⑧)。
  • 为什么每条结论带依据 :explain() 返回维度/依据/出处/核实日期------只吐 PASS/FAIL 不吐依据,审计员问一句就哑(断言⑦,开篇那个场景的教训)。
  • 为什么审计要求一改结论就改 :load_policies() 是数据,Policy.rule 是规则表的键;加一条要求 = 加一行数据、引一个规则,audit_all() 一行不改。且 Policy.verified_at=None 的条目输出里显式标 pending------把"这份口径会烂"焊进数据结构(断言⑨)。
  • 真实生产怎么替换 :把 load_policies() / load_registry() 换成你们机构维护的真实口径数据与模型/Prompt/数据注册表、给链哈希加上签名和密钥管理、把 render_audit_table() 换成内部平台/前端,verify_chain() / audit_all() / explain() 的逻辑一行不改------同前几篇"生产换数据、骨架不动"的替换心智。

🎯 更多专栏系列文章可以查看博客主页📑 👍 若文章对你有所触动,恳请点赞 ⭐ 关注 ⭐ 收藏

相关推荐
IanSkunk1 小时前
从T/SMA 0090—2026到视光中心落地:标准化体系模块清单怎么拆
人工智能
万物智能信息科技1 小时前
血氧心跳传感器MAX30100芯片驱动开发—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
人工智能·驱动开发·华为·开源·harmonyos·鸿蒙
Alice-YUE1 小时前
从「能用」到「可控」:Prompt 工程与日常写 Prompt 的本质区别
人工智能·大模型·llm·prompt·prompt工程·提示词·ai应用
qq_365320601 小时前
AI使用心得7
人工智能
Skrrapper1 小时前
AI项目实战日记ep2:把 GitHub Issue 的第一轮脏活交给 AI:做一个 Issue 分诊助手
人工智能·github·issue
Eric.461 小时前
2025 深度实战:本地部署 AI 漫剧与 AI 视频全量产方案,彻底解决云端画质抖动、角色漂移、成本超标
大数据·人工智能·音视频·comfyui·ai漫剧
东坡肘子1 小时前
Swift Server,又多了一个 Google -- 肘子的 Swift 周报 #156
人工智能·swiftui·swift
枫叶丹41 小时前
AI Agent 说完成了,怎样验证任务真的完成
人工智能·chatgpt·开源·agent·codex
搬砖小趴菜1 小时前
【科研速递】Applied Sciences | 冻融循环作用下玄武岩的三轴力学行为与强度模型:对寒区工程结构的意义
大数据·论文阅读·人工智能·全文检索·ai自动写文章