第 6 章 · 03 PolicyEngine 策略门禁与贷款审批配方 ★


第 6 章 · 03 PolicyEngine 策略门禁与贷款审批配方 ★

本节摘要:压轴章的收尾一节。决策智能缺最后一块拼图:决策之前的合规把关PolicyEnginepolicy_engine.py,1043 行)把合规策略存为版本化图节点,用 min_/max_/required_ 三前缀规则 DSL 对决策做合规评估——"拒贷必须给出三条理由"这类监管要求可以写成一条 required_ 规则;不合规决策在入库前被拦截,合规记录经 APPLIED_POLICY 边永久留痕,例外走 GRANTED_EXCEPTION 审批链。后半段把全书配方做一次端到端演练:以 README 的贷款审批例子为脚本,走完注册决策→记录证据链→监管审计→先例对比四步,并回答压轴之问——决策智能的"为什么可信"。

内容来源:semantica/context/policy_engine.py(1043 行)、decision_models.py(Decision/Policy 数据类)、decision_recorder.py(例外与审批链)、README.md(Decision Intelligence 与 Recipe: Audit Trail)、docs/guides/decision-intelligence.md(Gating 一节)

⚠️ 注意PolicyEngine.check_compliance 的兜底行为是"异常即不合规"(第 398 行 except ... return False)——策略节点缺失、规则求值抛错都会静默归入"违规"。fail-closed 对合规是正确默认,但调试时策略 ID 拼错与真实违规在返回值上不可区分,务必配合日志排查。

学习目标

  1. 掌握 Policy 的版本化存储:policy_id:version 节点 + VERSION_OF 版本链。
  2. 掌握 min_/max_/required_ 三前缀规则 DSL 与 _evaluate_compliance 的求值顺序。
  3. 理解违规拦截的完整闭环:check_compliance → record_policy_application / record_exception。
  4. 会跑通贷款审批端到端配方:注册决策→证据链→监管审计→先例对比。
  5. 能总结决策智能"为什么可信"的三支柱。

一、策略也是图节点:版本化的 Policy

PolicyEngine 的世界观与 6.1 节一脉相承:策略不该躺在配置文件里,而该是图上有版本、有历史、有引用关系的节点Policy 数据类(decision_models.py 第 175 行)的核心字段:policy_id/name/rules/category/version。入库时节点 ID 直接编码版本(policy_engine.py 第 146 行):

node_id = f"{policy.policy_id}:{policy.version}" self.graph_store.add_node( node_id=node_id, node_type="Policy", content=policy.name or policy.policy_id, policy_id=policy.policy_id, name=policy.name, description=policy.description, rules=policy.rules, category=policy.category, version=policy.version, ...)

改策略不是覆盖而是出新版update_policy(第 167—242 行)调 _generate_next_version 递增补丁号,新版本入库后连一条 VERSION_OF 边(Cypher 后端是 MERGE (old)-[:VERSION_OF]->(new),内存后端是 add_edge(..., edge_type="VERSION_OF", change_reason=...))——变更原因随之入图。get_applicable_policies(第 244 行)取"没有后继版本"的节点为现行版(Cypher 写法是 WHERE NOT (p)-[:VERSION_OF]->(:Policy)),并支持按实体范围收窄(_policy_matches_entities:metadata 里的 entities/entity_ids/applies_to_entities 与决策实体有交集才适用)。一条 Cypher 查询 get_policy_history(第 528 行)能拉出全版本时间线——监管问"当时生效的是哪版政策",答案就是决策引用的那个版本号。

二、规则 DSL:min_/max_/required_

策略的灵魂在 rules 字典。_evaluate_compliance(第 879—914 行)定义了一门极简但够用的规则语言:

for rule_key, rule_value in rules.items(): # min_X → metadata["X"] >= rule_value if rule_key.startswith("min_"): field = rule_key[4:] field_value = self._get_metadata_field(metadata, decision, field) if field_value is None: return False # 字段缺失即违规(fail-closed) if field_value < rule_value: return False # max_X → metadata["X"] <= rule_value elif rule_key.startswith("max_"): ... # required_X → metadata["X"] 包含列表所有项(或等于字符串) elif rule_key.startswith("required_"): field = rule_key[9:] field_value = self._get_metadata_field(metadata, decision, field) if field_value is None: return False if isinstance(rule_value, list): if not all(item in field_value for item in rule_value): return False ... # 三个特例键:min_confidence / allowed_outcomes / required_categories elif rule_key in {"min_confidence", "allowed_outcomes", "required_categories"}: decision_data = {"confidence": decision.confidence, "outcome": decision.outcome, "category": decision.category} if not self._check_compliance_with_rules(decision_data, {rule_key: rule_value}): return False

