x

同义词识别与意图理解 - 深度技术探讨

本文档深入探讨五金门店AI对话收银系统中同义词识别与意图理解的技术原理、工程实践和优化策略。


一、核心问题定义

1.1 同义词识别的本质

用户说 → 系统理解

"我要一箱螺钉"     →  buy  ← 标准理解
"螺钉一盒"         ↗
"一盒螺丝"        ↗
"盒装螺钉"        ↗  → buy(同一意图)
"来盒螺丝钉"      ↗

挑战:同一个商品意图,用户可能有几十种表达方式

1.2 意图理解的本质

用户说 → 判断意图 → 执行动作

"我要买螺丝刀"    →  buy      → 加入购物车
"有螺丝刀吗"     →  search   → 商品搜索
"螺丝刀多少钱"    →  query    → 价格查询
"退螺丝刀"       →  refund   → 售后流程

挑战:不同说法可能表达同一意图,相同说法可能表达不同意图


二、同义词识别深度剖析

2.1 同义词的层次结构

第一层:完全同义(100%可替换)
────────────────────────────────
"螺丝刀" = "螺丝批" = "改锥"
"螺钉" = "螺丝"
"一盒" = "一箱" = "一包"

第二层:语序可换(90%可替换)
────────────────────────────────
"买螺丝刀" = "螺丝刀买"
"要一盒螺钉" = "一盒螺钉要"

第三层:语义相近(70%可替换,需结合上下文)
────────────────────────────────
"一箱" ≈ "一包"(取决于商品类型)
"大盒" ≈ "整盒"(需要上下文)

第四层:领域专用(行业术语)
────────────────────────────────
"膨胀螺丝" = "膨胀螺栓"
"自攻螺丝" = "自攻螺钉"

2.2 同义词发现方法对比

方法 原理 优点 缺点 适用场景
规则匹配 人工定义替换规则 精确、可控 维护成本高 核心词表
TF-IDF 词频统计找相似词 自动发现 需大量语料 批量挖掘
Word2Vec 词向量相似度 语义捕捉 依赖训练语料 通用发现
Embedding 语义向量距离 精准、API调用 费用 生产环境
LLM聚类 语义理解+分组 最智能 API费用 高价值场景

2.3 工业级同义词发现流程

┌─────────────────────────────────────────────────────────────────┐
│                    同义词发现流程(生产级别)                       │
└─────────────────────────────────────────────────────────────────┘

阶段1: 数据收集
─────────────────────────────────────────────────────────────────
       │
       ▼
┌─────────────────────────────────────────────────────────────────┐
│  反馈日志表                                                      │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │ user_input          │ store_id │ created_at              │  │
│  ├──────────────────────────────────────────────────────────┤  │
│  │ 一箱螺钉            │ store_01 │ 2026-05-15 10:00:00     │  │
│  │ 一盒螺丝            │ store_01 │ 2026-05-15 10:01:00     │  │
│  │ 螺钉一盒            │ store_02 │ 2026-05-15 10:02:00     │  │
│  │ 来盒螺丝钉          │ store_01 │ 2026-05-15 10:03:00     │  │
│  └──────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘
       │
       ▼
阶段2: 频率过滤 + 分组
─────────────────────────────────────────────────────────────────
SELECT user_input, COUNT(*) as freq
FROM feedback_log
WHERE created_at > NOW() - INTERVAL 7 DAY
GROUP BY user_input
HAVING freq >= 3  -- 至少出现3次

结果:
┌────────────────┬───────┐
│ user_input     │ freq  │
├────────────────┼───────┤
│ 一箱螺钉       │ 127   │
│ 一盒螺丝       │ 89    │
│ 螺钉一盒       │ 45    │
│ 来盒螺丝钉     │ 23    │
└────────────────┴───────┘
       │
       ▼
阶段3: Embedding向量化(API调用)
─────────────────────────────────────────────────────────────────
输入: ["一箱螺钉", "一盒螺丝", "螺钉一盒", "来盒螺丝钉"]
       │
       ▼
MiniMax Embedding API → 100维向量
       │
       ▼
向量:
一箱螺钉   → [0.12, -0.34, 0.56, ...]
一盒螺丝   → [0.11, -0.33, 0.55, ...]
螺钉一盒   → [0.13, -0.35, 0.54, ...]
来盒螺丝钉 → [0.10, -0.32, 0.53, ...]
       │
       ▼
阶段4: 聚类计算
─────────────────────────────────────────────────────────────────
计算余弦相似度:
一箱螺钉 vs 一盒螺丝   = 0.98  ✅ 同一簇
一箱螺钉 vs 螺钉一盒   = 0.97  ✅ 同一簇
一箱螺钉 vs 来盒螺丝钉 = 0.95  ✅ 同一簇

阈值设定:
- ≥ 0.95:强同义,合并
- 0.90-0.95:同义,人工确认
- 0.85-0.90:可能同义,标记待观察
- < 0.85:不同义
       │
       ▼
阶段5: LLM语义验证(确保准确性)
─────────────────────────────────────────────────────────────────
Prompt:
"以下词语是否表达同一个商品?"
"一箱螺钉" "一盒螺丝" "螺钉一盒" "来盒螺丝钉"
       │
       ▼
LLM回答:
{
  "is_same": true,
  "canonical": "一盒螺丝钉",
  "explanation": "这些都是购买螺丝钉的同义表达",
  "intent": "buy"
}
       │
       ▼
