https://www.bilibili.com/video/BV19RJhzyEWN
此刻你正盯着一个悲催的那部文档,敲着一份更加悲催的程序,不出所料,很快就遇到了问题,你问问大模型,结果他从来没见过你这份文档,他就开始一本正经胡说八道,回答却跟你的问题没有半毛钱关系,这种情况就叫做大模型的幻觉,但你是个聪明的程序员,于是很快就想到了解决办法,把文档和问题一起发给模型,这次AI就给出了正确的回答,问题似乎解决了,但很快就又出现了新的问题,你的文档变得越来越大,而答案可能只藏在文档的一小段话里,甚至是零散的只言片语。
AI看到整份文档反而找不到重点,总之信息多模型也容易跑偏明的,你马上就想到那我能不能不把整个文档都发过去,发那些和问题真正相关的部分呢?
当然可以了,这个就是 RAG(Retrieval Augmented Generation)
想要解决的问题。怎么判断文字和用户的问题有没有关系呢?
我们需要一种新的模型叫做Embedding模型。Embedding模型的输入也是一段文字,但和大语言模型不同它的输出是一个固定长度的数字比如说 OpenAI 的 text-embedding-3-small 模型输出的就是一个1536位的数组。而 text-embedding-3-large 模型输出的是3072位的数组,这个时候无论你输入的是一整句话还是一整段话模型输出的数组长度都是固定的,你可以把这个数组理解成原始内容的有损压缩信息被浓缩了,但是意思却还在似的内容压缩出来的结果也会离得很近,所以我们就能通过这些数组之间的距离来判断两段文字是否相关。
为了方便说明我们来画一个为数和数字长度一样的坐标系,老王好像不会画1536位的坐标系,那么假设我们用了一个特别挫的id模型输出的数组只包含了两个数字,于是我们就能画出一个二维的坐标系就在这个坐标系里面占了一个点,尽量让意思接近的文字也就越靠近,比如说老王爱吃瓜和老王喜欢吃瓜意思差不多,那么他们的位置就会离得特别的近,我也爱Python这种就会稍微远一点,而刚买的飞机被打了就会坠落到非常非常远的地方。
当然了,二维坐标系,其实根本没办法,准确表示所有的距离关系,这张图很快就会被各种句子塞得满满当当的,完全没法用,所以在现实中引领模型,真正的向量空间是1000多位,甚至是3000多位坐标系在这么高的空间里面,句子之间的距离关系就能表达的更加准确,有了这个向量空间,接下来假如用户想问一个问题,比如说老王爱吃什么,我们就可以把这个问题交给同一个Embedding模型处理一下,他也会被映射成坐标系中的一个点Embedding模型会让老王爱吃什么这样的问题贴近向老王爱吃瓜,老王喜欢吃瓜这样的语义片段,于是程序就可以计算每个已有点和这个问题点之间的距离了,然后筛选出距离最近的那几段文字当作上下文和用户的问题,一起发给AI模型模型,看到的就全是问题相关的内容了,产生幻觉的风险也就小了很多,这个架构就是RAG。
我们再回到之前的老问题文档太长了怎么办?我们可以在用户提问之前先把这个文档处理一遍要怎么处理呢?第一步把整个文档切成很多的小片段骗的方法有很多种,比如说按四数来切按段落来切句子来切,当然还有一些更复杂的缺乏这个过程,有一个专有名词听上去非常高级,叫做
Chungking
其实就是切块的意思。
之后,接下来我们要做的事,每一小段文字都做Embedding,把它们变成长度一致的数组或者专业一点叫做向量,但光有这些向量还是不够的,我们还要把每个项量和原始文本片段的对应关系保存起来,一般来说保存数据我们会有数据库,但数据库擅长的是根据明确的数值来查找记录,并且这些数值也并不是向量,但现在我们想查的并不是等于多少这种精确值,而是哪个向量离我们的问题对应的向量最近这就不是传统数据库可以干的事情了,就有一个专门为这类场景设计的东西叫做
向量数据库数据库
里面。
向量数据库每条数据都可以有一个与之相关联的向量查询的时候,我们输入一个向量数据库就会找到和输入的向量距离最近的那几条数据,这种特性正好适合我们用来存储
Embedding的结果,结果常见的向量数据库有
pinecone
、chromaDB
、PostgreSQL+pgvector插件
这类组合方式等等,这样我们就完成了文档的切片编码和存储的工作,所有的片段和他们对应的
Embedding 已经准备好等待被检索了,但用户提出问题的时候,我们用同样的
Embedding
模型把问题也转化成向量,然后再从向量数据库里面挑出距离,最近的极段内容再把它们和用户问题一起发给AI模型完整的RAG架构到这里拼好了。
但是本身其实并不是一个非常完美的架构,他有一些先天的缺陷,首先是文章应该怎么分块的问题因为每篇文章的结构顺序都是不一样的,无论你是按照句子按段落还是更复杂的算法复杂了,都没有办法适配所有的场景,文章里面有一些关键内容,有时候会刚好被截段,比如说我是程序员老王,我爱吃瓜在这里后面的我其实指的是老王,但是如果这段话被拆成两部分,那么后面的我也就失去了和老王的纸带关系,这个时候如果有女生问老王喜欢吃什么,那这个问题和我爱吃瓜之间的向量距离就可能变远再杂的分块策略也只能尽量减少这种误伤,没有办法彻底的避免二个问题是缺乏一个全局的视角,比如用户问这篇文章里面一共出现了多少个字?这个问题其实和文章里面的每一句话都有关系,但是都不够相关,这种没有哪句特别相关,但整体都占点边的问题,RAG基本上是处理不了的,为了弥补这些缺陷,现在也出现了很多改进的方案,比如在预处理的时候把我统一都换成老王或者干脆就让大模型参与到方块的过程,根据雨衣自动判断应该在哪里断应该怎么切,但是目前来说还没有哪个方案是真正的十全十美的新的想法还在不断地涌现中这里我就不展开奖了。
不过说到底RAG就是这么一种结构,我觉得他更像是一种妥协,在大模型上下文有限的情况,下面我们用这种种方式尽量让模型的回答别太离谱,他能解决一部分的问题,但也确实还有很多问题,没有办法解决,所以我也一直在等那个真正意义上突破了妥协的下一代架构筛选所引把重要的留下不重要的东西我就可以丢掉了,其实我每天的生活也是这样的,每天我们面对了太多的人太多的事情也就慢慢学会了分类和取舍,这个要紧那个可以晚一点,这个需要记住那些事情,也许就可以忘记了,我们这是成熟清醒,但有的时候东西难免会失去上下文误解的原意一些原本重要的东西,也许就失去了链接同桌或者他最后条消息还停留在哈哈哈的死党,要了我们各自生活的坐标越来越远了,前几天偶然翻到一张以前一起打游戏的截图,我盯着他们看了好久,突然间发现那个时候他的DPS(Damage Per Second)是真的呀。