三个前缀覆盖了监管条款的高频句式:min_confidence: 0.85(置信度下限)、max_loan_amount: 500000(额度上限)、allowed_outcomes: ["approved", "rejected", "conditional"](结论白名单)。字段查找走 _get_metadata_field(第 862 行)三级回退:metadata 精确键 → 后缀匹配(规则 status 能命中 verification_status)→ 决策属性。

**"拒贷必须给出三条理由"**就落在 required_ 前缀上。给拒贷类决策配一条策略:

rules = { "required_reasons": ["dti_ratio_check", "credit_history_check", "income_verification"], "min_confidence": 0.85, }

求值时 required_metadata["reasons"](或后缀匹配 rejection_reasons 等),要求列表包含全部三项——少给一条理由,决策就过不了门禁。注意各规则是 AND 语义:任何一条不满足整体即不合规,return False 立即短路。

三、拦截闭环:合规放行、例外留痕

门禁的用法是决策入库前的 if 分支(指南 Gating 一节的完整示例):

engine.add_policy(Policy( policy_id = "lending_policy_v3", name = "Lending Compliance Policy v3", description = "Credit decisions require confidence >= 0.85 and documented reasoning", rules = {"min_confidence": 0.85, "requires_reasoning": True}, category = "loan_approval", version = "3.0", ...)) if engine.check_compliance(d, "lending_policy_v3"): loan_id = context.record_decision(...) engine.record_policy_application(d.decision_id, "lending_policy_v3", "3.0") else: # 拦截:不合规决策不入库 ...

放行路径上 record_policy_application(第 400 行)连一条 APPLIED_POLICY 边并在边上记 applied_at/policy_id/version——决策与"当时适用的策略版本"从此绑定,这就是 6.1 节"可追溯"在策略维度的落点。拦截不等于路堵死:紧急场景可以走例外审批,record_exception(第 446 行)创建 Exception 节点并连两条边:

MERGE (d)-[:GRANTED_EXCEPTION]->(e) MERGE (e)-[:OVERRIDDEN_POLICY]->(p)

重型版 DecisionRecorder.record_exception(decision_recorder.py 第 271 行)还要 approver/approval_method/justification 三要素——指南的安全示例里连"03:14 UTC 的 CISO 口头批准"都写进了 justification。策略变更的历史责任同样可查:get_affected_decisions(policy_id, from_version, to_version)(第 589 行)沿 APPLIED_POLICY 边反查"引用了旧版的全部决策",analyze_policy_impact(第 711 行)更进一步支持 what-if——拟议新规则与现行规则的 diff、受影响决策数、平均合规分、风险增幅一次算清,让改政策前先看冲击面。

四、端到端配方:一笔贷款从录入到审计

现在把全书零件装成一台整机。以下配方以 README 的 Decision Intelligence 一节为蓝本(category/scenario 原样保留),四步走完:

第一步,注册决策链。 三笔决策、两条因果边:

from semantica.context import ContextGraph graph = ContextGraph(advanced_analytics=True) app_id = graph.record_decision( category="credit_application", scenario="Personal loan, $85k income, 31% DTI, 3yr employment", reasoning="Income meets threshold; employment stable; no adverse credit events", outcome="proceed_to_underwriting", confidence=0.88, metadata={"applicant_id": "A-7291"}) uw_id = graph.record_decision( category="loan_underwriting", scenario="Underwriting review for A-7291", reasoning="DTI within policy; clean 36-month credit history", outcome="approved", confidence=0.94) rate_id = graph.record_decision( category="interest_rate", scenario="Rate assignment for approved loan A-7291", outcome="rate_set_8.9pct", reasoning="Prime + 2.4% based on risk tier B2", confidence=0.99) graph.add_causal_relationship(app_id, uw_id, relationship_type="CAUSED") graph.add_causal_relationship(uw_id, rate_id, relationship_type="INFLUENCED")

每笔决策入库即过 6.1 节的校验与织图:决策节点、involves/belongs_to/made_by 边一步到位。

第二步,记录证据链。 申请人实体与决策挂接,溯源同步落账(README Recipe 的模式,接第 7 章的 PROV-O):

