金融 Function Calling:风控规则引擎 + LLM 的联合判决设计
金融 Function Calling风控规则引擎 LLM 的联合判决设计一、单靠 LLM 做风控漏掉的是真金白银金融风控场景中决策的正确性直接影响资金安全。一个典型的例子用户提交一笔跨境转账申请。传统风控系统通过规则引擎判断金额超过 5 万、收款方在敏感地区、用户历史无跨境记录 → 触发人工审核。如果把这个决策交给 LLMLLM 可能会综合判断为正常交易——因为它不懂风控规则的优先级和绝对性。但如果纯靠规则引擎又无法处理规则的灰色地带和组合场景。正确的方案是规则引擎做硬约束必定拦截的LLM 做软判断需要上下文理解的。二、联合判决架构联合判决的核心分工规则引擎负责必定拦截的场景LLM负责需要理解上下文的灰色地带三、Go 实现风控联合判决规则引擎package risk import ( context fmt time ) // RiskDecision 风控决策 type RiskDecision string const ( DecisionPass RiskDecision pass // 放行 DecisionReview RiskDecision review // 人工审核 DecisionBlock RiskDecision block // 拒绝 ) // RiskLevel 风险等级 type RiskLevel int const ( RiskNone RiskLevel 0 RiskLow RiskLevel 1 RiskMedium RiskLevel 2 RiskHigh RiskLevel 3 RiskMaximum RiskLevel 4 ) // Transaction 交易信息 type Transaction struct { TransID string UserID string Amount int64 // 金额分 Currency string Direction string // in / out CounterParty string // 交易对手方 CounterPartyRegion string // 交易对手方地区 TransType string // transfer/payment/withdraw Timestamp time.Time } // RuleResult 规则引擎结果 type RuleResult struct { Passed bool RiskLevel RiskLevel HitRules []string // 触发的规则列表 Decision RiskDecision Reason string NeedLLMReview bool // 是否需要 LLM 辅助判断 ContextForLLM map[string]interface{} // 提供给 LLM 的上下文 } // RuleEngine 规则引擎 type RuleEngine struct { rules []RiskRule } type RiskRule interface { Name() string Evaluate(ctx context.Context, tx *Transaction) RuleEvaluation } type RuleEvaluation struct { Triggered bool RiskLevel RiskLevel Reason string } // AmountRule 金额规则 type AmountRule struct { SingleLimitFen int64 // 单笔限额 DailyLimitFen int64 // 日累计限额 } func (r *AmountRule) Name() string { return 金额规则 } func (r *AmountRule) Evaluate(ctx context.Context, tx *Transaction) RuleEvaluation { // 单笔限额检查 if tx.Amount r.SingleLimitFen { return RuleEvaluation{ Triggered: true, RiskLevel: RiskMedium, Reason: fmt.Sprintf(单笔金额 %0.2f 超过限额 %0.2f, float64(tx.Amount)/100, float64(r.SingleLimitFen)/100), } } return RuleEvaluation{Triggered: false} } // RegionRule 地区规则——高风险地区直接拦截 type RegionRule struct { HighRiskRegions []string // 高风险地区清单 } func (r *RegionRule) Name() string { return 地区规则 } func (r *RegionRule) Evaluate(ctx context.Context, tx *Transaction) RuleEvaluation { for _, region : range r.HighRiskRegions { if tx.CounterPartyRegion region { return RuleEvaluation{ Triggered: true, RiskLevel: RiskMaximum, // 最高风险——直接拦截 Reason: fmt.Sprintf(收款方位于高风险地区: %s, region), } } } return RuleEvaluation{Triggered: false} } // FrequencyRule 频率规则 type FrequencyRule struct { DB *Database WindowMinutes int // 时间窗口分钟 MaxTransactions int // 最大交易次数 } func (r *FrequencyRule) Name() string { return 频率规则 } func (r *FrequencyRule) Evaluate(ctx context.Context, tx *Transaction) RuleEvaluation { count : r.DB.CountRecentTransactions(ctx, tx.UserID, r.WindowMinutes) if count r.MaxTransactions { return RuleEvaluation{ Triggered: true, RiskLevel: RiskMedium, Reason: fmt.Sprintf(%d 分钟内交易 %d 次超过阈值 %d, r.WindowMinutes, count, r.MaxTransactions), } } return RuleEvaluation{Triggered: false} } // RunAllRules 运行所有规则汇总结果 func (re *RuleEngine) RunAllRules(ctx context.Context, tx *Transaction) RuleResult { result : RuleResult{ Passed: true, RiskLevel: RiskNone, ContextForLLM: make(map[string]interface{}), } maxRisk : RiskNone for _, rule : range re.rules { eval : rule.Evaluate(ctx, tx) if eval.Triggered { result.HitRules append(result.HitRules, fmt.Sprintf(%s: %s, rule.Name(), eval.Reason)) if eval.RiskLevel maxRisk { maxRisk eval.RiskLevel } } } result.RiskLevel maxRisk // 判决逻辑 switch { case maxRisk RiskMaximum: result.Passed false result.Decision DecisionBlock result.NeedLLMReview false // 直接拦截不需要 LLM case maxRisk RiskHigh: result.Passed false result.Decision DecisionBlock case maxRisk RiskMedium: result.Passed true // 规则层面通过 result.Decision DecisionReview result.NeedLLMReview true // 需要 LLM 做辅助判断 default: result.Decision DecisionPass } return result }LLM 辅助审核// LLMAuditor LLM 辅助风控审核 type LLMAuditor struct { llm LLMClient maxAuditAmount int64 // LLM 参与审核的金额上限超过的直接人工 } // AuditWithLLM 使用 LLM 做辅助判断 func (la *LLMAuditor) AuditWithLLM( ctx context.Context, tx *Transaction, ruleResult RuleResult, historicalContext map[string]interface{}, ) (RiskDecision, string) { // 如果金额超过 LLM 审核上限直接转人工 if tx.Amount la.maxAuditAmount { return DecisionReview, 金额超过 LLM 审核上限转人工审核 } // 构造 LLM Prompt prompt : la.buildAuditPrompt(tx, ruleResult, historicalContext) // LLM 分析 analysis, err : la.llm.Generate(ctx, prompt) if err ! nil { // LLM 不可用保守处理 → 转人工 return DecisionReview, fmt.Sprintf(LLM 分析不可用: %v, err) } // 解析 LLM 建议 suggestion : la.parseLLMSuggestion(analysis) return suggestion.Decision, suggestion.Reason } func (la *LLMAuditor) buildAuditPrompt( tx *Transaction, ruleResult RuleResult, historicalContext map[string]interface{}, ) string { return fmt.Sprintf(你是一个金融风控审核助手。请分析以下交易的风险。 【交易信息】 交易ID: %s 用户ID: %s 金额: %.2f 元 方向: %s 交易对手方: %s (%s) 交易类型: %s 【触发的风控规则】 %s 【用户历史行为】 %s 【分析要求】 1. 结合用户历史行为判断该笔交易是否合理 2. 考虑规则触发的上下文例如用户在出差期间的高频交易可能是正常的 3. 给出你的建议pass放行/ review人工审核/ block拒绝 4. 必须给出明确理由 【注意】 - 不要编造用户历史信息中没有的数据 - 金额规则触发的如果历史同类交易金额接近可能是合理的 - 频率规则触发的如果有合理场景如发薪日集中转账可能是正常的 请以 JSON 格式返回{decision: pass|review|block, reason: ...}, tx.TransID, tx.UserID, float64(tx.Amount)/100, tx.Direction, tx.CounterParty, tx.CounterPartyRegion, tx.TransType, joinStrings(ruleResult.HitRules, \n), formatContext(historicalContext), ) } func (la *LLMAuditor) parseLLMSuggestion(response string) LLMSuggestion { // 解析 LLM 返回的 JSON var suggestion LLMSuggestion // json.Unmarshal 解析 return suggestion } type LLMSuggestion struct { Decision RiskDecision Reason string }联合判决最终决定// RiskController 风控控制器——规则引擎 LLM 联合判决 type RiskController struct { ruleEngine *RuleEngine llmAuditor *LLMAuditor auditLogger *AuditLogger } func (rc *RiskController) EvaluateTransaction( ctx context.Context, tx *Transaction, ) RiskDecision { // 第一步运行规则引擎 ruleResult : rc.ruleEngine.RunAllRules(ctx, tx) // 第二步如果规则引擎直接拦截或放行直接返回 if !ruleResult.NeedLLMReview { rc.auditLogger.LogDecision(ctx, tx, ruleResult.Decision, ruleResult.HitRules) return ruleResult.Decision } // 第三步需要 LLM 辅助判断——收集上下文 historicalContext : rc.collectContext(ctx, tx) // 第四步LLM 辅助分析 llmDecision, llmReason : rc.llmAuditor.AuditWithLLM(ctx, tx, ruleResult, historicalContext) // 第五步最终决定保守策略规则不放行时LLM 最多建议人工审核不能直接放行 var finalDecision RiskDecision switch { case ruleResult.RiskLevel RiskHigh: // 高风险即使用 LLM 说放行仍然拦截 finalDecision DecisionBlock case llmDecision DecisionBlock: finalDecision DecisionBlock case llmDecision DecisionPass ruleResult.RiskLevel RiskMedium: finalDecision DecisionPass default: finalDecision DecisionReview } // 记录审计日志 rc.auditLogger.LogDecision(ctx, tx, finalDecision, append(ruleResult.HitRules, fmt.Sprintf(LLM建议: %s (%s), llmDecision, llmReason))) return finalDecision }四、边界分析与 Trade-offsLLM 不能推翻硬规则地区黑名单触发的拦截LLM 不能推翻——这是合规要求LLM 只能对标记但未拦截的交易做辅助判断LLM 分析的成本与延迟每笔需要 LLM 辅助的交易增加 200-500ms 延迟约 5-10% 的交易会触发 LLM 辅助规则标记但未拦截的成本远低于人工审核但仍需要在延迟和成本之间平衡审查的可解释性规则引擎的输出是规则 ID 条件天然可解释LLM 的输出需要附带推理过程用于后续审计监管机构可能要求展示为什么这笔交易被拦截LLM 幻觉风险LLM 可能编造用户历史行为中的合理解释必须约束 LLM 只能基于提供的上下文做分析不能创造性推理五、总结金融风控的 Function Calling 设计应遵循规则做硬约束LLM 做软判断规则引擎——处理确定的、不容协商的风控规则金额、地区、频率LLM 辅助——处理需要上下文理解的灰色地带模式异常但场景合理联合判决——规则是底线规则说拦截就拦截LLM 是辅助可以在模糊区域建议放行审计完整——每笔交易的决策链路可追溯LLM 在金融风控中的正确角色不是替代规则而是减少人工审核的负担。

