llmapis

深入理解 RAG 系统:核心原理与技术架构

· 12 min read

深入理解 RAG 系统

核心原理与技术架构


📋 目录

第一部分:RAG 基础概念

  1. 什么是 RAG?
  2. RAG 的核心价值
  3. RAG 系统架构全景
  4. 数据准备流程
  5. 系统核心组件

第二部分:三大核心技术深度解析

  1. 一、文本切块 (Text Chunking)

    • 为什么需要切块?
    • 三种主流切块策略
    • 切块的关键参数
    • 重叠策略的重要性
    • 元数据增强
  2. 二、向量嵌入 (Embedding)

    • 为什么需要向量?
    • 从 One-Hot 到词嵌入的演进
    • 向量空间的几何直观
    • 余弦相似度 vs 欧氏距离
    • 向量维度的语义意义
  3. 三、查询增强 (Query Enhancement)

    • 为什么需要查询增强?
    • HyDE (假设文档嵌入)
    • 查询扩展
    • 查询分解
    • 混合检索
    • 重排序 (Reranking)

第三部分:实战与最佳实践

  1. 实战案例:Quka.AI
  2. 总结:RAG 系统构建要点
  3. 常见陷阱避免
  4. 进阶学习资源

第一部分:RAG 基础概念


什么是 RAG?

RAG(Retrieval-Augmented Generation) = 检索增强生成

一种将信息检索大语言模型生成相结合的 AI 架构模式


RAG 的核心价值

解决 LLM 的四大痛点

痛点RAG 的解决方案
知识时效性实时检索最新信息,无需重新训练
领域专业性注入私有知识库,支持垂直领域
可验证性提供来源引用,答案可追溯
成本效益无需微调,动态更新知识

RAG 系统架构全景

┌─────────────────────────────────────────────┐
│              RAG 完整工作流程                 │
└─────────────────────────────────────────────┘

              用户提问

         ┌──────────────┐
         │  查询增强     │  ← 理解用户意图
         │  Query       │
         │  Enhancement │
         └──────────────┘

         ┌──────────────┐
         │  混合检索     │  ← 召回相关文档
         │  Hybrid      │
         │  Retrieval   │
         └──────────────┘

         ┌──────────────┐
         │  重排序       │  ← 精排最相关内容
         │  Reranking   │
         └──────────────┘

         ┌──────────────┐
         │  LLM 生成     │  ← 基于检索内容生成答案
         │  Generation  │
         └──────────────┘

              返回答案

数据准备流程

在用户查询之前,需要先将知识库进行向量化处理:

原始文档 (PDF/Markdown/HTML...)

┌──────────────────┐
│  文档解析          │  解析各种格式
└──────────────────┘

┌──────────────────┐
│  文本切块          │  切分成小段落 ⭐️ 核心技术1
│  Text Chunking   │
└──────────────────┘

┌──────────────────┐
│  向量嵌入          │  转换为数字向量 ⭐️ 核心技术2
│  Embedding       │
└──────────────────┘

┌──────────────────┐
│  向量存储          │  存储到向量数据库
│  Vector Store    │  (Pinecone/Qdrant/PgVector)
└──────────────────┘

系统核心组件

📦 数据处理层

  • 文档解析器:处理 PDF、Word、HTML、Markdown 等格式
  • 文本切块器:将长文档分割成语义完整的片段
  • 元数据提取器:提取标题、日期、作者等结构化信息

🧮 向量化层

  • 嵌入模型:将文本转换为高维向量(OpenAI/BERT/多语言模型)
  • 向量数据库:高效存储和索引向量(支持毫秒级检索)
  • 相似度计算:余弦相似度、欧氏距离等

🔍 检索层

  • 查询理解:分析和增强用户问题 ⭐️ 核心技术3
  • 检索策略:向量检索、关键词检索、混合检索
  • 重排序模块:优化检索结果的相关性排序

🤖 生成层

  • 提示工程:构建高质量的提示模板
  • 大语言模型:生成最终回答(GPT-4/Claude/Qwen等)

第二部分:三大核心技术深度解析

接下来重点讲解 RAG 系统的三大核心技术


一、文本切块 (Text Chunking)

为什么需要切块?

技术限制

  • 嵌入模型有输入长度限制(通常 512 tokens)
  • LLM 上下文窗口有限(即使是 GPT-4 也只有 128K tokens)
  • 单次处理整个文档不现实