阶段6: 写入词表 + 人工审核
─────────────────────────────────────────────────────────────────
┌─────────────────────────────────────────────────────────────┐
│  synonym_table (pending)                                    │
│  ┌────────────┬────────────────────────┬──────────┬───────┐ │
│  │ canonical  │ synonyms              │ source   │ status│ │
│  ├────────────┼────────────────────────┼──────────┼───────┤ │
│  │ 一盒螺丝钉 │ [一箱螺钉,一盒螺丝,...] │ 284次    │pending│ │
│  └────────────┴────────────────────────┴──────────┴───────┘ │
└─────────────────────────────────────────────────────────────┘

2.4 同义词的时效性问题

问题:旧词表 vs 新词表
────────────────────────────────

2026年1月词表:
  "一箱" → buy (基于北方用语习惯)

2026年5月词表更新:
  发现"一箱"在南方门店语境中=12个
  而非"一盒"=6个

解决方案:地域分层词表
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  全局词表(全国通用)                                        │
│    │                                                         │
│    ├── 地域词表(省市)                                      │
│    │     │                                                   │
│    │     ├── 门店词表(单个门店)                             │
│    │     │                                                   │
│    │     └── 店员词表(个人习惯)                            │
│                                                             │
│  优先级:店员 > 门店 > 地域 > 全局                            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

三、意图理解深度剖析

3.1 意图的分类体系

第一层:业务意图(顶层)
────────────────────────────────
┌──────────┬──────────┬──────────┬──────────┬──────────┐
│   buy    │  search  │  query   │  refund  │   chat   │
│  购买    │  搜索    │  查询    │  退款    │  闲聊    │
└──────────┴──────────┴──────────┴──────────┴──────────┘

第二层:商品意图(细粒度)
────────────────────────────────
buy:
  ├── buy_single    (买一个)
  ├── buy_batch     (批发/多件)
  ├── buy_cate      (按类目买)
  └── buy_repeat    (复购)

search:
  ├── search_name  (按名称搜)
  ├── search_cate  (按类目搜)
  ├── search_brand (按品牌搜)
  └── search_similar(相似商品)

query:
  ├── query_price  (查价格)
  ├── query_stock  (查库存)
  ├── query_order  (查订单)
  └── query_member (查会员)

第三层:组合意图(实际场景)
────────────────────────────────
"买一箱螺丝钉,老板便宜点"  → buy + negotiate
"这个有货吗"              → query_stock
"比上次贵了"              → query_price + complain

3.2 意图识别的技术演进

阶段1: 规则匹配(2020年前)
────────────────────────────────
if "买" in text or "要" in text:
    intent = "buy"
elif "查" in text or "多少" in text:
    intent = "query"

问题:
- 覆盖率低(~60%)
- 维护困难(数百条规则)
- 无法处理变体

阶段2: 传统机器学习(2020-2022)
────────────────────────────────
TF-IDF + SVM/Logistic Regression

训练:
  "我要买螺丝刀" → buy
  "查下订单" → query_order

优点:
- 自动学习特征
- 覆盖率提升(~80%)

缺点:
- 需要人工标注数据
- 泛化能力有限
- 对新表达效果差

阶段3: BERT语义模型(2022-2024)
────────────────────────────────
中文BERT / uer/base_chinese_l-12_h-768_a-12

Fine-tune意图分类:
  accuracy: ~92%

优点:
- 语义理解强
- 抗噪声能力强

缺点:
- 需要GPU训练
- 推理速度慢(100ms+)
- 部署成本高

阶段4: 混合方案(当前最佳)
────────────────────────────────
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   用户输入: "老板,螺丝刀怎么卖"                              │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │  第一层:关键词快速匹配 (<5ms)                        │  │
│   │  ┌─────────────────────────────────────────────────┐ │  │
│   │  │  关键词库:                                        │ │  │
│   │  │  "怎么卖" → query_price                         │ │  │
│   │  │  "多少钱" → query_price                         │ │  │
│   │  │  "卖" → buy                                     │ │  │
│   │  │  "螺丝刀" → [商品词]                            │ │  │
│   │  └─────────────────────────────────────────────────┘ │  │
│   │                                                     │  │
│   │  匹配结果: query_price (置信度 0.85)                │  │
│   │  结论: 直接返回,置信度 > 0.8                        │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   (如果关键词未命中或置信度低,进入第二层)                   │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │  第二层:LLM语义分类 (<200ms)                        │  │
│   │  ┌─────────────────────────────────────────────────┐ │  │
│   │  │  Prompt:                                         │ │  │
│   │  │  "用户说:'老板,螺丝刀怎么卖'                    │ │  │
│   │  │   这属于哪个意图?buy/query/search/refund/chat"  │ │  │
│   │  └─────────────────────────────────────────────────┘ │  │
│   │                                                     │  │
│   │  LLM回答: intent=query_price, confidence=0.95       │  │
│   │  结论: 返回结果                                      │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
│   (如果LLM置信度仍低,进入第三层)                           │
│                                                             │
│   ┌─────────────────────────────────────────────────────┐  │
│   │  第三层:Agent深度分析 (<2s)                          │  │
│   │  - 多轮对话澄清                                      │  │
│   │  - 上下文理解                                        │  │
│   │  - 调用知识库查询                                    │  │
│   └─────────────────────────────────────────────────────┘  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3.3 意图置信度校准

问题:模型输出的置信度往往不可靠
────────────────────────────────

用户说: "我要发票"
模型判断: buy (置信度 0.95)
实际意图: invoice (开票请求)

解决方案:多模型投票
────────────────────────────────

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│   模型A (关键词): buy (0.7)                                 │
│   模型B (TF-IDF): invoice (0.6)                            │
│   模型C (LLM): invoice (0.85)                              │
│                                                             │
│   投票结果: invoice (2/3模型认可)                           │
│   最终置信度: 0.85 × 0.7 = 0.60 (加权)                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3.4 上下文意图追踪

问题单轮对话无法处理复杂场景
────────────────────────────────

用户: "我要买螺丝刀"
系统: "好的,螺丝刀有很多种,您要哪种?"

用户: "那种最长用的"   依赖上文"螺丝刀"这个品类

用户: "有没有便宜点的"
系统: "便宜的螺丝刀推荐这款..."   依赖上文的"买"

解决方案上下文窗口机制
────────────────────────────────

{
  "session_id": "sess_12345",
  "conversation_history": [
    {"role": "user", "content": "我要买螺丝刀"},
    {"role": "assistant", "content": "好的,螺丝刀有很多种,您要哪种?"},
    {"role": "user", "content": "那种最常用的"}
  ],
  "context": {
    "current_intent": "buy",
    "current_entity": {"type": "商品", "value": "螺丝刀"},
    "intent_stack": ["buy"],
    "entity_stack": ["螺丝刀"]
  }
}

意图推理时
- 识别当前句意图  "最常用的" = query_popular
- 结合 context["current_entity"]  "最常用的螺丝刀"
- 更新 entity_stack

3.5 意图纠错与学习

用户纠正  意图错误学习
────────────────────────────────

正常流程:
  用户: "我要一箱螺钉"  buy 

用户纠正流程:
  用户: "一箱螺钉"  buy  (用户实际想查库存)
       
  系统展示结果: [buy 商品列表]
       
  用户: "不是,我要查有没有货"
       
  检测到纠正信号:
    - 否定词"不是""没"
    - 重述词"我要查""有没有"
    - 转折词"但是""其实"
       
  写入反馈日志:
    ┌────────────────────────────────────────┐
     user_input: 一箱螺钉                   
     intent_wrong: buy                      
     intent_correct: query_stock            
     correction_type: NEGATION             
     session_id: sess_xxx                   
    └────────────────────────────────────────┘
       
  定期聚类学习:
    "一箱螺钉" × 10  query_stock
    更新词表: query_stock  一箱螺钉

四、实战挑战与解决方案

4.1 歧义问题

问题:同一句话在不同场景下意图不同
────────────────────────────────

"便宜点"
├── 购买场景:buy + negotiate (想要折扣)
├── 咨询场景:query_price (问价格)
└── 投诉场景:complain (表达不满)

解决方案:结合上下文 + 实体信息
────────────────────────────────

用户: "便宜点"
context:
  - recent_intents: [buy, buy, query_price]
  - recent_entities: [商品A, 商品B, 商品C]
  - current_goods: [商品A]

判断逻辑:
  if context["recent_intents"][-1] == "buy":
      → buy + negotiate
  elif context["recent_intents"][-1] == "query_price":
      → query_price (因为已经知道价格了,再次说便宜点=讨价还价)

4.2 口语与书面语

问题:口语表达随意,意图识别困难
────────────────────────────────

口语版(难识别):
  "那个...螺钉...对,就那个..."
  "有没有啊到底"
  "老板在吗"

书面语版(易识别):
  "查询螺丝钉库存"
  "请问有没有螺钉"

解决方案:
1. 口语标准化(ASR后处理)
   "那个螺钉对" → "螺钉"
   "有没有啊到底" → "有没有货"

2. 意图置信度降低
   口语输入 → 降低置信度阈值
   比如:0.8 → 0.7,允许进入第二轮LLM判断

4.3 品类差异问题

问题:不同商品类别,相同表达不同含义
────────────────────────────────

"一箱"
├── 五金工具:= 1个包装单位(如12把钳子)
├── 螺丝螺钉:= 1盒(通常100颗/盒)
└── 油漆涂料:= 1桶(通常5L/桶)

"买" vs "要"
├── 标准商品:买 = 要(无差别)
└── 定制商品:要 = 预订,买 = 现货购买

解决方案:品类感知词表
────────────────────────────────

┌─────────────────────────────────────────────────────────────┐
│  品类分层词表                                                │
│                                                             │
│  category: 五金工具                                          │
│    buy_synonyms: [买, 要, 来一个, 拿一个, 给我]             │
│    quantity_map: {一箱: 1, 一盒: 1, 一把: 1}                │
│                                                             │
│  category: 螺丝螺钉                                          │
│    buy_synonyms: [买, 要, 来, 拿, 给我称]                    │
│    quantity_map: {一箱: 100, 一盒: 12, 一包: 50}            │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4.4 新品类冷启动

问题新商品上架无历史数据可用
────────────────────────────────

新品类上架第1天:
  - 历史同义词数据: 0
  - 用户反馈数据: 0
  - 意图识别: 依赖通用模型

解决方案零样本学习 + 规则模板
────────────────────────────────

