编辑
2025-10-15
个人笔记
00

目录

什么是 RAG?
更深层次的搜索——RAG
RAG 架构
索引构建
数据清洗
分块处理
为什么要切分文档?
常见的切分方式
检索流程深度解析
流程架构
第1步:Query (用户查询)
第2步:Query 解析 (查询解析)
第3步:召回文档 (文档召回 )
第4步:生成总结 (答案生成 - AI的综合与创作)
补充:反馈循环 (Feedback Loop)
RAG 推理流程分类
串型结构
循环型结构
分支型结构
我们在 RAG 中现在要解决什么问题?
构建更准确、细化的索引
更高的文档召回准确旅率
更好的回答生成优化

什么是 RAG?

检索增强生成(RAG)作为一种结合信息检索与文本生成的技术,已成为解决大语言模型(LLM)"知识过时"和"幻觉输出"问题的关键方案。RAG通过将外部知识库与LLM生成能力相结合,使模型能够基于真实、最新的信息输出答案,显著提升了生成内容的准确性和时效性

更深层次的搜索——RAG

核心思想:从给你链接到给你答案,一种从传统关键词搜索向下一代AI驱动的生成式搜索演进的完整构想。

传统的搜索是你输入关键词、系统返回一个相关的文档列表、你需要自己去逐篇阅读、寻找答案。而这套新的生成式搜索(Generative Search)流程、目标是直接理解你的问题、并通过阅读和总结相关文档、直接生成一个精准、连贯的答案。这是典型的检索增强生成(RAG、Retrieval-Augmented Generation)架构。

RAG 架构

RAG系统的核心流程可概括为"先检索、后生成",主要分为三个关键环节:索引构建、检索和生成。

索引构建

数据清洗

  • 数据清洗:RAG 依赖于准确且清洁的原始知识数据。为了保证数据的准确性、需要优化文档读取器和多模态模型。特别是处理如 CSV 表格等文件时,单纯的文本转换可能会丢失表格原有的结构
    • 因此我们需引入额外的机制以在文本中恢复表格结构
    • 比如使用分号或其他符号来区分数据
    • 另一方面也需要对知识文档做一些基本数据清洗其中包括:
      • 基本文本清理:规范文本格式、去除特殊字符和不相关信息。除重复文档或冗余信息
      • 实体解析:消除实体和术语的歧义以实现一致的引用。例如、将LLM、大语言模型和大模型标准化为通用术语
      • 文档划分:合理地划分不同主题的文档、不同主题是集中在一处还是分散在多处?如果作为人类都不能轻松地判断出需要查阅哪个文档才能来回答常见的提问、那么检索系统也无法做到
      • **数据增强:**使用同义词、释义甚至其他语言的翻译来增加语料库的多样性
      • 用户反馈循环:基于现实世界用户的反馈不断更新数据库、标记它们的真实性
      • **时间敏感数据:**对于经常更新的主题、实施一种机制来使过时的文档失效或更新

分块处理

在 RAG 系统中、文档需要被分割成多个文本块后再进行向量嵌入

什么是chunk?

  • chunk 就是把一份长文档分割成多个 较小的文本片段 (text chunks)
  • 每个 chunk 作为一个独立的检索单元,被编码成向量。
  • 当用户发起查询时、RAG 系统会在向量库里查找与 query 最相关的 chunk、把这些 chunk 作为上下文传递给大模型。

Chunk = 文本块。在 RAG 中、把文档切成 chunk、再做 embedding、可以提升检索精度、减少冗余、是业界常用的做法

为什么要切分文档?

  • 避免嵌入超长文本
    • 向量模型通常对输入文本长度有限制(比如 512 或 1024 tokens)。
    • 如果直接拿整篇文档做 embedding、容易截断信息、效果差。
  • 提高检索精度
    • 把文档切分后、检索更细粒度。
    • 用户 query 更容易命中具体片段、而不是整篇文章。
  • 减少上下文冗余
    • chunk 更小、可以只把最相关的几个 chunk 提供给大模型、节省 prompt 长度

不考虑大模型输入长度限制和成本问题的情况下、其目的是在保持语义上的连贯性的同时、尽可能减少嵌入内容中的噪声、从而更有效地找到与用户查询最相关的文档部分

  • 如果分块太大、可能包含太多不相关的信息、从而降低了检索的准确性。
  • 分块太小可能会丢失必要的上下文信息、导致生成的回应缺乏连贯性或深度。

在 RAG 系统中实施合适的文档分块策略,旨在找到这种平衡、确保信息的完整性和相关性。一般来说、理想的文本块应当在没有周围上下文的情况下对人类来说仍然有意义、这样对语言模型来说也是有意义的。

