十步构建智能应用:RAG从原型到生产的全链路解析
创始人
2025-07-07 17:40:38
0

引言

当今,大多数的公司主要依靠文档开发运营工作。这或许是近年来检索增强生成系统如此流行的原因之一。这个想法很简单:通过向系统提示和用户查询提供附加信息,克服LLM当前的局限性——例如幻觉和知识截止。

于是,人们可以快速构建和部署第一个RAG应用程序原型。但是,当用户真正与这套首个RAG系统交互时,缺陷开始显现。RAG系统给出的答案显得肤浅,重要的上下文信息被遗漏,检索悄然失败。而且,系统的性能还随着文档数量的增加而下降。

不过,我们最终还是可以通过制定计划来构建、部署和增强先进的RAG应用程序,从而避免这种情况。

本文将提供从最初的客户问题到最终部署的应用程序的清晰路线图,从而简化了开发满足人们需求的高级RAG框架的复杂过程。

本文将上述整个过程划分为10个具体步骤,从而有利于方便指导每一个RAG项目实现从构思到生产的全流程。

1. 需要解决的问题

在进行任何编程之前,我们必须问自己:实际问题是什么?我们对情况了解得越深入,就越容易找到解决方案。

这个问题理解过程的一个重要部分是确定用户的理想或“梦想”结果是什么样的。

明确定义问题和期望结果标志着我们路线图的开始和结束。

解决该问题的一个可能方案是检索增强生成(RAG)系统,该系统能够利用外部知识增强大型语言模型。这有助于克服信息过时或领域专业知识浅薄等局限性。

然而,RAG系统引入了额外的复杂性。现在,需要开发和维护两个独立的组件:索引部分和生成部分。

因此,我们首先应该问:这个问题有没有更简单的解决方案?也许一个基本的关键词搜索、一个基于规则的系统或一个常见问题解答页面就足够了——这些都不需要LLM。

RAG的替代方案是缓存增强生成,它将整个上下文加载到模型的内存中,从而无需完全检索。

解决问题的方法有很多,RAG只是其中之一。不要落入“工具法则”(又称“马斯洛锤”)的陷阱。该法则描述的是一种认知偏差,即过度依赖熟悉的工具,即使它并非最合适的解决方案。

一位留着胡子、戴着帽子的卡通男子在一辆爆胎的汽车旁边弹吉他唱歌,旁边有一个对话框说:“♪我的方向盘掉了,但我的精神很高♪”。

此图展示了马斯洛锤子理论的一个幽默例子:一位音乐家坐在车旁,拿着吉他唱歌。真正的问题是爆胎了;但是,他没有去换,而是开始写一首关于爆胎的歌,因为写歌是他应对任何问题的工具。

2. 为问题提供的数据

最终的RAG系统的质量取决于你输入的文档。

首先,我们必须确保手头有合适的文件来解答最常见情况的问题。如果没有足够且最新的文件,LLM通常会给出“我不知道”的答案,或者在最糟糕的情况下,给出一个不切实际的答案。

收集完所有必需的文档后,我们来检查一下数据的格式和质量。它是纯文本、PDF、HTML页面、图像,还是各种格式的混合?

从文档中提取信息是任何RAG流程中不可避免的一步,而你的LLM答案的质量很大程度上取决于你从来源中提取内容的效率。

换句话说:输入的是垃圾,输出的也是垃圾。

垃圾进,垃圾出(【引文1】)

此图展示的这幅火柴人漫画幽默地解释了机器学习:一个人将“数据”倒入标有“线性代数”的一堆数据中,在另一边收集“答案”,如果答案是错误的,他们只需“搅拌这堆数据,直到看起来正确为止”。

结构化数据(例如数据库或CSV文件)非常适合处理。这些格式更易于查询,并更易于线性化为文本。

