做完 RAG 技术培训之后的一些想法
最近花了一些时间整理 RAG 相关的内容,也算是把之前零零散散接触过的东西重新过了一遍。
刚开始接触 RAG 的时候,其实觉得这个东西挺简单。
把文档丢进去,切一下,做 Embedding,存到向量库里,用户提问的时候检索一下,再把检索结果交给大模型。
整个流程并不复杂。
真正自己去做、去讲的时候,才发现里面有不少细节。
最开始觉得问题都在模型
以前遇到回答不准确,第一反应比较容易想到模型。
是不是模型能力不够?
是不是 Prompt 写得不好?
是不是换个模型就好了?
但把 RAG 的整个流程拆开之后,会发现很多问题其实和模型没什么关系。
比如一个很简单的问题:
知识库里明明有这条内容,为什么就是没搜出来?
这个问题继续往下查,可能发现是文档解析的问题,也可能是 Chunk 切得不合适,也可能是用户的问题和原文表达差异比较大,甚至可能是本来应该做关键词匹配,却只做了向量检索。
最后到了大模型这里,已经没有多少发挥空间了。
它拿到的内容都不对,你让它怎么回答?
所以现在再看到”RAG 幻觉”这个词,我不会第一时间把问题归到大模型身上。
很多时候,应该先看看:
到底给模型了什么。
文档处理可能是最容易被低估的一部分
做 Demo 的时候,文档上传进去就结束了。
真正做知识库的时候就不是这么回事了。
一个实际的业务文档可能是 PDF、Word、Excel,也可能是扫描件。
里面有标题、正文、表格、图片、页眉页脚,还有各种格式问题。
有些文档看起来人读起来完全没问题,但机器解析出来以后,顺序可能已经乱了。
尤其是表格。
人看表格的时候很容易知道哪一列对应哪一行,但文本解析出来以后,可能就是一堆没有关系的文字。
这时候再好的 Embedding 也解决不了。
所以后来我越来越觉得,RAG 前面的”数据处理”其实非常重要。
以前做后端的时候经常说一句话:
数据库设计得不好,后面业务再怎么写都难受。
RAG 其实也差不多。
只是以前处理的是结构化数据,现在处理的是文档和知识。
Chunk 也不是随便切
Chunk 是我觉得比较有意思的一个地方。
很多教程里都会给一个固定参数,比如多少 Token 一个 Chunk,Overlap 设置多少。
这样当然可以快速把 Demo 跑起来。
但实际使用的时候,很难找到一个万能的数字。
比如一段设备故障处理文档:
1 | 故障现象 |
如果刚好按照固定长度切开,很可能把”故障原因”和”处理方法”拆开。
单独检索的时候,每一块都看起来挺像回事,但真正回答问题的时候,信息是不完整的。
所以 Chunk 对我来说,后来不再只是一个”切多长”的参数。
更重要的是:
这一段内容本身是不是一个完整的知识单元?
这个问题可能比 500 Token 还是 800 Token 更重要。
Dify 给我的感觉还是很明显的
这次整理过程中也重新看了一些 Dify 的东西。
Dify 最大的价值,我觉得还是让很多 AI 应用可以非常快地跑起来。
以前如果想验证一个想法,可能需要自己写不少代码。
现在知识库、模型、Workflow、Agent 等东西组合起来,很快就可以做一个可以实际体验的版本。
对于验证思路来说,这非常方便。
但做到后面也会发现,有些东西最终还是需要回到代码。
比如业务系统的数据查询、自己的接口、特殊的检索逻辑、一些复杂的 Tool。
这也是我后来比较关注 LangChain 这类框架的原因。
不是说用了 Dify 就不用代码了。
更像是:
简单的东西先快速验证,复杂的东西再往代码里沉。
我觉得这种方式比较适合实际项目。
培训过程中,最大的收获反而不是 RAG
如果只是让我说这次学会了什么,其实挺容易列:
Embedding、向量数据库、Rerank、Dify、LangChain……
这些东西都可以记下来。
但真正让我比较有感觉的是,原来做 AI 应用和以前做业务系统,在很多地方其实是相通的。
以前做系统,我会比较关注:
数据库怎么设计、接口怎么拆、缓存怎么做、MQ 怎么用、性能怎么样、出了问题怎么排查。
现在做 RAG,换了一批名词,但很多思路还是一样。
出了问题,不应该直接去猜。
还是应该把链路拆开:
1 | 用户问题 |
到底是哪一步出了问题,应该能找到。
这可能也是我现在比较喜欢 AI 工程化的原因。
它不是完全换了一套东西。
更多的是在原来的软件工程基础上,又增加了一些新的东西。
从 Demo 到真正能用,中间还有很长一段距离
现在很多 AI Demo 做起来其实很快。
一个下午,可能就能把一个 RAG 问答系统跑起来。
但真正放到业务里面,问题就开始多了。
知识库多久更新一次?
旧文档怎么处理?
检索不到怎么办?
用户的问题本身不明确怎么办?
知识库里没有答案的时候,是不是应该直接说不知道?
回答能不能追溯到原始文档?
出了错误之后,怎么知道到底是检索错了还是模型答错了?
这些问题,可能比”怎么调用大模型 API”更值得花时间研究。
所以我现在对 RAG 的理解,已经和最开始有一些区别了。
它不是简单地:
给大模型接一个知识库。
而是要解决一个更实际的问题:
怎么让模型在需要的时候,找到正确的信息,并且尽可能基于这些信息回答。
至于最终能不能真的解决业务问题,还需要继续往下做。
这次培训算是一个阶段性的整理。
以前很多东西是”用过”,这次则是重新把它们串了一遍。
我觉得技术学习有时候就是这样。
真正把一个东西讲给别人听的时候,才会发现自己原来还有很多地方没有想明白。
所以这篇也不算什么 RAG 教程。
只是记录一下,从开始接触,到真正动手做了一段时间之后,对这个东西的一些变化。
后面如果继续做 RAG 相关项目,应该还会碰到更多实际问题。
到时候再继续记录。
