21 Embedding 向量化
Embedding 向量化
Embedding 向量化的核心是把 chunk 文本转换成可以计算相似度的数字向量,让后面的向量检索能够根据语义找到相关片段。
[TOC]
1. 学完本节要达到什么程度
前面已经完成了文档切片。
现在我们有:
documentId
chunkIndex
content
titlePath
pageStart
pageEnd
metadata
本节要做的是:
读取 chunk -> 调用 Embedding 模型
-> 得到向量
-> 写回 rag_chunk -> 更新处理状态
Embedding 不是回答问题。
它只是把文本变成向量,为检索做准备。
2. Embedding 流程
graph TD;
A["读取待向量化 chunks"] --> B["按批次组织文本"];
B --> C["调用 Embedding 模型"];
C --> D["返回 embedding 数组"];
D --> E["校验向量维度"];
E --> F["写入 rag_chunk.embedding"]; F --> G["更新 chunk 状态为 EMBEDDED"]; G --> H["记录模型名和向量版本"];
第一版可以同步执行。
后面数据量变大以后,再改成异步任务。
3. 为什么需要 Embedding
关键词检索依赖字面匹配。
比如:
文件上传限制是多少?
最大附件大小是多少?
这两句话意思接近,但字面词不完全一样。
Embedding 可以把语义相近的文本映射到距离更近的向量空间。
所以 RAG 里通常会对两类文本做 Embedding:
文档 chunk用户问题
然后用向量距离做相似度搜索。
4. 模型选择
选择 Embedding 模型时先看几件事:
是否支持中文
向量维度是多少
单次最多输入多少 token是否支持批量请求
价格和限流
和生成模型是否同一家服务商
学习阶段可以先固定一个模型。
不要频繁换。
因为一旦换 Embedding 模型,旧向量通常需要全部重算。
5. 向量维度
向量维度必须和数据库字段一致。
比如 pgvector 字段:
embedding vector(1536)
就要求模型返回的向量长度必须是 1536。
如果模型返回 1024 维,却写入 vector(1536),数据库会报错。
建议把维度写进配置:
rag.embedding.model=text-embedding
rag.embedding.dimension=1536
rag.embedding.batch-size=32
6. 批量向量化
不要一个 chunk 调一次接口。
更合理的方式是按批次处理:
一次读取 32 个 chunk一次请求 embedding 服务
一次批量写回数据库
好处:
减少网络请求
提高吞吐
便于失败重试
便于记录任务进度
第一版批量大小不要太大。
先从 16 或 32 开始。
7. 需要保存的信息
除了 embedding 本身,还建议保存:
embeddingModel
embeddingDimension
embeddingVersion
embeddedAt
status
errorMessage
原因是后面会遇到:
换模型
重算向量
排查检索效果
比较不同版本
如果只存向量,不存模型信息,后面很难追溯。
8. Java 和 Python 怎么分工
第一版可以有两种做法。
方案一:Java 直接调用 Embedding API。
适合:
项目主流程都在 JavaEmbedding API 是普通 HTTP不想多一层 Python 服务
方案二:Java 调 Python Embedding 服务。
适合:
后面要接 LangChain需要复用 Python RAG 代码
Embedding 逻辑会做更多实验
学习阶段建议先保持一致:
Java 控制入库状态
Python 提供 AI 能力
9. 失败处理
Embedding 失败不要直接丢掉。
至少记录:
documentId
chunkIndex
失败原因
重试次数
最后失败时间
常见失败:
API Key 不正确
模型限流
文本太长
网络超时
向量维度不匹配
数据库写入失败
失败后可以把 chunk 状态标记为:
EMBED_FAILED
后面提供一个重试任务。
10. Embedding 的工程化落地
向量化真正困难的地方不是调用一次模型,而是保证模型、维度、文本版本和数据库中的每条向量长期一致。
10.1 模型身份和数据血缘
每条向量都应能够追溯到模型提供商、模型名、模型版本、输出维度、归一化方式、输入文本摘要和生成时间。只保存一个 embedding 字段,后续很难判断旧向量是否还能继续使用。
文本清洗或切片版本变化后,即使 chunk ID 没变,也应重新生成向量。可以为输入文本计算摘要,向量化前比较摘要,避免把旧向量错误地复用到新内容上。
10.2 批处理、限流和重试
批量大小需要同时考虑模型的单次输入限制、总 token 限制、网络超时和供应商限流。不要只按 chunk 数量分批,因为不同 chunk 的长度差异可能很大。
遇到限流和临时网络错误时使用指数退避,并设置最大重试次数。永久错误要单独记录,例如空文本、输入过长、模型不存在和维度不匹配,避免任务队列无限循环。
10.3 监控和验收
建议监控每批文本数、输入 token、请求耗时、失败率、重试次数、空向量数量和维度异常数量。模型接口成功不代表数据正确,还应检查返回数组数量是否与输入数量一一对应。
验收时至少验证中文短句、长段落、空白文本、超长文本、批量部分失败和重复执行。换模型前必须用固定问题集比较检索效果,而不是只比较价格或向量维度。
11. 常见问题
11.1 是否要对标题一起向量化
建议要。
chunk 内容里最好带上标题路径。
比如:
标题路径:产品手册 > 上传限制
正文:单个文件最大 20MB。
这样用户问“上传限制”时更容易召回。
11.2 换 Embedding 模型要不要重算
通常要。
不同模型生成的向量空间不一样。
不能把不同模型的向量混在同一个相似度索引里直接比较。
11.3 空文本要不要生成向量
不要。
空文本、过短文本、纯符号文本都应该提前过滤。
12. 练习清单
完成几件事:
能解释 Embedding 在 RAG 中的作用
能说明 chunk 向量和问题向量的区别
能写出 embedding 维度配置
能设计批量向量化流程
能列出 embedding 失败原因
能说明换模型为什么要重算向量
13. 小结
本节的结论:
Embedding 是 RAG 检索的基础,它把文本变成向量,但检索效果仍然取决于文本质量、切片质量和模型选择。
向量化链路:
chunk
-> Embedding 模型
-> embedding -> 写回数据库
-> 后续检索