RAG03:向量化
从Embedding模型选择、向量维度、批处理到版本管理,理解如何将文本转换为向量表示。
向量化是 RAG 的核心技术,它将文本转换为高维向量表示,使得语义相似的文本在向量空间中距离更近,为后续的向量检索提供基础。
向量化的重要性
为什么需要向量化
| 问题 | 传统方法 | 向量化方法 |
|---|---|---|
| 语义匹配 | 关键词匹配,无法理解语义 | 语义匹配,理解上下文 |
| 同义词处理 | 需要手动维护同义词表 | 自动处理同义词 |
| 多语言支持 | 需要翻译 | 跨语言语义理解 |
| 模糊匹配 | 难以实现 | 自然支持 |
向量表示的优势
| 优势 | 说明 | 示例 |
|---|---|---|
| 语义理解 | 理解文本语义 | ”苹果公司”和”Apple”语义相似 |
| 数学运算 | 支持向量运算 | 向量加减表示语义变化 |
| 距离度量 | 计算语义距离 | 余弦相似度衡量相似性 |
| 维度压缩 | 高维数据压缩 | 降维可视化 |
Embedding 模型选择
常见 Embedding 模型
| 模型 | 提供商 | 特点 | 适用场景 |
|---|---|---|---|
| text-embedding-3-small | OpenAI | 小模型,速度快 | 快速检索 |
| text-embedding-3-large | OpenAI | 大模型,精度高 | 高精度检索 |
| text-embedding-ada-002 | OpenAI | 平衡速度和精度 | 通用场景 |
| sentence-transformers | HuggingFace | 开源,可定制 | 私有部署 |
| bge-small-zh | HuggingFace | 中文优化,轻量 | 中文场景 |
| bge-large-zh | HuggingFace | 中文优化,精度高 | 高精度中文场景 |
模型选择策略
# 根据需求选择模型
def select_embedding_model(requirement):
if requirement == 'speed':
return 'text-embedding-3-small'
elif requirement == 'accuracy':
return 'text-embedding-3-large'
elif requirement == 'chinese':
return 'bge-large-zh'
elif requirement == 'open_source':
return 'sentence-transformers/all-MiniLM-L6-v2'
else:
return 'text-embedding-ada-002'
模型评估
| 评估指标 | 说明 | 目标值 |
|---|---|---|
| 语义相似度 | 语义相似文本的向量相似度 | > 0.8 |
| 语义区分度 | 语义不同文本的向量距离 | < 0.5 |
| 召回率 | 检索时的召回率 | > 85% |
| 推理速度 | 单条文本的向量化时间 | < 100ms |
| 向量维度 | 向量的维度大小 | 384-1536 |
向量维度选择
维度对检索的影响
| 维度 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 低维度 (384) | 速度快,存储小 | 精度较低 | 快速检索 |
| 中维度 (768) | 平衡速度和精度 | 中等存储 | 通用场景 |
| 高维度 (1024-1536) | 精度高 | 速度慢,存储大 | 高精度检索 |
维度选择策略
# 根据场景选择维度
def select_dimension(scenario):
if scenario == 'fast':
return 384
elif scenario == 'balanced':
return 768
elif scenario == 'accurate':
return 1536
else:
return 768
维度与性能的关系
维度:384
- 存储:约 3KB/向量
- 检索速度:快
- 精度:一般
维度:768
- 存储:约 6KB/向量
- 检索速度:中
- 精度:良好
维度:1536
- 存储:约 12KB/向量
- 检索速度:慢
- 精度:高
向量化实现
基本向量化
from openai import OpenAI
client = OpenAI(api_key='your-api-key')
def get_embedding(text, model='text-embedding-ada-002'):
text = text.replace('\n', ' ')
response = client.embeddings.create(
input=[text],
model=model
)
return response.data[0].embedding
批处理向量化
def batch_get_embeddings(texts, model='text-embedding-ada-002', batch_size=100):
embeddings = []
for i in range(0, len(texts), batch_size):
batch = texts[i:i+batch_size]
batch = [text.replace('\n', ' ') for text in batch]
response = client.embeddings.create(
input=batch,
model=model
)
embeddings.extend([item.embedding for item in response.data])
return embeddings
开源模型向量化
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
def get_open_source_embedding(text):
embedding = model.encode(text)
return embedding.tolist()
向量化的优化
文本预处理
文本预处理提高向量化质量:
| 预处理步骤 | 说明 | 示例 |
|---|---|---|
| 去除噪声 | 去除无关内容 | 广告、导航、页眉页脚 |
| 统一格式 | 统一文本格式 | 换行、空格、编码 |
| 分词处理 | 分词和词性标注 | 中文分词 |
| 停用词过滤 | 去除停用词 | 的、了、在 |
语义增强
语义增强提高向量的语义表达能力:
def enhance_text_for_embedding(text, metadata):
# 添加标题信息
enhanced = f"标题:{metadata.get('title', '')}\n"
# 添加上下文信息
enhanced += f"上下文:{metadata.get('context', '')}\n"
# 添加内容类型
enhanced += f"类型:{metadata.get('type', '文本')}\n"
# 添加正文内容
enhanced += f"内容:{text}\n"
return enhanced
向量归一化
向量归一化确保向量在同一尺度:
import numpy as np
def normalize_vector(embedding):
norm = np.linalg.norm(embedding)
if norm == 0:
return embedding
return (np.array(embedding) / norm).tolist()
向量版本管理
版本管理的重要性
| 问题 | 影响 | 后果 |
|---|---|---|
| 模型变更 | 向量表示变化 | 检索结果不一致 |
| 维度变更 | 向量维度变化 | 无法匹配 |
| 预处理变更 | 文本表示变化 | 检索精度下降 |
版本管理策略
class EmbeddingVersionManager:
def __init__(self):
self.versions = {}
def register_version(self, version_id, model, dimension, preprocessing):
self.versions[version_id] = {
'model': model,
'dimension': dimension,
'preprocessing': preprocessing
}
def get_version(self, version_id):
return self.versions.get(version_id)
def migrate_vectors(self, old_version_id, new_version_id, vectors):
# 重新向量化
new_version = self.get_version(new_version_id)
return [get_embedding(text, new_version['model']) for text in vectors]
版本迁移流程
1. 创建新版本
2. 注册版本信息
3. 标记旧版本为 deprecated
4. 逐步迁移向量
5. 验证迁移结果
6. 切换到新版本
7. 清理旧版本向量
向量化的常见问题
问题1:向量质量差
表现:语义相似的文本向量距离远
解决方案:
- 使用更高精度的模型
- 优化文本预处理
- 添加语义增强信息
问题2:向量化速度慢
表现:批量向量化耗时过长
解决方案:
- 使用更快的模型
- 使用批处理
- 并行处理
问题3:向量存储大
表现:向量占用大量存储空间
解决方案:
- 使用低维度模型
- 向量压缩
- 使用专门的向量数据库
问题4:模型版本不兼容
表现:不同版本的向量无法匹配
解决方案:
- 建立版本管理
- 统一版本
- 版本迁移
向量化的最佳实践
向量化流程
1. 文本预处理
2. 语义增强
3. 选择 Embedding 模型
4. 执行向量化
5. 向量归一化
6. 版本标记
7. 存储向量
质量保障
1. 定期评估 Embedding 模型
2. 监控向量质量
3. 建立版本管理
4. 优化预处理流程
5. 使用多个模型交叉验证
性能优化
1. 使用批处理提高吞吐量
2. 使用缓存减少重复计算
3. 选择合适的维度
4. 使用并行处理
5. 异步向量化
项目判断清单
- 需要高精度检索 → 使用 text-embedding-3-large 或 bge-large-zh
- 需要快速检索 → 使用 text-embedding-3-small 或 bge-small-zh
- 需要中文支持 → 使用 bge-*-zh 系列
- 需要私有部署 → 使用 sentence-transformers
- 向量质量差 → 优化预处理或换用更高精度模型
- 向量化速度慢 → 使用批处理或更快的模型
- 向量存储大 → 使用低维度模型或向量压缩
- 需要长期维护 → 建立版本管理和迁移机制