相关新闻

新店GEO优化快速起量

新店GEO优化快速起量

随着AI搜索技术的不断进步,生成式引擎优化(GEO)已经成为新店获取同城精准流量的重要手段。对于新开业的店铺来说,如何在竞争激烈的市场中迅速脱颖而出,吸引到目标客户群体是至关重要的。本文将深入探讨新店如何通过GEO…

2026/10/16 4:15:56 阅读更多 →
Go 高频交易模拟:纳秒级定时的实现与精度限制分析

Go 高频交易模拟:纳秒级定时的实现与精度限制分析

Go 高频交易模拟:纳秒级定时的实现与精度限制分析 一、time.Sleep(time.Microsecond) 实际上睡了多久? 写一个简单的 Go 程序测试: start : time.Now() time.Sleep(1 * time.Microsecond) elapsed : time.Since(start) fmt.Println(elapsed) …

2026/9/27 15:55:05 阅读更多 →
Go 金融系统的分布式对账和资金安全的工程保障

Go 金融系统的分布式对账和资金安全的工程保障

Go 金融系统的分布式对账和资金安全的工程保障 一、"账上少了 2 分钱"——对账系统最怕的不是大额差异,而是小额累积 金融系统的核心铁律是:钱不能少,账不能错。所有的分布式事务、分布式锁、消息队列最终都要服务于这个目标。 …

