策略调度平台智能推荐系统:向量搜索与AI分析实践

目录


1. 系统概述

1.1 业务背景

在抢票系统中,当订单扣位失败时,系统需要根据失败原因自动匹配并推荐合适的处理策略。然而当出现未知失败原因时,需要落地未知失败原因,然后人工根据经验配置暂停时间。

传统方式存在的缺点

  • 响应效率低:人工处理未知失败原因需要落地、分析、配置,流程耗时长,无法快速响应
  • 经验依赖性强:配置策略完全依赖人工经验,不同人员配置可能不一致,缺乏标准化
  • 知识无法复用:已有的策略配置经验无法系统化沉淀和复用,每次遇到类似问题都需要重新分析
  • 配置准确性差:人工根据经验配置的暂停时间可能不够准确,需要反复调整和验证

1.2 解决方案

自动推荐策略系统采用向量语义搜索 + AI智能分析的混合方案,实现:

  • 语义理解:通过向量嵌入技术理解失败原因的语义
  • 智能推荐:使用大模型分析并推荐最合适的策略
  • 自动配置:匹配成功后自动添加策略配置(需人工审核)
  • 三级降级:从精确匹配到相似匹配再到AI推荐,确保总能找到合适的策略

2. 核心原理

2.1 向量语义搜索

2.1.1 文本向量化

使用Embedding模型将文本转换为高维向量(通常为768或1536维),语义相似的文本在向量空间中距离更近。

文本 → Embedding模型 → 向量 [0.12, -0.45, 0.78, ...]
2.1.2 相似度计算

使用余弦相似度计算两个向量的相似程度:

相似度 = cos(θ) = (A · B) / (||A|| × ||B||)

相似度范围:[-1, 1],值越大表示越相似。

2.1.3 Elasticsearch kNN搜索

利用Elasticsearch的**k-Nearest Neighbors (kNN)**功能进行高效的向量相似度搜索:

  • 将策略的失败原因向量存储在ES中
  • 查询时,将未知原因向量化后,在ES中搜索最相似的策略向量
  • 返回Top-K个最相似的结果

2.2 AI智能分析

当向量搜索无法找到合适匹配时,使用**大语言模型(LLM)**进行智能分析:

  1. 原因提取:从原始失败原因中提取通用化的原因描述(移除人名、手机号、身份证等不可通用信息)
  2. 策略匹配:分析候选策略列表,选择最合适的策略
  3. 可信度评估:评估推荐策略的可信度(0-100)

3. 系统架构

在这里插入图片描述

3.1 核心组件说明

组件 职责
StrategyController REST API入口,接收未知原因分析请求
StrategyMatchService 策略匹配主服务,实现三级匹配逻辑
VectorSearchService 向量搜索服务,负责向量化和ES搜索
AiAnalysisService AI分析服务,使用大模型进行策略推荐
ScheduleStrategyProvider 策略数据提供者,缓存策略数据
Elasticsearch 向量存储与kNN搜索
ChatClient 大模型调用接口

4. 三级分析流程

系统采用三级降级匹配策略,确保在不同情况下都能找到合适的策略:

4.1 第一级:语义相同匹配(SEMANTIC_EXACT)

目标:在当前业务类型和场景范围内,找到语义高度相似的策略

匹配条件

  • ✅ 限制范围:line(产线) + bizType(业务类型) + scene(场景)
  • ✅ 相似度阈值:0.85(高阈值,要求高度相似)
  • ✅ 返回Top-K:20个候选策略

适用场景

  • 失败原因与已有策略的原因高度相似
  • 业务类型和场景完全匹配

流程图
在这里插入图片描述

4.2 第二级:语义相似匹配(SEMANTIC_SIMILAR)

目标:当第一级未找到时,扩展到全局搜索,找到语义相似的策略

匹配条件

  • ✅ 限制范围:line(产线) + scene(场景),不限制业务类型
  • ✅ 相似度阈值:0.6(低阈值,允许一定差异)
  • ✅ 返回Top-K:20个候选策略

适用场景

  • 第一级未找到匹配
  • 失败原因与跨业务类型的策略相似
  • 需要借鉴其他业务类型的处理经验

流程图
在这里插入图片描述

4.3 第三级:AI智能推荐(AI_RECOMMENDED)

目标:当前两级都未找到时,使用AI分析推荐最合适的策略

