战

实战中心

知识挖掘 / RAG

← 返回实战列表
⛏️ 知识挖掘 / RAG

knowledge-mining-lab:从会话日志到知识库的全链路跑通

2026-07-30 · 4 文档 + 24 通会话 → 14 条知识条目 + 16 条 Golden Set 评测 · 工具目录 knowledge-mining-lab/ · 零第三方依赖真实运行

机型 Apple Silicon macOS Python 3.9+(零第三方依赖) 检索 内置 BM25 + 中文 bigram 分词 LLM 增强 可选(设 DASHSCOPE_API_KEY 即启用)
本页导航: 背景速览 链路设计 环境与数据 跑通步骤 实测结果 三个真实踩坑 核心发现 接真实系统 生产级升级版

一、背景速览:把调研报告的"知识挖掘"章节变成能跑的代码

调研报告 《大模型场景知识体系建设》↗ §④ 讲了四条知识挖掘管道、§⑥ 讲了 Golden Set 评测——但都是方法论。本次实战把其中 最有性价比的一条链路(存量文档结构化 + 会话日志挖掘)完整写成代码并在本机跑通, 不依赖任何云服务和第三方包。

输入
4 份企业制度文档(Markdown)+ 24 通客服会话日志(JSONL,刻意埋入 PII、同义重复、闲聊、答不上来的问题)。
输出
18 个带元数据的知识块 + 14 条锚定过原文的 QA 知识条目 + 5 组带优先级的知识缺口清单 + 检索评测报告。
验证方式
16 条人工标注 Golden Set(含口语/错别字),双索引对照跑 Hit@1 / Hit@3 / MRR@3。
核心问题
会话挖掘出来的 QA,到底对检索有没有可测量的增益?(结论:有,Hit@1 0.938 → 1.0)

二、链路设计:六步流水线,每步一个脚本一份产物

步骤脚本做什么关键参数/机制
1 解析分块step1_parse_chunk.pyMarkdown → 带元数据知识块H2 章节为语义边界,超长按段落递归细分(400 token 上限 / 50 重叠);标题路径拼进检索文本
2 清洗脱敏step2_clean_pii.py会话 PII 脱敏 + 无效会话过滤手机/身份证/邮箱/订单号四类正则;纯寒暄会话直接剔除
3 抽取去重step3_extract_dedup.py会话 → QA 候选;答不上来的分流成缺口信号连续用户消息合并为一问;SimHash(64bit,阈值≤12)抓字面近拷贝
4 审核入库step4_curate_kb.py锚定校验 + 语义去重 + 缺口优先级答案与制度原文 token 重合率 ≥0.35 才自动入库;同锚点 QA 合并为一条;缺口按 负反馈+转人工 加权排序
5 建索引step5_build_index.py文档块 + 挖掘 QA 双形态统一索引内置 BM25(k1=1.5, b=0.75)+ 中文 bigram 分词;支持命令行即席查询
6 评测step6_eval.pyGolden Set 检索评测命中判定到 文档#章节 级;chunk-only vs 混合索引双跑对照
设计取舍:LLM 不在关键路径上——step4 的同义问法扩写做成可选增强(设 DASHSCOPE_API_KEY 自动启用、调用失败自动降级),保证链路在无网络、无 key 的机器上也能一键跑通。 这也是 qwen-bench 验证过的"mock 可跑、有 key 真跑"模式。

三、环境与数据:脏数据是故意埋的

测试数据不是干净样本,四类"脏"各有埋点,用来验证对应环节真的在干活:

埋点样本考验的环节
PII 泄露手机号 ×2、身份证号 ×1、邮箱 ×1、订单号 ×2step2 脱敏正则
同义重复S001/S010/S019 三通都在问"没拆封能不能退"step3 SimHash + step4 锚点聚合
闲聊噪声S005"在吗/没事发错了"、S015 找机器人讲笑话step2 无效会话过滤
知识缺口货到付款、价保、以旧换新等 5 个文档没写的问题step3 分流 + step4 缺口优先级
目录结构
knowledge-mining-lab/
├── data/
│   ├── raw_docs/            # 4 份制度文档:退款/物流/会员/发票
│   ├── chat_logs.jsonl      # 24 通客服会话(埋入四类脏数据)
│   └── golden_set.jsonl     # 16 条人工标注评测集(标到 文档#章节)
├── km_lab/
│   ├── common.py            # 中文 bigram 分词 + 内置 BM25
│   └── step1..step6         # 六步流水线(见上表)
├── out/                     # 运行产物:chunks/kb/gaps/index/eval_report
└── run_all.py               # 一键跑全链

