资讯动态

审计转大模型:符合性测试思维怎么变成输出护栏

发布时间:2026/10/14 11:26:10 来源:尧图企业网站定制
版权与内容来源声明本文为原创整理。文中涉及官方文档、开源仓库、论文与公开报道的内容均在附表 A 中标注来源引用官方原文保持原样不作改写。文中命令、版本号与界面截图以本文成文时的实测/核验结果为准标注「待验证」的部分请以你本地环境实际输出为判断依据。本文不推荐任何不合规的软件获取方式也不对任何收益结果作承诺。转载请注明出处。1. 你其实早就做过一次「输出护栏」只是当时它叫控制测试1.1 一个年底会真实发生的场景年底盘点你手上有一批采购合同要处理。过去是人工逐份翻把每份合同里的「付款条件、账期天数、违约金比例、是否含自动续约」抄进一张台账表。现在你想让模型来做一份合同喂进去吐出一行结构化数据直接汇总。风险很具体——模型把「账期 90 天」抄成「90 个月」或者漏掉「违约金比例」这一栏而你不逐份复核错误就会一路汇总进报表。这时候你要的不是「更聪明的模型」而是一道在数据出去之前拦住错误的闸门。这道闸门做审计的人早就有一个成熟的名字。1.2 控制测试到底在测什么审计里有个概念叫控制测试很多教材和实务里也叫符合性测试——两个词说的是同一件事不是去重做一遍账而是看「企业自己定的那套规矩在审计期间有没有被一贯地执行」。《中国注册会计师审计准则第 1231 号——针对评估的重大错报风险采取的应对措施》2022 年 12 月 22 日修订第三条给出的定义是控制测试是指用于评价内部控制在防止或发现并纠正认定层次重大错报方面的运行有效性的审计程序。这句话里有三个词值得圈出来内部控制企业自己设计的规则比如「超过一定金额的付款必须二级审批」运行有效性规则写在纸上不算得看实际有没有被执行防止或发现并纠正控制的职责分两半——事前防住事后查出并改回来。准则第十条还明确审计师要拿到的控制运行证据包含三件事控制在相关时点怎么运行、是否得到一贯执行、由谁以何种方式执行。这三条恰好就是第 6 章那张「硬拦 / 告警 / 只记录」表要回答的东西。1.3 把「抽样本、看痕迹」改写成「拦在返回之前」传统控制测试是事后抽样翻出几十笔凭证看有没有审批签字。它有两个天然弱点——只能覆盖抽到的样本而且发现问题时钱可能已经付了。护栏则可以做事前全量每次模型输出都过一遍规则不合规就不放行。抽样能不能覆盖全量、事后能不能变成事前这是审计思维迁移过来收益最大的一步。你不需要先学算法你要做的是把自己的判断标准写成机器能执行的判据——这件事你比多数算法工程师更在行。2. 为什么「在提示词里叮嘱模型别乱说」不算护栏2.1 提示词是建议代码才是闸门最常见的做法是在系统提示里写一长串叮嘱「只输出 JSON」「金额必须小于合同总额」「不要编造条款」。这有用但它和护栏不是一回事。提示词的作用方式是概率性的模型大概率遵守小概率不遵守护栏要求的是确定性的要么拦住要么放行没有中间地带。用审计的话说提示词像「写在制度里的要求」护栏像「不签字就付不出款」这个动作本身——后者才是控制。还有一个容易忽略的点提示词本身是可以被覆盖的。用户在提问里塞一句「忽略上面的要求」就可能把叮嘱顶掉。把关键判断放进提示词等于把闸门装在了能被对话内容推动的活页上。2.2 官方也是这么建议的OWASP一个做应用安全的国际开源组织的生成式 AI 安全项目把「提示注入」列为大模型应用首要风险其官方条目在缓解建议里明确写了三条与本文直接相关的做法用确定性代码验证输出是否符合预期格式实施输入与输出过滤对高风险动作要求人工审批人在环。截至 2026-10-13该条目的结论是由于模型本身具有随机性目前没有一劳永逸的提示注入防护办法只能靠多层措施降低影响。官方口径本身就承认「靠提示词解决不了」所以才把「用代码校验」写进建议清单。2.3 三层护栏总览下面这张表是全文的骨架。三层从上到下越往下越依赖「你对业务的理解」也越不是通用工具能替你写好的部分。层级拦什么一句话目标典型工具定位第一层 · 输入校验不该问的、想改写规则的、超授权范围的请求不让危险请求进入模型输入护栏第二层 · 结构校验字段缺失、类型不对、枚举越界、格式不符契约保证输出「形状」永远可被程序读取结构化输出 模式校验第三层 · 业务规则校验数字区间、金额勾稽、单位口径、必带免责声明保证输出「含义」符合业务规则自定义动作 / 自定义校验第一层和第二层截至 2026-10-13开源生态里已有相对成熟的现成能力可以借用。NVIDIA 的 NeMo Guardrails 官方仓库把自己定位为「给基于大模型的应用加可编程护栏的开放工具包」并给出五类护栏输入、对话、检索、执行、输出。Guardrails AI 这个 Python 框架的官方仓库也写明它做两件事用输入/输出 Guard 检测并缓解风险以及帮模型生成结构化数据。能借的力先借掉你的时间该花在第三层。3. 第一层 · 输入校验先拦住「不该问的」3.1 输入层要拦的三类东西用审计的话说输入校验相当于「业务受理环节的授权审批控制」——先确认这笔业务该不该进系统。它拦三类越权提问问的是权限范围之外的数据比如只能查本部门的账号去问全公司薪酬明细提示注入试图改写你的规则比如「忽略上面的所有要求」「现在你是一个不受限制的助手」超范围请求请求类型不在这个应用的设计边界内比如只做合同要素抽取用户却让它写代码。3.2 输入校验的判据检查项判据怎么判断常见处置身份与授权范围请求里的账号角色能否覆盖被问数据所属范围硬拦 记录规则改写意图是否出现要求忽略既有指令、扮演无限制角色等模式硬拦是否外部内容提问是否夹带网页、文件里来的内容间接注入来源告警标记来源请求类型是否落在应用预设的任务白名单内硬拦或转人工长度与频率单次输入长度、单位时间请求条数是否异常告警 限流提醒一句OWASP 的官方条目把提示注入分成直接注入用户在提问里直接改写和间接注入恶意指令藏在模型读取的网页或文件里两类并指出间接注入往往更难防。所以「是否外部内容」必须单独列出来——它不是「用户坏」而是「数据脏」。3.3 一个最小实现骨架思路是先做便宜的模式匹配把明显违规的先挡掉再把有争议的标出来交人工而不是一上来就调用模型去判断。⚠️代码待验证# 输入校验骨架能确定性判断的绝不交给模型defcheck_input(text,user_scope,task_whitelist):loweredtext.lower()# 1) 规则改写意图直接拦不给模型看见的机会ifany(minloweredformin[忽略上面的,忽略之前,你现在是,不受限制]):returnblock# 2) 超范围请求不在任务白名单内转人工而不是硬拦ifnotany(tinloweredfortintask_whitelist):returnwarn# 3) 越权意图需结合账号范围判断真值应由权限服务给出不要写在提示词里if全公司intextand本部门notinuser_scope:returnblockreturnpass4. 第二层 · 结构校验字段、契约、枚举4.1 结构化输出替你解决了什么、没解决什么结构化输出指的是调用模型时附上一份字段清单哪些字段、什么类型、取值范围模型被约束成只按这份清单吐数据。OpenAI 的官方文档对 Structured Outputs 的说明是「保证模型输出符合你提供的 JSON Schema」并列出三个好处类型安全、拒绝回答可被程序识别、不必靠强硬措辞的提示词来凑格式其中「严格模式」需要显式开启。但要分清它能做什么、不能做什么它解决形状字段在不在、类型对不对、枚举值合不合法它不解决含义金额算得对不对、两笔数能不能勾稽、口径是否一致。换句话说结构化输出把结构校验这一层的达标情况从「大概率」抬到了「几乎必然」于是你可以把有限精力全投到第三层。它不是护栏的替代品而是护栏的前置条件。4.2 结构校验清单检查项判据处置必填字段契约里标记为必填的字段是否都出现且非空硬拦重试一次后仍缺则拒返字段类型数字字段是否真的是数字而非字符串硬拦枚举值形如「合同类型」这类只能取固定几个值的字段是否越界硬拦日期格式是否可被解析为标准日期而非「上个月底」这类自然语言硬拦多余字段是否出现契约外的字段可能是模型自由发挥只记录空值语义空字符串和「确实没有」是否被区分开告警关于「空值语义」做过财务的人会有共鸣空着和填 0 是两回事。模型最容易犯的错就是把「合同里没写」输出成 0这个错误在结构层看不出来类型是对的必须在业务层拦。4.3 结构化输出与护栏的分工一句话分工契约定形状的事交给结构化输出业务定对错的事留给护栏。字段齐不齐、类型与枚举对不对契约保证数字算得对不对、单位口径是否一致、能不能对外护栏负责。护栏在这一层的另一项职责是兜底——万一上游被绕过、契约没生效也要能发现并把越界尝试记下来用于观察。一个容易踩的坑结构化输出的严格模式在某些 API 上与并行工具调用不兼容官方文档明确要求把并行调用关掉。这类细节必须在动手前回官方文档确认一次不要照抄别人的示例。⚠️代码待验证# 结构校验只做「形状」检查含义检查留给第 5 章REQUIRED[contract_no,payment_terms,payment_days,penalty_rate]ENUMS{contract_type:{采购,服务,租赁}}defcheck_structure(record):# 必填且非空空字符串也算缺失forfinREQUIRED:iffnotinrecordorrecord[f]in(None,):returnblock# 枚举越界forf,allowedinENUMS.items():ifrecord.get(f)notinallowed:returnblock# 数字字段被错误输出成字符串forfin(payment_days,penalty_rate):ifnotisinstance(record[f],(int,float)):returnblockreturnpass5. 第三层 · 业务规则校验数字、勾稽、口径、免责声明5.1 业务规则怎么变成可执行判据第三层是别人替你做不了的那一层因为规则就是你业务里的「会计口径」。写判据时记住一个原则每条规则都要能回答「怎么算违反」。只写「金额不能离谱」是不合格的判据。规则类别可执行判据示例处置数字区间违约金比例是否落在 0 到合同约定的上限之间告警标人工复核金额勾稽分项金额之和是否等于总额允许极小尾差硬拦单位与口径账期单位是「天」还是「月」是否与台账口径一致告警交叉一致性同一合同号在两次抽取里的关键字段是否一致告警必带声明对外内容是否附带了规定的内容标识或免责声明硬拦时间逻辑付款日是否早于合同签订日逻辑不可能硬拦表里「硬拦 / 告警」的分配不是拍脑袋第 6 章会给出定档方法。先记住两条逻辑上不可能的事付款日早于签约日必须硬拦需要判断、有争议的事比例是否偏高等走告警。5.2 免责声明与内容标识不是可选项如果模型输出的内容要对外发布那「必带声明」就不是内控偏好而是合规要求。截至 2026-10-13国家互联网信息办公室等四部门联合发布的《人工智能生成合成内容标识办法》已于 2025 年 9 月 1 日起施行。该办法的官方口径是生成合成内容标识包括显式标识和隐式标识两种——显式标识是加在内容或交互界面上、用户能明显感知到的文字/声音/图形标识隐式标识是加在文件元数据里、不易被用户直接感知的标识。对护栏设计的启示很直接「有没有带标识」是一个可以写进代码判断的确定性问题有就有、没有就没有不需要模型自己判断。凡是这种非黑即白的规则都不该交给提示词。⚠️代码待验证# 业务规则校验把口径写成可判定条件尾差单独设阈值defcheck_business(record):# 金额勾稽分项之和与总额的差异超出容许尾差即判平不了partsrecord.get(amount_parts)or[]totalrecord.get(amount_total)iftotalisnotNoneandabs(sum(parts)-total)total*0.001:returnblock# 时间逻辑付款日不得早于签约日ifrecord.get(pay_date)andrecord.get(sign_date):ifrecord[pay_date]record[sign_date]:returnblock# 比例合理性越界只标人工不直接拒返raterecord.get(penalty_rate)ifrateisnotNoneandnot(0raterecord.get(penalty_cap,1)):returnwarnreturnpass本文用到的三层护栏判据表上面第 3、4、5 章的三张判据表可以合并成一页「护栏清单」直接照着建。放在资料包里扫码即可获取6. 硬拦 / 告警 / 只记录优先级表怎么定6.1 定档前先回答三个问题这一章最该慢下来看。护栏做得好不好不在于规则多而在于每条规则的处置档位定得对不对。定档前问三个问题这条规则是确定性的还是概率性的「付款日早于签约日」是确定性判断「这段表述是否可疑」是概率判断。误判的代价可不可逆错误数字流进报表并被引用收回来成本很高一条观察日志记错了几乎无代价。此刻有没有人能复核有人能当场复核的可以降档没人盯的关键链路要升级。三条问题的答案直接映射到三档处置硬拦拒绝返回、告警放行但标记人工复核、只记录落日志观察。6.2 处置优先级表场景规则性质误判代价有无人在环处置试图改写系统规则确定性高不需要硬拦必填字段缺失确定性高不需要硬拦枚举值越界确定性高不需要硬拦金额勾稽不平确定性高不需要硬拦付款日早于签约日确定性高不需要硬拦缺内容标识 / 免责声明确定性高合规不需要硬拦违约金比例偏高概率性中有告警单位与口径不一致概率性中有告警反复抽取结果不一致概率性中有告警出现契约外字段观察性低无所谓只记录空值语义被误填观察性低先观察无所谓只记录这张表可以直接当落地模板把你业务里的每条规则往这三档里放放不进去的说明规则本身没定义清楚。这里也和内控的一条原则对上了。《企业内部控制基本规范》财会〔2008〕7 号第四条把成本效益原则列为建立内部控制的基本原则之一——以适当的成本实现有效控制。护栏同理为了拦住一个低代价的观察性问题却让正常业务大面积被拒就是设计失败。6.3 误杀怎么度量、阈值怎么调护栏最大的副作用是误杀把本来对的内容也拦下和漏放该拦的没拦。这两个词在评估里分别叫假阳性和假阴性。要度量它们需要三个基础指标定义在主流机器学习工具库的官方用户指南里写得很清楚精确率在你拦下的所有条目里真正该拦的占多少——衡量误杀程度这个值低说明拦得太宽正常内容被误伤召回率在所有真正该拦的条目里你拦住了多少——衡量漏放程度这个值低说明拦得太松问题内容被放行F1分数精确率与召回率的调和平均用来在两者之间取一个综合值偏高说明两边较均衡。阈值怎么调有一个可执行顺序先把判据跑在一批已人工标注的历史数据上统计三个指标再单点调阈值看精确率与召回率怎么此消彼长只有当某一档的代价不可逆时才优先保召回率宁可错拦不可放过。对应到上面的优先级表硬拦档优先保召回率告警档优先保精确率因为误报会浪费人工。⚠️代码待验证# 用标注集评估某一档规则的误杀与漏放再决定阈值往哪边挪defevaluate_rule(y_true,y_pred):tpsum(1fort,pinzip(y_true,y_pred)ift1andp1)fpsum(1fort,pinzip(y_true,y_pred)ift0andp1)fnsum(1fort,pinzip(y_true,y_pred)ift1andp0)precisiontp/(tpfp)if(tpfp)else0.0# 误杀看它recalltp/(tpfn)if(tpfn)else0.0# 漏放看它f12*precision*recall/(precisionrecall)if(precisionrecall)else0.0return{precision:precision,recall:recall,f1:f1}6.4 人在环的触发条件「人在环」指的是把判断交回给人。它不是「所有输出都人工看一遍」——那等于没自动化。写成判据才可执行触发条件为什么触发人工要做什么单笔金额超过设定阈值代价不可逆且金额大逐笔核对原始凭证命中告警档累计超过设定条数单条可放行成批出现说明口径可能变了抽检并回归判据同一请求多次抽取结果不一致说明模型对这份材料本身没把握以人工结论为准硬拦被请求方申诉规则可能有误杀复核判据是否需要放宽7. 迁移清单这周就能开始做的三件事7.1 从你现有的底稿里「抄」三张表不要从零设计护栏。你手上现成的审计底稿里至少有三样东西可以直接改写控制点清单变成你的护栏规则清单控制测试的样本与结论变成你的规则评估标注集发现的控制缺陷变成你的告警档与只记录档规则。你在审计里积累的「什么算异常」的判断正是第三层护栏最贵的那部分资产。7.2 灰度上线先只观察不拦第一次上线建议把硬拦档也先设成「只记录」跑一段时间看它到底会拦掉多少。这样你能在没有业务损失的前提下先量出误杀情况等精确率和召回率都稳定了再逐条把「只记录」升级为「硬拦」。先观察、再告警、最后硬拦这个顺序不要倒过来。7.3 三个常见误解「在提示词里写清楚就够了」提示词是概率性建议且可被覆盖规则要落到代码。「用了结构化输出就不用护栏了」结构化输出只管形状不管含义它只让结构层更省心。「护栏规则越多越安全」规则过多会推高误杀与维护成本要按成本效益取舍。审计人转大模型的能力地图把这七个章节对应的能力项标出来你就知道哪一块是现成工具能替你做的、哪一块必须自己补。放在资料包里扫码即可获取附表 A本文引用事实与出处对照表事实出处文档名 发布方 链接本文位置控制测试的定义用于评价内部控制运行有效性《中国注册会计师审计准则第 1231 号——针对评估的重大错报风险采取的应对措施》2022-12-22 修订第三条中国注册会计师协会官网「审计准则」栏目https://cicpa.org.cn/ztzl1/Professional_standards/xxzztx/zyzz/sjzz1.2控制运行有效性应获取的三类证据如何运行 / 是否一贯执行 / 由谁执行同上第十条中国注册会计师协会官网1.2、6.1内部控制五要素内部环境 / 风险评估 / 控制活动 / 信息与沟通 / 内部监督《企业内部控制基本规范》财会〔2008〕7 号财政部等2009-07-01 起施行第五条财政部官网会计财务评价中心页面http://kzp.mof.gov.cn/infor.jsp?infoid286class_id01_10_01_051.2、6.2成本效益原则是建立内部控制的基本原则之一同上第四条财政部官网6.2NeMo Guardrails 定位为可编程护栏工具包并给出输入 / 对话 / 检索 / 执行 / 输出五类护栏NVIDIA NeMo Guardrails 官方仓库 READMENVIDIAhttps://github.com/NVIDIA-NeMo/Guardrails2.3Guardrails AI 提供输入 / 输出 Guard 以检测缓解风险并帮助模型生成结构化数据Guardrails AI 官方仓库 READMEGuardrails AIhttps://github.com/guardrails-ai/guardrails2.3提示注入的定义以及直接注入与间接注入的区分OWASP GenAI Security Project 风险条目 LLM01:2025 Prompt InjectionOWASP Foundationhttps://genai.owasp.org/llmrisk/llm01-prompt-injection/3.2缓解建议含「用确定性代码校验输出格式」「输入输出过滤」「高风险动作人工审批」并说明模型随机性下暂无万无一失的防护办法同上OWASP Foundation截至 2026-10-13 该条目的表述2.2、6.4Structured Outputs 保证输出符合所提供的 JSON Schema并提供可程序化识别的拒绝回答OpenAI Platform 文档《Structured model outputs》OpenAIhttps://platform.openai.com/docs/guides/structured-outputs4.1结构化输出在部分 API 上不支持并行工具调用需将并行调用关闭Microsoft Learn 文档《Structured outputs》Microsofthttps://learn.microsoft.com/en-us/azure/foundry/openai/how-to/structured-outputs4.3精确率、召回率与 F-measure 的定义及公式scikit-learn 用户指南《Metrics and scoring: quantifying the quality of predictions》scikit-learn developershttps://scikit-learn.org/stable/modules/model_evaluation.html6.3《人工智能生成合成内容标识办法》自 2025-09-01 起施行标识含显式与隐式两种形式中央网络安全和信息化委员会办公室发布稿《四部门联合发布〈人工智能生成合成内容标识办法〉》国家互联网信息办公室https://www.cac.gov.cn/2025-03/14/c_1743654685899683.htm5.2附表 B术语速查表术语一句话解释在本文哪里用到控制测试评价企业内控规则是否被一贯执行的审计程序1.2符合性测试控制测试的另一种常见叫法关注合规与一贯执行1.2护栏加在模型输入或输出上、按规则拦住或标记内容的一道程序2.1提示注入通过在提问里塞入指令试图改写模型既有规则3.1间接注入恶意指令藏在模型读取的网页或文件里而非用户直接输入3.2结构化输出约束模型按你给的字段清单和类型吐数据的功能4.1JSON Schema一份描述数据应有哪些字段、什么类型的约定文件4.1枚举值只能取固定几个候选值的字段如合同类型只能是采购/服务/租赁4.2勾稽分项与合计、或两张表之间应当能对上5.1误杀假阳性本来对的内容被护栏拦下6.3漏放假阴性本该拦下的问题内容被放行6.3F1分数精确率与召回率的调和平均综合看两边是否均衡6.3人在环在关键节点把判断交回人工6.4显式标识 / 隐式标识前者用户明显能感知后者藏在文件元数据里5.2灰度先小范围或只观察地试跑确认稳定后再放开7.2写在最后这篇用到的资料写这篇文章时把相关的官方文档和源码又翻了一遍顺手也整理了几份配套的东西大模型学习路线图从零基础到能自己动手做 Agent按阶段说明每一步该学什么、哪些可以先跳过《LangChain LangGraph MCP 智能体开发实战》视频课7 个模块从私有化部署、EmbeddingRAG 到 MCPAgent 全流程AI 大模型知识库在线可查Agent Skills 从入门到落地、Claude Skills 完全指南等专题按目录浏览即可640 套 AI 大模型行业报告 经典 PDF 书籍看行业落地案例和别人怎么做的时候用得上大模型零基础到精通教学视频跟着敲一遍比只读文档快得多资料是我自己整理的放在下面这个码上扫码即可获取添加时备注「AI」优先通过。资料按「先路线、再动手、最后查漏」的顺序整理好了建议先看学习路线那一份照着它挑一条适合自己当前基础的路径再往下看。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