← 返回知识库

意图识别与工具检索方案

银行智能中台子方案 · 2026-06
30 万+
待检索工具总量
99%+
L0预过滤削减率
<80ms
混合检索延迟
>97%
Top-15命中率目标
6
准确性保障层级

问题定义

规模量化

银行存量服务 30 万个,每个工具平均约 300 tokens,全量描述 9000 万 tokens。而 LLM 上下文窗口 64K,实际可用空间约 40K tokens,单次可装载工具 ≤ 130 个——仅占全部工具的 0.04%

问题本质
用户自然语言问法
    │  "查一下张三的征信"  /  "我能贷多少钱"  /  "这笔转账合规吗"
    │
    ▼
┌─────────────────────────────────────────────┐
│  意图识别系统                                 │
│                                              │
│  输入: 自然语言 + 用户三维上下文               │
│  输出: 最匹配的 ≤15 个工具定义                 │
│                                              │
│  约束: 30万候选池 → 40K token预算              │
│        延迟要求: 端到端 < 300ms               │
│        准确率: Top-15 命中率 > 97%            │
│        确定性: 安全相关过滤必须 100% 可靠       │
└─────────────────────────────────────────────┘

银行场景的特殊难度

难点通用NLU银行意图识别
工具数量数十~数百个 API30 万个服务,且持续增长
领域术语通用词汇"征信""授信""保函""贴现""头寸"等金融专有名词,且行内大量缩写
问法多样性有限的同义表达同一意图可能有 50+ 种自然问法:"查额度""能贷多少""我的信用贷款上限是多少""给我看看可用贷款"
安全约束通常无某些"漏"和"错"不可接受——对公客户经理绝不能看到对私储蓄工具;未签约产品的 API 不可见
多意图混合较少高频:"帮我查这个客户的征信,再评估一下他的还款能力"(征信查询+风险评估,2个工具)

整体架构:意图识别在银行智能中台的位置

意图识别不是孤立模块,而是嵌入银行智能中台的工具检索漏斗中。整体链路如下:

用户消息 (自然语言)
    │  "查张三的征信"
    ▼
┌──────────────────────────────────────────────────────────────────┐
│  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 /       │    │                              │     │
│  │ 微调小模型            │    │ 延迟: < 80ms                  │     │
│  └─────────────────────┘    └──────────────────────────────┘     │
└──────────────────────────┬───────────────────────────────────────┘
                           │ Top-100 候选工具
                           ▼
┌──────────────────────────────────────────────────────────────────┐
│  L2: 精排 (Cross-encoder Rerank)                                  │
│  Cross-encoder 模型 → 100 候选重排序 → Top-15                      │
│  注入 Agent 当前对话上下文 → 延迟: < 150ms                         │
└──────────────────────────┬───────────────────────────────────────┘
                           │ Top-15 工具定义 (约 4500 tokens)
                           ▼
┌──────────────────────────────────────────────────────────────────┐
│  Agent Orchestration Layer                                        │
│  LLM 接收 {用户消息 + Top-15 工具定义 + System Prompt}             │
│  → 选择最合适的工具 → 生成调用参数 → 执行                           │
└──────────────────────────────────────────────────────────────────┘

设计原则

确定性优先于概率性:L0 用规则做硬过滤(安全底线),L1/L2 用语义做软匹配(效果上限)。
漏斗逐级收敛:30万 → 2000 → 100 → 15,每级延迟可控,总体 < 300ms。
意图提取与检索解耦:意图提取产出结构化意图对象,检索模块消费该对象,两者可独立迭代。


工具描述增强:LLM离线语义增强

意图识别的前提是工具有好的语义描述。30万存量服务的原始 API 文档通常只有技术参数,缺乏业务语义。本方案在工具入库前进行离线 LLM 增强。

增强前后对比

字段原始(来自 OpenAPI)增强后(LLM 离线生成)
namecbs_query_credit_reportcbs_query_credit_report(保留原名)
description"查询信用报告""查询个人或企业的信用报告,返回征信评分、贷款记录、逾期记录、担保记录等。适用于客户经理贷前审查、风控审批等场景。"
target_audience—(无)["客户经理", "风控审批员"]
common_questions—(无)["查张三的征信", "这个客户的信用怎么样", "看看他的征信评分", "有没有逾期记录"]
caveats—(无)"征信查询为敏感操作,需客户授权。仅返回持卡人授权范围内的数据。"
tags—(无)["征信", "信贷", "风控", "贷前审查"]

增强管道

原始 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 倒排索引               │
└─────────────────────────────────────────────┘

为什么是离线增强而非在线

在线增强(每次请求时让 LLM 理解工具)会产生 2-5s 额外延迟且不可缓存。离线增强将 LLM 的语义理解能力提前注入索引,检索时直接匹配向量,延迟 < 80ms。增强后语义检索命中率提升 30%+。


L1:意图提取

将用户的自然语言问法转化为结构化意图对象,作为后续混合检索的查询依据。

意图 Schema

// 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": [    // 建议的工具类别(用于检索加权)
    "征信查询", "客户信息", "风控评估"
  ]
}

实现方案选型

