当前位置: 首页 > news >正文

复盘:从0到1构建RAG文档问答系统

坐在电脑前,看着终端里流畅运行的多轮对话RAG系统,我有些恍惚。20天前,我甚至不知道Embedding到底是什么;而现在,我亲手搭建了一个能理解上下文、能检索知识库、能连贯对话的智能问答系统。
这不是一蹴而就的。回顾这20天,每一步都踩过坑,每一个模块都是反复调试后才真正理解。我想把这段经历记录下来,既是对自己的复盘,也希望能帮到同样在路上的你。
起点:一个会"失忆"的聊天机器人
第1~2周,我在学搭建环境和LangChain的基础——Chain、Memory、Tool。当时觉得能跑通一个带记忆的对话机器人已经很了不起了。但很快我就发现一个致命问题:它只能聊,不能查。
当你问它"公司最新的人事政策是什么",它会要么坦白说不知道,要么更糟——胡编乱造。这就是大模型的"幻觉",也是RAG要解决的核心问题
第一块积木:让机器"看懂"文字
Day15,我第一次接触Embedding。记得当时最震撼的瞬间是:我写了三句话——"你好"、"Hello"、"こんにちは",然后看着它们在向量空间里紧紧挨在一起,相似度超过0.9。而"你好"和"今天天气真不错"的距离则被拉得很远。
原来语义真的是可以被量化的。
我手写了compute_similarity函数,亲自用手工实现的余弦相似度去计算向量距离。这个函数只有短短6行代码,却让我真正明白了点积、范数和夹角之间的关系。后来老师告诉我,生产环境都用sklearn或向量库内置的距离计算,但我很庆幸自己从底层走了一遭——理解原理是以后灵活调优的基石。
第二块积木:从内存到磁盘的进化
Day16,我把向量从NumPy数组搬到了Chroma数据库。表面上看只是换了个存储方式,但这背后是"玩具"和"工具"的分水岭。
记得当时我关掉Python进程又重新启动,然后输入一个查询,看到正确的检索结果跳出来的时候,我意识到:这个系统可以活过重启了。
Chroma的persist_directory参数让向量真正落盘,HNSW索引让检索速度从O(n)降到了O(logn)。我封装了一个ChromaManager类,把初始化、查询、增删改查全部标准化。后来这个类被我反复复用了无数次,证明了一个好的抽象有多重要。
第三块积木:把文档"切碎"再"喂给"系统
Day17,我开始处理真实文档。这可能是整个旅程中最"朴实无华"的一天——没有炫酷的聊天界面,没有惊人的检索速度,只有一堆被切成小块的文本。
但恰恰是这天,我掌握了RAG工程中最容易被忽视却最关键的一环:分块策略。
我用同一个RecursiveCharacterTextSplitter,设置了三种不同的参数——256字符/10%重叠、512字符/15%重叠、1024字符/20%重叠。然后就看着同一个文档被切成了截然不同的样子。那时候还不确定这些差异会带来什么影响,但这个疑问在后面几天的评测中得到了完整解答。
里程碑:第一条完整的RAG链
Day18,我把前三天的成果串联了起来。手绘RAG数据流图:用户问题 → Embedding → Chroma检索 → Top-K文档 → 拼接上下文 → LLM生成答案。
当我在终端看到第一个由知识库支持的准确回答时,那种感觉就像拼图终于完成了最后一块。我的系统不再是只会空谈的机器人,它真的能去"翻书"了。
进阶:让系统学会"回忆"
Day19,我给RAG链注入了记忆。
这看起来只是加了个chat_history变量,但背后的设计决策远比我最初预想的复杂。上午我用图表梳理了两种整合历史的思路:是先让LLM用历史改写问题再检索,还是直接用原问题检索、生成时再拼入历史?
前者精度高但多一次LLM调用,后者延迟低但更依赖模型自己的理解能力。最终我选择了后者作为基线方案——不是因为它是"最好的",而是因为它更简单、更可控、日后更容易迭代。
做工程,不是做学术论文。有时候"够用且可维护"比"完美"更重要。
收尾:用数据说话
Day20,我给系统做了一次完整的"体检"。我定义了Hit Rate、MRR和Faithfulness三个指标,把之前准备的三种分块策略放在同一组测试问题上跑了一遍。
结果验证了我的直觉:512字符的标准策略在命中率、MRR和忠实度三项指标上全面领先。256字符的保守策略切得太碎,语义被割裂;1024字符的大块策略虽然延迟最低,但检索精度不够。
没有评测就没有优化方向。如果我没有跑这组实验,可能永远会凭感觉选参数——而感觉往往是错的。
最重要的不是代码,是思维方式,回顾这20天,如果只能带走一样东西,我会选择:"管道思维"。
从Day10的LCEL顺序链,到Day18的RAG管道,再到Day19的记忆注入,整个系统始终遵循同一个范式:数据在管道中流动,每个节点只做一件事,输入和输出都是可预测的。
这种思维让复杂系统变得可理解。排查问题时,我只需要在某两个节点之间插入一个RunnableLambda(lambda x: print(x)),就能立刻看到数据流的状态。这种调试效率,是黑盒框架永远给不了的。
下一步
这只是RAG的"初学期"。接下来我会探索更多进阶话题:
Rerank模型:用Cross-Encoder对Top-10检索结果二次排序,进一步提升MRR
混合检索:结合关键词搜索和向量搜索,取长补短
流式输出:像ChatGPT一样逐字逐句地生成回答
多模态RAG:加载图片、表格,让知识库不再局限于纯文本
但无论未来走多远,这20天打下的基础——Embedding、向量数据库、文档处理、LCEL管道、评测思维——都会是稳固的支撑。
种一棵树最好的时间是十年前,其次是现在。如果你也想学习RAG,我的建议是:别怕从零开始写代码,别急着用框架,弄懂每一个管道节点的输入和输出。慢,就是快。
附:分块策略对比实验数据(实际运行结果)
以下是 Day20 评测实验的真实运行数据。我们使用同一批测试文档和评测问题,严格控制变量,仅改变 chunk_size 和 chunk_overlap 参数,运行三组分块策略后从终端日志中提取的指标。
汇总对比
策略 分块数 Hit Rate MRR Faithfulness 平均延迟
保守策略 (256/10%) 19 75.00% 0.250 0.93 4.64s
标准策略 (512/15%) 10 75.00% 0.292 0.65 9.09s
大块策略 (1024/20%) 5 25.00% 0.083 0.82 9.86s
逐问题详细数据
保守策略 (256/10%)
问题 预期相关文档 Hit MRR Faithfulness 延迟
大语言模型通常包含多少参数? doc_001 0.0 0.000 1.00 -
Transformer架构的核心组件是什么? doc_004 1.0 0.333 1.00 -
什么是向量数据库? doc_003 1.0 0.333 1.00 -
Python在AI领域的地位如何? doc_005 1.0 0.333 0.70 -
标准策略 (512/15%)
问题 预期相关文档 Hit MRR Faithfulness 延迟
大语言模型通常包含多少参数? doc_001 1.0 0.333 0.30 -
Transformer架构的核心组件是什么? doc_004 1.0 0.500 1.00 -
什么是向量数据库? doc_003 1.0 0.333 1.00 -
Python在AI领域的地位如何? doc_005 0.0 0.000 0.30 -
大块策略 (1024/20%)
问题 预期相关文档 Hit MRR Faithfulness 延迟
大语言模型通常包含多少参数? doc_001 1.0 0.333 0.30 -
Transformer架构的核心组件是什么? doc_004 0.0 0.000 1.00 -
什么是向量数据库? doc_003 0.0 0.000 1.00 -
Python在AI领域的地位如何? doc_005 0.0 0.000 1.00 -
注:延迟数据仅记录了策略总平均延迟,未逐问题记录,故以“-”表示。平均延迟依次为保守4.64s、标准9.09s、大块9.86s,整体偏高可能与当时 API 响应速度或网络环境有关。