四、跑通步骤:两条命令

一键全链路
$ cd knowledge-mining-lab
$ python3 run_all.py
[step1] 解析 4 份文档 → 18 个知识块 → out/chunks.jsonl
[step2] 输入 24 通会话 → 有效 22 通,剔除无效 2 通 ['S005', 'S015']
[step2] PII 脱敏命中:{'id_card': 1, 'phone': 2, 'email': 1, 'order_no': 2}
[step3] 抽取 QA 候选 25 条:有效 20 条,缺口信号 5 条
[step4] 锚点聚合去重:合并 6 条同义 QA → 知识条目 14 条
[step4] 知识缺口 5 组(按优先级降序)
  [缺口] P4 可我用掉的积分比扣的多,现在是负的?…
  [缺口] P4 你们支持货到付款吗?…
[step5] 索引构建完成:文档块 18 + 挖掘QA 14 = 32 个检索单元
[step6] 仅文档块索引    :Hit@1=0.938  Hit@3=1.0  MRR@3=0.969
[step6] 文档块+挖掘QA   :Hit@1=1.0    Hit@3=1.0  MRR@3=1.0
✓ 全链路完成,产物见 out/ 目录
即席查询验证索引
$ python3 -m km_lab.step5_build_index "满多少免运费"
  即席查询:满多少免运费
     37.71 [ qa  ] KB-S008                 满多少免运费来着
     13.33 [chunk] membership-policy.md#1  会员等级
     13.15 [chunk] shipping-policy.md#2    配送范围与运费

挖掘出的 QA(真实用户问法"满多少免运费来着")检索分远高于制度原文——这就是会话挖掘的直观价值。

五、实测结果:每个环节的账

环节输入输出验证点
step1 分块4 份 Markdown18 块(71-229 token)全部带 doc/section/heading/version 元数据,无超限块
step2 清洗24 通会话22 通有效4 类 PII 6 处全部脱敏;S005/S015 两通闲聊被正确剔除
step3 抽取22 通会话QA 候选 20 + 缺口 5S006 连续两条用户消息正确合并为一问
step4 入库20 条候选14 条知识条目20/20 通过锚定校验;6 条同义 QA 被锚点聚合合并(含 S001/S010/S019 三胞胎)
step4 缺口5 条信号5 组带优先级负反馈+转人工的"积分负数"排 P4 首位——正确反映业务疼痛
step6 评测16 条 Golden Set混合索引 Hit@1=1.0对照实验拉开差距:chunk-only 在口语查询 G15 上 top1 排错
决定性的一条明细(G15):口语查询「快递好几天没动静了怎么办」——纯文档索引 top1 命中错误章节 refund-policy.md#4(拒收与退款,7.13 分);混合索引 top1 直接命中 KB-S018(挖掘自真实会话"物流5天没动了",15.29 分,归属 shipping-policy.md#3 正确)。 用户的话和文档的话不是一种话,会话挖掘补的就是这个 gap。

六、三个真实踩坑:全部被运行结果暴露,不是纸上推演

#坑暴露方式修复
1 中文语境下正则 \b 失效:Python 里中文也算 \w,"号330102…"处没有词边界 首轮运行 id_card: 0, order_no: 0——身份证和订单号一个都没脱敏 改前后环视 (?<!\d)…(?!\d),命中变为 1/2
2 SimHash 对短文本同义改写无效:只能抓字面近拷贝 三条同义"没拆封能退吗"实测汉明距离 19-31,与随机对(≈32)无法区分,去重 0 条 语义去重改为锚点聚合:同义问题答案必锚到同一制度章节,按 anchor_chunk 合并,成功合并 6 条
3 chunk_id 解析切错分隔符:split(".")[0] 切到 ".md" 的点 挖掘 QA 评测归属全错,混合索引 Hit@1 假性暴跌 1.0 → 0.167(差点得出"挖掘有害"的错误结论) 先按 # 切,再去小数后缀
坑 3 的教训最值钱:评测代码本身也会有 bug。如果当时直接相信 0.167 这个数字, 结论就会是"挖掘 QA 污染索引"——与真相完全相反。指标异常时先怀疑评测链路,再怀疑被评对象 (调研报告 §⑥ 说的"检索生成分开评"之外,还要加一条:评测器自己要先被验证)。