方案延迟准确率成本适用阶段
Few-shot LLM(千问/DeepSeek)200-500ms~92%Phase 1 快速启动,Prompt 迭代灵活
微调小模型(Qwen2.5-7B 微调)30-80ms~95%一次投入Phase 3+ 生产化,延迟和准确率最优
规则 + 关键词(无 LLM)< 5ms~70%极低兜底方案,简单高频问法

意图分类体系(银行业务域)

一级域二级意图典型问法示例涉及工具数(约)
credit(信贷)征信查询 / 额度查询 / 贷款申请 / 还款记录 / 利率查询"查张三征信""我能贷多少""申请经营贷"~8000
risk(风控)风险评估 / 反欺诈 / 关联交易 / 黑名单校验"评估这个客户风险等级""查关联方"~5000
customer(客户)客户信息 / 账户查询 / 交易流水 / 资产概览"张三的基本信息""最近三个月的流水"~12000
product(产品)产品查询 / 利率对比 / 签约状态 / 持有产品"这款理财收益多少""有哪些贷款产品"~6000
compliance(合规)反洗钱 / 大额可疑 / 监管报送 / 合规检查"这笔转账是否触发反洗钱规则"~3000
operation(运营)柜面操作 / 账户管理 / 参数维护 / 日终处理"开立对公账户流程""修改客户手机号"~5000
report(报表)经营报表 / 监管报表 / 绩效考核 / 数据统计"本月信贷投放情况""生成季度报表"~4000

多意图处理

当用户一次性提出复合需求时,意图提取模块识别并拆解为多个子意图:

输入: "帮我查这个客户的征信,再评估一下他的还款能力"

意图提取:
┌─────────────────────────────────────────────┐
│ 主意图判定: multi_intent = true              │
│                                              │
│ 子意图 1:                                    │
│   intent: "征信查询"                         │
│   domain: "credit"                          │
│   entities: [{type: PERSON, value: "这个客户"}]│
│                                              │
│ 子意图 2:                                    │
│   intent: "还款能力评估"                      │
│   domain: "risk"                            │
│   entities: [{type: PERSON, value: "这个客户"}]│
│                                              │
│ 执行顺序: 串行(子意图2依赖子意图1的结果)      │
└─────────────────────────────────────────────┘

L1:混合检索(Dense + Sparse → RRF)

单一检索方式在银行场景存在明显短板,本方案采用混合检索 + 倒数秩融合(RRF) 策略。

为什么需要混合

检索方式原理优势劣势银行场景典型失败 case
Dense(向量语义)text-embedding-v3 → pgvector HNSW理解同义改写和模糊表达对专有缩写和精确 ID 匹配差"调CBS查张三征信"——embedding 无法理解 CBS 是核心系统标识
Sparse(BM25 关键词)Elasticsearch BM25 倒排索引精确字段匹配、缩写、ID无法理解同义表达和上下文"看看他能借多少"——没有"贷款"关键词,BM25 可能漏掉

检索流程

意图对象 + 原始用户消息 + 增强后的常见问法
    │
    ├──────────────────┬──────────────────┐
    ▼                  ▼                  ▼
┌──────────┐   ┌──────────────┐   ┌──────────────┐
│ 向量检索   │   │ 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                             │
└─────────────────────────────────────────────────┘

向量化策略

索引内容向量模型维度说明
增强后的 descriptiontext-embedding-v31024主向量,承载核心业务语义
common_questions 扩展text-embedding-v31024每条常见问法作为独立虚拟文档,桥接自然语言与工具定义
意图标签组合text-embedding-v3256"{domain}_{intent}" 组合编码,加速意图路由

common_questions 虚拟文档扩展

这是提升检索命中率的关键技巧。一个工具的 5-10 条常见问法各自作为独立向量文档入库,parent_id 指向原始工具。检索时匹配到任意一条问法都能召回该工具。这实质上是将"用户会怎么问"的信息提前编码进索引。


L2:精排(Cross-encoder Rerank)

L1 混合检索产出 Top-100,但排序精度有天花板——双塔模型在 0.01s 内判断 100 个候选的语义相关性,和花 0.15s 精细比较 100 对(用户问法, 工具描述)的语义匹配度,后者准确得多。

Bi-encoder vs Cross-encoder

特性Bi-encoder(L1 Dense)Cross-encoder(L2 精排)
原理用户查询和工具描述分别编码为向量,计算余弦相似度用户查询和工具描述拼接后一起输入 Transformer,输出相关性分数
交互方式浅层交互(仅余弦相似度)深层交互(Attention 跨查询-文档)
速度快(向量已预计算,仅做内积)慢(每对都需过一次完整前向传播)
准确率中高高(显著优于 Bi-encoder)
使用方式在海量候选池中快速召回在少量候选(≤200)中精细排序

精排流程

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 上下文

模型选型

模型速度(100对)NDCG@10部署方式
BGE-Reranker-v2-m3~120ms本地 GPU (T4/L20)
Cohere Rerank API~200ms (网络)SaaS API(银行内网不可用)
BGE-Reranker-v2-minicpm~60ms中高本地 CPU 可运行

银行内网约束

