记忆与 RAG
Day 14 - Building a Minimal RAG Demo
今日目标
能实现本地文档加载、切分、检索、带来源引用的最小 RAG 问答 Demo。
学习安排
| 时间 | 模块 | 做什么 |
|---|---|---|
| 0-10 分钟 | 核心概念 | 通读当天术语表,圈出 3 个你最想在工作里用上的概念。 |
| 10-25 分钟 | 阅读输入 | 精读当天章节重点,只抓问题、思路、结论。 |
| 25-45 分钟 | 实践任务 | 动手完成输出模板,必须产出一份可复用产物。 |
| 45-55 分钟 | 追问与反思 | 回答追问练习,标记卡住的概念。 |
| 55-60 分钟 | 复盘与作业 | 整理自检清单,定下明天要复习的一点。 |
核心概念
| 术语 | 中文解释 | 应用场景 |
|---|---|---|
| minimal demo | 最小 Demo:只保留链路必需模块、能跑通闭环的版本,不追求生产级 | 用几个函数实现问答闭环 |
| loader | 文档加载器:读取本地文件(Markdown、TXT 等)并转为文本 | 读取 ./docs 目录下所有 .md 文件 |
| splitter | 切分器:把长文本按固定长度或结构切成小块 | 按 chunk_size=500 切分 |
| retriever | 检索器:根据问题召回相关片段,关键词或向量均可 | 按关键词匹配"Nginx CPU 升高" |
| generator | 生成器:LLM 基于检索片段组织最终答案 | 用 system prompt 约束"只基于片段回答" |
| source citation | 来源引用:答案附带片段出处,让用户能核验 | 每条答案附来源文件名与片段编号 |
| keyword search | 关键词检索:基于字面匹配(BM25 / TF-IDF),快、可解释、零索引成本 | 分词后按词频匹配片段 |
| vector search | 向量检索:基于语义相似度,能匹配同义改写 | 计算查询与片段的向量相似度 |
| chunk_size | 切分块大小:权衡信息完整性与命中精度 | 500 字符时一条片段约够一次回答 |
| production gap | 生产差距:Demo 与生产级的差距,如更新、权限、评估、监控、成本 | 生产环境要权限过滤、增量更新与效果评估 |
阅读重点
- 对应章节:第 3 章中 RAG、知识库相关内容(结合 Day 12 的完整链路)
- 关注点:最小闭环需要哪几个模块:load → split → retrieve → generate → cite
- 关注点:检索结果怎么判断够不够:看 top-k 里有没有真正相关的片段
- 关注点:生成端如何避免编造:约束只基于片段、信息不足就明说
- 关注点:Demo 与生产级的差距:更新、权限、评估、监控、成本
- 补充材料:LangChain 官方文档中 loader 与 text splitter 的用法
- 补充材料:向量数据库(Chroma / FAISS)官方快速入门,跑通一次相似度检索
理解检查
- 最小 RAG 系统必须包含哪些模块?哪个模块可以最后再做?
- 不用向量数据库能不能做 RAG?可以用什么替代?
- 如何判断检索结果是否足够?只看相似度分数够吗?
- 答案生成时如何避免编造?约束手段有哪些?
实践任务
背景:测试团队经常被问"Nginx CPU 升高怎么排查",你要做一个最小知识库问答 Demo,输入本地 Markdown 文档,输出带来源引用的回答。
- 建一个 docs 目录,放入 3 篇 Markdown 排查文档(可复用 Day 12 选的文档)
- 实现 5 个函数:load_markdown_files / split_docs / retrieve / llm_answer / print
- 用示例问题"如何排查 Nginx CPU 升高?"跑通一次完整闭环
- 检查输出:答案是否基于片段、引用是否指向真实来源文件与片段编号
- 保存运行输出,这是 Day 15 设计文档的证据材料
- 提示:retrieve 先用关键词匹配(分词加词频)跑通,向量检索留到调优阶段再换
- 提示:卡住时先打印 chunks 的前 100 字符,确认切分结果合理,再查检索逻辑
docs 目录结构示例:
docs/
nginx-cpu-spike.md
load-test-report-template.md
defect-report-guideline.md
输出模板
docs = load_markdown_files("./docs")
chunks = split_docs(docs, chunk_size=500)
query = "如何排查 Nginx CPU 升高?"
results = retrieve(chunks, query, top_k=5)
answer = llm_answer(query, results)
print(answer)
各函数职责(用你熟悉的语言实现,不限于 Python):
- load_markdown_files(dir):遍历目录,返回 [文件名, 正文] 列表
- split_docs(docs, chunk_size):按固定长度切分,返回带来源编号的片段列表
- retrieve(chunks, query, top_k):关键词或向量检索,返回 top_k 片段与来源
- llm_answer(query, results):把片段拼进 prompt,要求只基于片段回答并附来源
示范输出
问:如何排查 Nginx CPU 升高?
答:根据知识库排查手册,建议按以下顺序排查:
- 确认时间窗口与关联事件,先看是否与流量高峰或 WAF 开关对应。
- 检查 access log 中 5xx 与超时比例的上升。
- 对比 WAF 开启前后的 CPU 曲线与 upstream 响应时间。
- 定位高 CPU 的 worker 进程,抓取调用栈,确认是流量型还是配置型。
- 验证后给出结论,并标记"已验证"与"待验证"项。
来源:
- [nginx-cpu-spike.md #3] 排查步骤与时间窗口确认方法
- [nginx-cpu-spike.md #5] WAF 开关对比方法
- [load-test-report-template.md #2] 压测指标口径说明
追问练习
- 不用向量数据库能不能做 RAG?关键词检索的优劣分别是什么?
- 如何判断检索结果是否足够?top-5 里没有相关片段时你会怎么处理?
- 答案生成时如何避免编造?如果片段之间相互矛盾,生成端应该怎么办?
- Demo 和生产级 RAG 的差距在哪里?列出 4 项并按重要性排序。
常见误区
- 一上来就上重型框架(LangGraph、整套向量平台):链路没跑通先被框架复杂度困住,应该先做最小闭环。
- 检索结果不检查直接给模型生成:top-k 全是噪声时,模型只能靠编。
- 引用只是装饰:引用必须能回溯到真实片段,否则等于没有。
- chunk_size 与 top_k 随手定:先跑通再调参,调参依据是检索效果而不是感觉。
进阶扩展
- 生产差距清单:知识库更新、权限过滤、检索质量评估、监控与成本控制,是 Demo 到生产的主路。
- 混合检索:关键词与向量并行召回,用 RRF 合并结果,专有名词命中率提升明显。
- 检索端评估:用一组标准问题加期望片段构建小 eval set,持续回归检索质量。
今日作业
- 跑通最小 Demo,保存一次完整问答输出(必须含引用)。
- 换一个你真实工作里的问题(如"如何排查接口 P95 升高")再跑一次,对比两次引用质量。
- 写出 Demo 与生产级 RAG 的 4 项差距清单。
- 明天用 Demo 经验输出《知识库问答 Agent 设计 v0.1》。