Embedding 与向量基础
High Contrast
Dark Mode
Light Mode
Sepia
Forest
3 min read597 words

Embedding 与向量基础

Embedding(嵌入向量)是 RAG 系统的核心技术。理解 Embedding 的原理,是掌握 RAG 的基础。

什么是 Embedding?

Embedding 是将文本、图片等非结构化数据转换为固定长度的数值向量的过程。转换后的向量能够捕捉数据的语义信息,语义相近的内容在向量空间中距离更近。

graph LR subgraph 文本 T1["我喜欢吃苹果"] T2["我爱吃水果"] T3["今天股市大跌"] end subgraph 向量空间 V1["[0.82, 0.15, 0.93, ...]"] V2["[0.80, 0.18, 0.91, ...]"] V3["[0.12, 0.87, 0.23, ...]"] end T1 -->|Embedding 模型| V1 T2 -->|Embedding 模型| V2 T3 -->|Embedding 模型| V3 V1 -.->|相似度 0.95| V2 V1 -.->|相似度 0.12| V3 style V1 fill:#c8e6c9,stroke:#388e3c,stroke-width:2px style V2 fill:#c8e6c9,stroke:#388e3c,stroke-width:2px style V3 fill:#ffcdd2,stroke:#c62828,stroke-width:2px

核心概念

概念 说明
维度 向量的长度,如 1536 维
语义相似度 向量之间的距离,越近语义越相似
余弦相似度 最常用的相似度计算方法
向量空间 所有向量所在的高维空间

相似度计算

余弦相似度

余弦相似度衡量两个向量的方向是否一致,是 RAG 中最常用的相似度指标。

"""
三种常用的相似度计算方法
"""
import numpy as np
def cosine_similarity(a: list[float], b: list[float]) -> float:
"""
余弦相似度
- 值域: [-1, 1]
- 1 = 完全相同, 0 = 无关, -1 = 完全相反
- 最常用于文本相似度
"""
a, b = np.array(a), np.array(b)
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
def euclidean_distance(a: list[float], b: list[float]) -> float:
"""
欧氏距离
- 值域: [0, +inf)
- 越小越相似
- 适合低维空间
"""
a, b = np.array(a), np.array(b)
return np.linalg.norm(a - b)
def dot_product(a: list[float], b: list[float]) -> float:
"""
点积
- 值域: (-inf, +inf)
- 越大越相似
- 需要归一化后使用
"""
a, b = np.array(a), np.array(b)
return np.dot(a, b)
# 演示
vec1 = [0.82, 0.15, 0.93, 0.41]  # "我喜欢吃苹果"
vec2 = [0.80, 0.18, 0.91, 0.39]  # "我爱吃水果"
vec3 = [0.12, 0.87, 0.23, 0.66]  # "今天股市大跌"
print(f"苹果 vs 水果: {cosine_similarity(vec1, vec2):.4f}")  # ~0.999
print(f"苹果 vs 股市: {cosine_similarity(vec1, vec3):.4f}")  # ~0.573

Embedding 模型

主流 Embedding 模型对比

模型 提供方 维度 最大 Token 中文支持 价格
text-embedding-3-small OpenAI 1536 8191 $0.02/1M tokens
text-embedding-3-large OpenAI 3072 8191 $0.13/1M tokens
embed-v3 Cohere 1024 512 $0.10/1M tokens
BGE-large-zh BAAI 1024 512 优秀 免费(开源)
E5-large-v2 Microsoft 1024 512 中等 免费(开源)
GTE-large Alibaba 1024 8192 优秀 免费(开源)

如何选择?

graph TB A{你的场景?} --> B{预算充足?} A --> C{主要语言?} B -->|是| D[OpenAI text-embedding-3-large] B -->|否| E{需要私有部署?} E -->|是| F{主要语言?} E -->|否| G[OpenAI text-embedding-3-small] F -->|中文| H[BGE-large-zh] F -->|英文| I[E5-large-v2] F -->|多语言| J[GTE-large] C -->|中文为主| K[BGE 或 GTE 系列] C -->|英文为主| L[E5 或 OpenAI] style D fill:#fff3e0,stroke:#f57c00,stroke-width:2px style G fill:#c8e6c9,stroke:#388e3c,stroke-width:3px style H fill:#e3f2fd,stroke:#1976d2,stroke-width:2px