检索精度

  • 小块更容易匹配具体问题
  • 粗粒度文档会包含大量无关内容
  • 降低噪声,提高信噪比

成本控制

  • API 调用按 token 计费
  • 精准切块减少不必要的 token 消耗

语义聚焦

  • 每个块聚焦单一主题
  • 提高匹配相关性
  • 便于后续引用和追溯

三种主流切块策略

策略 1:固定大小切块 (Fixed-Size)

原理

  • 按固定字符数或 token 数切分
  • 可设置重叠区域避免语义断裂

示例

原文:[5000 tokens 的长文档]

块1: tokens 0-512 (重叠 50)
块2: tokens 462-974 (重叠 50)
块3: tokens 924-1436 (重叠 50)
...

✅ 优点

  • 实现简单,处理速度快
  • 块大小可控,便于管理
  • 适合批量处理

❌ 缺点

  • 可能在句子中间切断
  • 忽略文档语义结构
  • 可能破坏段落完整性

适用场景:日志文件、聊天记录、均匀分布的文本


策略 2:语义切块 (Semantic Chunking) (<- QukaAI)

原理

  • 基于语义边界,通过Embedding模型进行智能切分
  • 识别段落、章节、主题转换点
  • 保持语义完整性

语义边界识别

文档结构分析:
├─ 标题识别 (#、##、加粗文本)
├─ 段落边界 (双换行)
├─ 列表结构 (1. 2. 3. / - - -)
└─ 语义相似度跳变点

✅ 优点

  • 保持语义完整性
  • 尊重文档结构
  • 提高检索质量
  • 用户体验更好

❌ 缺点

  • 实现复杂度较高
  • 处理速度较慢
  • 块大小不够均匀
  • 需要额外的语义分析

适用场景:技术文档、教程、结构化文章


策略 3:递归字符切块 (Recursive Character Splitting)

原理

  • 按优先级尝试多个分隔符
  • 递归切分直到满足大小要求

分隔符优先级

1. 段落边界: "\n\n"
2. 换行符: "\n"
3. 句子边界: "。!?"
4. 子句边界: ",、;"
5. 词边界: " "
6. 字符级别: ""

工作流程

文档
 ↓ 尝试按 "\n\n" 切分
段落列表
 ↓ 段落仍过大?按 "\n" 切分
句子列表
 ↓ 句子仍过大?按 "。" 切分
子句列表
 ↓ 直到满足大小要求
最终块

✅ 优点

  • 兼顾结构和大小
  • 灵活适应不同文档
  • LangChain 官方推荐
  • 平衡性最佳

❌ 缺点

  • 配置较复杂
  • 需要针对语言调整分隔符

适用场景:通用文档处理,生产环境首选


切块的关键参数

参数推荐值说明
块大小256-1024 tokens根据模型限制和文档特点调整
重叠率10-20%避免语义断裂,保持上下文连续性
最小块大小100 tokens过小的块语义不完整
最大块大小模型限制的 80%留出空间给元数据和提示

重叠策略的重要性

问题场景

❌ 无重叠切块:
Chunk 1: "...机器学习模型需要大量数据"
Chunk 2: "进行训练。深度学习是..."

关键信息被切断了!

解决方案

✅ 有重叠切块(20% 重叠):
Chunk 1: "...机器学习模型需要大量数据"
Chunk 2: "模型需要大量数据进行训练。深度学习是..."

两个块都包含完整信息!

重叠率建议

  • 一般文档:10-20%
  • 技术文档:15-25%(概念连续性强)
  • 对话记录:20-30%(上下文依赖性高)

元数据增强

为每个块添加元数据,大幅提升检索效果:

核心元数据字段

{
  "chunk_id": "doc123_chunk_5",
  "content": "实际文本内容...",
  "document_id": "doc123",
  "document_title": "RAG 系统设计指南",
  "section": "第三章:向量检索",
  "page_number": 42,
  "author": "张三",
  "created_at": "2024-11-15",
  "chunk_index": 5,
  "total_chunks": 23,
  "keywords": ["RAG", "向量检索", "嵌入"],
  "prev_chunk_id": "doc123_chunk_4",
  "next_chunk_id": "doc123_chunk_6"
}

元数据的价值

  • 过滤检索:按文档、章节、日期筛选
  • 上下文扩展:获取相邻块补充信息
  • 答案引用:提供精确的来源定位
  • 权重调整:重要章节加权

二、向量嵌入 (Embedding)

为什么需要向量?

计算机本质上只能处理数字,而人类语言是符号系统。

向量嵌入 = 从符号到数值的桥梁


从 One-Hot 到词嵌入的演进

One-Hot 编码的局限

原理

  • 为每个词分配一个唯一索引
  • 用一个超长向量表示,只有一位是 1,其余都是 0

示例

词汇表 = ["猫", "小猫", "狗", "鱼", "爱"]

"猫"   → [1, 0, 0, 0, 0]
"小猫" → [0, 1, 0, 0, 0]
"狗"   → [0, 0, 1, 0, 0]

致命缺陷

1️⃣ 维度爆炸

  • 50,000 词汇 = 50,000 维向量
  • 99.998% 的位置都是 0(极度稀疏)
  • 存储和计算成本巨大

2️⃣ 无法表达语义

  • 任意两个不同词的相似度都是 0
  • “猫” 和 “小猫” 的相似度 = 0
  • “猫” 和 “汽车” 的相似度 = 0
  • 无法反映词与词之间的语义关系

数学证明

"猫"   = [1, 0, 0, 0, 0]
"小猫" = [0, 1, 0, 0, 0]

点积 = 1×0 + 0×1 + 0×0 + 0×0 + 0×0 = 0

结论:所有不同词都相互"正交"

词嵌入 (Word Embedding) 的突破

核心思想

  • 密集的低维向量表示词汇
  • 语义相似的词,向量距离更近

示例对比

One-Hot(50,000 维,稀疏):
"猫"   → [0, 0, 1, 0, 0, ..., 0]  (只有 1 个非零值)
"小猫" → [0, 0, 0, 0, 1, ..., 0]  (相似度 = 0)

Word Embedding(300 维,密集):
"猫"   → [0.8, -0.3, 0.5, ..., 0.2]
"小猫" → [0.75, -0.4, 0.52, ..., 0.18]
相似度 = 0.96 ✅ 高度相似!

关键特性

语义相似性可计算

相似度("猫", "小猫")   = 0.96  ← 非常接近
相似度("猫", "狗")     = 0.75  ← 都是宠物
相似度("猫", "汽车")   = 0.08  ← 不相关

支持语义运算

vector(国王) - vector(男人) + vector(女人) ≈ vector(女王)
vector(北京) - vector(中国) + vector(日本) ≈ vector(东京)

维度大幅降低

One-Hot: 50,000 维
Embedding: 300-1536 维(降低 98%)

向量空间的几何直观

想象一个三维空间(实际是 768 维或更高):

      动物性

        |    猫 •
        |     • 小猫
    狗 •|
        |
        |_______________→ 体型
       /
      / • 鱼

   水生性

空间特性

1️⃣ 相似词聚集成簇

  • 动物类:猫、狗、兔子、老虎
  • 水果类:苹果、香蕉、橙子
  • 交通工具:汽车、飞机、火车

2️⃣ 方向代表语义

  • 余弦相似度测量向量夹角
  • 方向相同 = 语义相似
  • 长度不重要,方向才重要

3️⃣ 可进行向量运算

  • 加法:组合语义
  • 减法:去除某种属性
  • 结果仍是有效的语义向量

余弦相似度 vs 欧氏距离

为什么用余弦相似度?

余弦相似度:关注方向,忽略长度

公式:cos(θ) = (A · B) / (||A|| × ||B||)

特点:
- 范围:-1 到 +1
- +1 表示方向完全相同(最相似)
- 0 表示垂直(不相关)
- -1 表示方向相反(对立)

欧氏距离:关注两点间的直线距离

公式:d = √[(x₁-x₂)² + (y₁-y₂)² + ...]

问题:
- 受向量长度影响大
- 长度相同方向相同的两个向量,距离可能很大

直观对比

向量 A = [1, 0]     (长度 = 1, 方向 = →)
向量 B = [2, 0]     (长度 = 2, 方向 = →)
向量 C = [0, 1]     (长度 = 1, 方向 = ↑)

欧氏距离:
d(A, B) = 1.0   ← 方向相同,但距离不为 0
d(A, C) = 1.41  ← 垂直

余弦相似度:
cos(A, B) = 1.0   ← 完全相同 ✅
cos(A, C) = 0.0   ← 不相关 ✅

结论:余弦相似度更准确反映语义关系

向量维度的语义意义

每一维可以理解为一种”隐含特征”或”概念”

简化示例(5 维嵌入空间)

维度含义:
- 维度 0: 动物性    (-1 非动物 ~ +1 动物)
- 维度 1: 情感倾向  (-1 负面 ~ +1 正面)
- 维度 2: 抽象程度  (-1 具体 ~ +1 抽象)
- 维度 3: 动态性    (-1 静态 ~ +1 动态)
- 维度 4: 时间性    (-1 过去 ~ +1 未来)

不同词的向量:
"猫"    →  [ 0.9,  0.3, -0.8,  0.4,  0.0]
"爱"    →  [ 0.0,  0.9, -0.2,  0.7,  0.0]
"悲伤"  →  [ 0.0, -0.8,  0.5, -0.6,  0.0]
"未来"  →  [ 0.0,  0.2,  0.9, -0.3,  0.9]

实际模型的维度

  • BERT: 768 维
  • OpenAI text-embedding-3-small: 1536 维
  • OpenAI text-embedding-3-large: 3072 维

每个维度的含义是隐式学习的,人类无法直接解释


向量是如何学到语义的?

核心理论:分布式假设

“一个词的意思由其上下文决定” —— J.R. Firth

学习过程示意

训练语料:
- "猫 喜欢吃 鱼"
- "小猫 喜欢追逐 老鼠"
- "猫 在树上 爬"
- "猫 是可爱的 宠物"

模型学习到:
- "猫" 经常出现在 "宠物"、"可爱"、"爬树" 等上下文
- "小猫" 出现在相似的上下文
→ 结论:相似上下文 → 相似向量

结果:
vector(猫) ≈ vector(小猫)  ✅
vector(猫) ≠ vector(鱼)    ✅

三、查询增强 (Query Enhancement)

为什么需要查询增强?

用户查询的典型问题

过于简短

用户:RAG 优化
系统:需要更多上下文才能理解具体问题

表达模糊

用户:这个怎么搞?
系统:"这个"是什么?"怎么搞"具体指什么操作?

专业术语缺失

用户:怎么让 AI 不胡说八道?
系统:用户实际想问 "如何减少 LLM 幻觉"

多义词歧义

用户:苹果怎么样?
系统:是水果还是科技公司?

查询增强的价值

  • 将模糊查询转化为精确查询
  • 扩展语义覆盖范围
  • 提高召回率和准确率

技术 1:HyDE (假设文档嵌入)

核心思想

  • 不直接搜索查询
  • 让 LLM 先生成”假设的答案”
  • 用假设答案的向量去检索

为什么有效?

问题:
"RAG 系统如何优化?"
→ 短查询向量,语义信息少

HyDE 生成的假设答案:
"RAG 系统优化可以通过以下方式:
1. 改进文档切块策略,使用语义切块...
2. 使用混合检索结合向量和关键词...
3. 引入重排序模块提升精度..."
→ 长文本向量,语义信息丰富

检索结果:
假设答案 ↔ 真实文档
语义更接近,匹配更准确 ✅

流程对比

传统检索:
查询 → 向量化 → 检索
"RAG优化" → vec → 结果

HyDE:
查询 → LLM生成假设答案 → 向量化 → 检索
"RAG优化" → "详细优化方案..." → vec → 结果

优点

  • 显著提升长尾查询的召回率
  • 自动补全用户未说明的上下文
  • 对专业领域查询效果显著

缺点

  • 额外的 LLM 调用成本
  • 增加延迟(约 1-2 秒)
  • 依赖 LLM 生成质量

适用场景

  • 复杂、专业性强的查询
  • 用户表达不完整的场景
  • 对召回率要求高的场景

技术 2:查询扩展 (Query Expansion)

核心思想

  • 生成多个查询变体
  • 对每个变体分别检索
  • 合并结果

扩展策略

策略 1:同义词替换

原查询:"如何优化 RAG 检索?"

生成变体:
- "如何提升 RAG 检索效果?"
- "如何改进 RAG 检索性能?"
- "怎样增强 RAG 搜索能力?"

策略 2:多角度改写

原查询:"RAG 系统很慢"

多角度变体:
- "如何提升 RAG 系统速度?"(解决方案角度)
- "RAG 系统性能瓶颈在哪?"(诊断角度)
- "RAG 响应时间优化方法"(技术角度)

策略 上下文扩展

参考

原查询:"优化向量检索"

扩展:
---
历史记录:
"""
user: 对话背景。
assistant: 当前对话是关于 Nginx 的介绍和使用等。
user: 报错 "no connection"
assistant: 报错"no connection"可能是因为……
"""
原问题: 怎么解决
检索词: ["Nginx报错"no connection"如何解决?","造成'no connection'报错的原因。","Nginx提示'no connection',要怎么办?"]
---

结果合并策略

多个查询变体 → 多组检索结果

按文档 ID 分组

计算加权平均分数

重新排序

返回 Top-K

优点

  • 提高召回率
  • 覆盖不同表达方式
  • 减少对单一查询的依赖

缺点

  • 多次检索增加计算成本
  • 可能引入噪声
  • 需要合理控制变体数量(建议 3-5 个)

技术 3:查询分解 (Query Decomposition)

核心思想

  • 将复杂查询拆分为多个子查询
  • 分别检索每个子查询
  • 综合多个答案

示例

复杂查询:
"对比 RAG 和微调的优缺点,并说明在什么场景下使用 RAG 更合适"

拆分为子查询:
1. "RAG 的优点和缺点是什么?"
2. "微调的优点和缺点是什么?"
3. "RAG 和微调的对比"
4. "RAG 的适用场景"

检索流程:
子查询 1 → 检索 → 答案片段 1
子查询 2 → 检索 → 答案片段 2
子查询 3 → 检索 → 答案片段 3
子查询 4 → 检索 → 答案片段 4

    综合生成最终答案

优点

  • 处理多跳推理问题
  • 每个子问题更精准
  • 答案更全面

缺点

  • LLM 调用成本增加
  • 子查询拆分质量影响结果
  • 答案综合需要额外处理

适用场景

  • 多方面对比问题
  • 需要多步推理的问题
  • 跨文档信息整合

核心思想

  • 结合向量检索和关键词检索
  • 发挥各自优势

两种检索方式对比

维度向量检索关键词检索 (BM25)
原理语义相似度词频统计
优势理解语义、处理同义词精确匹配、处理专有名词
劣势可能漏掉关键词无法理解语义
示例”猫” ≈ “小猫” ✅“iPhone 15” 精确匹配 ✅

混合检索流程

用户查询: "iPhone 15 的性能提升"

    ┌────┴────┐
    ↓         ↓
向量检索    关键词检索
(语义匹配)   (精确匹配)
    ↓         ↓
  结果A      结果B
    └────┬────┘

    分数归一化

  加权融合 (α × 向量分数 + (1-α) × BM25分数)

    最终排序

权重参数 α 的选择

α = 0.7  → 偏重语义理解(推荐)
α = 0.5  → 平衡模式
α = 0.3  → 偏重精确匹配

适用场景

  • 包含专有名词的查询(产品名、人名、地名)
  • 需要精确匹配和语义理解的场景
  • 生产环境的标准配置

技术 5:重排序 (Reranking)

为什么需要重排序?

初步检索的局限性

问题场景:
查询:"如何优化 RAG 系统的检索性能?"

初步检索结果(基于余弦相似度):
1. "RAG 系统是一种..." (分数 0.82) ← 相关但太泛
2. "性能优化的一般方法" (分数 0.79) ← 不够具体
3. "优化 RAG 检索的三种策略" (分数 0.75) ← 最相关!

问题:最相关的文档排名反而靠后!

根本原因

  • 向量相似度只看”方向”,不够精细
  • 没有考虑查询和文档的深层交互
  • 关键词匹配可能受词频影响

重排序的价值

  • 使用更强大的模型精细排序
  • 考虑查询-文档的交互关系
  • 显著提升前 K 个结果的质量

两阶段检索架构

第一阶段:召回 (Bi-Encoder)
10,000 个文档 → 向量检索 → Top 100 候选
速度:50ms

第二阶段:精排 (Cross-Encoder)
100 个候选 → 重排序 → Top 5 最佳结果
速度:200ms

总耗时:250ms  ✅ 可接受
准确率:提升 50-100%  ✅ 显著提升

完整的查询增强流程

生产环境推荐架构

用户查询

┌──────────────────┐
│  1. 查询理解       │
│  - 意图识别        │
│  - 实体提取        │
└──────────────────┘

┌──────────────────┐
│  2. 查询增强       │
│  - HyDE (可选)    │
│  - 查询扩展 (3变体)│
└──────────────────┘

┌──────────────────┐
│  3. 混合检索       │
│  - 向量检索 (70%) │
│  - BM25 (30%)     │
│  - 召回 Top 100   │
└──────────────────┘

┌──────────────────┐
│  4. 重排序         │
│  - Cross-Encoder  │
│  - 精选 Top 5     │
└──────────────────┘

┌──────────────────┐
│  5. 上下文构建     │
│  - 相邻块扩展      │
│  - 元数据注入      │
└──────────────────┘

送入 LLM 生成答案

第三部分:实战与最佳实践


五、实战案例:Quka.AI (Quokka)

项目简介

Quka.AI 是一个基于 RAG 的智能知识管理系统

核心定位

  • C 端用户为主
  • 重点:个人记忆存储,而非文档管理
  • 场景:日记、笔记、工作记录、生活灵感
  • 全场景AI助理,会根据语境进行Agent调用,避免一味地RAG,浪费Token引入噪音

系统架构

┌─────────────────────────────────────┐
│          前端 (React + WebSocket)   │
└─────────────────┬───────────────────┘

         ┌────────────────┐
         │  API Gateway   │
         └────────────────┘

     ┌────────────┼────────────┐
     ↓            ↓            ↓
┌─────────┐ ┌─────────┐ ┌─────────┐
│文档摄入  │ │查询服务  │ │管理服务 │
└─────────┘ └─────────┘ └─────────┘
     ↓            ↓            ↓
┌──────────────────────────────────┐
│   PostgreSQL + pgvector          │
│   (向量数据库)                    │
└──────────────────────────────────┘

         ┌────────────────┐
         │  LLM Service   │
         │  (多模型支持)   │
         └────────────────┘

核心功能

1. 记忆存储

  • 自定义录入:Block 富文本 / Markdown 自由输入
  • 文档上传:支持 PDF、Word、Markdown
  • 网页抓取:一键保存网页内容

2. 智能日记

  • 类似”每天一张草稿纸”
  • 内置 @工作助理,协助整理日记
  • 自动提取每日 TODO
  • 以WebSocket为通信基础,方便扩展 多人 + 实时协同

3. 管家 Agent

  • 类似 Excel 的数据管理
  • 与 PostgreSQL 交互
  • 自动理解并归类内容
  • 支持自然语言查询表格

技术亮点

1. C 端交互设计

  • 独立用户的 UI/UX 设计
  • 突出个人记忆而非长篇文档
  • 更贴近真实生活需求
  • WebSocket 基底,支持协同和共享

2. 自适应切块

  • 根据文档类型自动选择策略
  • 代码文档保持函数完整性
  • 表格数据保持结构完整
  • Markdown 按标题层级切分

3. 实时更新

  • 增量索引更新
  • 无需重建整个知识库
  • 支持文档修订和版本控制

实现概述

QukaAI 的 Chunk 策略

用户自定义录入内容(手动编辑,非文件导入)

使用LLM对用户文本进行理解与分析

  • Summary

首先让 LLM 对完整的输入内容进行理解,从内容中提取 标题,标签,与内容相关的时间节点(若无则使用内容的创建时间代替)

  • Chunk

将一块内容分成若干(如果有)个语义相关的分类,随后分别对原文及拆解后的分类内容做Embedding 最终形成 1 doc 对应 n chunks(embedding chunks),若有一个chunk被相似度命中,则引用原文全部内容(注意,这里的原文是指用户在界面中录入的一份自定义内容,而非一整份PDF) 。

文件导入

首先对文件进行转MarkDown处理,其次使用 语义切块 + 递归 + 重叠 的方式对文件进行 chunk,使用LLM阅读第一个分块来大概理解全文的内容,生成本篇内容的元信息,该元信息会关联至本篇内容的所有 chunk,同时每个 chunk 会记录下它的 前一个chunk 与 后一个chunk。

QukaAI 的 Retrieval 策略

  1. 语义增强

    对用户的输入进行增强,结合上下文+当前用户的输入进行同义词替换 + 多角度改写 + 上下文替换,随后获得一组增强后的query

  2. 基础检索

    将增强后的 query 进行 embedding 与系统中已经 embedding 后的 chunk 进行语义相似度对比,通过简单的 limit 算法取出大部分近似内容,若匹配到的 chunk 是通过文件切分出来的,则会拼接上该 chunk 的前后内容以及文件的元信息。

  3. 重排

    将较多的近似内容再通过专业的重排模型与 query 进行进一步相似度评分,再通过 limit 算法取较少的最相似的部分内容

QukaAI 的 Generation 策略

组织用于 Generation 阶段的 Prompt,在 Prompt 中加入现实世界中的 时间节点(前后一个月),国际上大部分的节日日期,等等一系列与日常生活相关的元信息,再结合重排后的文档内容,最终由 LLM 融合理解并给出最终的回答。

比如:我把车停在了 B2 116号车位
问:我昨天把车停哪了?

思考:用户肯定不止一次记录了车位信息,所以昨天是什么时候就显得尤为重要,故需要在Prompt中加入近期时间节点的介绍(有了近期,LLM可以推理出跟久或更早的日期)

比如:(情人节当天):我今天给女朋友买了一辆车。 这段内容通过QukaAI处理后,会从内容中提取时间,LLM识别到是“今天”, 再对照Prompt中的时间节点知道了今天是 xxxx年2月14日
问:我去年的情人节给女朋友送了什么礼物? 通过Prompt中对国际上大部分主流节日日期的注入后,LLM可能会知道,中国的情人节是几月几号,美国的情人节是几月几号,也通过 “去年” 这个输入结合当前的时间节点信息推出去年是 xxxx年,随后在 Retrieval 的内容中除了匹配 “给女朋友送了什么礼物” 的语义,还会匹配事件发生的时间,最终得出 “xxxx年的情人节送了一辆车” 的结论。


在线体验

访问 quka.ai 免费试用

快速开始

  1. 注册账号
  2. 创建第一个笔记或上传文档
  3. 与 AI 对话,体验智能问答
  4. 使用 @工作助理 整理日记

开源地址


六、总结:RAG 系统构建要点

技术架构很基础,细节还是在于 Prompt 优化上。

文档切块 ✂️

选择合适的切块策略

  • 一般文档:递归字符切块(LangChain 推荐)
  • 结构化文档:语义切块
  • 简单场景:固定大小切块

关键参数

  • 块大小:256-1024 tokens
  • 重叠率:10-20%
  • 添加丰富的元数据

向量嵌入 🧮

模型选择

  • 预算有限:开源模型(all-MiniLM)
  • 中文为主:bge-large-zh
  • 追求精度:OpenAI text-embedding-3-large

优化策略

  • 批处理提高效率
  • 缓存降低成本
  • 维度与性能平衡(1024-1536 维为佳)

查询增强 🔍

多策略组合

  • 简单查询:直接检索
  • 复杂查询:HyDE + 查询扩展
  • 专有名词:混合检索(向量 + BM25)

重排序是关键

  • 两阶段架构:Bi-Encoder 召回 + Cross-Encoder 精排
  • 显著提升准确率(50-100%)
  • 生产环境必备

系统优化 ⚡

性能优化

  • ANN 索引(HNSW)
  • 批处理 + GPU 加速
  • 缓存热点查询

质量优化

  • 建立评估数据集
  • A/B 测试验证
  • 持续迭代改进

七、常见陷阱避免 ⚠️

切块陷阱

切块过大:超过模型限制,检索粗糙 ❌ 切块过小:语义不完整,上下文缺失 ❌ 无重叠:关键信息被截断

检索陷阱

忽略查询增强:用户查询简短模糊,直接检索效果差 ❌ 单一检索策略:不同场景需要不同策略 ❌ 缺少重排序:初步检索的排序不够精准

优化陷阱

过度优化:盲目追求速度,牺牲准确率 ❌ 缺少评估体系:无法量化改进效果 ❌ 忽视成本:LLM 调用成本失控


八、进阶学习资源 📚

论文

框架和工具

  • LangChain:RAG 应用开发框架
  • LlamaIndex:数据索引和查询引擎
  • Sentence Transformers:句子嵌入库
  • Haystack:端到端 NLP 框架

向量数据库

  • Pinecone:托管向量数据库
  • Qdrant:开源向量搜索引擎
  • Milvus:云原生向量数据库
  • Weaviate:开源向量搜索引擎
  • pgvector:PostgreSQL 向量扩展
Share: