📚 知识库构建
数据采集 · 清洗 · 分块(Chunking)· 元数据设计——知识库质量的 80% 在这里
1. 知识库的数据从哪里来?怎么采集?
常见数据源(以学校为例):
- 官网/网页:校史介绍、师资队伍页面 → 爬虫/直接导出 HTML → Markdown
- 文档:PDF(宣传册、招生简章)、Word(规章制度)、PPT → 解析工具抽取文本
- 结构化数据:数据库表(教师信息、课程表)→ 导出为表格/JSON(问答时走精确查询)
- FAQ 手册:现成的问答对 → 直接作为"问答对"入库(命中率最高)
- 视频/音频:讲座、访谈 → 先转写(ASR)再入库
采集工具速查
网页 → markdown:markitdown / trafilatura / Jina Reader (r.jina.ai)
PDF:PyMuPDF(fitz)提取文本 / pdfplumber(表格)
Word:python-docx
批量:LangChain 的文档加载器(Document Loaders)
🎯 面试要点
- 采集原则:来源权威、版本可控——建库前先定"哪些文档为准"(如以官网发布页为唯一事实源)
- FAQ 对是性价比最高的数据:问答式命中远比长文档检索准
2. 数据清洗要做什么?
- 去噪:页眉页脚、导航栏、水印、乱码、表格串行——这些会污染检索和生成
- 去重:同一内容多版本(旧版招生简章)→ 只保留最新;近似重复去重
- 结构整理:保留标题层级(h1/h2/h3)、表格转成易读文本(Markdown 表格)
- 敏感/隐私过滤:身份证、电话等脱敏;涉密内容剔除(入库前必须过)
- 质量门禁:过短的碎片(广告语)、纯乱码段落丢弃
🎯 面试要点
- "垃圾进,垃圾出":清洗质量直接决定检索质量和幻觉率
- 清洗产物格式建议:带标题层级的 Markdown——后续分块和检索都受益
3. 文本分块(Chunking)策略?块多大合适?
为什么分块:LLM 上下文有限,且整篇文档向量化后"语义太糊"——检索要的是小而准的片段。
三种策略:
- 固定大小 + 重叠:每 500 字符一块、重叠 50 字符(防切断语义)。简单通用
- 按结构切(推荐):按标题层级切——每个二级标题下一块。语义完整、引用定位准("出自《校史》第三章")
- 语义切分:按句子嵌入相似度断点切分。质量最高,成本最高
块大小权衡:块太小 → 语义不全(答不出上下文);块太大 → 向量模糊(检索不准)+ 塞爆提示词。经验值:200~800 字符(中文),按文档类型调。
按标题分块示例(伪代码)
def chunk_by_headings(md_text):
chunks = []
for heading, body in parse_headings(md_text): # 遍历标题层级
chunk = {
"content": heading + "\n" + body, # 标题带进块内容
"metadata": { # 元数据(见下节)
"source": "school-history.md",
"section": heading,
"updated": "2026-08-01",
},
}
chunks.append(chunk)
return chunks
🎯 面试要点
- 分块是最容易被忽视的质量杠杆:先按结构切,不行再调大小
- 题目类/表格类内容要特殊处理(表格单独成块、问答对整对成块)
4. 元数据(Metadata)有什么用?
- 过滤检索:按分类过滤("只搜校史类")、按时间过滤("只查 2026 年招生")——检索前先过滤,精度大增
- 引用溯源:回答附"来源:校史馆资料-第 2 章",来源信息就是元数据
- 排序加权:权威来源(官网)权重高于转载
- 管理维护:知道哪些块过期了、归属哪个文档、版本号
推荐元数据字段
source: 文档来源(文件名/URL)
title: 文档标题
category: 分类(校史/学风/师资/招生/制度)
section: 所属章节/标题
updated_at: 更新时间
author: 编写人(可选)
version: 版本号(可选)
🎯 面试要点
- 元数据 = 检索的"索引条件"和回答的"证据链"——建库时就要设计好
- 常见错误:只存 content 不存元数据,后期引用和过滤都做不了