常见的切分方式

  • 固定大小的分块:最简单和直接的方法、直接设定块中的字数、并选择块之间是否重复内容。通常我们会保持块之间的一些重叠、以确保语义上下文不会在块之间丢失。与其他形式的分块相比、固定大小分块简单易用且不需要很多计算资源。

  • 带重叠切分(sliding window / overlap)

    • 每个 chunk 之间保留部分重叠内容、避免语义被截断。
    • 例如:200 tokens 长度、每次滑动 150 tokens(50 overlap)
  • 特殊结构的分块:针对特定结构的文档的专门分块器。这些分块器专门设计来处理这些类型的文档、以确保正确地保留和理解其结构。langchain 提供的特殊分块器包括:Markdown 文件、LaTeX 文件、以及各种主流代码语言分块器

  • 递归分块:在大多数情况下推荐的方法、通过重复地应用分块规则来递归地分解文本。例如在 langchain 中会先通过段落换行符(\n\n)进行分割、然后检查这些块的大小。如果块大小不超过一定阈值、则该块被保留。对于大小超过标准的块、使用单换行符(\n)再次分割。这种方法可以灵活地调整块的大小。例如、对于文本中的密集信息部分、可能需要更细的分割来捕捉细节、而对于信息较少的部分、则可以使用更大的块。它的挑战在于、需要制定精细的规则来决定何时和如何分割文本

  • 从小到大分块:既然小的分块和大的分块各有优势、一种更为直接的解决方案是将同一文档从大到小所有尺寸的分块、然后将不同大小的块全部存储在数据库中、并保存每个分块的上下级关系、进行递归搜索。因为我们需要存储大量重复的内容、这种方案的缺点是需要更大的存储空间。

  • 按语义切分

    • 按段落、句子、标题层级(markdown / HTML tag)来切分。
    • 更贴近语义、减少断句问题、但实现复杂

分块大小的选择

首先不同的嵌入模型有其最佳输入大小、例如 OpenAI 的 text-embedding-ada-002 模型在 256 或 512 大小的块上表现更好。其次文档的类型和用户查询的长度及复杂性也是决定分块大小的重要因素。处理长篇文章或书籍时、较大的分块有助于保留更多的上下文和主题连贯性、而对于社交媒体帖子、较小的分块可能更合适捕捉每个帖子的精确语义。如果用户的查询通常是简短和具体的、较小的分块可能更为合适。相反如果查询较为复杂、可能需要更大的分块


检索流程深度解析

流程架构

第1步:Query (用户查询)

  • 传统: 用户习惯于输入关键词、例如基金 分红 REITs
  • 现在 (TBD流程): 系统鼓励用户输入**完整的自然语言问题、**例如今年以来基金分红有什么特点?REITs在其中扮演了什么角色?这种输入的转变、要求后台具备更强大的语言理解能力。

第2步:Query 解析 (查询解析)