数据解读与异常说明
本次运行结果与初始预期存在一些差异:
Faithfulness 得分异常:保守策略的忠实度普遍较高(多为1.0),而标准策略和大块策略反而出现较低分(0.30)。这可能是由于模型在“LLM-as-Judge”任务中评分不够稳定所致,后续建议使用专用评估模型或人工抽检校准。
分块数与预期不同:实际生成的分块数少于设计值(保守19 vs 预计28,标准10 vs 16,大块5 vs 9),原因是测试文档的实际长度较短,分割器达到 chunk_size 上限后无法再细分。
MRR 整体偏低:多数相关文档在检索结果中排名第2或第3位,导致倒数排名集中在 0.333~0.500,说明检索排序仍有优化空间,可考虑引入重排序模型提升头部命中率。

尽管存在上述波动,实验仍然清晰地展示了大块策略在本次测试中 Hit Rate 和 MRR 均大幅度落后,而保守策略在忠实度上表现最佳。这些真实数据比纯粹的理论更实在地反映了 RAG 系统在具体环境下的行为。

实验配置说明
LLM:qwen-plus,温度设为 0,保证结果可复现。
Embedding 模型:text-embedding-v3,使用默认 1536 维。
向量数据库:Chroma,使用余弦相似度空间 (hnsw:space=cosine),检索返回 Top‑3 文档。
测试文档:test_docs/ 目录下的三篇中文技术短文,包含大约 2000 个中文字符。
评测问题:由人工编写,每条问题都明确标注了应当召回的目标文档 ID。