相反,非结构化数据则需要更多的处理步骤,因为信息并非以易于使用的形式提供。非结构化文档处理流程可能包含多个步骤,具体取决于所使用的工具。我最喜欢的PDF处理工具是:

  • Mistral OCR:用于快速将文档转换为MarkDown格式的文件。
  • Docling:一个将文档转换为MarkDown格式并提供额外布局信息的开源解决方案。
  • Vision LLM:你可以在其中传递页面的屏幕截图以及提取所有文本并以MarkDown格式返回的指令。半结构化数据包括部分有组织的格式,例如JSON文件或网页——网页尤其成为信息提取的常见来源。在这种情况下,必须首先删除样板内容,包括导航菜单和广告等不相关的元素。
  • 你可以使用常见的网络抓取工具(如BeautifulSoup和Scrapy)来实现此目标。
  • 这凸显了一个重要的观点:RAG并非魔法。LLM只能利用事先提供的信息。因此,拥有正确、机器可读且清晰的格式对最终表现有着巨大的影响。

3.数据预处理

收集所需数据并选择适当的信息提取方法后,可以设计预处理流程。

这一步至关重要,因为数据的切片和注释方式直接影响检索器为LLM找到的内容。

在数据预处理的设计过程中,应考虑以下几点:

(1)分块策略

分块策略定义了在索引之前如何将文档拆分成多个部分。这是必要的,因为嵌入模型和LLM都有输入标记的限制。此外,所选的块大小对整体系统性能有巨大的影响。

  • 分块大小(例如128个标记)提供详细、细粒度的信息,但由于上下文丢失,可能会丢失不可或缺的内容。
  • 较大的块大小(例如512个或更多标记)可确保保留全面的信息,但可能会降低系统速度。此外,在单个提示中组合多个长块可能会导致上下文过长。这会使模型感到困惑——这种现象通常被称为“迷失在中间”。
  • 不幸的是,没有通用的规则来确定最佳的块大小或策略。这些选择很大程度上取决于数据的结构和性质。

GPT-3.5-Turbo-0613在答案位于20个文档上下文(约4000个标记)的开头或结尾时,准确率最高,中间部分则急剧下降,呈现出U形的位置偏差。其中的虚线表示闭卷准确率(56.1%)(【引文2】)。

此折线图展示了准确率与包含答案的文档在总共20篇检索到的文档中的位置的关系。随着答案从第一位移动到后面的位置,准确率急剧下降,在中间位置触底,并在接近第20位时再次上升。红色虚线标记了闭卷考试的准确率,以便进行比较。图例显示了“GPT-3.5-Turbo-0613”和“GPT-3.5-Turbo-0613(闭卷)”的结果。

(2)元数据提取

每个块可以携带元数据(属性),这些元数据提供上下文信息,但不出现在正文中。例如,元数据可以包括文档标题、作者、日期、章节名称、来源URL等。

这些元数据对于筛选或提升最终检索过程非常有用。它还支持访问控制机制,允许系统确定哪些人可以访问某些信息。

元数据可以手动提供,也可以自动派生,例如,使用命名实体识别(NER)来标记提到的产品或人员,或者对每个块的主题进行分类。

(3)搜索方法

RAG并非只要求向量搜索。任何搜索方法都可以用来检索相关的文本块。常用方法包括向量搜索、关键字搜索和混合搜索。

  • 向量搜索会嵌入查询,并根据语义相似度找到最近的嵌入向量。它非常适合概念匹配,但在处理罕见的、特定领域的术语时可能会表现不佳。
  • 关键词(词汇)搜索通过倒排索引(例如BM25)将查询词与文本匹配。这种方法擅长检索特定的技术术语或不常用的术语。
  • 混合搜索并行运行向量和关键字搜索,并使用倒数秩融合或线性融合等方法对结果进行重新排序以合并分数。

(4)索引和存储

随着RAG应用的日益普及,提供向量存储功能的公司数量也显著增加。由于选项众多,我在下表中总结了其中最突出的几个,以便你做出更好的决策。

此表总结了主流向量数据库(包括Meta FAISS、Pinecone、Weaviate、Milvus、ChromaDB、Qdrant和Neo4j)的主要特性。表中列出了每个数据库的常规信息、开源状态、开发语言、算法、混合搜索、距离度量、优势和局限性。

这里展示了当前业界领先的向量数据库的功能比较,突出它们的优势、支持的算法以及高效相似性搜索和人工智能应用的关键限制。