这是整个流程中技术含量最高、最关键的一步、它远不止是简单的分词。

  • 传统: 对基金 分红进行分词、变成基金分红两个词(传统用ES和MongoDB)
  • 现在 (TBD流程): 这一步需要一个复杂的自然语言理解(NLU)模块来完成多项任务:
    • 意图识别 (Intent Recognition): 分析用户的真实意图。用户是想找一篇具体的文章?还是需要一个总结性的答案?或是想进行数据对比?
    • 实体提取 (Entity Extraction): 识别出查询中的关键信息、如基金分红REITs今年以来(时间状语)等。
    • 查询改写/扩展 (Query Rewriting/Expansion): 将一个复杂问题、拆解成多个适合送入底层搜索引擎(Elasticsearch)的、结构化的子查询。例如将原始问题拆解为:
      • search(keywords="基金分红、 time_range="2025-01-01 to now")
      • search(keywords="REITs 分红 特点")
      • search(keywords="债券基金 分红 比例")
      • 这个过程极大地提升了后续召回文档的精准度

第3步:召回文档 (文档召回 )

  • 动作: 将第二步生成的多个结构化子查询、发送到Elasticsearchitem_feature索引中,执行检索。
  • 目标: 这一步的核心目标不是直接找到答案、而是尽可能全面、精准地找到所有能用来回答用户问题的原始材料或证据
  • 产出: 一个根据相关性排序的、包含Top-K(比如Top 10)篇最相关文章的列表。这些文章将作为下一步生成总结的上下文。

第4步:生成总结 (答案生成 - AI的综合与创作)

  • 动作: 将第三步召回的Top-K篇文章的全文或摘要连同用户的原始Query、**一起打包发送给一个大语言模型(LLM)
    • 例如系统中的通用能力服务
  • 实现:
    • 构建Prompt: 设计一个精巧的提示词(Prompt)、指令LLM扮演一个专家的角色、并要求它
    • :“请基于以下[K篇参考文章]、用简洁、连贯的语言、回答这个问题:[用户的原始Query]
    • 请确保你的回答内容完全来自于提供的参考文章、并在关键信息后标注来源
    • AI生成: LLM阅读并理解这K篇文章、然后像一个研究员一样、从中提炼关键信息、重新组织语言、生成一个直接、精准、且通常是多段落的总结性答案
  • 产出: 一段高质量的、直接回答用户问题的文本

补充:反馈循环 (Feedback Loop)

图中从生成总结指回Query解析的反馈、是流程最先进、最智能的部分

它代表了一种多轮、迭代的搜索思想

  • 它解决了什么问题?

  • 有时候、第一轮召回的文档可能不足以完美地回答用户的问题

  • 比如用户问AI对经济的宏观和微观影响、第一轮召回的文章可能大多是关于宏观影响的。

  • 它如何工作?

    1. 系统生成第一版总结后、可以进行一次自我评估。它发现总结中缺少微观影响的部分。
    2. 基于这个发现,系统自动生成一个新的、更具体的查询、例如AI对中小企业生产效率的影响(这就是一次Query改写)。
    3. 用这个新查询再次执行第3步和第4步、获得关于微观影响的补充材料和总结。
    4. 最后、将两轮的总结合并成一个更全面、更完美的最终答案。
  • 价值: 这个反馈循环、让搜索从一次性的请求-响应模式、进化成了一个能够像人类一样思考、反思、并进行多步推理AI代理(AI Agent)

RAG 推理流程分类

在我们平常的 RAG 中通常是简单地基于上述的一条链路来回答用户的问题的,有时候第一轮召回的文档可能不足以完美地回答用户的问题。基于前面提到过的反馈环节,在 UltraRAG 中提出了 RAG Pipeline 方式编排推理流程来实现反馈环节。

[!summary] 什么是 Pipeline? 在 UR-2.0 中,Pipeline 是你定义“推理任务如何执行”的流程脚本。它像一个“任务计划表”或“工作流蓝图”,用来明确告诉系统每一步该做什么、怎么做、做完后怎么走下一步。你可以通过 Pipeline 组合不同模块(Server)中的功能(Tool),构建出一个完整、可复现、可控制的 RAG 推理流程。例如:

  • 加载数据 → 检索文档 → 构造 prompt → 调用大模型 → 评估结果;
  • 或者在多轮生成中,根据模型中间的表现决定是否重新检索或停止生成。 Pipeline 的核心作用是:让复杂的 RAG 流程结构清晰、灵活、模块化,并通过 YAML 配置实现零代码编排。

在 UR-2.0 中,Pipeline 是你定义“推理任务如何执行”的流程脚本。它像一个“任务计划表”或“工作流蓝图”,用来明确告诉系统每一步该做什么、怎么做、做完后怎么走下一步。你可以通过 Pipeline 组合不同模块(Server)中的功能(Tool),构建出一个完整、可复现、可控制的 RAG 推理流程。例如:

  • 加载数据 → 检索文档 → 构造 prompt → 调用大模型 → 评估结果;
  • 或者在多轮生成中,根据模型中间的表现决定是否重新检索或停止生成。

Pipeline 的核心作用是:让复杂的 RAG 流程结构清晰、灵活、模块化,并通过 YAML 配置实现零代码编排。

串型结构

串行结构是 UltraRAG Pipeline 中最基本、最常见的执行方式。多个步骤按顺序依次执行,前一步的输出(若有)可以作为下一步的输入,也可以独立执行。构建一个基础的 RAG 工作流通常只需使用串行结构即可完成。

循环型结构

在一些多轮推理、多跳问答、多轮检索等任务中,单次执行流程往往不足以获得最终答案。此时就需要使用 循环结构(loop),以重复执行某些模块,逐步迭代信息、强化生成结果。

分支型结构

在复杂的推理任务中,我们常常需要根据模型当前的输出或中间状态决定流程是否继续。例如:

  • 如果模型生成的是查询,就进行下一轮检索;
  • 如果模型已经生成了最终答案,就结束流程。

为实现上述能力,UR-2.0 提供了 分支结构(branch),用于构建具备 条件跳转逻辑 的动态推理流程。

我们在 RAG 中现在要解决什么问题?

构建更准确、细化的索引

  • 数据清洗
  • 文档分块处理
  • 元数据增强
  • 调用 MCP 与数据源交互;使用工具获取更多信息,如联网搜索

更高的文档召回准确旅率

  • 调参,TopK、评分比例。根据 RAG 知识库应用领域不同,在准确性和广度上进行取舍

更好的回答生成优化

  • 优化prompt(太玄学,不会)
    • 设定角色,科研型,文学型,专业型