自动推荐策略系统搭建指南
AI 向量搜索,java
策略调度平台智能推荐系统:向量搜索与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)**进行智能分析:
- 原因提取:从原始失败原因中提取通用化的原因描述(移除人名、手机号、身份证等不可通用信息)
- 策略匹配:分析候选策略列表,选择最合适的策略
- 可信度评估:评估推荐策略的可信度(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);
}
流程:
- 从策略库获取所有策略
- 提取策略的失败原因文本(
message字段) - 使用Embedding模型批量向量化
- 存储到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():加载策略数据到ESsearchByVectorWithScore():带元数据过滤的向量搜索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 初始化流程
-
系统启动时:
VectorSearchService监听容器刷新事件- 异步加载所有策略数据
- 批量向量化并存储到ES
-
定时刷新:
- 每2小时刷新一次策略数据
- 确保ES中的策略数据与数据库同步
-
策略数据缓存:
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 自动添加策略
匹配成功后,系统会自动:
- 调用接口添加策略配置(状态为禁用)
- 发送飞书通知,包含:
- 订单信息
- 推荐策略详情
- 可信度和推荐原因
- 提示需要人工审核
10. 总结
10.1 系统优势
- 智能化:使用向量语义搜索和AI分析,理解语义而非关键词
- 自动化:匹配成功后自动添加策略配置,减少人工操作
- 降级策略:三级匹配确保总能找到合适的策略
- 可扩展:新增策略无需修改代码,自动纳入匹配范围
10.2 关键设计点
- 向量化:使用Embedding模型将文本转换为向量,支持语义理解
- kNN搜索:利用Elasticsearch的kNN功能进行高效向量搜索
- 三级降级:从精确到相似再到AI推荐,确保覆盖率
- 原因提取:AI提取通用化原因,提高匹配准确性
- 人工审核:自动添加的策略默认禁用,需要人工审核后开启
10.3 未来优化方向
- 模型优化:使用更先进的Embedding模型,提高语义理解能力
- 阈值调优:根据实际效果调整相似度阈值
- 策略评估:收集策略执行效果,优化推荐算法
更多推荐



所有评论(0)