使用 OpenAI Embedding

"""
使用 OpenAI Embedding API
"""
from openai import OpenAI
client = OpenAI()
def get_embeddings(texts: list[str], model: str = "text-embedding-3-small") -> list[list[float]]:
"""批量获取文本向量"""
response = client.embeddings.create(
model=model,
input=texts
)
return [item.embedding for item in response.data]
# 单条文本
embedding = get_embeddings(["你好,世界"])[0]
print(f"向量维度: {len(embedding)}")  # 1536
print(f"前5个值: {embedding[:5]}")
# 批量处理
texts = [
"Python 是一门优秀的编程语言",
"Java 也是流行的编程语言",
"今天天气很好",
]
embeddings = get_embeddings(texts)
print(f"处理了 {len(embeddings)} 条文本")

使用开源 Embedding(本地部署)

"""
使用 sentence-transformers 本地部署 Embedding 模型
适合私有化部署场景
"""
from sentence_transformers import SentenceTransformer
# 加载模型(首次会下载)
model = SentenceTransformer("BAAI/bge-large-zh-v1.5")
# 编码文本
texts = [
"Python 设计模式是软件工程的重要基础",
"设计模式帮助编写更优雅的代码",
"今天的晚餐吃什么好呢",
]
embeddings = model.encode(texts, normalize_embeddings=True)
print(f"向量维度: {embeddings.shape[1]}")  # 1024
print(f"处理了 {len(embeddings)} 条文本")
# 计算相似度
from numpy import dot
similarity = dot(embeddings[0], embeddings[1])
print(f"设计模式 vs 优雅代码: {similarity:.4f}")  # 高相似度
similarity = dot(embeddings[0], embeddings[2])
print(f"设计模式 vs 晚餐: {similarity:.4f}")  # 低相似度

向量数据库基础

向量数据库专门用于存储和检索高维向量数据,是 RAG 系统的核心基础设施。

向量数据库的核心能力

graph TB A[向量数据库] --> B[存储] A --> C[检索] A --> D[过滤] A --> E[管理] B --> B1[高维向量存储] B --> B2[元数据存储] C --> C1[相似度搜索 ANN] C --> C2[精确搜索 KNN] D --> D1[元数据过滤] D --> D2[混合查询] E --> E1[CRUD 操作] E --> E2[索引管理] style A fill:#e3f2fd,stroke:#1976d2,stroke-width:3px

ChromaDB 快速上手

ChromaDB 是最轻量的向量数据库,适合学习和原型开发:

"""
使用 ChromaDB 构建向量存储
pip install chromadb
"""
import chromadb
# 创建客户端(内存模式)
client = chromadb.Client()
# 创建集合
collection = client.create_collection(
name="knowledge_base",
metadata={"hnsw:space": "cosine"}  # 使用余弦相似度
)
# 添加文档
collection.add(
documents=[
"Python 是一门解释型编程语言",
"JavaScript 主要用于前端开发",
"Rust 以内存安全著称",
"Go 语言适合构建高并发服务",
],
metadatas=[
{"language": "Python", "type": "backend"},
{"language": "JavaScript", "type": "frontend"},
{"language": "Rust", "type": "system"},
{"language": "Go", "type": "backend"},
],
ids=["doc1", "doc2", "doc3", "doc4"]
)
# 查询
results = collection.query(
query_texts=["哪种语言适合做后端?"],
n_results=2,
where={"type": "backend"}  # 元数据过滤
)
print("查询结果:")
for doc, meta, dist in zip(
results["documents"][0],
results["metadatas"][0],
results["distances"][0]
):
print(f"  [{meta['language']}] {doc} (距离: {dist:.4f})")

向量搜索算法

算法 全称 特点 适用场景
Flat 暴力搜索 精确但慢 小数据集<10K
IVF Inverted File Index 分区检索 中等数据集
HNSW Hierarchical Navigable Small World 最快最准 大多数场景
PQ Product Quantization 压缩存储 超大数据集

本章小结

下一章:我们将学习如何加载和解析不同格式的文档。