你是否曾对 AI 给出的答案产生过怀疑?RAG 可能就是解决这个问题的关键。
RAG ,对于技术人员肯定已经不陌生,但是对于普通人来说可能还是个模糊的词汇。
关于 RAG,在我们使用 AI 的过程中随处可见。
不管我们在 Kimi、ChatGPT、Claude 提供文件或网页来提问,还是使用 Coze、Dify 这类平台构建 AI 客服、法律助手、或者其他利用知识库的智能体,本质上都涉及到 RAG 技术。
昨天,Claude 发布了一篇 RAG 优化方案——“Contextual Retrieval” 。在群里简单分享后,发现很多小伙伴都很感兴趣。
如果你还不太了解,让我们一起来回顾一下:
Contextual Retrieval 的优势是什么?
一、为什么需要 RAG? 分享前,我们先聚焦于当用户询问一个问题:我想知道“八宝茶是哪个少数民族的传统饮品”。
恰好这个问题涉及的领域较为冷门。
一般情况下,我们会直接向 AI 提问。如果大模型没有这方面的知识,那么可能会产生“幻觉”,也就是瞎编。
正确答案其实是 “回族”。
后来,我们了解到可以通过提示词编写的策略:提供参考文本 。我们可以将一段引用内容和原始的问题组合来提问。
提示词:
八宝茶是哪个少数民族的传统饮品,请根据这段文字进行回答"""xxxxxxxxx""",如果找不到答案,则回复“不知道”。这种方式存在两个问题。
第一,如果这段引用的内容过长,超出大模型的上下文限制,便得不到正确答案。
例如,大模型上下文限制为 8 千字,而给出了 1 万字,且答案恰好位于最开始的 2000 字左右内,那么很可能会错过正确答案。
第二,如果我们提供的文字内容不够全面或质量较低,那么即使得到答案,也极有可能不全面或完全不正确。
如何解决这些问题呢?
由此,RAG 便诞生了。我们先来一张 Claude 生成的图片,针对刚才的技术演化过程,看看 RAG 的优势。
什么是 RAG 呢?
简而言之,它是一种通过从外部知识库检索相关信息来辅助大语言模型生成更准确、更丰富的文本内容的技术。
RAG 全称 Retrieval-augmented Generation, 中文叫做:检索增强生成。
1、检索 :检索是 RAG 流程的第一步,从提前构建好的知识库中找出和问题有关的信息。这一步是为后面的生成环节提供背景信息和知识支持。
2、增强 :增强是把检索到的信息作为大模型的上下文输入,以此提升模型对特定问题的理解和回答能力。通过增强这一步,大模型可以充分运用外部知识库中的特殊信息。
3、生成 :生成是 RAG 流程的最后一步。这一步会利用检索到的内容作为上下文,再最终组合后的提示词指引 LLM 生成符合用户需求的回答。
最终,我们理解这个术词的完整含义:RAG 通过检索 外部信息来增强 大模型的提示词,从而生成 更准确的答案。
那么,RAG 是怎么工作的呢?
我们来看下 Claude 最新优化方案中提及的常规 RAG 是如何工作的。下面我来进行通俗解释。
第一步 :如果是文件,系统会运用一些识别工具提取文字内容。如果是网页,系统则会利用爬虫技术获取网页数据。
备注:网页上用户是直接提供文件。智能体平台,用户会提前上传文件。
第二步 :系统会根据长度设定把每份提供的内容分成一段一段的文本块,术语叫 Chunk。然后,利用向量模型将这些 Chunks 存储到向量数据库中。
图中还提到另一项技术,叫做 TF-IDF 。通过这项技术,可以为这些块创建 TF-IDF 编码 ,从而在检索信息时提供双重保障。
TF-IDF 是通过计算词在文档中的出现次数(TF)以及在整个文档集合中的普遍重要性(IDF),来确定哪些词对特定文档比较重要。这样,它可用于提取文档关键信息。
第三步 :当用户提出问题“八宝茶是哪个少数民族的传统饮品”时,系统会在向量库中依据 TF-IDF 的索引定位到与这个问题相关的 chunks。
第四步 :按照一定规则给这些 chunks 排名。
为什么要排名呢?
因为可能有很多 Chunk 都与“八宝茶是哪个少数民族的传统饮品” 这个问题有关的内容。
但是,不能将所有 Chunk 作为上下文去问大模型,这样内容太多太杂,不但会影响回答质量,还极有可能超出大模型的上下文限制。
排名后,获取最接近问题的一个或多个 Chunk。至于具体是几个,得看系统设定和用户的配置。
最后一步 :将获取后的 chunk 作为上下文,结合用户最初的问题,拼接成提示词,让大模型分析并从中获取答案。
提示词类似这样(取自 FastGPT 的提示词):
忘记你已有的知识,仅使用{{knowledge}}中的内容作为你的知识,回答用户的问题{{question}}: 思考流程: 1. 判断问题{{question}}是否与{{knowledge}}标记中的内容有关。 2. 如果有关,你按下面的要求回答。 3. 如果无关,你直接拒绝回答本次问题。 回答要求: - 保持答案与中描述的一致。 - 使用 Markdown 语法优化回答格式。 - 使用与问题{{question}}相同的语言回答。{{knowledge}} 就是最重要的几个 Chunk 组合后的内容。
这时候,根据这段提示词,大模型就可以更准确地回答我们。
当然,这也并非完美,在特殊情况下,会存在一些明显问题。我们参考 Claude 官方提供的一个例子来说明。
比如,我们的问题是“八宝茶是哪个少数民族的传统饮品?”,正确答案是“回族”。
但某个 Chunk 中正好有一段类似文字,是用来介绍蒙古族马奶茶的:“该茶是蒙古族的传统饮品”,这里有个指代词“该”,若不处理,基于这个 chunk,答案就不对了。
二、Contextual Retrieval 的优势是什么? Claude 最新发布的 “Contextual Retrieval” 到底如何解决这个问题呢?
这个方法的核心是利用整个文档作为上下文,借助提示词对这个 Chunk 做简洁概述,并在向量化之前,将这段解释放在 Chunk 的开头,作为其中的一部分。
另外一点优化是:这个方法在交给大模型之前,多做了一步排名,叫 Reranker,这样可以进一步找到更接近用户问题的 Chunk。
那它是借助什么提示词来给每个 Chunk 做简述的呢?
原始版本:
<document> {{WHOLE_DOCUMENT}} </document> Here is the chunk we want to situate within the whole document <chunk> {{CHUNK_CONTENT}} </chunk> Please give a short succinct context to situate this chunk within the overall document for the purposes of improving search retrieval of the chunk. Answer only with the succinct context and nothing else.中文版本:
<document> {{WHOLE_DOCUMENT}} </document> 这是我们想要放在整个文档中的块。 <chunk> {{CHUNK_CONTENT}} </chunk> 请提供一个简短而简洁的上下文,以便在整个文档中定位此块,以提高块的搜索检索效果。仅用简洁的上下文回答,不要有其他内容。那我们再回到刚才的小故事里。
针对原先这个 Chunk:该茶是蒙古族的传统饮品就会被处理成这样:这段内容来自蒙古族马奶茶的介绍文件;该茶是蒙古族的传统饮品。
通过这种处理,系统能够更准确地筛选信息,从而提升了答案的精确度。
三、总结 总结一下,这只是 Claude 建议的一种 RAG 优化策略,主要包括内容切分方式以及结果重排的优化。
文章地址 :https://www.anthropic.com/news/contextual-retrieval
方案代码地址 :https://github.com/anthropics/anthropic-cookbook/tree/main/skills/contextual-embeddings
但是,优化 RAG 不止于此。在前面我们提到的很多步骤中都存在优化空间。
比如,文件内容提取的准确度 、网页爬虫的准确度 以及 数据清洗的策略 (去除内容中的杂质)。
关于内容提取,如果内容提取不准确,后面的努力都是白费。
我在之前的实践过程中针对内容提取遇到过很多问题。
例如,PDF 有很多复杂的格式,比如扫描件、手写件。PDF 内容又会涉及到复杂的表格、数学公式和图片等等。
以下是之前做的一次方案调研:
免费AI神器!精准解析 PDF 还能一键翻译!
备注:这文章里推荐的这家最近出了点问题,服务器在修复,大家要用的话,推荐先用 TextIn。
此外,还有一些优化空间。比如,可以利用大模型来优化用户提出的问题。因为很多时候,用户提出的问题本身存在问题。
还有,怎么在检索过程中怎么评估哪些信息是最相关的,以及它们如何相互影响等等很多方面。
关于这一点,微软过去提出过 GraphRAG ,这是一种通过知识图谱的方式来构建和检索知识的方案。但是,成本也非常高,它只适用于需要处理大量、高度相关性信息的应用场景。
比如 法律分析、医疗诊断。法律中,条文和判例引用复杂;在医疗中,医生查找病历、药物等高度关联的信息。
GraphRAG 就可以用“图谱”的方式把这些场景的知识组织起来,让用户得到更完整的答案。
今天只是做了一次简单的分享,如果你对 RAG 优化有什么见解或者有趣的 idea,欢迎在评论区回复。