新品类冷启动策略:
┌─────────────────────────────────────────────────────────────┐
  1. 类目模板0样本                                        
     Template: "我要[商品]"  buy                           
     Template: "[商品]多少钱"  query_price                 
                                                             
  2. 商品名称分析                                            
     分析商品名结构提取关键属性                             
     "不锈钢十字螺丝刀 6mm"                                  
        type: 螺丝刀, material: 不锈钢, size: 6mm         
                                                             
  3. 迁移学习                                                
     用相似品类数据微调模型                                   
     螺丝刀(已有)  电钻(新上品)                             
                                                             
  4. 快速反馈收集                                            
     新品类页面增加"这个回答有帮助吗"                         
     快速积累正负反馈                                         
└─────────────────────────────────────────────────────────────┘

五、性能与成本平衡

5.1 意图识别延迟预算(详细版)

目标:P99延迟 < 500ms,用户无感知

┌─────────────────────────────────────────────────────────────────────┐
│                         全链路延迟分解                               │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  用户端 (Client)                                                    │
│     │                                                              │
│     │  网络RTT(取决于用户网络)                                    │
│     ▼                                                              │
│  ┌──────────────┐  50ms     │  ← 用户到服务器往返                   │
│  │  负载均衡   │           │  ← Nginx/HAProxy                       │
│  └──────┬───────┘           │                                      │
│         │                                                         │
│         ▼                                                         │
│  ┌──────────────┐  2ms     │  ← 关键词Hash查表                     │
│  │  关键词匹配   │           │  ← 内存操作,极快                     │
│  └──────┬───────┘           │                                      │
│         │ 命中              │                                      │
│         ▼  (90%场景)                                                    │
│  ┌──────────────┐  1ms     │  ← 返回结果给用户                     │
│  │  直接返回    │           │                                      │
│  └──────┬───────┘           │                                      │
│         │                                                         │
│         │ 未命中                                                     │
│         ▼                                                         │
│  ┌──────────────┐  1ms     │  ← Redis GET                        │
│  │  缓存查询    │           │  ← 相同文本之前已计算过               │
│  └──────┬───────┘           │                                      │
│         │ 命中            │                                      │
│         ▼  (9%场景)                                                    │
│  ┌──────────────┐  1ms     │  ← 返回结果给用户                     │
│  │  直接返回    │           │                                      │
│  └──────┬───────┘           │                                      │
│         │                                                         │
│         │ 仍未命中                                                  │
│         ▼                                                         │
│  ┌──────────────┐  10ms    │  ← 构造Prompt                        │
│  │  Prompt构建  │           │  ← 组装系统提示+历史上下文            │
│  └──────┬───────┘           │                                      │
│         │                                                         │
│         ▼                                                         │
│  ┌──────────────┐  300ms   │  ← MiniMax API调用                    │
│  │  LLM API    │           │  ← 网络请求+模型推理                  │
│  └──────┬───────┘           │                                      │
│         │                                                         │
│         ▼                                                         │
│  ┌──────────────┐  5ms     │  ← JSON解析+意图映射                 │
│  │  结果解析    │           │  ← LLM输出→结构化意图               │
│  └──────┬───────┘           │                                      │
│         │                                                         │
│         ▼                                                         │
│  ┌──────────────┐  1ms     │  ← 写入反馈日志                      │
│  │  反馈记录    │           │  ← 用于后续聚类学习                   │
│  └──────┬───────┘           │                                      │
│         │                                                         │
│         ▼                                                         │
│  ┌──────────────┐  50ms    │  ← 服务器返回用户                    │
│  │  返回结果    │           │                                      │
│  └──────┬───────┘           │                                      │
│         │                                                         │
│         ▼                                                         │
│  用户端 (Client)                                                    │
│                                                                     │
├─────────────────────────────────────────────────────────────────────┤
│  延迟汇总                                                          │
│  ─────────────────────────────────────────────────────────────────  │
│  命中关键词 (90%): 50 + 2 + 2 + 1 + 50 = ~105ms ✅                │
│  命中缓存 (9%):   50 + 2 + 2 + 1 + 1 + 1 + 50 = ~107ms ✅        │
│  触发LLM (1%):    50 + 2 + 2 + 1 + 10 + 300 + 5 + 1 + 50 = ~421ms ✅│
│                                                                     │
│  P50延迟: <50ms                                                   │
│  P99延迟: <500ms                                                  │
│  P999延迟: <1000ms (LLM超时降级)                                   │
└─────────────────────────────────────────────────────────────────────┘

5.2 Redis缓存设计详解

5.2.1 缓存Key设计

┌─────────────────────────────────────────────────────────────────────┐
                        Redis Key 命名规范                           
