【0-1的agent进阶篇】RAG:从Embedding到检索增强生成的底层逻辑

🔥个人主页:代码不加冰(欢迎来访)

🎬作者简介:java后端学习者

❄️个人专栏:LeetCode刷题日记 ,苍穹外卖日记SSM框架深入JavaWeb

命运的结局尽可永在,不屈的挑战却不可须臾或缺!


大家好,我是代码不加冰,好久没有发文章了,最近开始回归更新,让我们一起进步。这篇主要给大家分享一下RAG的相关内容。不是仅仅是一个词汇,而是带你从项目的源码看起,分析内部的逻辑。


RAG = 把用户的问题变成向量 → 去知识库找相关内容 → 把找到的内容塞回 Prompt → 再让大模型回答。

而 LangChain4j 做的事情,就是把这套流程拆成了一组非常清晰的抽象。

而我们今天主要侧重第一步Embedding,也就是文本向量化,文字怎么变成向量,刚听到这些词的时候我也会觉得莫名其妙,这明明是毫不相关的领域,到底是什么联系的,这篇文章就带你深入了解。

一、RAG 到底是什么

RAG = Retrieval-Augmented Generation

翻译成人话:

先检索,再增强,最后生成。

它解决的核心问题是:

LLM 的知识是死的(训练数据截止日期之后的事它不知道),

但 RAG 可以在用户提问时,从外部知识库实时检索相关信息,塞进 Prompt,让 LLM 基于这些信息回答。

所以 RAG 不是重新训练 LLM,而是给 LLM 配一个"外挂知识库"


二、RAG 整体链路

RAG 有两条链路,一上一下,缺一不可:

复制代码
text

                    RAG
                     │
          ┌──────────┴──────────┐
          │                     │
       Ingestion             Retrieval
        数据入库                数据检索

链路一:Ingestion(数据入库)------ 提前准备好知识

复制代码
text

公司员工手册.pdf
       ↓
   Document
       ↓
DocumentSplitter(切分)
       ↓
  TextSegment(文本片段)
       ↓
 EmbeddingModel(向量化)  ← 这里就是 Embedding
       ↓
    Embedding(向量)
       ↓
 EmbeddingStore(向量数据库)

最终库里存的是:

复制代码
text

TextSegment: "员工请假需要提前3天提交申请..."
Embedding:    [0.023, -0.182, 0.731, ...]

Ingestion 的本质 :把人类能理解的知识,转换成机器能进行语义检索的向量。


链路二:Retrieval(检索增强)------ 用户提问时实时检索

复制代码
text

用户:"请假需要提前多久?"
       ↓
  UserMessage
       ↓
     Query
       ↓
QueryTransformer(查询改写)
       ↓
   QueryRouter(路由选择)
       ↓
ContentRetriever(真正检索)  ← 这里会用到 Embedding 进行相似度搜索
       ↓
 EmbeddingStore(向量库)
       ↓
   Top-K 相关内容
       ↓
ContentAggregator(汇总排序)
       ↓
 ContentInjector(注入 Prompt)
       ↓
增强后的 UserMessage
       ↓
    ChatModel(LLM)
       ↓
     Answer

三、现在,我们聚焦Embedding

上面的链路中,Ingestion 的 EmbeddingModelRetrieval 的相似度搜索,都围绕同一个核心概念:

Embedding(文本向量化)


四、Embedding 到底是什么

在 LangChain4j 源码中,Embedding 就是一个 float[]

复制代码
java

public class Embedding {
    private final float[] vector;
}

例如一个 384 维的向量:

复制代码
java

float[] vector = {
    0.12f, -0.52f, 0.83f, 0.19f, ...
};  // 长度 = 384

Embedding ≠ 文本

Embedding 是文本经过模型编码后得到的一组数字

维度取决于模型:

模型 维度
某些轻量模型 384
OpenAI text-embedding-ada-002 1536
Cohere 某些模型 768

所以:

复制代码
text

Embedding = float[dimension]

五、为什么一定要 Embedding

这是最核心的问题。

用户问:

"请假需要提前多久申请?"

知识库里可能根本没有这句话,它写的是:

"员工休假须至少提前三个工作日提交审批。"

如果用传统字符串匹配(关键词搜索),基本匹配不到。

但如果用 Embedding

复制代码
text

问题:"请假需要提前多久申请?"
       ↓
    Embedding
       ↓
[0.21, 0.83, -0.14, 0.52, ...]

知识:"员工休假须至少提前三个工作日提交审批。"
       ↓
    Embedding
       ↓
[0.19, 0.79, -0.11, 0.48, ...]

这两个向量在向量空间中距离很近,所以能被检索到。

复制代码
text

请假需要提前多久?
        ↓
     Embedding
        ↓
   [0.21, 0.83...]
        ↓
向量数据库进行相似度搜索
        ↓
找到:"员工休假须至少提前三个工作日......"

这就是 Semantic Search(语义搜索)

不是字面匹配,而是意思匹配。


六、CosineSimilarity:怎么判断两个向量像不像

向量数据库找到了候选结果,但怎么排序呢

相似度计算 ,最常用的是 余弦相似度

源码中的计算逻辑:

复制代码
java