2026/10/16 21:42:18 阅读更多 →

最新新闻

C# WebSocket实战:从握手到心跳重连的完整Demo解析

C# WebSocket实战:从握手到心跳重连的完整Demo解析

简介:这是一套面向C#开发者的WebSocket通信完整示例,适合需要实现实时双向通信、研究服务端与客户端交互逻辑的中高级程序员,也可作为ASP.NET项目集成WebSocket功能的参考。资源包内含客户端与服务端两个完整工程,共76个文件&…

2026/10/18 8:38:19 阅读更多 →
Spring Boot自动配置与Maven依赖管理:从原理到实战排查

Spring Boot自动配置与Maven依赖管理:从原理到实战排查

直接说结论:Spring Boot 最核心的“魔法”就是自动配置,而 Maven 则是支撑这一切运转的基石。很多人在项目里把依赖一引、启动类一写,应用就跑起来了,但一旦遇到版本冲突、配置失效或想自定义 Starter 时,就会卡住。这…

2026/10/18 8:38:19 阅读更多 →
投资者结构优化与市场波动率:实证检验与倒U型规律

投资者结构优化与市场波动率:实证检验与倒U型规律

这两年聊到市场波动,总绕不开一个词:投资者结构。几乎每次市场剧烈震荡之后,都会有人把原因归到散户太多、机构太少,顺手得出一个结论——结构优化了,市场自然就稳了。我刚接手这块研究时也差不多是这个直觉&#xff0…

2026/10/18 8:38:19 阅读更多 →
MFC中COleDispatchException异常处理实践:从错误码到自动化调用排坑

MFC中COleDispatchException异常处理实践:从错误码到自动化调用排坑

1. 从一个诡异的崩溃说起:OLE自动化异常到底是怎么回事先讲一个我实际遇到的场景。某项目里需要程序自动操作本机的一个ActiveX组件,往外部系统推送数据。功能跑起来倒是顺畅,但是运行到某个中间环节,程序突然弹出错误对话框——不…

2026/10/18 8:38:19 阅读更多 →
LangChain4j声明式Agent底层真相:动态代理与大模型函数回调

LangChain4j声明式Agent底层真相:动态代理与大模型函数回调

1. 声明式Agent:Java生态里被严重低估的“接口即服务”设计我用LangChain4j写过几个实际项目之后,最大的感受是:很多人在初学阶段就被AiServices那一套“接口定义Agent”的写法震住了,第一反应是“这不就是个注解处理器吗”。但如…

2026/10/18 8:38:19 阅读更多 →
对话式Linux运维Agent:高危操作强制确认与断线自动守候

对话式Linux运维Agent:高危操作强制确认与断线自动守候

长期在 Linux 运维一线干活的人都有过这种纠结时刻:一台线上服务器在手边,一条 rm -rf 敲下去,回车键一按,几秒钟可能就毁掉团队几个月的积累。做这个对话式 Linux 运维 Agent 的初衷很简单,我想让机器替我处理那些繁琐…

2026/10/18 8:37:18 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →