feat: 入库 17 个新报告页
Deploy Wiki to Production / deploy (push) Has been cancelled

- 银行业Agent建设方案/报告/ 4 篇:建设方案 · 智能中台 · 意图识别 · 合规风险
- 研发型企业AI转型方案/报告/ 9 篇:角色矩阵(交互版) · 培训1-6课 · 角色矩阵 · 实操培训 · 培训路线图
- AI Agent 驾驭工程/报告/ 1 篇:Harness Engineering 全面解析
- 简历AI技术讲解.html + .md
- Dify部署分析报告.html
This commit is contained in:
zdh
2026-06-20 22:38:20 +08:00
parent 35f3ee4243
commit c677393d08
17 changed files with 12128 additions and 0 deletions
@@ -0,0 +1,591 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AgentScope-Java 银行智能中台架构方案(龙虾)</title>
<style>
:root {
--color-primary: #0078D4;
--color-primary-hover: #1E8CD8;
--color-primary-active: #005A9E;
--color-primary-bg: #E8F3FB;
--color-success: #107C10;
--color-success-bg: #E7F2E7;
--color-success-border: #9FC89F;
--color-warning: #FF8C00;
--color-warning-bg: #FFF4E5;
--color-warning-border: #FFC97F;
--color-error: #FF4D4F;
--color-error-bg: #FFF0F0;
--color-error-border: #FFB7B8;
--bg: #F5F5F5;
--bg-container: #FFFFFF;
--bg-elevated: #FAFAFA;
--border: #D9D9D9;
--border-light: #F0F0F0;
--text-primary: #141414;
--text-secondary: #595959;
--text-tertiary: #767676;
--radius-sm: 4px;
--radius-md: 6px;
--radius-lg: 8px;
--shadow-sm: 0 1px 2px rgba(0,0,0,0.03), 0 1px 6px -1px rgba(0,0,0,0.02);
--shadow-md: 0 2px 4px rgba(0,0,0,0.04), 0 4px 12px -2px rgba(0,0,0,0.04);
--shadow-lg: 0 4px 8px rgba(0,0,0,0.06), 0 8px 24px -4px rgba(0,0,0,0.08);
--sidebar-w: 280px;
--header-h: 64px;
--fluent-font-family-text: 'Segoe UI Variable Text', 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
--fluent-font-family-mono: 'Cascadia Code', 'Fira Code', 'SF Mono', 'Consolas', monospace;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: var(--fluent-font-family-text);
background: var(--bg); color: var(--text-primary);
line-height: 1.57; font-size: 14px;
}
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-tertiary); }
/* ===== HEADER ===== */
.header {
position: fixed; top: 0; left: 0; right: 0; height: var(--header-h);
background: rgba(255,255,255,0.88); backdrop-filter: blur(12px);
border-bottom: 1px solid var(--border-light);
display: flex; align-items: center; padding: 0 2rem; z-index: 100;
}
.header h1 {
font-size: 18px; font-weight: 700;
background: linear-gradient(135deg, var(--color-primary), #1E8CD8);
-webkit-background-clip: text; background-clip: text;
-webkit-text-fill-color: transparent; color: transparent;
}
.header .back-link {
margin-right: 16px; font-size: 13px; color: var(--color-primary);
text-decoration: none; flex-shrink: 0;
}
.header .back-link:hover { text-decoration: underline; }
.header .version {
margin-left: auto; font-size: 12px; color: var(--text-tertiary);
font-family: var(--fluent-font-family-mono);
}
/* ===== SIDEBAR ===== */
.sidebar {
position: fixed; top: var(--header-h); left: 0; bottom: 0;
width: var(--sidebar-w); background: var(--bg-container);
border-right: 1px solid var(--border); overflow-y: auto;
padding: 1.25rem 0; z-index: 90;
}
.sidebar .toc-label {
font-size: 12px; text-transform: uppercase; letter-spacing: 0.1em;
color: var(--text-tertiary); padding: 0 1.25rem; margin-bottom: 0.75rem;
}
.sidebar nav ol { list-style: none; padding: 0; counter-reset: toc; }
.sidebar nav li { counter-increment: toc; padding: 0; }
.sidebar nav a {
display: block; padding: 0.45rem 1.25rem; color: var(--text-secondary);
text-decoration: none; font-size: 13px; line-height: 1.4;
border-left: 2px solid transparent; transition: all 0.15s;
}
.sidebar nav a::before {
content: counter(toc) ". "; color: var(--color-primary);
font-weight: 600; font-size: 12px; margin-right: 0.4rem;
}
.sidebar nav a:hover { color: var(--color-primary); background: var(--color-primary-bg); }
.sidebar nav a.active { color: var(--color-primary); border-left-color: var(--color-primary); background: var(--color-primary-bg); font-weight: 600; }
.hamburger-btn {
display: none; position: fixed; top: 12px; right: 16px; z-index: 200;
background: var(--bg-container); border: 1px solid var(--border);
border-radius: var(--radius-md); width: 40px; height: 40px;
font-size: 20px; cursor: pointer; align-items: center; justify-content: center;
}
/* ===== MAIN ===== */
.main {
margin-left: var(--sidebar-w); margin-top: var(--header-h);
padding: 32px 40px 64px; min-height: calc(100vh - var(--header-h));
max-width: 1200px;
}
/* ===== SECTIONS ===== */
section {
margin: 48px 0; scroll-margin-top: calc(var(--header-h) + 1rem);
}
section h2 { font-size: 22px; line-height: 30px; padding-bottom: 8px; border-bottom: 1px solid var(--border); margin-bottom: 20px; color: var(--color-primary); }
h3 { font-size: 18px; line-height: 26px; margin: 24px 0 12px; color: #0078D4; }
h4 { font-size: 15px; line-height: 22px; margin: 16px 0 8px; color: var(--color-success); }
/* ===== PARAGRAPH ===== */
p { color: var(--text-secondary); font-size: 14px; margin: 10px 0; text-align: justify; }
p strong { color: var(--text-primary); }
/* ===== CODE ===== */
code {
font-family: var(--fluent-font-family-mono);
font-size: 13px; background: var(--bg-elevated);
padding: 2px 6px; border-radius: var(--radius-sm);
border: 1px solid var(--border-light); color: #D4380D;
}
pre {
background: #1E1E1E; color: #D4D4D4; border-radius: var(--radius-md);
padding: 16px 20px; overflow-x: auto; margin: 16px 0;
font-family: var(--fluent-font-family-mono); font-size: 13px;
line-height: 1.6; tab-size: 4;
}
pre code { background: none; border: none; padding: 0; color: inherit; font-size: inherit; }
pre.ascii-diagram {
background: var(--bg-elevated); color: var(--text-secondary);
border: 1px solid var(--border); font-family: var(--fluent-font-family-mono);
font-size: 12px; line-height: 1.35; padding: 16px 20px; white-space: pre;
}
/* ===== TABLES ===== */
.table-wrap { overflow-x: auto; margin: 20px 0; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { padding: 10px 14px; border: 1px solid var(--border); text-align: left; vertical-align: top; }
th { background: var(--bg-elevated); font-weight: 700; color: var(--text-primary); white-space: nowrap; }
td { background: var(--bg-container); color: var(--text-secondary); }
tbody tr:hover td { background: var(--color-primary-bg); }
/* ===== LISTS ===== */
ul, ol { margin: 8px 0 8px 20px; }
li { margin: 6px 0; color: var(--text-secondary); font-size: 14px; }
li strong { color: var(--text-primary); }
/* ===== INFO BOXES ===== */
.box {
border-radius: var(--radius-md); padding: 20px 24px; margin: 18px 0;
}
.box h4 { margin: 0 0 8px; font-size: 14px; font-weight: 700; }
.box p { font-size: 14px; margin: 4px 0; text-indent: 0; }
.box-info { background: var(--color-primary-bg); border: 1px solid #91CAFF; }
.box-info h4 { color: var(--color-primary); }
.box-good { background: var(--color-success-bg); border: 1px solid var(--color-success-border); }
.box-good h4 { color: var(--color-success); }
.box-warn { background: var(--color-warning-bg); border: 1px solid var(--color-warning-border); }
.box-warn h4 { color: var(--color-warning); }
/* ===== BLOCKQUOTE ===== */
blockquote {
margin: 16px 0; padding: 16px 22px; background: var(--bg-elevated);
border-left: 3px solid var(--color-primary);
border-radius: 0 var(--radius-sm) var(--radius-sm) 0; color: var(--text-secondary);
}
blockquote p { text-indent: 0; }
hr { border: none; border-top: 1px solid var(--border-light); margin: 32px 0; }
.footer {
text-align: center; padding: 28px 0; color: var(--text-tertiary);
font-size: 13px; border-top: 1px solid var(--border-light); margin-top: 40px;
}
/* ===== KPI BAR ===== */
.kpi-bar {
display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 32px;
}
.kpi {
flex: 1; min-width: 130px; background: var(--bg-container);
border: 1px solid var(--border-light); border-radius: var(--radius-md);
padding: 16px 14px; text-align: center; box-shadow: var(--shadow-sm);
}
.kpi .num { font-size: 22px; font-weight: 800; color: var(--color-primary); line-height: 1.2; }
.kpi .label { font-size: 11px; color: var(--text-tertiary); margin-top: 4px; }
@media (max-width: 768px) {
.sidebar { display: none; }
.sidebar.open {
display: block; position: fixed; top: var(--header-h); left: 0; bottom: 0;
width: 280px; z-index: 150; box-shadow: var(--shadow-lg);
}
.hamburger-btn { display: flex; }
.main { margin-left: 0; padding: 20px 16px 40px; }
table { font-size: 12px; }
th, td { padding: 6px 8px; }
section { margin: 28px 0; }
section h2 { font-size: 18px; }
.kpi-bar { gap: 8px; }
.kpi { min-width: 90px; padding: 10px 8px; }
.kpi .num { font-size: 18px; }
}
</style>
</head>
<body>
<header class="header">
<a href="../../index.html" class="back-link">← 返回知识库</a>
<h1>龙虾 · 银行智能中台架构方案</h1>
<span class="version">v2.0 · 三维鉴权版 · 2026-06</span>
</header>
<button class="hamburger-btn" onclick="document.getElementById('sidebar').classList.toggle('open')"></button>
<aside class="sidebar" id="sidebar">
<div class="toc-label">方案目录</div>
<nav><ol>
<li><a href="#context-与定位">Context 与定位</a></li>
<li><a href="#鉴权模型三维授权体系">鉴权模型:三维授权体系</a></li>
<li><a href="#令牌传播链渠道认证--龙虾授权">令牌传播链:渠道认证 → 龙虾授权</a></li>
<li><a href="#架构总览5-层扩展版">架构总览(5 层扩展版)</a></li>
<li><a href="#关键技术决策与分析">关键技术决策与分析</a></li>
<li><a href="#30万存量服务集成策略">30万存量服务集成策略</a></li>
<li><a href="#核心挑战30万工具--64k-上下文--准确高效调用">核心挑战:30万工具 × 64K 上下文 → 准确高效调用</a></li>
<li><a href="#关键场景走查">关键场景走查</a></li>
<li><a href="#银行合规中间件链">银行合规中间件链</a></li>
<li><a href="#里程碑规划12-周">里程碑规划(12 周)</a></li>
<li><a href="#关键风险与缓解">关键风险与缓解</a></li>
<li><a href="#验证方式">验证方式</a></li>
</ol></nav>
</aside>
<main class="main" onclick="document.getElementById('sidebar').classList.remove('open')">
<div class="kpi-bar">
<div class="kpi"><div class="num">30<span style="font-size:11px;font-weight:400"> 万+</span></div><div class="label">存量服务规模</div></div>
<div class="kpi"><div class="num">3<span style="font-size:11px;font-weight:400"></span></div><div class="label">鉴权模型(用户×渠道×数据)</div></div>
<div class="kpi"><div class="num">5<span style="font-size:11px;font-weight:400"></span></div><div class="label">系统架构分层</div></div>
<div class="kpi"><div class="num">6<span style="font-size:11px;font-weight:400"></span></div><div class="label">工具检索准确性保障</div></div>
<div class="kpi"><div class="num">12<span style="font-size:11px;font-weight:400"></span></div><div class="label">交付周期</div></div>
</div>
<section><h2 id="context-与定位">Context 与定位</h2>
<p>本方案使用 <strong>AgentScope-Java v2.0</strong> 构建「银行智能中台」(代号:龙虾),定位为<strong>基础服务层</strong>——不直接面向终端用户,而是作为其他业务系统的后端能力引擎被调用。</p>
<div class="box box-info"><h4>龙虾的定位边界</h4><p><strong>做什么</strong>:提供 AI Agent 对话能力 + 30万存量服务工具化封装 + 统一的智能工具调度入口。<br>
<strong>不做什么</strong>:不做终端用户认证(由上游渠道完成)、不做 IM/消息渠道、不做业务流程编排(由调用方系统负责)。</p></div>
<hr>
<section><h2 id="鉴权模型三维授权体系">鉴权模型:三维授权体系</h2>
<p>龙虾作为基础服务,调用方来自<strong>三个维度</strong>的交叉,鉴权模型必须从传统 RBAC 升级为三维 ABAC:</p>
<h3>三维主体矩阵</h3>
<div class="table-wrap"><table>
<tr><th>维度</th><th>行内员工 (B2E)</th><th>对公客户 (B2B)</th><th>对私客户 (B2C)</th></tr>
<tr><td><strong>身份标识</strong></td><td>工号 (HR/UM系统)</td><td>企业客户号 (ECIF)</td><td>个人客户号 (CIF)</td></tr>
<tr><td><strong>身份来源</strong></td><td>行内 LDAP/统一用户中心</td><td>核心客户信息系统</td><td>核心客户信息系统</td></tr>
<tr><td><strong>典型角色</strong></td><td>客户经理 / 风控审批 / 柜员 / 运营</td><td>企业法人 / 财务 / 经办人</td><td>个人持卡人</td></tr>
<tr><td><strong>数据可见范围</strong></td><td>所属机构 + 岗位授权范围</td><td>仅限本企业及关联企业</td><td>仅限本人</td></tr>
<tr><td><strong>接口可见性</strong></td><td>按角色 + 系统白名单</td><td>按产品签约 + 企业类型</td><td>按产品持有 + 客户等级</td></tr>
</table></div>
<h3>渠道维:调用方系统身份</h3>
<p>龙虾不直接面向终端用户,所有调用来自上游业务系统。每个渠道具有不同的<strong>可信等级</strong><strong>接口权限集</strong></p>
<div class="table-wrap"><table>
<tr><th>渠道类型</th><th>典型系统</th><th>认证强度</th><th>典型调用场景</th></tr>
<tr><td><strong>内部业务系统</strong></td><td>信贷系统 / 风控系统 / 柜面</td><td>高(行内 SSO + mTLS</td><td>客户经理查客户征信 → 龙虾调CBS接口</td></tr>
<tr><td><strong>电子渠道</strong></td><td>手机银行 / 网银 / 小程序</td><td>中(用户已登录 + 设备指纹)</td><td>客户问"我的贷款额度" → 龙虾调零售信贷接口</td></tr>
<tr><td><strong>外部合作方</strong></td><td>第三方支付 / 银联 / 合作平台</td><td>低(仅限特定API + 证书绑定)</td><td>合作方查产品利率 → 龙虾调产品信息接口</td></tr>
<tr><td><strong>管理后台</strong></td><td>Web Dashboard</td><td>高(管理员工号 + OTP</td><td>租户管理员配置工具白名单</td></tr>
</table></div>
<h3>数据维:谁能看什么数据</h3>
<p>鉴权不仅控制"能否调接口",还控制"能看什么数据"。数据范围分三级:</p>
<div class="table-wrap"><table>
<tr><th>数据范围</th><th>说明</th><th>适用场景</th></tr>
<tr><td><strong>SELF</strong></td><td>仅限数据主体本人/本企业</td><td>C端客户查自己的账户/征信/贷款</td></tr>
<tr><td><strong>BRANCH</strong></td><td>所属分行/支行范围内</td><td>客户经理查本支行所有客户</td></tr>
<tr><td><strong>ALL_AUTHORIZED</strong></td><td>按角色+产品签约的完整授权范围</td><td>风控审批员跨支行评估风险</td></tr>
</table></div>
<hr>
<section><h2 id="令牌传播链渠道认证--龙虾授权">令牌传播链:渠道认证 → 龙虾授权</h2>
<p>龙虾<strong>不做终端认证</strong>,而是信任上游渠道已完成的认证,通过令牌传播链实现鉴权:</p>
<pre class="ascii-diagram">终端用户 (员工/客户)
│ [渠道完成认证]
│ 手机银行 → 密码/生物识别
│ 柜面 → 工号+密码+OTP
│ 信贷系统 → 行内SSO
渠道系统
│ 调用龙虾时携带:
│ ┌─────────────────────────────────┐
│ │ X-Channel-Id: credit-system │ ← 谁在调我
│ │ X-End-User-Type: EMPLOYEE │ ← 终端用户类型
│ │ X-End-User-Id: EMP-00342 │ ← 终端用户标识
│ │ X-Data-Scope: BRANCH │ ← 数据范围
│ │ X-Tenant-Id: branch-beijing │ ← 所属租户
│ │ Authorization: Bearer &lt;JWT&gt; │ ← 渠道签发的JWT
│ └─────────────────────────────────┘
龙虾 (基础服务)
│ 验签 → 解析三维上下文 → 决定可用接口+数据过滤
├─ 1. 验渠道签名 → 确认调用来自合法渠道
├─ 2. 解析用户身份 → EMPLOYEE / CORP_CUSTOMER / RETAIL_CUSTOMER
├─ 3. 叠加数据范围 → SELF / BRANCH / ALL_AUTHORIZED
└─ 4. 执行工具调用 → 仅返回授权范围内的数据
</pre>
<h3>核心设计决策:为什么是令牌传播而非统一认证</h3>
<div class="table-wrap"><table>
<tr><th>方案</th><th>优点</th><th>缺点</th><th>适用场景</th></tr>
<tr><td><strong>统一认证中心</strong><br>(所有渠道跳转龙虾登录)</td><td>权限集中管控<br>审计日志完整</td><td>渠道接入成本高<br>用户体验割裂<br>存量系统改造大</td><td>新建系统、<br>渠道数量少</td></tr>
<tr><td><strong>令牌传播</strong><br>(渠道认证后签发JWT)</td><td><strong>渠道零改造接入</strong><br>终端用户体验无感<br>存量系统友好</td><td>需信任渠道认证强度<br>需渠道签名校验</td><td>已有多个渠道<br>存量系统多<br><strong>(本方案选择)</strong></td></tr>
<tr><td><strong>混合模式</strong><br>(关键操作回源验证)</td><td>安全性与便利性平衡</td><td>实现复杂度最高</td><td>金融交易等高安全场景</td></tr>
</table></div>
<div class="box box-warn"><h4>风险提示</h4><p>令牌传播的核心风险是"渠道认证强度不一致"——柜面系统使用工号+OTP(高安全),手机银行可能仅用密码+设备指纹(中安全)。龙虾需要根据渠道认证强度,对高风险操作(大额转账、授信审批)追加二次确认。</p></div>
<hr>
<section><h2 id="架构总览5-层扩展版">架构总览(5 层扩展版)</h2>
<p>原 5 层架构不变,但 Gateway Layer 从单纯的"多租户路由"升级为<strong>"三维鉴权网关"</strong></p>
<pre class="ascii-diagram">┌──────────────────────────────────────────────────────────────────┐
│ Web Dashboard (唯一前端) │
│ Vue3 + Arco Design │ SSE流式 │ 租户管理 │ 审计 │ 工具市场 │
└──────────────────────────┬───────────────────────────────────────┘
│ SSE / HTTP REST
┌──────────────────────────▼───────────────────────────────────────┐
│ Gateway Layer ★ 升级为三维鉴权网关 │
│ │
│ ┌──────────────┐ ┌────────────────┐ ┌─────────────────────┐ │
│ │ 渠道签名校验 │ │ 三维上下文构建 │ │ 令牌校验 + 范围裁剪 │ │
│ │ ChannelId→ │ │ User×Channel │ │ JWT验签 → DataScope│ │
│ │ 公钥验签 │ │ ×DataScope │ │ → 预过滤 BitMap │ │
│ └──────────────┘ └────────────────┘ └─────────────────────┘ │
│ │
│ Spring Boot 3.5 + WebFlux │ Redis Session │ Nacos 注册 │
└──────────────────────────┬───────────────────────────────────────┘
┌──────────────────────────▼───────────────────────────────────────┐
│ Agent Orchestration Layer (智能体编排) │
│ Master Agent → Router Agent → Sub-Agent Pool │
│ 信贷 │ 风控 │ 客服 │ 数据查询 │ 运营 │ 合规 │ IT运维 │ ... │
└──────────────────────────┬───────────────────────────────────────┘
┌──────────────────────────▼───────────────────────────────────────┐
│ Capability Layer (能力层) │
│ Tools (30万服务) │ Skills 技能库 │ Memory 三层记忆 │ Sandbox │
└──────────────────────────┬───────────────────────────────────────┘
┌──────────────────────────▼───────────────────────────────────────┐
│ Enterprise Service Integration (30万存量服务集成) │
│ 元数据注册 → ToolDefinition自动生成 → 动态调用 │
└──────────────────────────────────────────────────────────────────┘</pre>
<hr>
<section><h2 id="关键技术决策与分析">关键技术决策与分析</h2>
<div class="table-wrap"><table>
<tr><th>决策点</th><th>选型</th><th>依据</th><th>替代方案</th><th>优缺点</th></tr>
<tr><td>Agent 框架</td><td>AgentScope-Java v2.0-RC2</td><td>分布式+事件系统+Middleware完整,天然支持多Agent编排</td><td>LangChain4j / Spring AI / 自研</td><td><strong></strong> 原生Java生态,无 Python 依赖;<strong></strong> RC2 尚未GAAPI可能变动</td></tr>
<tr><td>唯一交互界面</td><td>Web Dashboard(无IM</td><td>银行内网环境,浏览器天然可用;IM渠道需额外适配</td><td>企业微信/钉钉/飞书 Bot</td><td><strong></strong> 零渠道适配成本;<strong></strong> 员工需打开浏览器,不如IM方便</td></tr>
<tr><td>鉴权模型</td><td>三维ABAC(用户×渠道×数据范围)</td><td>调用方包含行内员工+C端客户,渠道多样,传统RBAC无法覆盖</td><td>纯RBAC / OAuth2.0 Scope / OPA策略引擎</td><td><strong></strong> 覆盖全场景;<strong></strong> 实现复杂度高,上下文传播需全链路治理</td></tr>
<tr><td>30万服务集成</td><td>自动发现+动态Tool生成</td><td>手工封装需225人年,物理不可行</td><td>手工MCP Server封装 / API网关手动配置</td><td><strong></strong> 唯一可行方案;<strong></strong> 依赖OpenAPI覆盖率(当前~40%</td></tr>
<tr><td>多租户隔离</td><td>Workspace物理隔离 + 三维TenantContext</td><td>银行合规底线:租户间数据不可互见</td><td>逻辑隔离(单DB+tenant_id列)/ 混合模式</td><td><strong></strong> 安全最高;<strong></strong> 资源开销大,每租户独立Agent实例</td></tr>
<tr><td>通信协议</td><td>SSE(对话流)+ HTTP REST(管理API</td><td>比WebSocket简单可靠,银行内网丢包率低</td><td>WebSocket / gRPC Stream</td><td><strong></strong> 防火墙友好,无协议升级;<strong></strong> 单向流,客户端不能中途发指令</td></tr>
</table></div>
<hr>
<section><h2 id="30万存量服务集成策略">30万存量服务集成策略</h2>
<h3>核心思路:ToolDefinition 而非 MCP Server</h3>
<p>这是整个方案最关键的差异化设计。面对30万存量服务,手工封装 MCP Server 需要 <strong>225 人年</strong>,物理不可行。本方案的核心创新是:<strong>自动化产物是数据库记录(ToolDefinition),而非进程(MCP Server</strong></p>
<div class="table-wrap"><table>
<tr><th>对比维度</th><th>手工MCP模式</th><th>自动化ToolDefinition模式(本方案)</th></tr>
<tr><td><strong>产物</strong></td><td>每个服务一个MCP Server进程</td><td>每条API一条ToolDefinition记录(~2KB</td></tr>
<tr><td><strong>30万服务资源</strong></td><td>15TB内存 + 30万进程</td><td>~600MB数据库 + 0新进程</td></tr>
<tr><td><strong>启动速度</strong></td><td>MCP Server冷启动2-5s</td><td>无需启动,随查随用</td></tr>
<tr><td><strong>新服务上线</strong></td><td>需手工编写+部署</td><td>注册中心出现 → 10分钟内自动可用</td></tr>
<tr><td><strong>调用链</strong></td><td>Agent → MCP Client → MCP Server → 真实服务(多一跳)</td><td>Agent → ServiceInvoker → 真实服务(直连)</td></tr>
<tr><td><strong>维护成本</strong></td><td>30万个进程的运维监控</td><td>1个ServiceInvoker通用组件</td></tr>
</table></div>
<h3>自动化管道</h3>
<pre class="ascii-diagram">注册中心(Nacos/Eureka) → 元数据提取 → LLM描述增强 → 分组标注
每10分钟增量同步 OpenAPI/Swagger qwen-turbo批量 按客群/业务线
gRPC Reflection 原始 → 语义增强 自动分类
API Gateway元数据
→ ToolDefinition入库 → 工具市场上架 → 租户启用 → Agent可调用
PostgreSQL+pgvector 状态:待审核 人工一次配置 零人工
+Elasticsearch全文索引</pre>
<h3>元数据覆盖率与降级策略</h3>
<p>自动生成的工具质量取决于上游API文档的完整度。对不同类型的服务采用分级处理:</p>
<div class="table-wrap"><table>
<tr><th>元数据质量</th><th>预期占比</th><th>处理方式</th><th>工具质量</th></tr>
<tr><td><strong>OpenAPI/Swagger 完整</strong></td><td>~40%</td><td>完整解析 name/desc/params/response schemaLLM增强描述</td><td>⭐⭐⭐⭐⭐ 高</td></tr>
<tr><td><strong>gRPC Proto Reflection</strong></td><td>~15%</td><td>Proto 解析 → method/field映射 → 补充业务描述</td><td>⭐⭐⭐⭐ 较高</td></tr>
<tr><td><strong>API Gateway 基础元数据</strong></td><td>~35%</td><td>提取 path+method+基础参数 → LLM推断业务语义</td><td>⭐⭐⭐ 中等</td></tr>
<tr><td><strong>无元数据(遗留系统)</strong></td><td>~10%</td><td>仅生成占位ToolDefinitionname+path),标记"待完善"</td><td>⭐⭐ 低(需人工补文档)</td></tr>
</table></div>
<div class="box box-info"><h4>实用主义策略</h4><p>优先保障核心系统(CBS/CRM/风控/信贷等前20%高频服务)的工具质量,这些系统通常已有完整OpenAPI文档。长尾遗留系统允许低质量占位,逐步补文档——80%的Agent调用集中在前20%的工具上。</p></div>
<hr>
<section><h2 id="核心挑战30万工具--64k-上下文--准确高效调用">核心挑战:30万工具 × 64K 上下文 → 准确高效调用</h2>
<h3>问题量化</h3>
<p>30万工具 × 每工具~300 tokens = <strong>9000万 tokens</strong>。64K上下文可用空间约40K tokens,单次可装载工具 ≤ <strong>130个</strong>——仅占全部工具的 <strong>0.04%</strong>。必须把工具选择变成一个三级过滤漏斗。</p>
<h3>三级过滤漏斗</h3>
<pre class="ascii-diagram">30万工具
┌──────────────────────────────────────────────────────────┐
│ Layer 0: 确定性预过滤 (Deterministic Pre-filter) │
│ ★ 核心创新:三维上下文硬过滤 │
│ │
│ 用户画像 × 渠道权限 × 数据范围 → BitMap AND 运算 │
│ │
│ 规则1: 渠道 → 手机银行看不到柜面专用接口 │
│ 规则2: 用户类型 → C端客户看不到员工管理工具 │
│ 规则3: 客群/角色 → 对公客户经理物理看不到对私储蓄工具 │
│ 规则4: 地区 → 北京分行看不到上海分行专属服务 │
│ 规则5: 已开通系统 → 未签约产品对应接口不可见 │
│ 规则6: 数据范围 → SELF/Branch/ALL 三级过滤 │
│ 规则7: 合规评级 → 低评级用户看不到高风险操作 │
│ │
│ 效果: 30万 → 500~3000(削减 99%+
│ 延迟: &lt; 5ms (纯内存BitMap) 确定性: 100% 无遗漏 │
└──────────────────────────┬───────────────────────────────┘
│ ~2000 候选
┌──────────────────────────────────────────────────────────┐
│ Layer 1: 意图提取 + 混合检索 │
│ Dense(向量) + Sparse(BM25) → RRF融合 → Top-100 │
│ 延迟: &lt; 80ms 命中率: &gt;95% │
└──────────────────────────┬───────────────────────────────┘
│ 100 候选
┌──────────────────────────────────────────────────────────┐
│ Layer 2: 精排 + Agent上下文注入 │
│ Cross-encoder → 100→15 注入Agent context │
│ 延迟: &lt; 150ms 最终准确率: &gt;97% │
└──────────────────────────────────────────────────────────┘</pre>
<h3>检索准确性保障(六层)</h3>
<div class="table-wrap"><table>
<tr><th>层级</th><th>机制</th><th>效果</th><th>可验证性</th></tr>
<tr><td><strong>L0 确定性预过滤</strong></td><td>7条规则 × BitMap AND(新增3条渠道/类型/数据范围规则)</td><td>30万→500~3000100%确定性</td><td>抽样100用户,验证过滤后工具数</td></tr>
<tr><td><strong>L1 工具描述增强</strong></td><td>LLM离线增强:用途+客群+常见问法+注意事项</td><td>语义检索命中率提升30%+</td><td>A/B对比增强前后检索效果</td></tr>
<tr><td><strong>L2 混合检索+精排</strong></td><td>Dense+Sparse → RRF → Cross-encoder Rerank</td><td>Top-15命中率>97%</td><td>人工标注1000条银行问法</td></tr>
<tr><td><strong>L3 Agent自行验证</strong></td><td>LLM判断检索结果是否匹配意图 → 不匹配则 search_tools()</td><td>首次无结果率<3%</td><td>统计二次检索触发率</td></tr>
<tr><td><strong>L4 用户/租户个性化</strong></td><td>高频工具加权 + 协同过滤</td><td>常用工具排第一</td><td>统计首位工具点击率</td></tr>
<tr><td><strong>L5 人工反馈闭环</strong></td><td>Dashboard「工具选错了」按钮 → 回流校准Reranker</td><td>持续优化</td><td>误调用率趋势图</td></tr>
</table></div>
<div class="box box-good"><h4>为什么预过滤必须是确定性的</h4><p>向量检索是概率性的(可能漏、可能错),但在银行场景,<strong>某些"漏"和"错"不可接受</strong>——对公客户经理看到对私储蓄工具 → 合规事故;未签约产品的API被调用 → 越权。Layer 0 用 BitMap 确定性硬过滤,保证了这类错误的概率为 0。</p></div>
<hr>
<section><h2 id="关键场景走查">关键场景走查</h2>
<h3>场景 1:客户经理查客户征信(B2E 典型场景)</h3>
<pre class="ascii-diagram">触发: 客户经理在信贷系统输入 &quot;查张三的征信&quot;
渠道: 信贷系统 (Channel=credit-system, Auth=mTLS+SSO)
│ Header: End-User-Type=EMPLOYEE, User-Id=EMP-00342, Data-Scope=BRANCH
龙虾 Gateway:
│ Layer 0 预过滤:
│ 规则1: credit-system → 允许信贷/风控/查询类接口
│ 规则2: EMPLOYEE → 允许内部员工工具集
│ 规则3: 客户经理+对公 → 对公信贷类 + 通用查询
│ 规则4: 北京分行 → 北京分行可见的服务
│ 规则5: 已开通CBS,CRM → CBS+CRM的API
│ 规则6: BRANCH → 可查本支行客户数据
│ 规则7: 合规评级HIGH → 全部工具可用
│ → 30万 → 约1200个候选工具
│ 意图提取: &quot;查征信&quot; → {intent:征信查询, domain:credit, entity:个人客户}
│ 混合检索: 在1200个候选内 → Top-100
│ 精排: → Top-15 → 注入Agent
Agent: 选择 cbs_query_credit_report(idNumber=&quot;110101...&quot;)
│ 调用前: PermissionMiddleware 验证:
│ ✓ 客户经理可查征信 (角色权限)
│ ✓ 张三在北京分行范围内 (数据范围)
│ ✓ 信用查询是读操作 (自动放行)
ServiceInvoker → CBS核心信贷系统 → 返回征信报告
│ 审计中间件记录: EMP-00342 | credit-system | query_credit_report | 北京分行 | SUCCESS
Agent: &quot;张三征信评分720分,共有3笔贷款记录...&quot; (脱敏展示)</pre>
<h3>场景 2:C端客户查贷款额度(B2C 典型场景)</h3>
<pre class="ascii-diagram">触发: 对私客户在手机银行问 &quot;我能贷多少钱&quot;
渠道: 手机银行 (Channel=mobile-bank, Auth=密码+设备指纹)
│ Header: End-User-Type=RETAIL_CUSTOMER, User-Id=CUST-88231, Data-Scope=SELF
龙虾 Gateway:
│ Layer 0 预过滤:
│ 规则1: mobile-bank → 仅限电子渠道开放的接口(不含柜面/内部专用)
│ 规则2: RETAIL_CUSTOMER → 仅限C端客户可见工具
│ 规则3: 对私客户 → 对私产品类工具
│ 规则6: SELF → 仅限本人数据(硬限制)
│ → 30万 → 约300个候选工具
│ 意图提取: &quot;我能贷多少钱&quot; → {intent:贷款额度查询, domain:retail_loan}
│ 混合检索: 300候选 → Top-50
│ 精排: → Top-10 → 注入Agent
Agent: 选择 retail_query_loan_limit(customerId=&quot;CUST-88231&quot;)
│ 调用前: PermissionMiddleware 验证:
│ ✓ 数据范围=SELF → 只能查 CUST-88231 本人的贷款信息
│ ✓ 渠道=mobile-bank → 贷款额度查询是开放接口
│ ✗ 如果Agent试图调 &quot;修改贷款额度&quot; → DENY(写操作 + 渠道认证强度不够)
ServiceInvoker → 零售信贷系统 → 返回额度信息
Agent: &quot;您目前的可用额度为30万元,其中信用贷20万、抵押贷10万...&quot;
</pre>
<h3>场景 3:跨渠道数据泄漏防御(安全关键场景)</h3>
<p><strong>攻击假设</strong>:攻击者获取了手机银行的合法Token(C端客户身份),试图通过龙虾查询非本人数据。</p>
<pre class="ascii-diagram">攻击路径: 手机银行Token → 龙虾 → 构造请求查他人征信
防御层次:
① Data-Scope=SELF → 硬限制,只能查 CUST-88231 本人
② Layer 0 预过滤 → tool_definitions 的 data_scope 字段 = SELF 的工具
只有&quot;本人可查&quot;标签的接口才出现在候选池
③ PermissionMiddleware → 工具调用前再次校验:
请求的 customerId 必须 == Context.endUserId
不匹配 → DENY + 告警
④ SensitiveDataMiddleware → 即使绕过(理论上不可能),输出脱敏
⑤ AuditMiddleware → 全量记录: 谁、什么时候、从哪个渠道、调了什么、返回了什么
结论: 5层纵深防御。即使单层被突破,后续4层仍可拦截。</pre>
<hr>
<section><h2 id="银行合规中间件链">银行合规中间件链</h2>
<p>龙虾内置<strong>5个核心中间件</strong>,以责任链模式串联,每次 Agent 操作依次经过。中间件不是"可选插件"而是<strong>银行合规的底线实现</strong></p>
<div class="table-wrap"><table>
<tr><th>中间件</th><th>拦截时机</th><th>功能</th><th>为什么必须</th></tr>
<tr><td><strong>ChannelAuthMiddleware</strong></td><td>请求到达时</td><td>验证渠道签名+令牌有效性+构建三维上下文</td><td>防止非法系统调用龙虾;渠道认证强度分级决定了后续权限决策</td></tr>
<tr><td><strong>PermissionCheckMiddleware</strong></td><td>每次工具调用前</td><td>工具白名单校验 + 写操作人工确认 + 数据范围校验</td><td>防止越权操作;写操作必须本人确认(即使角色允许)</td></tr>
<tr><td><strong>SensitiveDataMiddleware</strong></td><td>用户输入&LLM输出时</td><td>身份证/银行卡/手机号自动脱敏 + 疑似泄露告警</td><td>防止敏感数据通过LLM泄漏(即使内网也可能有日志泄露风险)</td></tr>
<tr><td><strong>AuditMiddleware</strong></td><td>每次操作全程</td><td>全量记录:谁+渠道+操作+入参+出参+耗时+成功/失败</td><td>银保监会合规要求;事后溯源唯一依据</td></tr>
<tr><td><strong>ComplianceMiddleware</strong></td><td>每次Agent决策后</td><td>检查Agent输出是否符合监管要求(不推荐非持牌产品、不提供投资建议等)</td><td>LLM幻觉可能导致合规风险——Agent可能"建议"客户买非授权产品</td></tr>
</table></div>
<hr>
<section><h2 id="里程碑规划12-周">里程碑规划(12 周)</h2>
<div class="table-wrap"><table>
<tr><th>阶段</th><th>周期</th><th>核心目标</th><th>交付物</th><th>风险点</th></tr>
<tr><td><strong>Phase 1</strong><br>骨架+单Agent对话</td><td>Week 1-3</td><td>Spring Boot + AgentScope 基础搭建;HarnessAgent 最小可用;Web Dashboard 对话界面</td><td>可对话的 Dashboard 原型;千问模型联通;基础 Workspace</td><td>AgentScope RC2 稳定性;千问模型延迟</td></tr>
<tr><td><strong>Phase 2</strong><br>多Agent+工具市场MVP</td><td>Week 4-6</td><td>Sub-Agent池;Router Agent;动态Tool生成引擎;30万服务扫描器</td><td>工具市场Dashboard;信贷/风控/客服三个Sub-Agent可用;~100个核心系统工具自动生成</td><td>OpenAPI覆盖率不足导致工具质量差;Router Agent意图识别不准</td></tr>
<tr><td><strong>Phase 3</strong><br>三维鉴权+合规+企业集成</td><td>Week 7-9</td><td>三维ABAC鉴权落地;5个合规中间件全部就绪;渠道签名校验;租户物理隔离</td><td>完整鉴权链路可演示;敏感数据脱敏生效;审计日志可查询</td><td>渠道对接工作量可能超预期;合规中间件可能误拦截</td></tr>
<tr><td><strong>Phase 4</strong><br>生产加固</td><td>Week 10-12</td><td>分布式部署;Sandbox隔离;监控告警;压力测试;安全渗透测试</td><td>1000并发会话稳定运行;P99延迟<5s安全测试通过报告</td><td>性能瓶颈未知;国产化适配(信创)</td></tr>
</table></div>
<hr>
<section><h2 id="关键风险与缓解">关键风险与缓解</h2>
<div class="table-wrap"><table>
<tr><th>风险</th><th>概率</th><th>影响</th><th>缓解措施</th><th>触发信号</th></tr>
<tr><td>AgentScope v2.0 未按预期GA</td><td></td><td></td><td>基于RC2开发核心逻辑,预留升级脚本;备选方案:退回AgentScope v1.x + 自研补缺失功能</td><td>RC3延迟超过4周</td></tr>
<tr><td>30万服务OpenAPI覆盖率不足40%</td><td></td><td></td><td>三种降级路径(Swagger→gRPC→基础元数据);优先保障核心系统工具质量(前20%高频服务)</td><td>Phase 2扫描后覆盖率<30%</td></tr>
<tr><td><strong>三维鉴权上下文丢失/篡改</strong></td><td></td><td>严重</td><td>渠道签名校验+JWT防篡改;全链路traceId关联验证;异常上下文自动降级为最小权限</td><td>审计日志发现上下文不一致</td></tr>
<tr><td><strong>LLM幻觉触发错误业务操作</strong></td><td></td><td>严重</td><td>写操作必须人工确认;ComplianceMiddleware拦截不合规输出;关键操作二次确认</td><td>Agent输出含非授权建议</td></tr>
<tr><td>多租户数据泄漏</td><td></td><td>严重</td><td>Workspace物理隔离+审计全量+渗透测试;租户销毁时立即清理所有数据</td><td>渗透测试发现跨租户访问</td></tr>
<tr><td><strong>C端与B2E权限混淆</strong></td><td></td><td></td><td>三维ABAC的UserType字段决定权限模型分叉;代码审查确保两套逻辑完全隔离</td><td>C端客户成功调用了B2E接口</td></tr>
<tr><td>银行系统响应慢/超时</td><td></td><td></td><td>3次重试+降级提示+缓存GET结果;对超过2s的接口异步化</td><td>P95延迟>3s</td></tr>
</table></div>
<hr>
<section><h2 id="验证方式">验证方式</h2>
<ol><li><strong>Dashboard E2E</strong>:打开浏览器 → 登录 → 发送消息 → SSE流式返回 → 工具调用卡片展示 → 审计日志可查询</li><li><strong>三维鉴权验证</strong>C端客户Token + Data-Scope=SELF → 试图查他人数据 → 被拦截;员工Token + Data-Scope=BRANCH → 可查本支行数据</li><li><strong>多租户隔离</strong>:租户A的Agent调用工具返回"未授权",租户B同名工具正常</li><li><strong>渠道隔离</strong>:手机银行渠道 → 仅开放电子渠道工具集;信贷系统渠道 → 完整内部工具集</li><li><strong>30万服务扫描</strong>:启动后10分钟内完成全量元数据同步,Dashboard工具市场可见新服务</li><li><strong>合规验证</strong>:输入身份证号 → 自动脱敏;尝试write工具 → 被拦截弹确认;Agent输出含投资建议 → ComplianceMiddleware拦截</li><li><strong>压力测试</strong>JMeter 1000并发SSE连接 → 错误率<1%P99延迟<5s</li></ol>
<div class="footer">
<p>龙虾 · 银行智能中台架构方案 v2.0 · 基于 AgentScope-Java · 2026-06</p>
</div>
</main>
<script>
(function() {
var sidebarLinks = document.querySelectorAll('.sidebar nav a');
var sections = [];
sidebarLinks.forEach(function(a) {
var target = document.querySelector(a.getAttribute('href'));
if (target) sections.push({link: a, target: target});
});
function onScroll() {
var scrollPos = window.scrollY + 100, current = null;
sections.forEach(function(s) { if (s.target.offsetTop <= scrollPos) current = s; });
sidebarLinks.forEach(function(a) { a.classList.remove('active'); });
if (current) current.link.classList.add('active');
}
window.addEventListener('scroll', onScroll);
onScroll();
})();
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,848 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>银行智能中台 — 意图识别与工具检索方案</title>
<style>
:root {
--color-primary: #0078D4;
--color-primary-hover: #1E8CD8;
--color-primary-active: #005A9E;
--color-primary-bg: #E8F3FB;
--color-success: #107C10;
--color-success-bg: #E7F2E7;
--color-success-border: #9FC89F;
--color-warning: #FF8C00;
--color-warning-bg: #FFF4E5;
--color-warning-border: #FFC97F;
--color-error: #FF4D4F;
--color-error-bg: #FFF0F0;
--color-error-border: #FFB7B8;
--bg: #F5F5F5;
--bg-container: #FFFFFF;
--bg-elevated: #FAFAFA;
--border: #D9D9D9;
--border-light: #F0F0F0;
--text-primary: #141414;
--text-secondary: #595959;
--text-tertiary: #767676;
--radius-sm: 4px;
--radius-md: 6px;
--radius-lg: 8px;
--shadow-sm: 0 1px 2px rgba(0,0,0,0.03), 0 1px 6px -1px rgba(0,0,0,0.02);
--shadow-md: 0 2px 4px rgba(0,0,0,0.04), 0 4px 12px -2px rgba(0,0,0,0.04);
--shadow-lg: 0 4px 8px rgba(0,0,0,0.06), 0 8px 24px -4px rgba(0,0,0,0.08);
--sidebar-w: 280px;
--header-h: 64px;
--fluent-font-family-text: 'Segoe UI Variable Text', 'Segoe UI', 'PingFang SC', 'Microsoft YaHei', sans-serif;
--fluent-font-family-mono: 'Cascadia Code', 'Fira Code', 'SF Mono', 'Consolas', monospace;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: var(--fluent-font-family-text);
background: var(--bg); color: var(--text-primary);
line-height: 1.57; font-size: 14px;
}
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-tertiary); }
/* ===== HEADER ===== */
.header {
position: fixed; top: 0; left: 0; right: 0; height: var(--header-h);
background: rgba(255,255,255,0.88); backdrop-filter: blur(12px);
border-bottom: 1px solid var(--border-light);
display: flex; align-items: center; padding: 0 2rem; z-index: 100;
}
.header h1 {
font-size: 18px; font-weight: 700;
background: linear-gradient(135deg, var(--color-primary), #1E8CD8);
-webkit-background-clip: text; background-clip: text;
-webkit-text-fill-color: transparent; color: transparent;
}
.header .back-link {
margin-right: 16px; font-size: 13px; color: var(--color-primary);
text-decoration: none; flex-shrink: 0;
}
.header .back-link:hover { text-decoration: underline; }
.header .version {
margin-left: auto; font-size: 12px; color: var(--text-tertiary);
font-family: var(--fluent-font-family-mono);
}
/* ===== SIDEBAR ===== */
.sidebar {
position: fixed; top: var(--header-h); left: 0; bottom: 0;
width: var(--sidebar-w); background: var(--bg-container);
border-right: 1px solid var(--border); overflow-y: auto;
padding: 1.25rem 0; z-index: 90;
}
.sidebar .toc-label {
font-size: 12px; text-transform: uppercase; letter-spacing: 0.1em;
color: var(--text-tertiary); padding: 0 1.25rem; margin-bottom: 0.75rem;
}
.sidebar nav ol { list-style: none; padding: 0; counter-reset: toc; }
.sidebar nav li { counter-increment: toc; padding: 0; }
.sidebar nav a {
display: block; padding: 0.45rem 1.25rem; color: var(--text-secondary);
text-decoration: none; font-size: 13px; line-height: 1.4;
border-left: 2px solid transparent; transition: all 0.15s;
}
.sidebar nav a::before {
content: counter(toc) ". "; color: var(--color-primary);
font-weight: 600; font-size: 12px; margin-right: 0.4rem;
}
.sidebar nav a:hover { color: var(--color-primary); background: var(--color-primary-bg); }
.sidebar nav a.active { color: var(--color-primary); border-left-color: var(--color-primary); background: var(--color-primary-bg); font-weight: 600; }
.hamburger-btn {
display: none; position: fixed; top: 12px; right: 16px; z-index: 200;
background: var(--bg-container); border: 1px solid var(--border);
border-radius: var(--radius-md); width: 40px; height: 40px;
font-size: 20px; cursor: pointer; align-items: center; justify-content: center;
}
/* ===== MAIN ===== */
.main {
margin-left: var(--sidebar-w); margin-top: var(--header-h);
padding: 32px 40px 64px; min-height: calc(100vh - var(--header-h));
max-width: 1200px;
}
/* ===== SECTIONS ===== */
section {
margin: 48px 0; scroll-margin-top: calc(var(--header-h) + 1rem);
}
section h2 { font-size: 22px; line-height: 30px; padding-bottom: 8px; border-bottom: 1px solid var(--border); margin-bottom: 20px; color: var(--color-primary); }
h3 { font-size: 18px; line-height: 26px; margin: 24px 0 12px; color: #0078D4; }
h4 { font-size: 15px; line-height: 22px; margin: 16px 0 8px; color: var(--color-success); }
/* ===== PARAGRAPH ===== */
p { color: var(--text-secondary); font-size: 14px; margin: 10px 0; text-align: justify; }
p strong { color: var(--text-primary); }
/* ===== CODE ===== */
code {
font-family: var(--fluent-font-family-mono);
font-size: 13px; background: var(--bg-elevated);
padding: 2px 6px; border-radius: var(--radius-sm);
border: 1px solid var(--border-light); color: #D4380D;
}
pre {
background: #1E1E1E; color: #D4D4D4; border-radius: var(--radius-md);
padding: 16px 20px; overflow-x: auto; margin: 16px 0;
font-family: var(--fluent-font-family-mono); font-size: 13px;
line-height: 1.6; tab-size: 4;
}
pre code { background: none; border: none; padding: 0; color: inherit; font-size: inherit; }
pre.ascii-diagram {
background: var(--bg-elevated); color: var(--text-secondary);
border: 1px solid var(--border); font-family: var(--fluent-font-family-mono);
font-size: 12px; line-height: 1.35; padding: 16px 20px; white-space: pre;
}
/* ===== TABLES ===== */
.table-wrap { overflow-x: auto; margin: 20px 0; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { padding: 10px 14px; border: 1px solid var(--border); text-align: left; vertical-align: top; }
th { background: var(--bg-elevated); font-weight: 700; color: var(--text-primary); white-space: nowrap; }
td { background: var(--bg-container); color: var(--text-secondary); }
tbody tr:hover td { background: var(--color-primary-bg); }
/* ===== LISTS ===== */
ul, ol { margin: 8px 0 8px 20px; }
li { margin: 6px 0; color: var(--text-secondary); font-size: 14px; }
li strong { color: var(--text-primary); }
/* ===== INFO BOXES ===== */
.box {
border-radius: var(--radius-md); padding: 20px 24px; margin: 18px 0;
}
.box h4 { margin: 0 0 8px; font-size: 14px; font-weight: 700; }
.box p { font-size: 14px; margin: 4px 0; text-indent: 0; }
.box-info { background: var(--color-primary-bg); border: 1px solid #91CAFF; }
.box-info h4 { color: var(--color-primary); }
.box-good { background: var(--color-success-bg); border: 1px solid var(--color-success-border); }
.box-good h4 { color: var(--color-success); }
.box-warn { background: var(--color-warning-bg); border: 1px solid var(--color-warning-border); }
.box-warn h4 { color: var(--color-warning); }
/* ===== BLOCKQUOTE ===== */
blockquote {
margin: 16px 0; padding: 16px 22px; background: var(--bg-elevated);
border-left: 3px solid var(--color-primary);
border-radius: 0 var(--radius-sm) var(--radius-sm) 0; color: var(--text-secondary);
}
blockquote p { text-indent: 0; }
hr { border: none; border-top: 1px solid var(--border-light); margin: 32px 0; }
.footer {
text-align: center; padding: 28px 0; color: var(--text-tertiary);
font-size: 13px; border-top: 1px solid var(--border-light); margin-top: 40px;
}
/* ===== KPI BAR ===== */
.kpi-bar {
display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 32px;
}
.kpi {
flex: 1; min-width: 130px; background: var(--bg-container);
border: 1px solid var(--border-light); border-radius: var(--radius-md);
padding: 16px 14px; text-align: center; box-shadow: var(--shadow-sm);
}
.kpi .num { font-size: 22px; font-weight: 800; color: var(--color-primary); line-height: 1.2; }
.kpi .label { font-size: 11px; color: var(--text-tertiary); margin-top: 4px; }
/* ===== FIGURE ===== */
.figure-block {
margin: 24px 0; padding: 20px 24px; background: var(--bg-container);
border: 1px solid var(--border); border-radius: var(--radius-md);
}
.figure-block .fig-title {
font-size: 13px; font-weight: 700; color: var(--text-primary); margin-bottom: 12px;
}
@media (max-width: 768px) {
.sidebar { display: none; }
.sidebar.open {
display: block; position: fixed; top: var(--header-h); left: 0; bottom: 0;
width: 280px; z-index: 150; box-shadow: var(--shadow-lg);
}
.hamburger-btn { display: flex; }
.main { margin-left: 0; padding: 20px 16px 40px; }
table { font-size: 12px; }
th, td { padding: 6px 8px; }
section { margin: 28px 0; }
section h2 { font-size: 18px; }
.kpi-bar { gap: 8px; }
.kpi { min-width: 90px; padding: 10px 8px; }
.kpi .num { font-size: 18px; }
}
</style>
</head>
<body>
<header class="header">
<a href="../../index.html" class="back-link">← 返回知识库</a>
<h1>意图识别与工具检索方案</h1>
<span class="version">银行智能中台子方案 · 2026-06</span>
</header>
<button class="hamburger-btn" onclick="document.getElementById('sidebar').classList.toggle('open')"></button>
<aside class="sidebar" id="sidebar">
<div class="toc-label">方案目录</div>
<nav><ol>
<li><a href="#问题定义">问题定义</a></li>
<li><a href="#整体架构意图识别在银行智能中台的位置">整体架构:意图识别在银行智能中台的位置</a></li>
<li><a href="#工具描述增强llm离线语义增强">工具描述增强:LLM离线语义增强</a></li>
<li><a href="#l1-意图提取">L1:意图提取</a></li>
<li><a href="#l1-混合检索dense--sparse--rrf">L1:混合检索(Dense + Sparse → RRF</a></li>
<li><a href="#l2-精排cross-encoder-rerank">L2:精排(Cross-encoder Rerank</a></li>
<li><a href="#l3-l5-多层兜底与持续优化">L3-L5:多层兜底与持续优化</a></li>
<li><a href="#场景走查意图识别实战">场景走查:意图识别实战</a></li>
<li><a href="#准确率指标与验证方式">准确率指标与验证方式</a></li>
<li><a href="#风险与缓解">风险与缓解</a></li>
</ol></nav>
</aside>
<main class="main" onclick="document.getElementById('sidebar').classList.remove('open')">
<div class="kpi-bar">
<div class="kpi"><div class="num">30<span style="font-size:11px;font-weight:400"> 万+</span></div><div class="label">待检索工具总量</div></div>
<div class="kpi"><div class="num">99<span style="font-size:11px;font-weight:400">%+</span></div><div class="label">L0预过滤削减率</div></div>
<div class="kpi"><div class="num">&lt;80<span style="font-size:11px;font-weight:400">ms</span></div><div class="label">混合检索延迟</div></div>
<div class="kpi"><div class="num">&gt;97<span style="font-size:11px;font-weight:400">%</span></div><div class="label">Top-15命中率目标</div></div>
<div class="kpi"><div class="num">6<span style="font-size:11px;font-weight:400"></span></div><div class="label">准确性保障层级</div></div>
</div>
<!-- ===== 1. 问题定义 ===== -->
<section><h2 id="问题定义">问题定义</h2>
<h3>规模量化</h3>
<p>银行存量服务 <strong>30 万个</strong>,每个工具平均约 300 tokens,全量描述 <strong>9000 万 tokens</strong>。而 LLM 上下文窗口 64K,实际可用空间约 40K tokens,单次可装载工具 ≤ <strong>130 个</strong>——仅占全部工具的 <strong>0.04%</strong></p>
<div class="figure-block">
<div class="fig-title">问题本质</div>
<pre class="ascii-diagram">用户自然语言问法
│ "查一下张三的征信" / "我能贷多少钱" / "这笔转账合规吗"
┌─────────────────────────────────────────────┐
│ 意图识别系统 │
│ │
│ 输入: 自然语言 + 用户三维上下文 │
│ 输出: 最匹配的 ≤15 个工具定义 │
│ │
│ 约束: 30万候选池 → 40K token预算 │
│ 延迟要求: 端到端 &lt; 300ms │
│ 准确率: Top-15 命中率 &gt; 97% │
│ 确定性: 安全相关过滤必须 100% 可靠 │
└─────────────────────────────────────────────┘</pre>
</div>
<h3>银行场景的特殊难度</h3>
<div class="table-wrap"><table>
<tr><th>难点</th><th>通用NLU</th><th>银行意图识别</th></tr>
<tr><td><strong>工具数量</strong></td><td>数十~数百个 API</td><td>30 万个服务,且持续增长</td></tr>
<tr><td><strong>领域术语</strong></td><td>通用词汇</td><td>"征信""授信""保函""贴现""头寸"等金融专有名词,且行内大量缩写</td></tr>
<tr><td><strong>问法多样性</strong></td><td>有限的同义表达</td><td>同一意图可能有 50+ 种自然问法:"查额度""能贷多少""我的信用贷款上限是多少""给我看看可用贷款"</td></tr>
<tr><td><strong>安全约束</strong></td><td>通常无</td><td>某些"漏"和"错"不可接受——对公客户经理绝不能看到对私储蓄工具;未签约产品的 API 不可见</td></tr>
<tr><td><strong>多意图混合</strong></td><td>较少</td><td>高频:"帮我查这个客户的征信,再评估一下他的还款能力"(征信查询+风险评估,2个工具)</td></tr>
</table></div>
</section>
<hr>
<!-- ===== 2. 整体架构 ===== -->
<section><h2 id="整体架构意图识别在银行智能中台的位置">整体架构:意图识别在银行智能中台的位置</h2>
<p>意图识别不是孤立模块,而是嵌入银行智能中台的<strong>工具检索漏斗</strong>中。整体链路如下:</p>
<pre class="ascii-diagram">用户消息 (自然语言)
│ "查张三的征信"
┌──────────────────────────────────────────────────────────────────┐
│ Gateway Layer: 三维鉴权网关 │
│ 渠道验签 → 用户身份解析 → 数据范围确定 → 构建 SecurityContext │
└──────────────────────────┬───────────────────────────────────────┘
│ SecurityContext {userType, channelId, dataScope, tenantId, ...}
┌──────────────────────────────────────────────────────────────────┐
│ L0: 确定性预过滤 (Deterministic Pre-filter) ★ 非意图识别 │
│ 规则引擎 × BitMap AND → 30万 → 500~3000 候选 │
│ 安全属性,100% 确定性,不依赖语义 │
└──────────────────────────┬───────────────────────────────────────┘
│ ~2000 候选工具
┌──────────────────────────────────────────────────────────────────┐
│ L1: 意图提取 + 混合检索 ★ 意图识别核心 │
│ │
│ ┌─────────────────────┐ ┌──────────────────────────────┐ │
│ │ 意图提取 (NLU) │ │ 混合检索 (Hybrid Retrieval) │ │
│ │ │ │ │ │
│ │ 自然语言 → 结构化意图 │ │ Dense (向量语义) │ │
│ │ {intent, domain, │ │ + Sparse (BM25关键词) │ │
│ │ entities, params} │ │ → RRF 倒数秩融合 │ │
│ │ │ │ → Top-100 │ │
│ │ LLM few-shot / │ │ │ │
│ │ 微调小模型 │ │ 延迟: &lt; 80ms │ │
│ └─────────────────────┘ └──────────────────────────────┘ │
└──────────────────────────┬───────────────────────────────────────┘
│ Top-100 候选工具
┌──────────────────────────────────────────────────────────────────┐
│ L2: 精排 (Cross-encoder Rerank) │
│ Cross-encoder 模型 → 100 候选重排序 → Top-15 │
│ 注入 Agent 当前对话上下文 → 延迟: &lt; 150ms │
└──────────────────────────┬───────────────────────────────────────┘
│ Top-15 工具定义 (约 4500 tokens)
┌──────────────────────────────────────────────────────────────────┐
│ Agent Orchestration Layer │
│ LLM 接收 {用户消息 + Top-15 工具定义 + System Prompt} │
│ → 选择最合适的工具 → 生成调用参数 → 执行 │
└──────────────────────────────────────────────────────────────────┘</pre>
<div class="box box-info"><h4>设计原则</h4><p><strong>确定性优先于概率性</strong>:L0 用规则做硬过滤(安全底线),L1/L2 用语义做软匹配(效果上限)。<br>
<strong>漏斗逐级收敛</strong>30万 → 2000 → 100 → 15,每级延迟可控,总体 < 300ms<br>
<strong>意图提取与检索解耦</strong>:意图提取产出结构化意图对象,检索模块消费该对象,两者可独立迭代。</p></div>
</section>
<hr>
<!-- ===== 3. 工具描述增强 ===== -->
<section><h2 id="工具描述增强llm离线语义增强">工具描述增强:LLM离线语义增强</h2>
<p>意图识别的前提是<strong>工具有好的语义描述</strong>。30万存量服务的原始 API 文档通常只有技术参数,缺乏业务语义。本方案在工具入库前进行离线 LLM 增强。</p>
<h3>增强前后对比</h3>
<div class="table-wrap"><table>
<tr><th>字段</th><th>原始(来自 OpenAPI</th><th>增强后(LLM 离线生成)</th></tr>
<tr><td><strong>name</strong></td><td><code>cbs_query_credit_report</code></td><td><code>cbs_query_credit_report</code>(保留原名)</td></tr>
<tr><td><strong>description</strong></td><td>"查询信用报告"</td><td>"查询个人或企业的信用报告,返回征信评分、贷款记录、逾期记录、担保记录等。适用于客户经理贷前审查、风控审批等场景。"</td></tr>
<tr><td><strong>target_audience</strong></td><td>—(无)</td><td>["客户经理", "风控审批员"]</td></tr>
<tr><td><strong>common_questions</strong></td><td>—(无)</td><td>["查张三的征信", "这个客户的信用怎么样", "看看他的征信评分", "有没有逾期记录"]</td></tr>
<tr><td><strong>caveats</strong></td><td>—(无)</td><td>"征信查询为敏感操作,需客户授权。仅返回持卡人授权范围内的数据。"</td></tr>
<tr><td><strong>tags</strong></td><td>—(无)</td><td>["征信", "信贷", "风控", "贷前审查"]</td></tr>
</table></div>
<h3>增强管道</h3>
<pre class="ascii-diagram">原始 API 元数据 (OpenAPI / gRPC Proto / API Gateway)
┌─────────────────────────────────────────────┐
│ Step 1: 元数据标准化 │
│ 统一为内部 ToolDefinition schema │
│ 提取: name, path, method, params, response │
└──────────────────┬──────────────────────────┘
┌─────────────────────────────────────────────┐
│ Step 2: LLM 批量增强 (qwen-turbo 离线) │
│ │
│ Prompt 模板: │
│ "你是一个银行系统专家。以下是API的技术定义: │
│ [原始元数据] │
│ 请补充: │
│ 1. 用3-5句话描述这个API的业务用途 │
│ 2. 列出可能使用此API的角色/客群 │
│ 3. 生成5-10条用户可能的自然语言问法 │
│ 4. 标注注意事项和风险提示 │
│ 5. 打上3-8个业务标签" │
│ │
│ 批次: 100条/批,qwen-turbo,离线异步 │
│ 成本: ~0.3元/千条 │
└──────────────────┬──────────────────────────┘
┌─────────────────────────────────────────────┐
│ Step 3: 向量化 + 入库 │
│ description → text-embedding-v3 → pgvector │
│ common_questions → 扩展为虚拟文档 → 索引 │
│ tags → Elasticsearch 倒排索引 │
└─────────────────────────────────────────────┘</pre>
<div class="box box-good"><h4>为什么是离线增强而非在线</h4><p>在线增强(每次请求时让 LLM 理解工具)会产生 2-5s 额外延迟且不可缓存。离线增强将 LLM 的语义理解能力<strong>提前注入索引</strong>,检索时直接匹配向量,延迟 < 80ms增强后语义检索命中率提升 30%+</p></div>
</section>
<hr>
<!-- ===== 4. L1 意图提取 ===== -->
<section><h2 id="l1-意图提取">L1:意图提取</h2>
<p>将用户的自然语言问法转化为<strong>结构化意图对象</strong>,作为后续混合检索的查询依据。</p>
<h3>意图 Schema</h3>
<pre class="ascii-diagram">// Intent 结构化输出
{
"intent": "征信查询", // 主意图分类
"domain": "credit", // 业务域
"sub_domain": "credit_report", // 子域
"entities": [ // 实体抽取
{ "type": "PERSON_NAME", "value": "张三" },
{ "type": "ID_TYPE", "value": "身份证" }
],
"intent_type": "QUERY", // QUERY | ACTION | ANALYSIS | APPROVAL
"confidence": 0.94, // 置信度
"multi_intent": false, // 是否多意图
"suggested_tool_categories": [ // 建议的工具类别(用于检索加权)
"征信查询", "客户信息", "风控评估"
]
}</pre>
<h3>实现方案选型</h3>
<div class="table-wrap"><table>
<tr><th>方案</th><th>延迟</th><th>准确率</th><th>成本</th><th>适用阶段</th></tr>
<tr><td><strong>Few-shot LLM(千问/DeepSeek</strong></td><td>200-500ms</td><td>~92%</td><td></td><td>Phase 1 快速启动,Prompt 迭代灵活</td></tr>
<tr><td><strong>微调小模型(Qwen2.5-7B 微调)</strong></td><td>30-80ms</td><td>~95%</td><td>一次投入</td><td>Phase 3+ 生产化,延迟和准确率最优</td></tr>
<tr><td><strong>规则 + 关键词(无 LLM</strong></td><td>&lt; 5ms</td><td>~70%</td><td>极低</td><td>兜底方案,简单高频问法</td></tr>
</table></div>
<h3>意图分类体系(银行业务域)</h3>
<div class="table-wrap"><table>
<tr><th>一级域</th><th>二级意图</th><th>典型问法示例</th><th>涉及工具数(约)</th></tr>
<tr><td><strong>credit(信贷)</strong></td><td>征信查询 / 额度查询 / 贷款申请 / 还款记录 / 利率查询</td><td>"查张三征信""我能贷多少""申请经营贷"</td><td>~8000</td></tr>
<tr><td><strong>risk(风控)</strong></td><td>风险评估 / 反欺诈 / 关联交易 / 黑名单校验</td><td>"评估这个客户风险等级""查关联方"</td><td>~5000</td></tr>
<tr><td><strong>customer(客户)</strong></td><td>客户信息 / 账户查询 / 交易流水 / 资产概览</td><td>"张三的基本信息""最近三个月的流水"</td><td>~12000</td></tr>
<tr><td><strong>product(产品)</strong></td><td>产品查询 / 利率对比 / 签约状态 / 持有产品</td><td>"这款理财收益多少""有哪些贷款产品"</td><td>~6000</td></tr>
<tr><td><strong>compliance(合规)</strong></td><td>反洗钱 / 大额可疑 / 监管报送 / 合规检查</td><td>"这笔转账是否触发反洗钱规则"</td><td>~3000</td></tr>
<tr><td><strong>operation(运营)</strong></td><td>柜面操作 / 账户管理 / 参数维护 / 日终处理</td><td>"开立对公账户流程""修改客户手机号"</td><td>~5000</td></tr>
<tr><td><strong>report(报表)</strong></td><td>经营报表 / 监管报表 / 绩效考核 / 数据统计</td><td>"本月信贷投放情况""生成季度报表"</td><td>~4000</td></tr>
</table></div>
<h3>多意图处理</h3>
<p>当用户一次性提出复合需求时,意图提取模块识别并拆解为多个子意图:</p>
<pre class="ascii-diagram">输入: "帮我查这个客户的征信,再评估一下他的还款能力"
意图提取:
┌─────────────────────────────────────────────┐
│ 主意图判定: multi_intent = true │
│ │
│ 子意图 1: │
│ intent: "征信查询" │
│ domain: "credit" │
│ entities: [{type: PERSON, value: "这个客户"}]│
│ │
│ 子意图 2: │
│ intent: "还款能力评估" │
│ domain: "risk" │
│ entities: [{type: PERSON, value: "这个客户"}]│
│ │
│ 执行顺序: 串行(子意图2依赖子意图1的结果) │
└─────────────────────────────────────────────┘</pre>
</section>
<hr>
<!-- ===== 5. L1 混合检索 ===== -->
<section><h2 id="l1-混合检索dense--sparse--rrf">L1:混合检索(Dense + Sparse → RRF</h2>
<p>单一检索方式在银行场景存在明显短板,本方案采用<strong>混合检索 + 倒数秩融合(RRF</strong> 策略。</p>
<h3>为什么需要混合</h3>
<div class="table-wrap"><table>
<tr><th>检索方式</th><th>原理</th><th>优势</th><th>劣势</th><th>银行场景典型失败 case</th></tr>
<tr><td><strong>Dense(向量语义)</strong></td><td>text-embedding-v3 → pgvector HNSW</td><td>理解同义改写和模糊表达</td><td>对专有缩写和精确 ID 匹配差</td><td>"调CBS查张三征信"——embedding 无法理解 CBS 是核心系统标识</td></tr>
<tr><td><strong>SparseBM25 关键词)</strong></td><td>Elasticsearch BM25 倒排索引</td><td>精确字段匹配、缩写、ID</td><td>无法理解同义表达和上下文</td><td>"看看他能借多少"——没有"贷款"关键词,BM25 可能漏掉</td></tr>
</table></div>
<h3>检索流程</h3>
<pre class="ascii-diagram">意图对象 + 原始用户消息 + 增强后的常见问法
├──────────────────┬──────────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ 向量检索 │ │ BM25 关键词 │ │ Tag 精准匹配 │
│ (Dense) │ │ (Sparse) │ │ (Filter) │
│ │ │ │ │ │
│ pgvector │ │ ES BM25 │ │ ES term │
│ HNSW │ │ 在 L0 过滤后 │ │ 标签过滤 │
│ cosine │ │ 的候选池内 │ │ │
│ │ │ │ │ │
│ Top-200 │ │ Top-200 │ │ 全部命中标签 │
└────┬──────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
└─────────────────┴──────────────────┘
┌─────────────────────────────────────────────────┐
│ RRF (Reciprocal Rank Fusion) 倒数秩融合 │
│ │
│ score(doc) = Σ 1/(k + rank_i(doc)) │
│ i∈{dense, sparse, tag} │
│ │
│ k=60 (标准平滑参数) │
│ 如果一个工具在三种检索中分别排第3、第8、未出现: │
│ score = 1/(60+3) + 1/(60+8) + 0 = 0.031 │
│ │
│ → 融合排序 → Top-100 │
└─────────────────────────────────────────────────┘</pre>
<h3>向量化策略</h3>
<div class="table-wrap"><table>
<tr><th>索引内容</th><th>向量模型</th><th>维度</th><th>说明</th></tr>
<tr><td><strong>增强后的 description</strong></td><td>text-embedding-v3</td><td>1024</td><td>主向量,承载核心业务语义</td></tr>
<tr><td><strong>common_questions 扩展</strong></td><td>text-embedding-v3</td><td>1024</td><td>每条常见问法作为独立虚拟文档,桥接自然语言与工具定义</td></tr>
<tr><td><strong>意图标签组合</strong></td><td>text-embedding-v3</td><td>256</td><td>"{domain}_{intent}" 组合编码,加速意图路由</td></tr>
</table></div>
<div class="box box-info"><h4>common_questions 虚拟文档扩展</h4><p>这是提升检索命中率的关键技巧。一个工具的 5-10 条常见问法各自作为独立向量文档入库,<code>parent_id</code> 指向原始工具。检索时匹配到任意一条问法都能召回该工具。这实质上是将"用户会怎么问"的信息提前编码进索引。</p></div>
</section>
<hr>
<!-- ===== 6. L2 精排 ===== -->
<section><h2 id="l2-精排cross-encoder-rerank">L2:精排(Cross-encoder Rerank</h2>
<p>L1 混合检索产出 Top-100,但排序精度有天花板——双塔模型在 0.01s 内判断 100 个候选的语义相关性,和花 0.15s 精细比较 100 对(用户问法, 工具描述)的语义匹配度,后者准确得多。</p>
<h3>Bi-encoder vs Cross-encoder</h3>
<div class="table-wrap"><table>
<tr><th>特性</th><th>Bi-encoderL1 Dense</th><th>Cross-encoderL2 精排)</th></tr>
<tr><td><strong>原理</strong></td><td>用户查询和工具描述分别编码为向量,计算余弦相似度</td><td>用户查询和工具描述拼接后一起输入 Transformer,输出相关性分数</td></tr>
<tr><td><strong>交互方式</strong></td><td>浅层交互(仅余弦相似度)</td><td>深层交互(Attention 跨查询-文档)</td></tr>
<tr><td><strong>速度</strong></td><td>快(向量已预计算,仅做内积)</td><td>慢(每对都需过一次完整前向传播)</td></tr>
<tr><td><strong>准确率</strong></td><td>中高</td><td>高(显著优于 Bi-encoder</td></tr>
<tr><td><strong>使用方式</strong></td><td>在海量候选池中快速召回</td><td>在少量候选(≤200)中精细排序</td></tr>
</table></div>
<h3>精排流程</h3>
<pre class="ascii-diagram">L1 产出 Top-100 工具
┌─────────────────────────────────────────────┐
│ 构建 Cross-encoder 输入对 (100 对) │
│ │
│ Pair i: │
│ Query: "查张三的征信" │
│ Doc: "[工具名] cbs_query_credit_report │
│ [描述] 查询个人或企业的信用报告... │
│ [常见问法] 查征信/信用评估/... │
│ [标签] 征信, 信贷, 风控" │
│ │
│ → 100 对并行推理 │
└──────────────────┬──────────────────────────┘
┌─────────────────────────────────────────────┐
│ Cross-encoder 模型 (BGE-Reranker-v2-m3) │
│ 对每对输出 relevance_score ∈ [0, 1] │
└──────────────────┬──────────────────────────┘
┌─────────────────────────────────────────────┐
│ Agent 上下文注入 │
│ │
│ ● 对话历史中已确认的实体加权 │
│ "之前提到客户是张三" → 含"张三"的工具加权 │
│ ● 当前任务类型偏好 │
│ 查询类 > 写操作类(安全偏好) │
│ ● 用户角色偏好 │
│ 客户经理常用工具加权 │
└──────────────────┬──────────────────────────┘
Top-15 工具定义
(~4500 tokens)
注入 Agent LLM 上下文</pre>
<h3>模型选型</h3>
<div class="table-wrap"><table>
<tr><th>模型</th><th>速度(100对)</th><th>NDCG@10</th><th>部署方式</th></tr>
<tr><td><strong>BGE-Reranker-v2-m3</strong></td><td>~120ms</td><td></td><td>本地 GPU (T4/L20)</td></tr>
<tr><td><strong>Cohere Rerank API</strong></td><td>~200ms (网络)</td><td></td><td>SaaS API(银行内网不可用)</td></tr>
<tr><td><strong>BGE-Reranker-v2-minicpm</strong></td><td>~60ms</td><td>中高</td><td>本地 CPU 可运行</td></tr>
</table></div>
<div class="box box-warn"><h4>银行内网约束</h4><p>银行生产环境无法访问外网 API,Reranker 必须本地部署。推荐 BGE-Reranker-v2-m3 部署在推理 GPU 节点,单卡可支撑 200+ QPS。</p></div>
</section>
<hr>
<!-- ===== 7. L3-L5 ===== -->
<section><h2 id="l3-l5-多层兜底与持续优化">L3-L5:多层兜底与持续优化</h2>
<h3>L3Agent 自行验证</h3>
<p>即使前两层给出了 Top-15 工具,LLM 也可能判断检索结果不匹配用户意图。此时 Agent 可主动调用 <code>search_tools()</code> 进行二次检索(调整查询词、放宽过滤条件)。</p>
<div class="figure-block">
<div class="fig-title">Agent 自验证逻辑(System Prompt 内置)</div>
<pre class="ascii-diagram">给定 {用户消息} 和 {Top-15 工具列表}
1. 逐一评估每个工具与用户意图的匹配度
2. 如果至少有一个工具匹配度 ≥ 0.8 → 选择最匹配的执行
3. 如果所有工具匹配度 < 0.5 调用 search_tools(rewrite_query)
- 改写策略: 扩展缩写补充同义词拆分多意图
4. 如果改写后仍无匹配 告知用户"未找到对应服务请提供更多信息"
目标: 首次无结果率 < 3%</pre>
</div>
<h3>L4:用户/租户个性化加权</h3>
<p>不同角色、不同租户的工具使用频率差异巨大。个性化加权让高频工具自动排前:</p>
<ul>
<li><strong>个人级别</strong>:当前用户最近30天高频调用的工具加权 1.5×</li>
<li><strong>角色级别</strong>:同角色(如"客户经理")群体的高频工具加权 1.3×</li>
<li><strong>租户级别</strong>:当前租户(如"北京分行")的高频工具加权 1.2×</li>
<li><strong>协同过滤</strong>:相似用户群体使用但当前用户未用过的工具轻度加权(发现新工具)</li>
</ul>
<p>权重在 RRF 融合后的分数上叠加,不参与 RRF 计算本身,确保不会因为个性化而掩盖语义相关性。</p>
<h3>L5:人工反馈闭环</h3>
<pre class="ascii-diagram">Agent 执行工具调用
Web Dashboard 展示 "工具调用卡片"
│ 显示: 调用了哪个工具、参数、结果摘要
├─ 用户点击 [✓ 工具正确] → 正反馈 → 该(query, tool)对进入正样本池
└─ 用户点击 [✗ 工具选错了] → 负反馈
┌─────────────────────────────────────────┐
│ 负反馈处理: │
│ 1. 弹出 "正确的工具应该是?" 搜索框 │
│ 2. 用户选择正确工具 │
│ 3. (query, wrong_tool) → 负样本 │
│ (query, correct_tool) → 正样本 │
│ 4. 回流到 Reranker 微调数据集 │
│ 5. 每月增量微调 Cross-encoder │
└─────────────────────────────────────────┘</pre>
</section>
<hr>
<!-- ===== 8. 场景走查 ===== -->
<section><h2 id="场景走查意图识别实战">场景走查:意图识别实战</h2>
<h3>场景 1:客户经理查客户征信(B2E</h3>
<pre class="ascii-diagram">┌─ 原始输入 ─────────────────────────────────────────────┐
│ 用户消息: "查张三的征信" │
│ 渠道: 信贷系统 (Channel=credit-system) │
│ 用户: EMPLOYEE | 客户经理 | 北京分行 | BRANCH │
└────────────────────────────────────────────────────────┘
L0 预过滤:
规则1: credit-system → 信贷/风控/查询类接口
规则2: EMPLOYEE → 内部员工工具集
规则3: 客户经理+对公 → 对公信贷类 + 通用查询
规则6: BRANCH → 本支行客户数据
→ 30万 → ~1200 候选
L1 意图提取:
输入: "查张三的征信"
输出: {
intent: "征信查询",
domain: "credit",
entities: [{type: PERSON_NAME, value: "张三"}],
intent_type: "QUERY",
confidence: 0.96
}
L1 混合检索 (在 1200 候选内):
Dense: 向量相似度 Top-200
Sparse: BM25 "征信"+"张三" Top-200
RRF 融合 → Top-100
延迟: 72ms
L2 精排:
Cross-encoder: 100 对 → 排序 → Top-15
上下文注入: 当前对话是新会话,无历史加权
延迟: 118ms
Agent 上下文 (注入 LLM):
System: "你是银行客户经理助手..."
Tools: Top-15 定义 (含 cbs_query_credit_report 排第1)
User: "查张三的征信"
Agent 输出:
→ 选择 cbs_query_credit_report(idNumber="...")
→ PermissionMiddleware ✓
→ 返回: "张三征信评分720分,共有3笔贷款记录..."</pre>
<h3>场景 2C端客户模糊问法(B2C</h3>
<pre class="ascii-diagram">┌─ 原始输入 ─────────────────────────────────────────────┐
│ 用户消息: "我能贷多少钱" │
│ 渠道: 手机银行 (Channel=mobile-bank) │
│ 用户: RETAIL_CUSTOMER | CUST-88231 | SELF │
└────────────────────────────────────────────────────────┘
L0 预过滤:
规则1: mobile-bank → 仅限电子渠道开放接口
规则2: RETAIL_CUSTOMER → 仅限C端客户工具
规则6: SELF → 仅限本人数据
→ 30万 → ~300 候选
L1 意图提取:
输入: "我能贷多少钱" (无"贷款"关键词!)
输出: {
intent: "贷款额度查询",
domain: "retail_loan",
entities: [{type: SELF_REFERENCE, value: "我"}],
intent_type: "QUERY",
confidence: 0.91
}
注: LLM 意图提取识别出"能贷多少" = "贷款额度查询"
即使没有"贷款"二字
L1 混合检索 (在 300 候选内):
Dense: "我能贷多少钱" 与工具描述的语义匹配
→ "retail_query_loan_limit" 的 common_questions 包含
"我能贷多少钱"/"可用额度是多少"/"贷款上限查询"
→ 余弦相似度 0.94,排第 1
Sparse: "贷" 匹配到"贷款"、"额度"
RRF 融合 → Top-50
延迟: 58ms
L2 精排:
Cross-encoder 确认 retail_query_loan_limit 排第 1
→ Top-10 → 注入 Agent
Agent 输出:
→ retail_query_loan_limit(customerId="CUST-88231")
→ "您目前的可用额度为30万元,其中信用贷20万、抵押贷10万..."
┌────────────────────────────────────────────────────────┐
│ ★ 关键: Dense 检索命中了 common_questions 虚拟文档。 │
│ 如果仅用 BM25"能贷多少" 没有"贷款"关键词可能漏排。 │
│ 如果仅用 Dense,可能召回"理财产品收益"等语义相近但 │
│ 实际无关的工具。混合检索 + 精排保证了鲁棒性。 │
└────────────────────────────────────────────────────────┘</pre>
<h3>场景 3:精确缩写查询(B2E</h3>
<pre class="ascii-diagram">用户: "调CBS查一下这个企业的ECIF信息"
├─ CBS = 核心银行系统 (Core Banking System)
├─ ECIF = 企业客户信息文件 (Enterprise Customer Information File)
└─ 这是银行内部的高度专业化缩写
L1 意图提取:
intent: "企业客户信息查询"
domain: "customer"
entities: [
{type: SYSTEM, value: "CBS"},
{type: CUSTOMER_TYPE, value: "企业"},
{type: DATA_TYPE, value: "ECIF"}
]
混合检索:
Dense: "ECIF" 的 embedding 可能与工具描述中的"企业客户信息文件"
有语义距离(缩写向量 vs 全称向量)
Sparse: BM25 精确命中 tool tags 中的 "ECIF"、"CBS"
→ 互补!Sparse 救了 Dense 的缩写盲区
→ RRF 融合后,目标工具排 Top-3
结论: 混合检索在银行缩写密集场景下不可或缺。</pre>
</section>
<hr>
<!-- ===== 9. 验证方式 ===== -->
<section><h2 id="准确率指标与验证方式">准确率指标与验证方式</h2>
<h3>核心指标</h3>
<div class="table-wrap"><table>
<tr><th>指标</th><th>目标值</th><th>测量方式</th></tr>
<tr><td><strong>Top-15 命中率</strong></td><td>&gt; 97%</td><td>人工标注 1000 条银行真实问法,检查正确答案是否在 Top-15 内</td></tr>
<tr><td><strong>Top-1 命中率</strong></td><td>&gt; 80%</td><td>相同标注集,检查第一位是否即正确答案</td></tr>
<tr><td><strong>首次无结果率</strong></td><td>&lt; 3%</td><td>统计生产环境中 Agent 触发 search_tools() 重试的比例</td></tr>
<tr><td><strong>MRR (Mean Reciprocal Rank)</strong></td><td>&gt; 0.85</td><td>标注集上正确答案排名的倒数的平均值</td></tr>
<tr><td><strong>端到端检索延迟 P99</strong></td><td>&lt; 300ms</td><td>Prometheus + Grafana 监控 L0+L1+L2 全链路延迟</td></tr>
</table></div>
<h3>验证方式</h3>
<ol>
<li><strong>离线标注集评估</strong>:构建 1000 条银行典型问法 + 正确答案标注,每次检索模型迭代时跑评估</li>
<li><strong>A/B 对比</strong>:工具描述增强前后检索命中率对比(预期提升 30%+);混合检索 vs 纯 Dense vs 纯 Sparse 对比</li>
<li><strong>生产监控</strong>:统计 L3 Agent 二次检索触发率(首次无结果率);统计 L5 人工"工具选错了"按钮点击率趋势</li>
<li><strong>抽样验证</strong>:每日随机抽取 100 次真实调用,人工检查工具选择是否正确</li>
<li><strong>压力测试</strong>:1000 并发检索请求,P99 延迟 < 300ms错误率 < 0.1%</li>
</ol>
</section>
<hr>
<!-- ===== 10. 风险 ===== -->
<section><h2 id="风险与缓解">风险与缓解</h2>
<div class="table-wrap"><table>
<tr><th>风险</th><th>概率</th><th>影响</th><th>缓解措施</th></tr>
<tr><td><strong>Router Agent 意图识别不准</strong></td><td></td><td></td><td>Phase 2 投入人工标注 1000+ 银行问法;微调替代 Few-shot;规则兜底保证高频 20 种意图 100% 准确</td></tr>
<tr><td><strong>工具描述增强质量差</strong></td><td></td><td></td><td>Prompt 迭代 + 人工抽检增强结果;核心系统工具人工审核描述;低质量描述标记"待完善"降低检索权重</td></tr>
<tr><td><strong>OpenAPI 覆盖率不足导致向量质量差</strong></td><td></td><td></td><td>三级降级(Swagger→gRPC→基础元数据);优先保障核心系统(前 20%)工具描述质量</td></tr>
<tr><td><strong>Dense 检索在缩写密集场景失效</strong></td><td></td><td></td><td>混合检索中 Sparse/BM25 互补;构建行内缩写词典索引增强</td></tr>
<tr><td><strong>Reranker 模型内网部署困难</strong></td><td></td><td></td><td>BGE-Reranker-v2-minicpm 可在 CPU 运行,作为 GPU 不可用时的降级方案</td></tr>
<tr><td><strong>C端问法多样性超出训练分布</strong></td><td></td><td></td><td>持续收集 C 端真实问法日志 → 每月扩充 common_questions;个性化加权提升高频用户命中率</td></tr>
</table></div>
<div class="footer">
<p>银行智能中台子方案 · 意图识别与工具检索 · 2026-06</p>
<p style="margin-top:4px;">基于 <a href="./agentscope-java-openclaw-banking-midplatform.html" style="color:var(--color-primary);">银行智能中台架构方案 v2.0</a> 提炼</p>
</div>
</main>
<script>
(function() {
var sidebarLinks = document.querySelectorAll('.sidebar nav a');
var sections = [];
sidebarLinks.forEach(function(a) {
var target = document.querySelector(a.getAttribute('href'));
if (target) sections.push({link: a, target: target});
});
function onScroll() {
var scrollPos = window.scrollY + 100, current = null;
sections.forEach(function(s) { if (s.target.offsetTop <= scrollPos) current = s; });
sidebarLinks.forEach(function(a) { a.classList.remove('active'); });
if (current) current.link.classList.add('active');
}
window.addEventListener('scroll', onScroll);
onScroll();
})();
</script>
</body>
</html>
File diff suppressed because it is too large Load Diff