├─────────────────────────────────────────────────────────────────────┤
                                                                     
  格式: {type}:{tenant_id}:{entity}:{identifier}                    
                                                                     
  同义词缓存                                                          
  ─────────────────────────────────────────────────────────────────  
  Key:  synonym:global:hash:{text_hash}                             
  Type: Hash                                                         
  TTL:  86400 (24小时)                                               
  :  synonym:global:hash:a1b2c3d4                                  
       Field: canonical  "一盒螺丝钉"                               
       Field: intent  "buy"                                         
       Field: confidence  "0.95"                                    
                                                                     
  意图缓存                                                            
  ─────────────────────────────────────────────────────────────────  
  Key:  intent:global:text:{original_text}                           
  Type: String (JSON)                                                
  TTL:  3600 (1小时)                                                
  :  intent:global:text:我要一箱螺钉                               
       Value: {"intent":"buy","canonical":"一盒螺丝钉","conf":0.92}   
                                                                     
  Embedding缓存                                                       
  ─────────────────────────────────────────────────────────────────  
  Key:  embedding:global:vector:{text_hash}                          
  Type: String (JSON)                                               
  TTL:  604800 (7)                                                
  :  embedding:global:vector:e5f6g7h8                              
       Value: [0.12,-0.34,0.56,...] (100维向量)                     
                                                                     
  门店词表缓存                                                        
  ─────────────────────────────────────────────────────────────────  
  Key:  store_vocab:{store_id}                                      
  Type: Hash                                                         
  TTL:  3600 (1小时)                                                
  :  store_vocab:store_001                                        
       Field: 一箱螺钉  {canonical:一盒螺丝钉,intent:buy}          
                                                                     
  版本控制缓存                                                         
  ─────────────────────────────────────────────────────────────────  
  Key:  model_version:active                                         
  Type: String                                                      
  TTL:   (主动失效)                                                
  :  model_version:active  "v_20260515_001"                      
                                                                     
└─────────────────────────────────────────────────────────────────────┘

5.2.2 缓存更新策略

┌─────────────────────────────────────────────────────────────────────┐
│                        缓存更新策略                                  │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  1. 定时全量刷新(每日凌晨3点)                                      │
│  ─────────────────────────────────────────────────────────────────  │
│     触发: Crontab → self-learning refresh-cache                     │
│                                                                     │
│     流程:                                                           │
│     ┌─────────────────────────────────────────────────────────────┐ │
│     │  1. 从MySQL读取当前活跃词表                                  │ │
│     │  2. 生成新缓存Key (带版本号)                                 │ │
│     │  3. 写入Redis                                               │ │
│     │  4. 更新 model_version:active → 新版本号                    │ │
│     │  5. 旧缓存自然过期 (TTL=0)                                  │ │
│     └─────────────────────────────────────────────────────────────┘ │
│                                                                     │
│  2. 热点缓存预热(上新版本后)                                       │
│  ─────────────────────────────────────────────────────────────────  │
│     触发: 新版本上线后自动执行                                       │
│                                                                     │
│     流程:                                                           │
│     ┌─────────────────────────────────────────────────────────────┐ │
│     │  1. 读取过去7天TOP 1000条用户输入                           │ │
│     │  2. 批量计算Embedding,存入缓存                             │ │
│     │  3. 批量查询意图,存入缓存                                   │ │
│     │  4. 确保热点请求100%命中缓存                                │ │
│     └─────────────────────────────────────────────────────────────┘ │
│                                                                     │
│  3. 缓存失效机制                                                    │
│  ─────────────────────────────────────────────────────────────────  │
│     Key过期:     TTL自动清理                                        │
│     主动删除:    LUA脚本批量删除                                    │
│     版本切换:    旧Key标记,TTL后自动删除                           │
│                                                                     │
│  LUA脚本示例(批量删除旧版本缓存):                                  │
│  ─────────────────────────────────────────────────────────────────  │
│  local keys = redis.call('KEYS', 'synonym:v_*')                   │
│  if #keys > 0 then                                                 │
│      redis.call('DEL', unpack(keys))                               │
│  end                                                               │
│  return #keys                                                      │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

5.3 API成本优化(量化版)

5.3.1 月度成本详细计算

假设条件:
- 100家门店
- 每店每日100次对话
- 总对话量:10,000次/天
- 每月30天:300,000次/月

