商品智能搜索失败归因分析技能 - 架构设计
1. 技能概述
商品智能搜索失败归因分析技能(goods_search_fail_analysis)用于对大批量商品智能搜索失败数据进行自动化归因分析,输出可视化的 HTML 交互式报告。核心价值是将人工逐条排查失败原因的工作自动化,快速定位系统优化方向。
2. 目录结构
goods_search_fail_analysis/
├── SKILL.md # 技能说明文档
├── scripts/
│ └── analysis.py # 核心分析脚本
├── templates/
│ └── report_template.html # HTML 报告模板
├── prompt/
│ ├── match_fail_classification_prompt.md # 分类提示词
│ ├── match_fail_detail_analysis_prompt.md # 详细归因分析提示词
│ └── match_fail_subcluster_aggregation_prompt.md # 子类聚合提示词
└── references/ # 业务知识库(略)
3. 业务架构
3.1 业务流程
搜索失败数据 → 数据加载与分组 → 快速D类预筛 → 原因分类 → 子类聚合 → 抽样归因分析 → HTML报告生成
3.2 搜索失败原因分类体系
| 大类 | 编码 | 含义 | 典型场景 |
|---|---|---|---|
| 六要素书写不规范 | A | 入参数据在清洗阶段被"改坏"导致评分失败 | 规格被误清空、通用名被截断 |
| 召回异常 | B | ES 召回阶段未能返回相关候选数据 | 候选列表为空 |
| 评分过滤异常 | C | 已找到正确商品,但表述差异导致评分未达阈值 | 单位不等价(Ug vs μg)、大包装后缀 |
| 主数据缺失/其他 | D | 标品库中不存在与入参对应的商品 | 新上市规格、字段单边缺失 |
3.3 评分阈值体系
不同搜索来源有不同的字段评分阈值:
| 来源 | 通用名 | 规格 | 厂商 | 品牌 |
|---|---|---|---|---|
| TEST_1 | >60 | >=70 | >=80 | >50 |
| DEFAULT_CONSUMER | >60 | >70 | >=80 | >50 |
| TEST_2 | >60 | >=80 | - | >=50 |
未定义的来源使用 DEFAULT_CONSUMER 阈值。
3.4 特殊分数含义
- 81分:代表入参或库中数据某个字段值单边缺失(绝大部分情况为入参字段缺失),不是评分算法计算结果。
3.5 输入数据要求
输入为 CSV 或 Excel 文件,核心字段:
| 字段 | 说明 |
|---|---|
| source | 搜索来源编码 |
| businessType | 商品类型(药品、医疗器械、保健品等) |
| esDetail_originalParam | 搜索原始入参(JSON) |
| esDetail_cleaning | 字段清洗流水日志(JSON) |
| esDetail_candidates | ES 召回候选数据及评分(JSON) |
3.6 输出产物
- HTML 交互式报告:按来源和商品类型分组展示分类分布、维度失败分布、子类详情及样本归因
- Excel 导出(可选):搜索失败 case 数据、归因分析结果案例数据
4. 技术架构
4.1 整体流程图
┌──────────────────────────────────────────────────────────────────┐
│ 数据加载与分组 │
│ load_data() → _group_records_by_source_and_type() │
└──────────────────────┬───────────────────────────────────────────┘
│ 按 source|businessType 分组
▼
┌──────────────────────────────────────────────────────────────────┐
│ 并发分组处理 (ThreadPoolExecutor) │
│ _analyze_group() │
│ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Step 1: 快速D类预筛 │ │
│ │ quick_check_d_category() │ │
│ │ - 规则1: 字段单边缺失(所有候选3+字段=81分) │ │
│ │ - 规则2: 语义不一致(所有候选与入参语义不匹配) │ │
│ └────────────────────────┬───────────────────────────────────┘ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Step 2: 原因分类 │ │
│ │ LLM模式: _batch_classify_records() → 批量LLM调用 │ │
│ │ 规则模式: _classify_by_rules() → 本地规则引擎 │ │
│ └────────────────────────┬───────────────────────────────────┘ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Step 3: 子类聚合 │ │
│ │ generate_subclusters() → aggregate_subclusters() │ │
│ │ 使用LLM将细粒度子标签聚合为≤10个有意义的子类 │ │
│ └────────────────────────────────────────────────────────────┘ │
└──────────────────────┬───────────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────────┐
│ 统一批量归因分析 (所有分组) │
│ _batch_attribution_for_all_groups() │
│ - 从每个子类抽取 N 条样本 │
│ - 调用归因模型进行深度分析 │
│ - 输出 rootCause + suggestion + matchedCandidate │
└──────────────────────┬───────────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────────────────────┐
│ HTML 报告生成 │
│ generate_html_report() → 注入模板 → 输出交互式报告 │
└──────────────────────────────────────────────────────────────────┘
4.2 核心类:MatchFailAnalyzer
python
class MatchFailAnalyzer:
def __init__(self, data_path, api_key, api_base_url, max_workers,
classification_batch_size, attribution_batch_size,
llm_business_types, max_llm_classification_per_group,
classification_model_name, attribution_model_name,
num_attribution_samples)
关键参数
| 参数 | 默认值 | 说明 |
|---|---|---|
| max_workers | 5 | 最大并发线程数 |
| classification_batch_size | 5 | 分类阶段每批数据条数 |
| attribution_batch_size | 1 | 归因阶段每批数据条数 |
| llm_business_types | {"药品"} | 使用LLM分析的商品类型 |
| max_llm_classification_per_group | 1000 | 每组最大LLM分类条数 |
| num_attribution_samples | 2 | 每子类抽取归因样本数 |
4.3 双模型策略
| 阶段 | 推荐模型 | 用途 | 特点 |
|---|---|---|---|
| 分类阶段 | qwen-plus / gpt-3.5-turbo | 批量原因分类、子类聚合 | 速度快、成本低 |
| 归因阶段 | qwen-max / gpt-4 | 深度归因分析、优化建议 | 质量高、推理能力强 |
4.4 快速D类预筛算法
quick_check_d_category() 方法包含两条规则,按优先级执行:
规则1 - 字段单边缺失:
- 遍历所有候选数据
- 检查6个评分字段(genericName, spec, manufacturer, approvalNum, tradeName, barcode)
- 如果每条候选均有 ≥3 个字段评分为81分 → 归为D类
规则2 - 语义不一致:
- 对评分低于阈值且双方字段值非空的维度
- 使用编辑距离计算语义相似度(阈值0.6)
- 如果所有候选均与入参语义不一致 → 归为D类
4.5 LLM 调用链路
分类调用 (_classify_with_llm_batch)
输入数据脱水(去除logs,仅保留前2条候选)
→ 填充 match_fail_classification_prompt.md
→ 调用分类模型
→ 解析JSON响应(含多策略容错)
→ 返回 [{index, mainLabel, subLabel}, ...]
归因调用 (_analyze_batch_detail)
输入数据脱水(保留logs,仅保留前2条候选)
→ 填充 match_fail_detail_analysis_prompt.md
→ 调用归因模型
→ 解析JSON响应
→ 返回 [{index, rootCause, suggestion, matchedCandidate}, ...]
子类聚合调用 (aggregate_subclusters)
收集所有子标签及其数量
→ 填充 match_fail_subcluster_aggregation_prompt.md
→ 调用分类模型
→ 合并相似子标签(最多保留10个)
4.6 并发模型
┌─── 分组1 ───┐
│ │
主线程 ──fork──────┼─── 分组2 ───┼──join──► 统一归因 ──fork──► 批次1
(ThreadPool │ │ (ThreadPool ► 批次2
max_workers) └─── 分组N ───┘ max_workers) ► 批次N
- 分组级别:各 source|businessType 分组并发处理
- 批次级别:分类和归因阶段内部按 batch_size 切分,并发调用 LLM
- 线程安全:使用
threading.Lock保护共享的性能统计数据
4.7 JSON 响应容错解析
_parse_llm_response() 实现6层容错策略:
- 直接 JSON 解析
- 清理 Markdown 代码块标记
- 提取
[...]数组模式 - 逐对象
{...}提取 - 修复常见 JSON 错误(尾逗号、未转义换行等)
- 完整字符串修复后重试
4.8 数据脱水策略
为节省 Token 消耗,发送给 LLM 的候选数据经过精简:
| 阶段 | 候选数量 | 包含 logs | 说明 |
|---|---|---|---|
| 分类阶段 | 前2条 | ❌ | 仅需值和分数判断类别 |
| 归因阶段 | 前2条 | ✅ | 需要 logs 解释扣分原因 |
4.9 报告生成
使用 report_template.html 模板,注入分析结果生成单页交互式 HTML:
- 按来源+商品类型分组展示
- 客户端 JavaScript 实现分组筛选切换
- 各大类(A/B/C/D)占比可视化
- 维度失败分布统计
- 子类展开/折叠详情
- 样本6维度对比表格
- 评分日志弹窗(Base64 编码传递)
5. 性能优化设计
| 优化手段 | 效果 |
|---|---|
| 快速D类预筛 | 无需LLM即可过滤大量D类数据,节省60-80% Token |
| 双模型策略 | 分类用廉价模型,归因用高质量模型,成本降低50-70% |
| 批量调用 | 减少API调用次数,降低网络开销 |
| 并发处理 | 分组级别+批次级别双重并发 |
| 数据脱水 | 分类阶段去除logs,减少Prompt长度 |
| 子类抽样 | 每子类仅抽取N条进行深度归因,避免全量分析 |
| LLM分类上限 | 每组最多1000条进入LLM分类,超出直接归D类 |
6. 使用示例
bash
# 规则引擎模式(无需API Key)
python analysis.py --data_path "data.xlsx" --output_path "report.html"
# 双模型 + 并发模式(推荐)
python analysis.py \
--data_path "data.xlsx" \
--output_path "report.html" \
--api_key "sk-xxx" \
--api_base_url "https://dashscope.aliyuncs.com/compatible-mode/v1" \
--classification_model_name "qwen-plus" \
--attribution_model_name "qwen-max" \
--max_workers 10 \
--classification_batch_size 10 \
--attribution_batch_size 1 \
--llm_business_types 药品 医疗器械
7. 依赖项
| 依赖 | 用途 | 必需 |
|---|---|---|
| pandas + openpyxl | Excel 读写 | 是(Excel输入时) |
| openai | LLM API 调用 | 否(规则引擎模式无需) |