金融场景 Agent 设计:合规约束下的智能投研助手方案
·
金融场景 Agent 设计:合规约束下的智能投研助手方案
一、"帮我查一下茅台的最近研报"——一个看似简单的请求需要多少层合规校验
金融领域的 AI Agent 和电商 Agent 有本质区别:电商出错最多是用户不满,金融出错可能涉及合规风险和被监管处罚。
一个投研助手 Agent 接到"分析茅台的投资价值"这种请求时,需要经过多层校验:
- 用户是否是合格投资者?(合规准入)
- 返回的信息是否包含内幕交易风险?(信息合规)
- 生成的建议是否构成了"投资建议"?(牌照合规)
- 数据来源是否有授权?(知识产权合规)
这些问题在通用 Agent 设计中不需要考虑,但在金融场景是生死线。
二、金融 Agent 的合规架构
三、Go 实现金融 Agent
合规校验引擎
package finance
import (
"context"
"fmt"
"strings"
"time"
)
// ComplianceLevel 合规等级
type ComplianceLevel int
const (
CompliancePass ComplianceLevel = 0 // 通过
ComplianceWarn ComplianceLevel = 1 // 警告但放行(记录审计日志)
ComplianceBlock ComplianceLevel = 2 // 阻止
)
// ComplianceCheck 合规检查结果
type ComplianceCheck struct {
Level ComplianceLevel
Reason string
AuditRequired bool // 是否需要人工复核
}
// FinancialCompliance 金融合规校验引擎
type FinancialCompliance struct {
// 白名单:允许的查询类型
allowedQueryTypes []string
// 黑名单词:涉及内幕交易/市场操纵的关键词
blockedKeywords []string
// 禁止的输出类型——绝对不能由 Agent 生成
forbiddenOutputs []string
}
func NewFinancialCompliance() *FinancialCompliance {
return &FinancialCompliance{
allowedQueryTypes: []string{
"financial_data", // 财务数据查询
"research_report", // 研报检索
"market_analysis", // 市场分析(不含建议)
"risk_assessment", // 风险评估
"regulatory_query", // 法规查询
"portfolio_review", // 持仓回顾(仅限自有持仓)
},
blockedKeywords: []string{
"内幕", "操纵", "坐庄", "对倒", "老鼠仓",
"保证收益", "稳赚", "翻倍",
},
forbiddenOutputs: []string{
"投资建议", "买卖推荐", "目标价位", "建议买入", "建议卖出",
},
}
}
// ValidateRequest 校验用户请求
func (fc *FinancialCompliance) ValidateRequest(ctx context.Context, userID string, query string) ComplianceCheck {
// 1. 关键词黑名单检查
queryLower := strings.ToLower(query)
for _, keyword := range fc.blockedKeywords {
if strings.Contains(queryLower, keyword) {
return ComplianceCheck{
Level: ComplianceBlock,
Reason: fmt.Sprintf("请求包含敏感词: %s", keyword),
AuditRequired: true,
}
}
}
// 2. 请求类型的意图检查
if fc.containsTradingIntent(query) {
return ComplianceCheck{
Level: ComplianceBlock,
Reason: "AI 助手不能提供投资建议",
AuditRequired: true,
}
}
// 3. 用户资格校验
if !fc.isQualifiedUser(ctx, userID) {
return ComplianceCheck{
Level: ComplianceBlock,
Reason: "用户不具备使用该功能的资格",
}
}
return ComplianceCheck{
Level: CompliancePass,
Reason: "合规检查通过",
}
}
// ValidateOutput 校验 Agent 输出
func (fc *FinancialCompliance) ValidateOutput(response string) ComplianceCheck {
// 1. 检查是否包含投资建议类输出
for _, forbidden := range fc.forbiddenOutputs {
if strings.Contains(response, forbidden) {
return ComplianceCheck{
Level: ComplianceWarn,
Reason: fmt.Sprintf("输出可能包含禁止内容: %s", forbidden),
AuditRequired: true,
}
}
}
// 2. 检查是否包含具体股票代码 + 建议性词汇
if fc.containsStockRecommendation(response) {
return ComplianceCheck{
Level: ComplianceWarn,
Reason: "输出包含可能被视为投资建议的内容",
AuditRequired: true,
}
}
return ComplianceCheck{Level: CompliancePass}
}
func (fc *FinancialCompliance) containsTradingIntent(query string) bool {
tradingPatterns := []string{
"能不能买", "该不该卖", "要不要持有",
"推荐", "建议买入", "目标价",
"明天涨", "下周跌",
}
for _, pattern := range tradingPatterns {
if strings.Contains(query, pattern) {
return true
}
}
return false
}
func (fc *FinancialCompliance) isQualifiedUser(ctx context.Context, userID string) bool {
// 实际实现中查询用户管理系统
return true
}
func (fc *FinancialCompliance) containsStockRecommendation(response string) bool {
// 简化版:检查 6 位数字(股票代码)+ 建议词汇的组合
// 生产环境需要更完善的 NLP 模型
return false
}
研报分析 Agent
// ResearchAssistant 研报助手
type ResearchAssistant struct {
compliance *FinancialCompliance
dataSources *DataSourceManager // Wind/聚源/Bloomberg
ragEngine *RAGEngine // 研报检索
riskEngine *RiskEngine // 风险评估
auditLogger *AuditLogger // 审计日志
}
// ResearchRequest 研报请求
type ResearchRequest struct {
Query string
StockCode string // 股票代码
ReportTypes []string // 研报类型:券商/独立/行业
DateRange DateRange
}
// HandleResearchRequest 处理研报请求
func (ra *ResearchAssistant) HandleResearchRequest(
ctx context.Context,
userID string,
req ResearchRequest,
) (string, error) {
// ===== 第一步:合规校验 =====
check := ra.compliance.ValidateRequest(ctx, userID, req.Query)
if check.Level == ComplianceBlock {
ra.auditLogger.Log(ctx, AuditEvent{
UserID: userID,
Action: "request_blocked",
Request: req.Query,
Reason: check.Reason,
Timestamp: time.Now(),
})
return ra.formatComplianceReject(check), nil
}
// ===== 第二步:数据获取 =====
// 2.1 财务数据(Wind/聚源)
financials, err := ra.dataSources.GetFinancialData(ctx, req.StockCode)
if err != nil {
return "", fmt.Errorf("获取财务数据失败: %w", err)
}
// 2.2 研报检索(RAG)
reports, err := ra.ragEngine.SearchReports(ctx, ResearchSearchQuery{
StockCode: req.StockCode,
ReportTypes: req.ReportTypes,
DateRange: req.DateRange,
TopK: 5,
})
if err != nil {
return "", fmt.Errorf("检索研报失败: %w", err)
}
// 2.3 风险数据
riskProfile, err := ra.riskEngine.Evaluate(ctx, req.StockCode)
if err != nil {
return "", fmt.Errorf("风险评估失败: %w", err)
}
// ===== 第三步:生成研报摘要 =====
summary := ra.generateResearchSummary(ctx, financials, reports, riskProfile)
// ===== 第四步:输出合规校验 =====
outputCheck := ra.compliance.ValidateOutput(summary)
if outputCheck.Level == ComplianceWarn {
// 附加合规声明
summary += ra.getComplianceDisclaimer()
}
// ===== 第五步:审计日志 =====
ra.auditLogger.Log(ctx, AuditEvent{
UserID: userID,
Action: "research_completed",
Request: req.Query,
StockCode: req.StockCode,
Sources: []string{"Wind", "ResearchDB", "RiskEngine"},
Timestamp: time.Now(),
})
return summary, nil
}
func (ra *ResearchAssistant) formatComplianceReject(check ComplianceCheck) string {
return fmt.Sprintf(
"抱歉,根据合规要求,无法处理此请求。原因: %s",
check.Reason,
)
}
func (ra *ResearchAssistant) getComplianceDisclaimer() string {
return `
---
【免责声明】
以上内容仅为信息整理,不构成任何投资建议。
所有数据来源于公开信息,AI 生成内容可能存在误差。
投资决策请基于个人判断或咨询持牌投资顾问。`
}
四、边界分析与 Trade-offs
合规校验性能:
- 每次请求的合规检查应在 50ms 内完成
- 关键词匹配做第一层过滤(< 1ms),复杂的 NLP 语义检查通过异步方式补充
审计日志的存储:
- 金融合规要求审计日志保留至少 3-5 年
- 日志必须包含:用户、时间、请求内容、处理结果、数据来源
- 审计日志本身要防篡改(建议用链式哈希)
输出控制的精确度:
- "不能给投资建议"的实际边界在哪儿?分析茅台的历史走势和建议买入茅台之间的界限很细
- 需要法务和合规部门共同定义输出红线
- 宁可误拦也不遗漏(合规优先于体验)
免责声明的作用:
- 法律上不能完全免责,但能降低风险
- 必须放在 AI 输出的显眼位置
- 内容需要法务审核
五、总结
金融 Agent 设计和通用 Agent 的核心区别在于增加了合规约束层:
- 请求合规校验——用户资格 + 请求类型 + 关键词黑名单
- 数据来源合规——只能使用授权数据源,标记数据来源
- 输出合规校验——禁止投资建议 + 事实性声明校验 + 免责声明
- 全链路审计——所有请求/处理/结果全量记录,不可篡改
金融 Agent 不能为了"好用"而牺牲合规。在金融领域,合规不是附加功能,而是基础功能。
更多推荐
所有评论(0)