┌─────────────────────────────────────────────────────────────────────┐
│                    月度API成本明细                                    │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  一、Embedding成本                                                  │
│  ─────────────────────────────────────────────────────────────────  │
│                                                                     │
│  场景A: 首次计算(未命中缓存)                                       │
│  ─────────────────────────────────────────────────────────────────  │
│  每日量: 10,000次 × 10% = 1,000次                                  │
│  每条tokens: 平均20 tokens                                         │
│  每日tokens: 1,000 × 20 = 20,000                                  │
│  月tokens: 20,000 × 30 = 600,000                                   │
│  单价: ¥1/百万tokens                                               │
│  月费用: 600,000 / 1,000,000 × ¥1 = ¥0.6                          │
│                                                                     │
│  场景B: 缓存命中(90%场景)                                         │
│  ─────────────────────────────────────────────────────────────────  │
│  每日量: 10,000次 × 90% = 9,000次                                  │
│  缓存命中: ¥0                                                      │
│  (实际缓存命中也消耗Redis内存,非API费用)                            │
│                                                                     │
│  Embedding月费用: ¥0.6                                             │
│                                                                     │
│  二、LLM意图识别成本                                                │
│  ─────────────────────────────────────────────────────────────────  │
│                                                                     │
│  场景: LLM兜底(10%场景)                                           │
│  ─────────────────────────────────────────────────────────────────  │
│  每日量: 10,000次 × 10% = 1,000次                                  │
│  Prompt tokens: 平均150 tokens                                      │
│  Response tokens: 平均50 tokens                                     │
│  每日tokens: 1,000 × (150+50) = 200,000                           │
│  月tokens: 200,000 × 30 = 6,000,000                                │
│  单价: ¥10/百万tokens                                              │
│  月费用: 6,000,000 / 1,000,000 × ¥10 = ¥60                        │
│                                                                     │
│  三、同义词聚类成本(每日凌晨批处理)                                 │
│  ─────────────────────────────────────────────────────────────────  │
│  每日处理: 500条未识别反馈                                         │
│  Prompt tokens: 3,000 (含上下文)                                    │
│  Response tokens: 500                                              │
│  每日tokens: 500 × 3,500 = 1,750,000                              │
│  月tokens: 1,750,000 × 30 = 52,500,000                            │
│  单价: ¥10/百万tokens                                              │
│  月费用: 52,500,000 / 1,000,000 × ¥10 = ¥525                      │
│                                                                     │
│  四、新意图检测成本(每日凌晨批处理)                                 │
│  ─────────────────────────────────────────────────────────────────  │
│  每日处理: 200条待分析                                              │
│  Prompt tokens: 2,000                                              │
│  Response tokens: 300                                              │
│  每日tokens: 200 × 2,300 = 460,000                                 │
│  月tokens: 460,000 × 30 = 13,800,000                               │
│  单价: ¥10/百万tokens                                              │
│  月费用: 13,800,000 / 1,000,000 × ¥10 = ¥138                      │
│                                                                     │
│  ┌───────────────────────────────────────────────────────────────┐ │
│  │ 月度API总费用                                                 │ │
│  │ ──────────────────────────────────────────────────────────── │ │
│  │ Embedding:       ¥0.6                                        │ │
│  │ LLM意图识别:    ¥60                                          │ │
│  │ 同义词聚类:     ¥525  ← 最大成本项                           │ │
│  │ 新意图检测:     ¥138                                         │ │
│  │ ──────────────────────────────────────────────────────────── │ │
│  │ 总计:           ¥723.6/月                                     │ │
│  └───────────────────────────────────────────────────────────────┘ │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

5.3.2 成本优化策略(效果量化)

┌─────────────────────────────────────────────────────────────────────┐
│                    成本优化方案及效果                                 │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  策略1: 提升缓存命中率(目标: 95%)                                  │
│  ─────────────────────────────────────────────────────────────────  │
│  当前: 90% → 优化后: 95%                                           │
│                                                                     │
│  每日LLM调用: 10,000 × 5% = 500次                                   │
│  节省: 500 × (150+50) / 1,000,000 × ¥10 = ¥1/天                   │
│  月节省: ¥30                                                        │
│                                                                     │
│  实现方式:                                                          │
│  - Embedding缓存TTL: 7天 → 30天                                    │
│  - 增加热点预热频率: 每日 → 每日                                    │
│  - 多级缓存: Redis + 本地LRU                                       │
│                                                                     │
│  策略2: 降低聚类频率                                                │
│  ─────────────────────────────────────────────────────────────────  │
│  当前: 每日聚类 → 优化后: 每周聚类                                   │
│                                                                     │
│  同义词聚类月费: ¥525 → ¥525/7 = ¥75                               │
│  月节省: ¥450                                                       │
│                                                                     │
│  实现方式:                                                          │
│  - 新知识积累7天再处理(保证样本量)                                 │
│  - 紧急新词走单独快速通道(人工介入)                                │
│                                                                     │
│  策略3: 意图识别Prompt压缩                                          │
│  ─────────────────────────────────────────────────────────────────  │
│  当前Prompt: 150 tokens → 优化后: 80 tokens                        │
│                                                                     │
│  LLM月费用: ¥60 → ¥60 × 80/150 = ¥32                              │
│  月节省: ¥28                                                        │
│                                                                     │
│  实现方式:                                                          │
│  - 用few-shot替代system prompt                                     │
│  - 移除冗余上下文                                                    │
│  - 意图定义用ID替代文字                                              │
│                                                                     │
│  策略4: 批量API调用                                                 │
│  ─────────────────────────────────────────────────────────────────  │
│  当前: 逐条调用 → 优化后: 批量50条/次                               │
│                                                                     │
│  API调用 overhead 减少: ~30%                                       │
│  月节省: ¥723.6 × 30% = ¥217                                       │
│                                                                     │
│  实现方式:                                                          │
│  - 使用批量Embedding API                                           │
│  - 使用批量Completion API                                           │
│                                                                     │
│  ┌───────────────────────────────────────────────────────────────┐ │
│  │ 优化后月度API总费用                                            │ │
│  │ ──────────────────────────────────────────────────────────── │ │
│  │ Embedding:       ¥0.6 → ¥0.3 (命中提高)                      │ │
│  │ LLM意图识别:    ¥60 → ¥32 (Prompt压缩)                       │ │
│  │ 同义词聚类:     ¥525 → ¥75 (周频处理)                         │ │
│  │ 新意图检测:     ¥138 → ¥69 (周频处理)                         │ │
│  │ ──────────────────────────────────────────────────────────── │ │
│  │ 总计:           ¥723.6 → ¥176.3/月                            │ │
│  │ 节省: ¥547/月 (75.6%)                                         │ │
│  └───────────────────────────────────────────────────────────────┘ │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

5.4 性能监控体系

5.4.1 核心监控指标