我个人最喜欢的是Qdrant,因为它提供了高级搜索功能,让你可以创造性地设计检索过程。

4.原型设计

基于“快速失败”的原则,原型设计在RAG系统的设计过程中起着至关重要的作用。如果没有丰富的经验,我们很可能不知道什么可行,什么行不通。

找出答案的最佳方法是快速构建第一个原型——从Jupyter笔记本中的基本RAG应用程序开始,不断增加复杂性以更接近所需的输出。

这样,我们就获得了关注,获得了实践经验,并确保如果最初的想法表现不佳或没有满足用户的要求,后续的工作不会导致时间的浪费。

这些实验可以涵盖多个方面,具体取决于最终目标和数据源。然而,向量存储的性能和相关性很大程度上取决于所使用的嵌入模型。

选择合适模型的一个很好的起点是参考HuggingFase嵌入排行榜,它根据不同的指标能够比较各种语言的文本和图像嵌入模型。

下面给出了嵌入排行榜界面截图,展示了多语言模型的性能。图表绘制了任务平均得分与参数数量的关系,各种模型以绿色气泡表示,左侧为基准类型的过滤器。

HuggingFase嵌入排行榜通过性能、大小和标记容量比较了1,000多种语言和131个任务的多语言嵌入模型。

关于向量存储,我会在原型设计阶段选择FAISS、ChromaDB或Qdrant,因为这三个数据库都提供了方便的本地实现,使得它们非常适合在Jupyter笔记本中进行实验。

设置初始索引原型后,你可以开始首次手动实验,并根据用户查询检索相关块。请考虑以下几点来手动评估结果:

  • 这些块真的与查询相关吗?
  • 块大小看起来合适吗?
  • 这些区块的排序合理吗?你会按照类似的顺序排列它们吗?
  • 这些块是否提供了足够的上下文来自信地回答查询?
  • 顶部结果中是否存在不相关或冗余的块?
  • 检索到的块在多大程度上代表了查询中的观点或子主题的多样性?
  • 是否存在语义漂移的迹象,即内容与实际查询含义略有偏差?
  • 块中的语言是否足够清晰且易于理解,以便进行下游处理?这种手动评估有助于在进行自动基准测试或与下游LLM集成之前改进分块、索引和检索策略。

5. 增强检索过程

如果原型阶段尚未完成,现在是时候根据从原型中获得的见解来提升检索过程了。即使是设计最精良、组织最完善的向量存储,如果没有能够有效利用其丰富结构的检索策略,也是毫无价值的。

与数据处理管道一样,链条的强度取决于其最薄弱的环节——并且在许多RAG应用程序中,该薄弱环节通常是检索过程。

如果你不确定如何进一步改进检索过程,以下给出三个基础型建议:

选择不同的相似性搜索算法

许多向量数据库使用HNSW(分层可导航小世界图)或其他近似最近邻(ANN)算法。你通常可以调整它们的参数,以在速度和准确性之间取得更好的平衡。

从我的角度来看,Pinecone在解释和可视化HNSW算法方面做得非常出色,如下图所示:

HNSW(分层可导航小世界图,见【引文3】)

该图展示了由箭头连接的三层节点,展示了HNSW(分层可导航小世界)图搜索过程。蓝色“入口点”从顶层开始,向下遍历各层,到达底层的黄色“查询向量”及其最近邻。

选择不同的相似度度量

余弦相似度很常用,但并非唯一选择。其他度量包括内积、欧氏距离和曼哈顿距离。根据你的数据和任务的不同情形,其中一种度量可能比其他度量表现更好。

集成混合搜索方法

混合搜索允许你将基于关键字(稀疏)的搜索与密集向量搜索相结合。许多向量数据库(例如Qdrant)支持混合搜索,并允许你配置复杂的组合,例如其博客文章图片中所示的组合。

此流程图展示了两种混合搜索流程:一种使用维度不断增加的Matryoshka嵌入,并在每个阶段重新排序;另一种使用密集、全密集和稀疏向量,在最终重新排序步骤(称为“后期交互”)之前融合它们的结果,以选择前10个匹配项。

在此图展示的Qdrant混合搜索流程的示例中,该流程将密集和稀疏向量检索与多阶段重排序相结合,以获得最佳搜索结果(【引文4】)。

添加业务逻辑

这是一个广泛的概念,指的是定制检索以更好地适合你的领域或用户的期望。

例如,你可能会提升某些类型的内容:如果你知道官方政策文件比Slack消息更值得信赖,那么你可以为来自“政策”文档的任何块分配更高的分数。

此外,许多向量数据库允许你按元数据(例如创建时间或其他上下文)进行筛选。这允许你将新近度和特定领域的筛选纳入检索过程。

用于重新排序的交叉编码器

交叉编码器将查询和单个文档一起作为输入,并直接输出相关性分数。

交叉编码器通常能更准确地进行排名,因为它们能捕捉查询和文档之间的微妙关系。然而,由于必须对每个文档进行单独评估,因此速度较慢。

下面的示意流程链接了一个图片和网页,完美地概括了双编码器和交叉编码器之间的区别。

双编码器与交叉编码器的比较(【引文5】)

这张图比较了双编码器和交叉编码器。双编码器通过BERT和池化分别处理两个句子,然后测量相似度;交叉编码器通过BERT和分类器同时处理两个句子,以获得相关性分数。

然而,面对所有这些可能性,人们很容易过度设计。在这种情况下,我始终牢记一个原则:保持简单,简洁(KISS)。整个框架应该尽可能简单——并且只在必要时才考虑复杂性。

顺便说一句,如果你决定使用自定义或开源模型进行嵌入、重新排序,甚至将其作为LLM而不是完全托管的服务,欢迎来到MLOps的世界!

除了设计和维护实际的RAG框架之外,还必须部署、监控和持续更新这些模型。

如果你希望避免这些额外的运营开销,不妨从托管服务入手,快速实现创新。最终,这始终还是要在控制力和便捷性之间进行权衡。

6. LLM答案生成

从数据源检索到最相关的文档后,我们将重点转移到RAG的生成部分。这一步骤旨在设计LLM如何使用检索到的信息来生成有用、正确且安全的响应。

LLM类型繁多,各有优缺点。申请LLM类型时,应考虑以下几点:

  • 开放式或封闭式模型
  • 自行部署(本地)或基于API的访问
  • 推理延迟(生成响应的速度)
  • 推理成本(例如,计算要求或API定价)
  • 上下文窗口大小(模型一次可以处理多少信息)
  • 多模式功能(文本、图像、音频等)
  • 与你的领域相关的基准模型性能
  • 安全、隐私和数据驻留合规性
  • 许可条款(商业用途与研究用途)选择合适的LLM与选择合适的提示设计同样重要,尤其是系统提示,它定义了模型的预期行为。一个好的系统提示远不止为LLM赋予一个角色,例如“你是……方面的专家”。已发布的Claude系统提示就证明了这一点,它涵盖了超过24,000个词条(【引文6】)。
  • 因此,非常值得投入时间和精力进行提示工程,并根据你所在领域的特定挑战定制提示(及其示例)。
  • 此外,一些应用程序可能需要实施“护栏”——检查和约束LLM的输出以防止不良行为。
  • 这些“护栏”可以通过简单的基于提示的指令来实现,例如:“你不得生成有关以下主题的答案......”。
  • 对于更高级的“护栏”,可能需要额外的工具,例如:
  • Guardrails AI
  • Rebuff
  • NeMo Guardrails
  • LMQL(语言模型查询语言)与护栏密切相关的另一个问题是幻觉,即LLM生成不正确或虚构的内容(与护栏情况下的不适当内容相反)。
  • 不幸的是,RAG框架并不能完全消除幻觉,但可以通过以下策略来缓解:
  • CRITIC:大型语言模型可通过工具交互批评进行自我纠正(【引文7】)
  • 基于文档信息来源页面的视觉基础,例如使用Docling(【引文8】)
  • 亚马逊的Bedrock幻觉检查语境基础(【引文9】)
  • Uqlm:语言模型的不确定性量化(【引文10】)此外,请为LLM调用实现超时和回退机制。没有什么比你的应用因为模型运行时间过长而挂起更糟糕的了。如果遇到超时或错误,你可以向用户返回一条友好的消息(“抱歉,我现在遇到问题,请重试”),而不是崩溃。

7.评估

目前为止,我们仅对中间步骤和结果进行了人工检查。然而,为了获得更深入的洞察,我们需要进行更全面、更准确的评估。

在其他软件项目中,单元测试通常在这一阶段编写。然而,对于RAG开发来说,事情有点棘手。

评估步骤从组装“黄金数据集”开始,其中包括你的系统应该能够处理的一组示例问题及其正确答案。

构建这样的数据集本身就是一种挑战,并且极大地受益于领域专家和最终用户之间的对话。

最后,每个问题都与一个基本事实信息源相关联。例如,如果可能的话,问题X应该由文档Y第2部分来回答。

RAG框架的整体评估是不同指标和工具的混合。

例如,信息检索(IR)指标衡量检索器获取相关信息的效果。这一过程常见指标包括:

  • Recall@K,是指正确答案块位于检索到的前K个答案块中的查询的百分比。
  • MRR(平均倒数排名),查看每个查询的第一个相关结果的排名(MRR越高意味着相关文档平均出现的位置越高)。另一方面,生成评估是一项更为艰巨的任务,因为评估自由格式文本的质量具有主观性。有一种方法是人工评估,它被认为是黄金标准,但可扩展性较差。
  • 一个自动化的替代方案是LLM-as-a-judge。该技术使用大型语言模型对答案进行评分,有效地将评估工作外包给了人工智能(见【引文11】)。
  • 有一个非常方便的用于增强生成评估的开源工具包是RAGAS,我建议你好好熟悉一下这个工具。这个工具还使用底层的LLM来评估以下标准:
  • 忠诚度:答案是否忠实于来源?
  • 相关性:答案是否解答了问题?
  • 上下文精度:检索到的信息中有多少部分被实际使用?因此,RAGAS可以被视为RAG应用程序的一种单元测试框架。

8.改进和实验

基于评估过程中获得的洞察,RAG框架可以得到进一步增强。此阶段遵循一个迭代循环:实验→评估→改进→重复。

这一步不是要增加随机的复杂性,而是要进行明智的实验。

以下是一些值得尝试的领域:

  • 分块策略:过去,人们探索了许多分块策略,例如基于大小的分块、语义分块、混合分块、重叠分块或分层分块。后者对于需要理解文档语料库中更广泛背景的答案生成任务特别有用。
  • 在分层分块中,文档被拆分成多个粒度的块,以反映内容的自然结构(例如章节、段落和句子),而不是仅仅依赖于固定大小的标记窗口。如果文档已转换为MarkDown格式,则此方法效果最佳。
  • 然而,原始文本也可以进行分层分块,正如RAPTOR所展示的那样,它使用自下而上的方法构建了更高级别摘要的树。
  • 下图展示了RAPTOR树的分层分块方法。文档被聚类到叶节点,由更高级别的LLM进行汇总,每个节点存储其索引、子节点、摘要文本和嵌入。

RAPTOR树展示:分层分块逐层聚类和汇总文本块,构建结构化树,以实现高效的文档理解和检索(【引文12】)

  • 提示结构:测试不同的提示公式、少量示例或单独的检索和推理步骤(又名ReAct提示)。
  • 检索参数:调整top_k、重新排序阈值或元数据过滤器。
  • 嵌入模型:将嵌入模型替换为针对你的领域或语言优化的模型。如果没有特定领域的嵌入模型,你可能需要自行微调。不过,在执行此操作之前,请考虑使用混合搜索来完成特定领域的任务,因为它可以更好地处理特定领域的关键词。在实验和调整流水线的各个部分时,很容易迷失方向并失去对性能的关注。此时,Git等版本控制系统便会展现出其真正的优势;如果一开始没有使用这样的系统的话,那么应该好好使用。这些实验最好在单独的分支中进行管理,理想情况下每个版本都有一个专用的分支。
  • 在这个阶段,由于存在大量的可能性,人们很容易盲目地进行优化。
  • 明确的假设和预先定义的可衡量结果有助于集中精力于应用程序想要解决的实际目标。