double dotProduct = 0.0;
double normA = 0.0;
double normB = 0.0;

for (int i = 0; i < vectorA.length; i++) {
    dotProduct += vectorA[i] * vectorB[i];
    normA += vectorA[i] * vectorA[i];
    normB += vectorB[i] * vectorB[i];
}

return dotProduct / Math.sqrt(normA) * Math.sqrt(normB);

用人话翻译:

判断两个向量的"方向"有多一致。

比如:

复制代码
text

A ────────────────>
B ──────────────>
方向非常接近 → 相似度高 ✅

text

A ────────────────>
B <────────────────
方向相反 → 相似度低 ❌

七、为什么用余弦,而不是算距离

因为 Embedding 关注的是语义方向 ,而不是长度

举个例子:

text

复制代码
A = [1, 1]
B = [10, 10]

虽然 |A| ≠ |B|(长度不同),但方向完全一样。

余弦相似度:

text

复制代码
cos θ = 1

所以它认为 A 和 B 非常相似 ,这非常适合语义向量------

"很小的事"和"很大的事"在语义上可能是同一类。


八、为什么 LangChain4j 又搞了一个 RelevanceScore

余弦相似度的范围是 [-1, 1],但 RAG 开发中更希望看到 [0, 1]

所以 LangChain4j 做了转换:

复制代码
java

return (cosineSimilarity + 1) / 2;

映射关系:

余弦相似度 RelevanceScore
-1 0
-0.5 0.25
0 0.5
0.5 0.75
1 1

然后就可以做阈值过滤:

复制代码
java

if (match.score() >= 0.7) {
    // 认为比较相关,采纳
}

九、不同 Embedding 模型为什么不能混用

这是一个非常容易踩的坑。

  • 模型 A:维度 = 1536

  • 模型 B:维度 = 384

如果你的向量数据库 Collection 定义的是 dimension = 1536,却塞入 384 维向量:

复制代码
text

❌ 报错

可以这样理解:

复制代码
text

EmbeddingModel.dimension() = 数据库表结构的 Schema

就像 age INT 不能塞字符串一样,向量维度必须严格匹配


十、Embedding 在 RAG 中的两个位置

理解了 Embedding,你就能看懂它在 RAG 中的两次出现:

复制代码
text

                    RAG
                     │
          ┌──────────┴──────────┐
          │                     │
       Ingestion             Retrieval
          │                     │
          ▼                     ▼
    文档 → EmbeddingModel   问题 → EmbeddingModel
          │                     │
          ▼                     ▼
       Embedding            Embedding
          │                     │
          ▼                     ▼
     EmbeddingStore      相似度搜索(Cosine)
                               │
                               ▼
                          找到相关内容
阶段 Embedding 的作用
Ingestion 把文档变成向量,存入数据库
Retrieval 把用户问题变成向量,去数据库里找最相似的

十一、整体回顾

复制代码
text

┌─────────────────────────────────────────────────────────────┐
│                      RAG 完整链路                          │
├──────────────────────────┬──────────────────────────────────┤
│       Ingestion          │           Retrieval              │
├──────────────────────────┼──────────────────────────────────┤
│                          │                                  │
│  PDF → Document         │  用户问题 → Query                │
│       ↓                 │           ↓                      │
│  DocumentSplitter       │  QueryTransformer               │
│       ↓                 │           ↓                      │
│  TextSegment            │  QueryRouter                    │
│       ↓                 │           ↓                      │
│  ★ EmbeddingModel ★     │  ContentRetriever               │
│       ↓                 │           ↓                      │
│  ★ Embedding ★          │  ★ 相似度搜索(Cosine)★       │
│       ↓                 │           ↓                      │
│  EmbeddingStore         │  ContentAggregator              │
│                          │           ↓                      │
│                          │  ContentInjector               │
│                          │           ↓                      │
│                          │  ChatModel → Answer             │
└──────────────────────────┴──────────────────────────────────┘

下一篇预告

这一篇我们重点攻克了 Embedding 是什么、为什么、怎么算相似度

下一篇继续深入:向量数据库的存储与索引

相关推荐
小强库计算机毕业设计1 小时前
SpringBoot+Vue3 学生宿舍管理系统实战
java·spring boot·后端·vue·学生宿舍管理系统
李冰然1 小时前
深入Java集合框架:HashMap源码解析(JDK 8)
java
武雄(小星Ai)2 小时前
Agent记忆系统工程排坑:从Prompt Cache被打碎到Embedding迁移数据税
ai·系统架构·agent·智能体·深度评测
新知图书2 小时前
6.4 关键时刻:它自己修好了 Bug
人工智能·agent·ai agent·智能体
罗高2 小时前
AI Agent 可观测性完全指南:遥测、追踪、指标与评估
llm·agent
罗高3 小时前
评估 AI Agent 技能:用 Langfuse 让技能质量变得可衡量
llm·agent
桦说编程3 小时前
盘点并发集合里那些容易误判的行为
java·后端·性能优化
ningmengjing_3 小时前
MCP 通讯方式与实现指南
python·agent·mcp
IT爱学堂4 小时前
java版数据结构和算法+AI算法和技能学习指南
java·开发语言