from semantica.provenance import ProvenanceManager from semantica.export import RDFExporter prov = ProvenanceManager(storage_path="./audit.db") graph.add_node("A-7291", "Person", name="Applicant A-7291") graph.add_edge(uw_id, "A-7291", "involves", confidence=0.94) prov.track_entity("A-7291", source="crm/applications/2025/A-7291.json", metadata={"extractor": "NamedEntityRecognizer"})

第三步,监管审计导出。 全图转 KG 字典后一键导出 W3C PROV-O:

kg = graph.to_kg_dict() RDFExporter().export(kg, "audit_trail.ttl", format="turtle") chain = graph.trace_decision_chain(rate_id) # 完整因果谱系 insights = graph.get_decision_insights() # 置信度/类别/结论统计

第四步,先例对比。 下一笔同类申请进来,先查历史:

similar = graph.find_similar_decisions( "personal loan approval, 31% DTI", max_results=5) compliant = graph.check_decision_rules( {"category": "loan_underwriting", "confidence": 0.94})

A-7291 的核保决策成为后继申请的先验;同口径场景从此同判。四步配方合计不到四十行,却覆盖了 SR 11-7 式模型治理审查要问的全部问题:谁在何时依据什么政策、基于哪些证据、参考哪些先例、做出了什么结论。

五、压轴总结:决策智能的"为什么可信"

第 5—6 章合起来,Semantica 给出了一个值得背下来的可信公式:

确定性图谱 + 确定性推理 + 全链路溯源 = 可审计决策。

  • 确定性图谱(第 3—4、6 章):实体、关系、冲突消解、决策记录全部结构化入图,同输入同状态;决策有法定记载事项与版本化策略门禁。
  • 确定性推理(第 5 章):Rete/Datalog/演绎全程零 LLM,结论可复现、前提可枚举,ExplanationGenerator 出具逐步推理链。
  • 全链路溯源(第 7 章展开):每个事实有 PROV-O 档案(从哪来/谁产生/怎么产生),决策经 APPLIED_POLICY/因果边/溯源账本三重留痕,export_prov 一键交付监管格式。

LLM 依然在管线里——但只负责理解语言与抽取结构,从不负责"要签字"的结论。正如 README 卷首语:Explainable, traceable, and trustworthy by design——可信不是事后补救,而是管线每一阶的设计属性。

💡 装配要点:PolicyEngine 的四张图要素——policy_id:version 节点、VERSION_OF 版本链、APPLIED_POLICY 应用留痕、GRANTED_EXCEPTION/OVERRIDDEN_POLICY 例外链。规则 DSL 三前缀 AND 语义:min_/max_ 数值比较、required_ 列表包含(拒贷三理由的落点)、三特例键(min_confidence/allowed_outcomes/required_categories);字段查找带后缀回退。拦截闭环:check_compliance 放行 → record_policy_application 留痕;不合规 → 拦截或 record_exception 留痕例外。配方四步(注册决策链→证据链→审计导出→先例对比)可作为任何受监管决策场景的模板。

本节要点回顾

  • 策略即版本化图节点:policy_id:version 节点 + VERSION_OF 链,update_policy 出新版不改史,get_applicable_policies 取无后继版本,实体范围可收窄。
  • 规则 DSL:min_X(≥)、max_X(≤)、required_X(包含全部列表项/等于字符串);三特例键 min_confidence/allowed_outcomes/required_categories;字段缺失即违规,规则间 AND 短路;_get_metadata_field 三级回退(精确→后缀→属性)。
  • "拒贷必须给出三条理由" = required_reasons: [三项];每个决策连 APPLIED_POLICY 边绑定当时策略版本;例外走 GRANTED_EXCEPTION/OVERRIDDEN_POLICY,审批人与方法入图。
  • 政策变更影响:get_affected_decisions 反查引用旧版的决策;analyze_policy_impact 做 what-if(规则 diff+合规分+风险增幅)。
  • 端到端配方:record_decision×3 + 因果边×2 → 证据挂接+prov.track_entity → to_kg_dict + RDFExporter 审计包 → find_similar_decisions 先例对比。
  • 可信公式:确定性图谱 + 确定性推理 + 全链路溯源 = 可审计决策;LLM 只在语言理解与抽取层。

下一节:进入第 7 章《溯源与时态》——01 PROV-O 溯源管理器:1486 行溯源管理器里的 Entity/Activity/Agent 三元模型与监管格式的审计轨迹导出。


作者与出处
原作者: 灏天文库
整理: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U