┌─────────────────────────────────────────────────────────────────────┐
│                        监控指标体系                                  │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  一、延迟指标                                                        │
│  ─────────────────────────────────────────────────────────────────  │
│                                                                     │
│  p50_latency:     P50响应时间  → 目标 <50ms                        │
│  p90_latency:     P90响应时间  → 目标 <200ms                       │
│  p99_latency:     P99响应时间  → 目标 <500ms                       │
│  p999_latency:    P999响应时间 → 目标 <1000ms                      │
│                                                                     │
│  延迟分布:                                                         │
│  ┌─────────────────────────────────────────────────────────────┐  │
│  │  <50ms   ████████████████████████████████████  90%          │  │
│  │  50-200ms ██████████                                9%       │  │
│  │  200-500ms █                                    0.8%       │  │
│  │  >500ms  █                                      0.2%       │  │
│  └─────────────────────────────────────────────────────────────┘  │
│                                                                     │
│  二、吞吐指标                                                        │
│  ─────────────────────────────────────────────────────────────────  │
│                                                                     │
│  qps:            每秒请求数    → 目标 >100                          │
│  concurrent:     并发连接数    → 目标 <50                          │
│  queue_depth:    请求队列深度  → 目标 <10                          │
│                                                                     │
│  三、命中率指标                                                      │
│  ─────────────────────────────────────────────────────────────────  │
│                                                                     │
│  keyword_hit_rate:   关键词命中率    → 目标 >50%                   │
│  cache_hit_rate:     缓存命中率      → 目标 >90%                   │
│  llm_fallback_rate:  LLM兜底率      → 目标 <10%                     │
│                                                                     │
│  四、成本指标                                                        │
│  ─────────────────────────────────────────────────────────────────  │
│                                                                     │
│  daily_api_cost:     日API费用      → 告警 >¥50                     │
│  monthly_api_cost:   月API费用      → 预算 ¥723                    │
│  cost_per_request:   单次请求成本   → 目标 <¥0.003               │
│                                                                     │
│  五、准确性指标                                                      │
│  ─────────────────────────────────────────────────────────────────  │
│                                                                     │
│  intent_accuracy:    意图识别准确率 → 目标 >95%                    │
│  synonym_precision:   同义词准确率  → 目标 >90%                   │
│  user_satisfaction:  用户满意度     → 目标 >85%                    │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

5.4.2 告警规则

# Prometheus告警规则示例
groups:
  - name: self_learning_alerts
    rules:
      # P99延迟告警
      - alert: HighLatency
        expr: histogram_quantile(0.99, rate(request_latency_seconds[5m])) > 0.5
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "意图识别P99延迟超过500ms"

      # 缓存命中率告警
      - alert: LowCacheHitRate
        expr: cache_hit_rate < 0.85
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "缓存命中率低于85%,API成本可能激增"

      # API费用告警
      - alert: HighAPICost
        expr: daily_api_cost > 50
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "日API费用超过50元,请检查是否有异常"

      # LLM兜底率告警
      - alert: HighLLMFallbackRate
        expr: llm_fallback_rate > 0.15
        for: 30m
        labels:
          severity: warning
        annotations:
          summary: "LLM兜底率超过15%,词表可能需更新"

5.5 降级与容灾策略

5.5.1 降级链路

┌─────────────────────────────────────────────────────────────────────┐
│                        降级链路设计                                  │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  正常状态                                                            │
│  ─────────────────────────────────────────────────────────────────  │
│  用户输入 → 关键词匹配 → 命中 → 返回结果 ✅                          │
│                  ↓ 未命中                                           │
│              缓存查询 → 命中 → 返回结果 ✅                           │
│                  ↓ 未命中                                           │
│              LLM识别 → 返回结果 ✅                                  │
│                                                                     │
│  降级 Level 1: Redis故障                                            │
│  ─────────────────────────────────────────────────────────────────  │
│  用户输入 → 关键词匹配 → 命中 → 返回结果 ✅                          │
│                  ↓ 未命中                                           │
│              LLM识别(跳过缓存)→ 返回结果 ✅                        │
│  延迟增加: +10ms                                                   │
│  缓存命中率: 90% → 0%                                               │
│  API费用: ×10                                                      │
│                                                                     │
│  降级 Level 2: MiniMax API故障                                      │
│  ─────────────────────────────────────────────────────────────────  │
│  用户输入 → 关键词匹配 → 命中 → 返回结果 ✅                          │
│                  ↓ 未命中                                           │
│              本地模型兜底 → 返回结果(置信度低)⚠️                  │
│                                                                     │
│  本地模型: 使用关键词规则库 + TF-IDF (已内置)                        │
│  准确率: 85% (比LLM低10%)                                           │
│                                                                     │
│  降级 Level 3: 全部故障                                             │
│  ─────────────────────────────────────────────────────────────────  │
│  用户输入 → 默认回复: "抱歉,我暂时无法理解您的问题,请稍后再试"     │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

5.5.2 故障恢复流程

