AI 大模型开发

RAG 架构的认识

JACIN··15 分钟阅读

主要步骤#

对于 rag 体系,主要分为以下的步骤:

阶段核心动作进阶动作
数据准备数据etl、分块、元数据提取、Embedding、索引建立语义切分、元数据提取
用户输入接收 Query查询改写、子问题拆解
召回向量数据库检索混合检索 (Hybrid Search)
排序Rerank (精排)阈值过滤、上下文去噪
生成LLM 生成答案引用溯源 (Citations)
阶段核心任务为什么“不简单”?
查询增强Query 改写/拆解难点在于维持对话上下文,不让 LLM 跑题。
混合检索语义 + 关键词难点在于权重分配(Alpha 值),调优很吃经验。
精排重测Rerank 模型计算难点在于性能平衡,要在精度和响应速度间取舍。
生成回复Prompt 组装难点在于防止幻觉,并实现高精度的引用溯源

数据准备(indexing pipeline)#

数据清洗(etl,extract,transform,load)#

在分块之前,原始文档往往是“脏”的。

  • 核心动作:解析 PDF、Word、HTML 等格式,提取纯文本。
  • 挑战点:PDF 里的多栏排版页眉页脚广告弹窗特殊字符。这些“噪音”如果进入向量库,会严重干扰 Embedding 的计算。
  • 进阶动作:使用布局分析(Layout Analysis)技术(如 LayoutParserUnstructured),识别出哪里是正文,哪里是表格。

分块(chunking)#

块太小,丢失上下文;块太大,向量特征会被稀释,检索不准。

  • 基础:固定长度切分 (Fixed-size)
    • 设定一个字数(如 500 字),每隔 500 字切一刀。
    • 缺点:经常会把一句话切成两半。
  • 核心:递归字符切分 (Recursive Character)
    • 先按段落切,段落太长按句子切,句子太长按空格切。
    • 优点:尽量保持了语义单元的完整性。
  • 进阶:语义切分 (Semantic Chunking)
    • 原理:计算相邻两句话的 Embedding 相似度,如果相似度突然断崖式下降,说明话题变了,就在这里切断。
    • 价值:保证了每一个 Chunk 内部只讲一件事情。

元数据提取 (Metadata Extraction)#

在同一个数据库的同一条记录(Row/Document)里,同时存放“特征向量”和“结构化属性”。

不要只存向量,要给每个 Chunk 打上“身份证”。

  • 核心动作:记录来源(文件名、页码、URL)。
  • 进阶动作
    • 摘要生成:用 LLM 给这个 Chunk 写一句摘要。
    • 实体提取:提取出里面提到的人名、项目名、日期。
    • 层级信息:记录它属于哪个章节标题。
  • 目的:在检索时,你可以先通过元数据过滤(比如:只搜“2024年”的文档),这比模糊的向量检索要可靠得多。
字段名内容类型示例
ID唯一标识符doc_chunk_123
Vector向量数据[0.12, -0.05, 0.88, ...] (1536维)
Payload/Metadata元数据 (身份证){ "title": "2024年报", "page": 15, "date": "2024-05-01", "category": "finance" }
Original Text原始文本"公司2024年第一季度营收增长15%..."

向量化 (Embedding)#

【*】入库(索引)时的 Embedding 模型和查询(检索)时的 Embedding 模型必须是同一个,甚至参数配置都必须完全一致。

将文本转为高维数学向量。

  • 核心动作:调用 Embedding 模型(如 OpenAI 的 text-embedding-3-small 或国产的 BGE 系列)。
  • 进阶知识
    • 模型选型:不同的模型“侧重点”不同。有的擅长短句,有的擅长长文档。
    • 多向量策略 (Multi-Vector):为一个大块生成多个小向量(比如:摘要向量、Q&A 向量),这样用户问法再刁钻也能匹配上。

索引构建 (Indexing)#

向量存进数据库时,需要一种“地图”来快速查找。

  • 核心算法:HNSW (Hierarchical Navigable Small World)
    • 这是目前最流行的算法。你可以把它想象成一个“朋友圈”,它通过建立多层级的小团体,让搜索时不需要遍历几百万条数据,而是通过几跳就能找到最接近的邻居。