七、核心发现

发现 ①
会话挖掘的增益可测量:混合索引把 Hit@1 从 0.938 提到 1.0、MRR 从 0.969 提到 1.0——增量全部来自口语查询。文档写"物流查询与异常",用户说"没动静了",靠挖掘 QA 建桥。
发现 ②
SimHash ≠ 语义去重:短文本同义改写的汉明距离和随机文本没差别。知识库的正确去重键是"锚定到哪个知识点",不是"文字长得像不像"。
发现 ③
锚定校验(≥0.35 重合率)是自动入库的安全阀:答案锚不上制度原文就进人工复核,防止客服口误被固化。本轮 20/20 通过是因为模拟数据干净,真实数据会大量拦截。
发现 ④
知识缺口清单是免费副产品:转人工/答不上的 5 组问题自动带优先级输出(负反馈 +2、转人工 +1),直接就是下一轮文档建设 backlog。

八、接真实系统要改哪些位置

环节本 Lab 实现生产替换方案
数据源本地 JSONLstep2 的 read_jsonl 换成客服系统会话表/工单 API 拉取;增量按天跑
文档解析Markdown 正则PDF/Word 换 RAGFlow DeepDoc 或云平台解析(报告 §⑤:表格密集文档是重灾区)
检索内置 BM25加向量通道做混合检索(BM25 0.3 + 向量 0.6 + 元数据 0.1),Embedding 用百炼 text-embedding 或 BGE 本地
同义扩写/聚类规则基线 + 可选 qwen-plus设 DASHSCOPE_API_KEY 即启用(代码已写好);QA 生成升级为 LLM 从会话直接抽取+改写
锚定校验token 重合率 ≥0.35升级为 LLM-as-Judge 的 Faithfulness 判定(报告 §⑥ 的 Judge Prompt 模板可直接用)
评测16 条 Golden Set按 50/25/15/10 配比扩到 50-200 条,badcase 每周回填(报告 §⑥)
复现入口:工具在 学习用/knowledge-mining-lab/,python3 run_all.py 一条命令复现本页全部数字; README 里有踩坑详解与逐步说明。

九、生产级升级版:knowledge-mining-pipeline(八项工程化设施全部实测)

教学版跑通之后,同一条业务链路升级为生产级工程 knowledge-mining-pipeline/: 错误码体系(KM-1xxx~5xxx)+ 多环境配置(dev/test/prod 深合并 + 环境变量覆盖)+ 轮转日志(prod 输出 JSON 行)+ 指标采集(p50/p95/吞吐/成功率/重试数)+ 令牌桶限流 + 熔断器 + 指数退避重试 + 隔离区 + 质量门禁 + SQLite 两级断点续传。

容错设施本机验证方式实测结果(2026-07-30)
坏数据隔离数据里埋 3 条脏行(JSON 截断/缺字段/非法 role)全部进 quarantine(KM-2002×1、KM-2003×2),主流程不中断;隔离率 11.1% < 门禁 20%
重试退避dev 环境 mock LLM 注入 35% 故障(超时/429/500)curate_kb 重试 5-6 次全部恢复,成功率 1.0;429 尊重 Retry-After
断点续传--fail-at curate_kb 第 5 条处注入失败 → --resume前 3 步跳过 + 条目级缓存命中 5 条(LLM 不重复调用),补跑后结果与全量一致
指纹失效改评测门禁配置后重跑指纹变化旧断点自动作废,防止"数据换了还用旧产物"
发布线门禁KM__eval__min_hit3=1.01 环境变量覆盖正确失败 [KM-5003],退出码 2,自动打印处置建议
三环境dev / test / prod 各跑一遍全通;prod 文件日志为 JSON 行(采集器友好);业务结果与教学版完全一致
复现:cd knowledge-mining-pipeline && python3 -m venv venv && ./venv/bin/pip install -r requirements.txt && ./venv/bin/python run.py --env dev; 故障演练与错误码手册见工程内 README.md / TROUBLESHOOTING.md。 设计取舍:mock 与真实 LLM 共用同一套重试/限流/熔断代码路径,容错链路在无 key 环境也能被真实演练。