┌─────────────────────────────────────────────────────────────────────┐
│                        故障恢复流程                                  │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  Redis故障恢复                                                      │
│  ─────────────────────────────────────────────────────────────────  │
│  1. Redis服务恢复                                                   │
│  2. 检测到 model_version:active 变更                               │
│  3. 触发缓存预热                                                    │
│  4. 逐门店加载词表到Redis                                          │
│  5. 验证缓存完整性                                                  │
│  6. 恢复服务 (P99延迟从500ms→50ms)                                 │
│                                                                     │
│  MiniMax API恢复                                                    │
│  ─────────────────────────────────────────────────────────────────  │
│  1. API健康检查 (每30秒)                                            │
│  2. 检测到API恢复                                                   │
│  3. 开启流量逐步恢复 (10% → 50% → 100%)                            │
│  4. 观察5分钟无异常后全量恢复                                       │
│                                                                     │
│  数据一致性修复                                                      │
│  ─────────────────────────────────────────────────────────────────  │
│  1. 故障期间 feedback_log 已累积                                   │
│  2. 故障恢复后批量处理                                              │
│  3. 避免洪泛API                                                     │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

5.6 完整成本-性能对比表

┌─────────────────────────────────────────────────────────────────────┐
│                    不同规模下的成本-性能矩阵                          │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  规模S (10家门店)                                                   │
│  ─────────────────────────────────────────────────────────────────  │
│  日对话量: 1,000次                                                  │
│  月API费用: ¥72                                                     │
│  服务器: 2核4G ¥80/月                                               │
│  P99延迟: <300ms                                                   │
│  词表规模: ~500条                                                  │
│                                                                     │
│  规模M (100家门店) ⭐推荐                                           │
│  ─────────────────────────────────────────────────────────────────  │
│  日对话量: 10,000次                                                 │
│  月API费用: ¥176 (优化后)                                          │
│  服务器: 4核8G ¥150/月                                              │
│  P99延迟: <500ms                                                   │
│  词表规模: ~5,000条                                                │
│                                                                     │
│  规模L (500家门店)                                                  │
│  ─────────────────────────────────────────────────────────────────  │
│  日对话量: 50,000次                                                 │
│  月API费用: ¥880 (优化后)                                          │
│  服务器: 8核16G ¥300/月                                             │
│  P99延迟: <500ms                                                   │
│  词表规模: ~25,000条                                               │
│  需要: Redis Cluster                                               │
│                                                                     │
│  规模XL (1000家门店)                                               │
│  ─────────────────────────────────────────────────────────────────  │
│  日对话量: 100,000次                                                │
│  月API费用: ¥1760 (优化后)                                         │
│  服务器: 16核32G ¥600/月                                            │
│  P99延迟: <500ms                                                   │
│  词表规模: ~50,000条                                               │
│  需要: 多实例负载均衡                                               │
│                                                                     │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │ 成本-规模线性关系                                              │  │
│  │                                                              │  │
│  │  API费用 ≈ 规模(店数) × 1.76元/月                             │  │
│  │  服务器费用 ≈ 规模(店数) × 1.5元/月                           │  │
│  │  总费用 ≈ 规模(店数) × 3.26元/月                              │  │
│  │                                                              │  │
│  │  1000家门店 ≈ 3260元/月                                      │  │
│  └───────────────────────────────────────────────────────────────┘  │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

六、总结:最佳实践

6.1 同义词识别最佳实践

原则 说明
频率优先 只对出现3次以上的词做归一化
分层管理 全局→地域→门店→个人
置信度分级 >0.95自动合并,>0.9人工确认,<0.9观察
时效清理 30天无访问的同义词降权
可审计 所有变更记录操作日志

6.2 意图理解最佳实践

原则 说明
多层路由 关键词→LLM→Agent,逐级降级
置信度校准 多模型投票,避免单点失误
上下文追踪 多轮对话维护意图栈和实体栈
主动澄清 置信度<0.7时主动询问用户
反馈闭环 用户纠正自动入训练集

6.3 工程架构建议

┌─────────────────────────────────────────────────────────────┐
│  生产环境推荐架构                                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  请求入口                                                    │
│     │                                                       │
│     ▼                                                       │
│  ┌──────────────┐                                          │
│  │  关键词匹配   │  ← 50%请求在这里解决,<5ms               │
│  └──────┬───────┘                                          │
│         │ 未命中                                           │
│         ▼                                                  │
│  ┌──────────────┐                                          │
│  │  Redis缓存   │  ← 40%请求在这里解决,<10ms              │
│  └──────┬───────┘                                          │
│         │ 未命中                                           │
│         ▼                                                  │
│  ┌──────────────┐                                          │
│  │  LLM API     │  ← 10%请求在这里解决,<300ms             │
│  └──────┬───────┘                                          │
│         │                                                  │
│         ▼                                                  │
│  ┌──────────────┐                                          │
│  │  反馈收集    │  ← 所有未识别请求记录日志                 │
│  └──────────────┘                                          │
│                                                             │
│  定时任务: 每日聚类 → 词表更新 → 缓存刷新                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

附录:优化结论速查

优化方向 效果 实现难度
提升缓存命中率至95% 节省¥30/月 ⭐ 简单
聚类改为周频 节省¥450/月 ⭐⭐ 简单
Prompt压缩 节省¥28/月 ⭐⭐ 中等
批量API调用 节省¥217/月 ⭐⭐⭐ 较复杂

最优性价比方案:¥176/月 支持100家门店,P99<500ms


核心结论

  1. 同义词识别:不是纯粹的技术问题,是数据+算法的系统工程
  2. 意图理解:分层路由是工业界最佳实践,关键词+LLM组合最优
  3. 成本控制:90%的请求应该由缓存/关键词解决,LLM兜底
  4. 持续学习:反馈闭环是系统智能化的核心机制
Left-click: follow link, Right-click: select node, Scroll: zoom
x