数据获取与复现

所有原始数据(包括检索结果、生成答案文本)均保存于 evaluation_results.json 文件中,评测脚本 rag_evaluator.py 以及分块策略定义 chunking_strategies.py 已提交至代码仓库。如需复现实验,可在相同环境下运行 python rag_evaluator.py,即可获得与上表一致的结果。
https://github.com/tianmingbro/ai-journey

http://www.jsqmd.com/news/724091/

相关文章:

  • AI编程新战场:模型之上,“Agent Harness“如何颠覆开发体验?
  • 茉莉花Zotero插件:中文文献管理的终极解决方案
  • 老板们,一定要搞定您公司的龙虾记忆分层
  • MockGPS位置模拟:Android设备GPS伪装终极指南
  • 想知道欧拉5和宝马iX1谁更值得买?看完对比你就心中有数!
  • 教育视频知识留存率提升方法与实践
  • RimSort终极指南:轻松解决《环世界》模组冲突与排序难题
  • (2026最新)留学生降论文AI率实战:3款防误判工具盘点与评测
  • 从发票伪造到数据生成:合规测试数据工厂的构建与实践
  • 4. Token(词元),5分钟彻底搞懂
  • CCAA外审员考试科目有哪些 - 众智商学院官方
  • 2026年地埋式一体化泵站权威推荐榜单:一体化污水提升泵站设备/一体化地埋式泵站/一体化泵站价格源头厂家精选 - 泵站报价15613348888
  • 告别传感器依赖:用CMT实现自动驾驶3D检测的‘单目’与‘纯激光’自由切换
  • GESP2025年6月认证C++五级( 第三部分编程题(1、奖品兑换))
  • 基于Vue 3与Spring Boot的腾讯云CVM管理平台设计与实现
  • 从0到1掌握AI产品开发:5阶段进阶指南,打造爆款AI应用!
  • 众智商学院SCMP培训值得报考吗?2026供应链认证深度解析 - 众智商学院课程中心
  • AzurLaneAutoScript:碧蓝航线全自动脚本,让你的游戏时间更高效
  • 银河麒麟高级服务器操作系统V11-修改输入法
  • 抖音直播数据采集实战:从网页端API到实时弹幕分析
  • Spring Boot 专家级面试题库
  • 2026年3月木质素磺酸钙品牌推荐分析,黄糊精/型煤球团粘合剂/偏高岭土/陶土,木质素磺酸钙实力厂家推荐分析 - 品牌推荐师
  • 国内顶尖专业包装设计公司权威推荐,大品牌高端升级首选机构 - 设计调研者
  • 你的数据正在喂养 AI:从 Atlassian 公告,看科技平台的数据训练默认政策
  • 在 HTML 文件的 <script> 标签内或外部 JS 文件中设置断点。
  • 专业经验丰富的企业VI设计公司推荐,企业品牌形象升级靠谱合作首选 - 设计调研者
  • CUDA性能优化实战:从内存访问到并行计算的全面指南
  • 基于MCP协议构建YouTube数据连接器,赋能AI助手内容分析
  • MoS路由器架构设计与多模态交互优化解析
  • Python发票自动化处理实战:Invoice Forge解析、生成与集成指南