flag92 flag92
博客
发布于 Wed Apr 15 2026 08:00:00 GMT+0800 (中国标准时间)
实战RAG知识库

知识库准备实战:从 Notion / 飞书 / Confluence 到 RAG 的全流程

知识库做不好,再贵的 LLM 也是浪费。本文给出导出 → 清洗 → 分块 → 入库的可复制流程,附 Python 脚本。

知识库准备的核心矛盾#

源数据(Notion / 飞书 / Confluence / Word)天然不是为 RAG 设计的:

  • 包含目录、TOC、装饰性内容
  • 表格被丢失结构
  • 大量”老旧文档”和”草稿”

直接丢进 RAG 的结果:检索一堆无关内容、回答幻觉、用户骂街。

标准流程#

源系统 → 导出 → 清洗 → 切分 → 增强 → 向量化 → 入库 → 评估

步骤 1:导出#

工具
Notion官方导出 → Markdown
飞书云文档feishu-doc-export 或 API
Confluenceconfluence-markdown-exporter
Word / PDFunstructured

步骤 2:清洗(Python 脚本)#

import re
from pathlib import Path

def clean(text: str) -> str:
    # 去掉 Notion 导出的 emoji 标题前缀
    text = re.sub(r'^[\U0001F300-\U0001FAFF]\s*', '', text, flags=re.MULTILINE)
    # 去掉空白 alt 图片
    text = re.sub(r'!\[\]\([^)]+\)', '', text)
    # 合并多余空行
    text = re.sub(r'\n{3,}', '\n\n', text)
    # 去掉「目录」「TOC」段落
    text = re.sub(r'(?ms)^#+\s*(目录|TOC).*?(?=^#)', '', text)
    return text.strip()

for p in Path('docs/raw').rglob('*.md'):
    out = Path('docs/clean') / p.relative_to('docs/raw')
    out.parent.mkdir(parents=True, exist_ok=True)
    out.write_text(clean(p.read_text()))

步骤 3:切分策略#

不要默认按 500 字硬切,根据文档类型选:

文档类型推荐切分
FAQ / Q&A 对按问答对切,1 问 1 答 = 1 chunk
教程 / 手册按二级标题切,保留上下文
API 文档按 endpoint 切,包含参数 + 示例
政策 / 合同按条款编号切

步骤 4:内容增强#

bge-m3 等模型对问句 Embedding 比对陈述句更稳。把每个 chunk 加一个「这一段在回答什么问题」前缀:

prefix = llm.generate(
    f"用一句话总结这段文本回答了什么问题:\n{chunk}"
)
augmented = f"问题:{prefix}\n答案:{chunk}"

实测能让 MRR@5 提升 3-8 个百分点。

步骤 5:评估#

每次知识库更新后跑一遍评估集:

# eval_set.jsonl 每行:{"question": "...", "expected_chunk_id": "..."}
hits = []
for item in eval_set:
    results = retriever.search(item['question'], top_k=5)
    hit_rank = next((i for i, r in enumerate(results)
                     if r.id == item['expected_chunk_id']), None)
    hits.append(hit_rank)

mrr5 = sum(1/(r+1) for r in hits if r is not None and r < 5) / len(hits)
print(f"MRR@5: {mrr5:.3f}")

低于上次结果 5% 立刻报警,回滚改动。

站内搜索

按 ⌘ K 随时唤起