9. RAG框架的部署

到目前为止,我们大多数人只在本地完成了开发。现在,到了一个重要的步骤:在生产基础设施中部署RAG系统。

这一步涉及软件工程和DevOps,以确保你的管道在现实世界中稳定、可扩展且可维护。

这通常需要:

  • 检索管道和LLM交互的后端托管(例如,Flask、FastAPI或LangChain Server)。
  • 前端集成,如果用户将通过网络应用程序或聊天机器人界面进行交互。
  • 模型服务基础设施,尤其是通过Docker、TorchServe或推理端点使用本地或微调模型时。
  • 你的向量数据库(例如Qdrant、Pinecone或Weaviate)以及任何文档提取管道的持久存储。
  • 可观察性和日志记录,用于跟踪查询负载、错误、延迟和系统健康状况。该领域的常用工具包括Prometheus和Grafana。

所有上述这些观点其实都只是触及了AI应用程序部署的表面,这至少与RAG框架本身的开发一样是一个广泛的话题,因此值得专门写一篇文章来探讨。

如果你不知道从哪里开始,那么在Hugging Face Spaces上部署和分享你的第一批成果将会给你带来一个快速的胜利体验,并允许你收集初步反馈。

下一步,Google Firebase可能会成为你的一个不错的选择,因为它可以为你自动处理后端。

10.持续改进的反馈循环

然而,在应用程序开发、测试和部署之后,RAG框架并不完整。

在收集初步用户反馈后——无论上一步选择了哪种部署方法——都必须不断整合这些反馈,以便更好地满足用户的需求。

这使得RAG与许多软件应用程序一样,不再是一个静态产品,而是一个不断发展的服务。

总结

本文描述的10个步骤强调了构建高级RAG应用程序不仅仅是检索几个相关的上下文块的问题。这是一项必须根据特定领域及其独特要求进行定制的服务——强调没有一刀切的解决方案。这是因为文档类型多样,并且每个领域都有不同的特定需求。

通过遵循本文概述的10个步骤,在开发RAG应用时,人们可以从基本原型转变为可以投入生产的服务,从而以可靠、可扩展和智能的方式真正帮助终端用户。

相关内容

热门资讯

豪丽坤取得吊车液压伸缩杆自带支... 金融界2025年7月7日消息,国家知识产权局信息显示,无锡豪丽坤自控设备有限公司取得一项名为“一种吊...
《慕慕到家》家政小程序组件化进... 获取ZY↑↑方打开链接↑↑ 领域驱动设计(DDD)在小程序组件化中的实践 在小程序开发中,随着业务复...
博格华纳新能源取得交流直流风机... 金融界2025年7月7日消息,国家知识产权局信息显示,博格华纳新能源(襄阳)有限公司取得一项名为“一...
恒勃控股取得滤芯组件及空气过滤... 金融界2025年7月7日消息,国家知识产权局信息显示,恒勃控股股份有限公司取得一项名为 “一种滤芯组...
无需抽血或标记!我国科学家使无... 快科技7月7日消息,据媒体报道,我国科研人员在无创诊断领域取得重要进展,成功开发出一种新型太赫兹光声...
伯曼机械取得移动分流装置专利,... 金融界2025年7月7日消息,国家知识产权局信息显示,伯曼机械制造(上海)有限公司取得一项名为“一种...
谷歌AI制药或迎来里程碑 即将... 《科创板日报》7月7日讯 Isomorphic Labs总裁兼谷歌DeepMind首席商务官Coli...
十步构建智能应用:RAG从原型... 引言 当今,大多数的公司主要依靠文档开发运营工作。这或许是近年来检索增强生成系统如此流行的原因之一。...
兆威机电发布全新一代灵巧手 持... 中证报中证网讯(王珞)日前,兆威机电在深圳召开新品发布会,正式推出新一代仿人灵巧手产品——DM17和...
2025全球数字经济大会亮点:... 7月3日,2025全球数字经济大会人工智能融合应用发展论坛在北京盛大启幕。心言集团凭借其创新成果——...