匹配条件

  • ✅ 限制范围:line(产线) + scene(场景)
  • ✅ 候选策略:从策略库中获取同场景的所有策略
  • ✅ AI分析:使用大模型分析并选择最佳策略

适用场景

  • 前两级都未找到匹配
  • 失败原因是全新的,但场景相同
  • 需要AI理解语义并推荐合适的策略

流程图
在这里插入图片描述

4.4 三级匹配决策树

在这里插入图片描述


5. 技术实现

5.1 向量化流程

5.1.1 策略向量化(离线)

系统启动时,异步加载所有策略数据并向量化:

// VectorSearchService.java
@EventListener(ContextRefreshedEvent.class)
@Async
public void onApplicationEvent(ContextRefreshedEvent event) {
    loadStrategiesToElasticsearch();
    // 每2小时刷新一次
    SCHEDULED_EXECUTOR_SERVICE.scheduleWithFixedDelay(
        this::loadStrategiesToElasticsearch, 3, 2, TimeUnit.HOURS);
}

流程

  1. 从策略库获取所有策略
  2. 提取策略的失败原因文本(message字段)
  3. 使用Embedding模型批量向量化
  4. 存储到Elasticsearch(包含向量和元数据)

存储结构

{
  "id": "2600",
  "reason": "未通过验证",
  "reason_embedding": [0.12, -0.45, 0.78, ...],
  "line": "SCHEDULE",
  "channel": "Qunar",
  "biz_type": "候补扣位",
  "scene": "暂停"
}
5.1.2 查询向量化(在线)

收到未知原因分析请求时,实时向量化:

private List<Float> convertTextToVector(String text) {
    float[] embeddingResult = embeddingModel.embed(List.of(text)).getFirst();
    return Arrays.stream(ArrayUtils.toObject(embeddingResult))
            .collect(Collectors.toList());
}

5.2 Elasticsearch kNN搜索

5.2.1 索引结构
{
  "mappings": {
    "properties": {
      "reason_embedding": {
        "type": "dense_vector",
        "dims": 1536,
        "index": true,
        "similarity": "cosine"
      },
      "line": { "type": "keyword" },
      "biz_type": { "type": "keyword" },
      "scene": { "type": "keyword" },
      "channel": { "type": "keyword" }
    }
  }
}
5.2.2 搜索请求
{
  "knn": {
    "field": "reason_embedding",
    "query_vector": [0.12, -0.45, 0.78, ...],
    "k": 20,
    "num_candidates": 100,
    "filter": {
      "bool": {
        "must": [
          { "term": { "line": "SCHEDULE" } },
          { "term": { "biz_type": "候补扣位" } },
          { "term": { "scene": "暂停" } }
        ]
      }
    }
  },
  "size": 20,
  "_source": ["id", "reason", "line", "biz_type", "scene"]
}

5.3 AI分析提示词

5.3.1 提示词结构
你是故障处理策略匹配专家。请为当前故障场景分析并选择最合适的处理策略。

【故障场景描述】
业务类型:候补扣位
场景:暂停
未知原因:手机号138****1234未通过验证

【原因提取要求】
请对输入的失败原因进行通用化处理,提取出可通用的原因描述。
需要排除以下不可通用的信息:
1. 人名(所有格式,必须完全移除)
2. 手机号(包括掩码格式)
3. 身份证号(包括掩码格式)
4. 地名、12306站名
5. 其他不可通用的信息

提取原则:
- 保留故障的核心原因和业务逻辑
- 直接移除不可通用信息,只保留通用部分
- 【重要】提取后的原因必须完全来自原始原因,不能添加任何字、减任何字

【可选用策略列表】
  ID: 2600
  渠道: Qunar
  业务类型: 候补扣位
  应用场景: 暂停
  策略描述: 暂停到当天23:59:59

【匹配要求】
1. 首先提取通用化的失败原因(extractedReason字段)
2. 从上述策略中选择唯一一个最匹配当前故障场景的策略
3. 评估置信度(0-100)
4. 给出具体的匹配理由

【返回格式】
请严格按照以下JSON格式返回结果:
{
  "selectedStrategyId": "2600",
  "confidence": 85,
  "matchReason": "该策略适用于验证失败场景...",
  "extractedReason": "未通过验证"
}
5.3.2 原因提取示例
原始原因 提取后原因 说明
手机号138****1234未通过验证 未通过验证 移除手机号
身份证320***********1234信息不匹配 信息不匹配 移除身份证号
田中太郎(138****5678)在当前乘车日期存在待支付订单 在当前乘车日期存在待支付订单 移除人名和手机号