银行生产环境无法访问外网 API,Reranker 必须本地部署。推荐 BGE-Reranker-v2-m3 部署在推理 GPU 节点,单卡可支撑 200+ QPS。


L3-L5:多层兜底与持续优化

L3:Agent 自行验证

即使前两层给出了 Top-15 工具,LLM 也可能判断检索结果不匹配用户意图。此时 Agent 可主动调用 search_tools() 进行二次检索(调整查询词、放宽过滤条件)。

Agent 自验证逻辑(System Prompt 内置)
给定 {用户消息} 和 {Top-15 工具列表}:

1. 逐一评估每个工具与用户意图的匹配度
2. 如果至少有一个工具匹配度 ≥ 0.8 → 选择最匹配的执行
3. 如果所有工具匹配度 < 0.5 → 调用 search_tools(rewrite_query)
   - 改写策略: 扩展缩写、补充同义词、拆分多意图
4. 如果改写后仍无匹配 → 告知用户"未找到对应服务,请提供更多信息"

目标: 首次无结果率 < 3%

L4:用户/租户个性化加权

不同角色、不同租户的工具使用频率差异巨大。个性化加权让高频工具自动排前:

权重在 RRF 融合后的分数上叠加,不参与 RRF 计算本身,确保不会因为个性化而掩盖语义相关性。

L5:人工反馈闭环

Agent 执行工具调用
    │
    ▼
Web Dashboard 展示 "工具调用卡片"
    │  显示: 调用了哪个工具、参数、结果摘要
    │
    ├─ 用户点击 [✓ 工具正确]  → 正反馈 → 该(query, tool)对进入正样本池
    │
    └─ 用户点击 [✗ 工具选错了]  → 负反馈
        │
        ▼
    ┌─────────────────────────────────────────┐
    │  负反馈处理:                              │
    │  1. 弹出 "正确的工具应该是?" 搜索框       │
    │  2. 用户选择正确工具                      │
    │  3. (query, wrong_tool) → 负样本         │
    │     (query, correct_tool) → 正样本       │
    │  4. 回流到 Reranker 微调数据集            │
    │  5. 每月增量微调 Cross-encoder            │
    └─────────────────────────────────────────┘

场景走查:意图识别实战

场景 1:客户经理查客户征信(B2E)

┌─ 原始输入 ─────────────────────────────────────────────┐
│ 用户消息: "查张三的征信"                                  │
│ 渠道: 信贷系统 (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笔贷款记录..."

场景 2:C端客户模糊问法(B2C)

┌─ 原始输入 ─────────────────────────────────────────────┐
│ 用户消息: "我能贷多少钱"                                  │
│ 渠道: 手机银行 (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,可能召回"理财产品收益"等语义相近但      │
│   实际无关的工具。混合检索 + 精排保证了鲁棒性。           │
└────────────────────────────────────────────────────────┘

场景 3:精确缩写查询(B2E)

用户: "调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

结论: 混合检索在银行缩写密集场景下不可或缺。

准确率指标与验证方式

核心指标

指标目标值测量方式
Top-15 命中率> 97%人工标注 1000 条银行真实问法,检查正确答案是否在 Top-15 内
Top-1 命中率> 80%相同标注集,检查第一位是否即正确答案
首次无结果率< 3%统计生产环境中 Agent 触发 search_tools() 重试的比例
MRR (Mean Reciprocal Rank)> 0.85标注集上正确答案排名的倒数的平均值
端到端检索延迟 P99< 300msPrometheus + Grafana 监控 L0+L1+L2 全链路延迟

验证方式

  1. 离线标注集评估:构建 1000 条银行典型问法 + 正确答案标注,每次检索模型迭代时跑评估
  2. A/B 对比:工具描述增强前后检索命中率对比(预期提升 30%+);混合检索 vs 纯 Dense vs 纯 Sparse 对比
  3. 生产监控:统计 L3 Agent 二次检索触发率(首次无结果率);统计 L5 人工"工具选错了"按钮点击率趋势
  4. 抽样验证:每日随机抽取 100 次真实调用,人工检查工具选择是否正确
  5. 压力测试:1000 并发检索请求,P99 延迟 < 300ms,错误率 < 0.1%

风险与缓解

风险概率影响缓解措施
Router Agent 意图识别不准Phase 2 投入人工标注 1000+ 银行问法;微调替代 Few-shot;规则兜底保证高频 20 种意图 100% 准确
工具描述增强质量差Prompt 迭代 + 人工抽检增强结果;核心系统工具人工审核描述;低质量描述标记"待完善"降低检索权重
OpenAPI 覆盖率不足导致向量质量差三级降级(Swagger→gRPC→基础元数据);优先保障核心系统(前 20%)工具描述质量
Dense 检索在缩写密集场景失效混合检索中 Sparse/BM25 互补;构建行内缩写词典索引增强
Reranker 模型内网部署困难BGE-Reranker-v2-minicpm 可在 CPU 运行,作为 GPU 不可用时的降级方案
C端问法多样性超出训练分布持续收集 C 端真实问法日志 → 每月扩充 common_questions;个性化加权提升高频用户命中率