向量空间里,数据是高维的点(比如 1536 维)。

  • 如果不建索引:用户提一个问题,数据库必须拿这个问题的向量,去跟库里 100 万个向量逐一计算“余弦相似度”。这叫 暴力搜索 (Brute-force),数据一多,服务器就崩了。
  • 如果建了索引:数据库预先给这些点建立了一种**“导航结构”**。查询时,它能像地图导航一样,通过几个关键路口,直接跳到目标点附近。

入库慢:因为要一边存数据,一边实时计算和调整这个复杂的层级地图(建索引)。查询快:因为有了地图,搜索复杂度从 O(N) 降到了 O(log N)。

A. 小世界 (Small World) —— “朋友圈”理论#

想象你在一个巨大的派对上要找“周杰伦”,但你不认识他。

  1. 你先问身边的人:“你认识周杰伦吗?”
  2. 身边的人说:“我不认识,但我认识一个搞音乐的,我带你去问他。”
  3. 这个搞音乐的人说:“我不认识,但我认识周杰伦的经纪人。”
  4. 经纪人带你找到了周杰伦。 这就是“六度分隔理论”:虽然每个人只连接了几个邻居,但通过这些“朋友圈”的跳转,你可以飞快地找到目标。在 HNSW 中,每个向量点都会选择几个距离它最近的向量作为“邻居”连线。

B. 分层 (Hierarchical) —— “高速公路”理论#

HNSW 把这个朋友圈分成了很多层。

  • 最顶层(高速公路):只有极少数的点。你在这里一跨步,可能就跨过了几万个数据点。
  • 中间层(省道):点稍微多一点,动作变细。
  • 最底层(街道):包含所有的数据点。

查询流程:

  1. 你从最顶层进入,在极少数的点里找到离你最近的那一个。
  2. 顺着这个点“降落”到下一层。
  3. 在这一层局部寻找更近的点,再降落。
  4. 最后降落到最底层,完成精准锁定。

用户输入处理#

用户往往不知道自己想要什么,或者问得很模糊。

  • 查询改写 (Query Rewriting)
    • 核心动作:利用 LLM 将用户的口语转化为更适合搜索的“关键词”或“标准问”。
    • 示例:用户问“那个去年那个卖得最好的蓝色的东西是啥?”,改写后变成“2024年度销量冠军 蓝色产品 名称”。
  • 子问题拆解 (Sub-query Decomposition)
    • 进阶动作:如果问题很复杂(如“对比 A 和 B 的财报”),LLM 会将其拆分为“A 的财报数据”和“B 的财报数据”两次检索。

检索阶段(多路召回与融合)#

较为复杂,这里就简单地进行罗列。

  • 混合检索 (Hybrid Search)
    • 核心动作:同时启动向量检索(搜意思)和关键词检索(搜字面)。
    • 为什么要混合?:向量检索擅长找“意思近的”,但容易漏掉“型号、人名、缩写”等精确信息。
  • 多路召回融合 (RRF)
    • 进阶动作:向量搜回来 50 条,关键词搜回来 50 条,如何给它们排总榜?通常使用 RRF 算法(倒数排名融合),给两边的排名加权求和,选出综合实力最强的 Top N。

排序与去噪#

  • Rerank (精排)
    • 核心动作:调用专门的 Reranker 模型(如 BGE-Reranker)。
    • 底层逻辑:向量检索是“看一眼长相”,Rerank 是“坐下来深度谈话”。它会让 Query 和每一个候选 Chunk 深度对齐计算得分,虽然慢,但极准。
  • 阈值过滤 (Thresholding)
    • 进阶动作:如果最相关的 Chunk 分数都很低(比如低于 0.3),系统应直接判定为“库里没答案”,直接告诉用户“不知道”,防止 LLM 强行编造。
  • 上下文去噪 (Context Compression)
    • 细节:把选中的 Chunk 里无关的句子删掉,只保留关键段落,节省 LLM 的 Token 消耗并减少干扰。

生成阶段:逻辑整合与溯源#

  • Prompt 注入
    • 核心动作:将检索到的背景知识拼接到 Prompt 中。
    • 黄金指令:要求 LLM “仅根据提供的 Context 回答,严禁自我发挥”。
  • 引用溯源 (Citations)
    • 进阶动作:要求 LLM 在回答的每一句话后面标注来源。
    • 示例:根据[文档1]显示,营收增长了 10%;而[文档2]提到研发投入在下降。这样用户点击引用标号就能看到原始出处,增加信任感。

评论

还没有评论,来发第一个吧