6. 关键组件

6.1 StrategyMatchService

职责:策略匹配主服务,实现三级匹配逻辑

核心方法

public MatchResponse analysisUnKnownReason(
    SchedulePlatformUnKnownReasonRequest request) {
    // 第一级:语义相同匹配
    List<StrategyWithScore> exactMatches = 
        vectorSearchService.searchByVectorWithScore(...);
    if (CollectionUtils.isNotEmpty(exactMatches)) {
        return processMatchedStrategies(request, exactMatches, 
            MatchTypeEnum.SEMANTIC_EXACT);
    }
    
    // 第二级:语义相似匹配
    List<StrategyWithScore> similarMatches = 
        vectorSearchService.searchGlobalWithScore(...);
    if (CollectionUtils.isNotEmpty(similarMatches)) {
        return processMatchedStrategies(request, similarMatches, 
            MatchTypeEnum.SEMANTIC_SIMILAR);
    }
    
    // 第三级:AI智能推荐
    return processUnknownReasonRecommendation(request);
}

6.2 VectorSearchService

职责:向量搜索服务,负责向量化和ES搜索

核心方法

  • loadStrategiesToElasticsearch():加载策略数据到ES
  • searchByVectorWithScore():带元数据过滤的向量搜索
  • searchGlobalWithScore():全局向量搜索
  • convertTextToVector():文本向量化

6.3 AiAnalysisService

职责:AI分析服务,使用大模型进行策略推荐

核心方法

  • selectBestStrategy():选择最佳策略
  • buildSelectionPrompt():构建AI提示词
  • parseAiResponse():解析AI响应

6.4 ScheduleStrategyProvider

职责:策略数据提供者,缓存策略数据

核心方法

  • getStrategiesByLineName():根据产线获取策略列表
  • getStrategyById():根据ID获取策略
  • searchSimilarStrategies():搜索相似策略(用于AI推荐)

7. 数据流转

7.1 完整流程

1. 接收请求
   └─ StrategyController.analysisUnKnownReason()
      │
2. 策略匹配
   └─ StrategyMatchService.analysisUnKnownReason()
      │
      ├─ 第一级:向量搜索(精确匹配)
      │   └─ VectorSearchService.searchByVectorWithScore()
      │       ├─ 向量化:convertTextToVector()
      │       ├─ ES搜索:executeElasticsearchSearch()
      │       └─ 解析结果:parseSearchResponse()
      │
      ├─ 第二级:向量搜索(相似匹配)
      │   └─ VectorSearchService.searchGlobalWithScore()
      │
      └─ 第三级:AI推荐
          └─ AiAnalysisService.selectBestStrategy()
              ├─ 构建提示词:buildSelectionPrompt()
              ├─ 调用大模型:chatClient.prompt()
              └─ 解析响应:parseAiResponse()
      │
3. 处理匹配结果
   └─ processMatchedStrategies() / processUnknownReasonRecommendation()
      │
      ├─ AI选择最佳策略(如果有多候选)
      ├─ 自动添加策略:addScheduleStrategyAddNotify()
      │   ├─ 调用接口:grabTicketAdminFacade.addScheduleStrategy()
      │   └─ 发送通知:notifyByFeiShu()
      │
      └─ 返回结果:buildSuccessResponse()

7.2 自动添加策略流程

当匹配到策略后,系统会自动添加策略配置:

private void addScheduleStrategyAddNotify(...) {
    // 1. 构建策略表单
    ScheduleStrategyForm strategyForm = new ScheduleStrategyForm();
    strategyForm.setLine(strategy.getLine());
    strategyForm.setBizType(strategy.getBizType());
    strategyForm.setScene(strategy.getScene());
    strategyForm.setChannel(strategy.getChannel());
    // 使用提取后的通用化原因
    String message = StringUtils.isBlank(matchResult.getExtractedReason()) 
        ? reason : matchResult.getExtractedReason();
    strategyForm.setMessage(String.format("%%%s%%", message));
    strategyForm.setExecStrategyClassName(strategy.getExecStrategyClassName());
    // 状态设置为禁用,需要人工审核后开启
    strategyForm.setStatus(StrategyStatus.DISABLE.getStatus());
    // ... 其他配置
    
    // 2. 调用接口添加策略
    AddScheduleStrategyRequest addRequest = new AddScheduleStrategyRequest();
    addRequest.setScheduleStrategyForm(strategyForm);
    boolean addSuccess = grabTicketAdminFacade.addScheduleStrategy(addRequest);
    
    // 3. 发送飞书通知
    if (addSuccess) {
        notifyByFeiShu(orderNumber, reason, strategy, matchResult);
    }
}

