嵌入模型(Embeddings) #
嵌入模型将文本转换为高维向量,使计算机能够理解文本的语义含义。这是 RAG、语义搜索、聚类等应用的基础。
嵌入模型概述 #
text
┌─────────────────────────────────────────────────────────────┐
│ 什么是嵌入? │
├─────────────────────────────────────────────────────────────┤
│ │
│ 文本 ───> 嵌入模型 ───> 向量 │
│ │
│ "机器学习" ───> [0.1, 0.3, -0.2, 0.5, ...] │
│ │
│ 特点: │
│ - 语义相似的文本,向量也相似 │
│ - 可以计算向量之间的相似度 │
│ - 支持多语言 │
│ │
│ 应用: │
│ ✅ 语义搜索 │
│ ✅ 文档检索 │
│ ✅ 聚类分析 │
│ ✅ 推荐系统 │
│ ✅ 异常检测 │
│ │
└─────────────────────────────────────────────────────────────┘
基本使用 #
OpenAI 嵌入模型 #
python
from langchain_openai import OpenAIEmbeddings
# 创建嵌入模型
embeddings = OpenAIEmbeddings(
model="text-embedding-3-small" # 或 text-embedding-3-large
)
# 嵌入单个文本
text = "机器学习是人工智能的一个分支"
vector = embeddings.embed_query(text)
print(f"向量维度: {len(vector)}") # 1536
print(f"前5个值: {vector[:5]}")
# 嵌入多个文本
texts = [
"机器学习是人工智能的一个分支",
"深度学习使用神经网络",
"今天天气很好"
]
vectors = embeddings.embed_documents(texts)
print(f"生成了 {len(vectors)} 个向量")
不同模型对比 #
python
# text-embedding-3-small
small_embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
# 维度: 1536
# 价格: $0.02/1M tokens
# text-embedding-3-large
large_embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
# 维度: 3072
# 价格: $0.13/1M tokens
# text-embedding-ada-002 (旧版)
ada_embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")
# 维度: 1536
嵌入模型提供商 #
OpenAI #
python
from langchain_openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings(
model="text-embedding-3-small",
# 可选参数
chunk_size=1000, # 批处理大小
max_retries=2, # 重试次数
request_timeout=60
)
HuggingFace(本地) #
python
from langchain_huggingface import HuggingFaceEmbeddings
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/all-MiniLM-L6-v2",
model_kwargs={'device': 'cpu'},
encode_kwargs={'normalize_embeddings': True}
)
# 常用模型:
# - all-MiniLM-L6-v2: 快速,384 维
# - all-mpnet-base-v2: 高质量,768 维
# - paraphrase-multilingual-mpnet-base-v2: 多语言
Ollama(本地) #
python
from langchain_ollama import OllamaEmbeddings
embeddings = OllamaEmbeddings(
model="nomic-embed-text"
)
# 常用模型:
# - nomic-embed-text: 通用嵌入
# - mxbai-embed-large: 高质量
Cohere #
python
from langchain_cohere import CohereEmbeddings
embeddings = CohereEmbeddings(
model="embed-english-v3.0",
cohere_api_key="your-key"
)
Google #
python
from langchain_google_genai import GoogleGenerativeAIEmbeddings
embeddings = GoogleGenerativeAIEmbeddings(
model="models/embedding-001"
)
Azure OpenAI #
python
from langchain_openai import AzureOpenAIEmbeddings
embeddings = AzureOpenAIEmbeddings(
azure_deployment="your-deployment",
azure_endpoint="https://your-resource.openai.azure.com/",
api_version="2024-02-15-preview"
)
相似度计算 #
余弦相似度 #
python
import numpy as np
def cosine_similarity(v1, v2):
"""计算两个向量的余弦相似度"""
return np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))
# 示例
text1 = "机器学习是人工智能的一个分支"
text2 = "深度学习是机器学习的一个分支"
text3 = "今天天气很好"
v1 = embeddings.embed_query(text1)
v2 = embeddings.embed_query(text2)
v3 = embeddings.embed_query(text3)
print(f"文本1 vs 文本2: {cosine_similarity(v1, v2):.4f}") # 高相似度
print(f"文本1 vs 文本3: {cosine_similarity(v1, v3):.4f}") # 低相似度
使用 LangChain 内置方法 #
python
from langchain_community.utils.math import cosine_similarity
# 计算相似度矩阵
vectors = embeddings.embed_documents([
"机器学习",
"深度学习",
"天气很好"
])
similarity_matrix = cosine_similarity(vectors, vectors)
print(similarity_matrix)
text
┌─────────────────────────────────────────────────────────────┐
│ 相似度矩阵示例 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 机器学习 深度学习 天气很好 │
│ 机器学习 [ 1.00 0.85 0.32 ] │
│ 深度学习 [ 0.85 1.00 0.28 ] │
│ 天气很好 [ 0.32 0.28 1.00 ] │
│ │
│ 相似度范围: [-1, 1] │
│ - 1: 完全相同 │
│ - 0: 无关联 │
│ - -1: 完全相反 │
│ │
└─────────────────────────────────────────────────────────────┘
批量处理 #
批量嵌入 #
python
# 大量文本的批量处理
texts = [f"这是第 {i} 段文本" for i in range(1000)]
# 自动分批处理
vectors = embeddings.embed_documents(texts)
# 控制批处理大小
embeddings = OpenAIEmbeddings(
model="text-embedding-3-small",
chunk_size=100 # 每批处理 100 个
)
异步嵌入 #
python
import asyncio
async def embed_async():
# 异步嵌入
vector = await embeddings.aembed_query("文本")
# 异步批量
vectors = await embeddings.aembed_documents(["文本1", "文本2"])
return vectors
vectors = asyncio.run(embed_async())
嵌入缓存 #
使用缓存加速 #
python
from langchain.embeddings import CacheBackedEmbeddings
from langchain_community.storage import LocalFileStore
# 创建底层嵌入模型
underlying_embeddings = OpenAIEmbeddings()
# 创建本地缓存
store = LocalFileStore("./embedding_cache")
# 创建带缓存的嵌入模型
cached_embeddings = CacheBackedEmbeddings.from_bytes_store(
underlying_embeddings,
store,
namespace=underlying_embeddings.model
)
# 首次调用会计算并缓存
vector1 = cached_embeddings.embed_query("测试文本")
# 再次调用相同文本会从缓存读取
vector2 = cached_embeddings.embed_query("测试文本")
Redis 缓存 #
python
from langchain_community.storage import RedisStore
store = RedisStore(redis_url="redis://localhost:6379")
cached_embeddings = CacheBackedEmbeddings.from_bytes_store(
underlying_embeddings,
store,
namespace="openai-embeddings"
)
自定义嵌入模型 #
继承 Embeddings 类 #
python
from langchain_core.embeddings import Embeddings
from typing import List
class CustomEmbeddings(Embeddings):
"""自定义嵌入模型"""
def __init__(self, model_path: str):
# 加载模型
pass
def embed_documents(self, texts: List[str]) -> List[List[float]]:
"""嵌入多个文档"""
return [self._embed(text) for text in texts]
def embed_query(self, text: str) -> List[float]:
"""嵌入查询"""
return self._embed(text)
def _embed(self, text: str) -> List[float]:
"""实际嵌入逻辑"""
# 实现你的嵌入逻辑
return [0.0] * 768 # 示例
async def aembed_documents(self, texts: List[str]) -> List[List[float]]:
"""异步嵌入多个文档"""
return self.embed_documents(texts)
async def aembed_query(self, text: str) -> List[float]:
"""异步嵌入查询"""
return self.embed_query(text)
实际应用 #
语义搜索 #
python
from langchain_community.vectorstores import FAISS
# 文档库
documents = [
"机器学习是人工智能的一个分支",
"深度学习使用多层神经网络",
"自然语言处理处理人类语言",
"计算机视觉让机器理解图像",
"今天天气很好,适合出行"
]
# 创建向量存储
embeddings = OpenAIEmbeddings()
vectorstore = FAISS.from_texts(documents, embeddings)
# 语义搜索
query = "AI 相关技术"
results = vectorstore.similarity_search(query, k=3)
for doc in results:
print(doc.page_content)
文档聚类 #
python
from sklearn.cluster import KMeans
import numpy as np
# 文档
documents = [
"机器学习算法",
"深度学习网络",
"自然语言处理",
"计算机视觉",
"天气预报",
"美食推荐"
]
# 获取嵌入向量
vectors = embeddings.embed_documents(documents)
vectors = np.array(vectors)
# K-means 聚类
kmeans = KMeans(n_clusters=2, random_state=42)
labels = kmeans.fit_predict(vectors)
# 输出聚类结果
for i, (doc, label) in enumerate(zip(documents, labels)):
print(f"Cluster {label}: {doc}")
文本去重 #
python
def deduplicate_texts(texts: list, threshold: float = 0.95) -> list:
"""基于语义相似度去重"""
vectors = embeddings.embed_documents(texts)
unique_texts = []
unique_vectors = []
for text, vector in zip(texts, vectors):
is_duplicate = False
for existing_vector in unique_vectors:
similarity = cosine_similarity(vector, existing_vector)
if similarity > threshold:
is_duplicate = True
break
if not is_duplicate:
unique_texts.append(text)
unique_vectors.append(vector)
return unique_texts
# 使用
texts = [
"机器学习是AI的分支",
"机器学习是人工智能的一个分支",
"深度学习使用神经网络"
]
unique = deduplicate_texts(texts)
print(unique)
模型选择指南 #
text
┌─────────────────────────────────────────────────────────────┐
│ 嵌入模型选择 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 云端模型: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ OpenAI text-embedding-3-small │ │
│ │ - 平衡性能和成本 │ │
│ │ - 1536 维,$0.02/1M tokens │ │
│ │ - 推荐日常使用 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ OpenAI text-embedding-3-large │ │
│ │ - 最高质量 │ │
│ │ - 3072 维,$0.13/1M tokens │ │
│ │ - 推荐高质量需求 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 本地模型: │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ all-MiniLM-L6-v2 │ │
│ │ - 快速,轻量 │ │
│ │ - 384 维 │ │
│ │ - 推荐资源受限场景 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ all-mpnet-base-v2 │ │
│ │ - 高质量本地模型 │ │
│ │ - 768 维 │ │
│ │ - 推荐隐私敏感场景 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
最佳实践 #
1. 文本预处理 #
python
import re
def preprocess_text(text: str) -> str:
"""文本预处理"""
# 去除多余空白
text = re.sub(r'\s+', ' ', text)
# 去除特殊字符
text = re.sub(r'[^\w\s\u4e00-\u9fff]', '', text)
return text.strip()
texts = [preprocess_text(t) for t in raw_texts]
vectors = embeddings.embed_documents(texts)
2. 批量处理优化 #
python
# 大量文本分批处理
def batch_embed(texts: list, batch_size: int = 100):
"""分批嵌入"""
all_vectors = []
for i in range(0, len(texts), batch_size):
batch = texts[i:i + batch_size]
vectors = embeddings.embed_documents(batch)
all_vectors.extend(vectors)
return all_vectors
3. 使用缓存 #
python
# 对于不变的文本,使用缓存
cached_embeddings = CacheBackedEmbeddings.from_bytes_store(
OpenAIEmbeddings(),
LocalFileStore("./cache"),
namespace="my-app"
)
下一步 #
最后更新:2026-03-30