通知内容

  • 产线、业务、订单号、失败原因
  • 推荐策略信息(策略名、描述、配置)
  • 可信度、推荐类型、推荐原因
  • 提示:已自动配置到生产环境(未开启),请人工二次校准后开启流量

8. 部署与配置

8.1 依赖组件

组件 说明 版本要求
Elasticsearch 向量存储与搜索 8.0+(支持kNN)
Spring AI AI框架 最新版本
Embedding Model 文本向量化模型 支持中文的模型

8.2 配置项

8.2.1 Embedding模型配置
spring:
  ai:
    openai:
      api-key: 
      base-url: 
      embedding:
        options:
          model: Qwen3-Embedding-4B
          dimensions: 2560
8.2.2 向量搜索参数
private static final int TOP_K = 20;  // 返回Top-K个结果

8.3 初始化流程

  1. 系统启动时

    • VectorSearchService监听容器刷新事件
    • 异步加载所有策略数据
    • 批量向量化并存储到ES
  2. 定时刷新

    • 每2小时刷新一次策略数据
    • 确保ES中的策略数据与数据库同步
  3. 策略数据缓存

    • ScheduleStrategyProvider每30秒刷新一次策略数据
    • 内存缓存,提高查询性能

9. 使用示例

9.1 API请求

接口POST /schedulePlatform/strategy/analysisUnKnownReason

请求体

{
  "channel": "Qunar",
  "bizType": "候补扣位",
  "scene": "暂停",
  "line": "SCHEDULE",
  "unKnownReason": "手机号138****1234未通过验证",
  "orderNumber": "1130340706213137",
  "similarityThreshold": 0.8
}

9.2 响应示例

9.2.1 语义相同匹配
{
  "success": true,
  "matchResult": {
    "strategyId": "2600",
    "strategyName": "PauseOrderToTodayStrategy",
    "description": "暂停到当天23:59:59",
    "confidence": 88,
    "matchType": "语义相同",
    "matchReason": "该策略适用于验证失败场景,通过暂停订单等待信息补全...",
    "extractedReason": "未通过验证"
  }
}
9.2.2 语义相似匹配
{
  "success": true,
  "matchResult": {
    "strategyId": "2601",
    "strategyName": "PauseOrderStrategy",
    "description": "暂停订单等待信息补全",
    "confidence": 75,
    "matchType": "语义相似",
    "matchReason": "虽然业务类型不同,但失败原因相似,该策略可以借鉴...",
    "extractedReason": "未通过验证"
  }
}
9.2.3 AI智能推荐
{
  "success": true,
  "matchResult": {
    "strategyId": "2602",
    "strategyName": "RetryStrategy",
    "description": "重试策略",
    "confidence": 65,
    "matchType": "AI智能推荐",
    "matchReason": "AI分析认为该策略可以处理验证失败的情况...",
    "extractedReason": "未通过验证"
  }
}

9.3 自动添加策略

匹配成功后,系统会自动:

  1. 调用接口添加策略配置(状态为禁用)
  2. 发送飞书通知,包含:
    • 订单信息
    • 推荐策略详情
    • 可信度和推荐原因
    • 提示需要人工审核

10. 总结

10.1 系统优势

  1. 智能化:使用向量语义搜索和AI分析,理解语义而非关键词
  2. 自动化:匹配成功后自动添加策略配置,减少人工操作
  3. 降级策略:三级匹配确保总能找到合适的策略
  4. 可扩展:新增策略无需修改代码,自动纳入匹配范围

10.2 关键设计点

  1. 向量化:使用Embedding模型将文本转换为向量,支持语义理解
  2. kNN搜索:利用Elasticsearch的kNN功能进行高效向量搜索
  3. 三级降级:从精确到相似再到AI推荐,确保覆盖率
  4. 原因提取:AI提取通用化原因,提高匹配准确性
  5. 人工审核:自动添加的策略默认禁用,需要人工审核后开启

10.3 未来优化方向

  1. 模型优化:使用更先进的Embedding模型,提高语义理解能力
  2. 阈值调优:根据实际效果调整相似度阈值
  3. 策略评估:收集策略执行效果,优化推荐算法
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