Embeddings 文本向量化完整指南
将文本转换为高维向量,实现语义搜索、相似度计算、聚类分析等高级功能
语义搜索
理解查询意图
向量数据库
高效存储检索
相似度计算
精确匹配内容
RAG 系统
知识增强生成
一、基础文本向量化
快速开始
import openai
import numpy as np
# 配置 API
openai.api_base = "https://api.n1n.ai/v1"
openai.api_key = "your-api-key"
# 1. 基础文本向量化
def get_embedding(text, model="text-embedding-3-small"):
"""获取文本的向量表示"""
response = openai.Embedding.create(
model=model,
input=text
)
return response['data'][0]['embedding']
# 单个文本向量化
text = "机器学习是人工智能的一个分支"
embedding = get_embedding(text)
print(f"向量维度: {len(embedding)}") # 1536维
# 批量文本向量化
texts = [
"深度学习是机器学习的子集",
"神经网络模拟人脑结构",
"自然语言处理让机器理解人类语言"
]
response = openai.Embedding.create(
model="text-embedding-3-small",
input=texts
)
embeddings = [item['embedding'] for item in response['data']]
print(f"处理了 {len(embeddings)} 个文本")模型选择
- • text-embedding-3-small (1536维)
- • text-embedding-3-large (3072维)
- • text-embedding-ada-002 (1536维)
成本对比
- • Small: $0.02/1M tokens
- • Large: $0.13/1M tokens
- • Ada-002: $0.10/1M tokens
应用场景
- • 问答系统
- • 推荐系统
- • 内容去重
二、语义相似度计算
相似度搜索
import numpy as np
from scipy.spatial.distance import cosine
import openai
openai.api_base = "https://api.n1n.ai/v1"
openai.api_key = "your-api-key"
def cosine_similarity(vec1, vec2):
"""计算余弦相似度"""
return 1 - cosine(vec1, vec2)
def get_embeddings(texts):
"""批量获取文本向量"""
response = openai.Embedding.create(
model="text-embedding-3-small",
input=texts
)
return [item['embedding'] for item in response['data']]
# 语义相似度计算示例
documents = [
"Python是一种流行的编程语言",
"JavaScript用于前端开发",
"机器学习需要大量数据",
"深度学习是AI的重要技术",
"猫是可爱的宠物"
]
query = "人工智能和深度学习的关系"
# 获取所有向量
doc_embeddings = get_embeddings(documents)
query_embedding = get_embeddings([query])[0]
# 计算相似度
similarities = []
for i, doc_emb in enumerate(doc_embeddings):
sim = cosine_similarity(query_embedding, doc_emb)
similarities.append((documents[i], sim))
# 排序并显示结果
similarities.sort(key=lambda x: x[1], reverse=True)
print(f"查询: {query}\n")
print("相似度排名:")
for doc, sim in similarities:
print(f" {sim:.4f} - {doc}")
# 输出示例:
# 相似度排名:
# 0.8234 - 深度学习是AI的重要技术
# 0.7891 - 机器学习需要大量数据
# 0.4523 - Python是一种流行的编程语言
# 0.3912 - JavaScript用于前端开发
# 0.1234 - 猫是可爱的宠物💡 相似度阈值参考
- • > 0.9: 几乎相同的内容
- • 0.8-0.9: 高度相关
- • 0.7-0.8: 明显相关
- • 0.6-0.7: 有一定相关性
- • < 0.6: 相关性较低
三、向量数据库集成
Chroma 向量库
from chromadb import Client
from chromadb.config import Settings
import openai
# 初始化 Chroma 向量数据库
client = Client(Settings(
chroma_db_impl="duckdb+parquet",
persist_directory="./chroma_db"
))
# 创建或获取集合
collection = client.get_or_create_collection(
name="documents",
metadata={"hnsw:space": "cosine"} # 使用余弦相似度
)
# OpenAI 配置
openai.api_base = "https://api.n1n.ai/v1"
openai.api_key = "your-api-key"
def get_embedding(text):
response = openai.Embedding.create(
model="text-embedding-3-small",
input=text
)
return response['data'][0]['embedding']
# 1. 添加文档到向量库
documents = [
{"id": "doc1", "text": "Vue.js 是渐进式JavaScript框架", "metadata": {"category": "frontend"}},
{"id": "doc2", "text": "React 使用虚拟DOM提高性能", "metadata": {"category": "frontend"}},
{"id": "doc3", "text": "Django 是Python的Web框架", "metadata": {"category": "backend"}},
{"id": "doc4", "text": "FastAPI 提供自动文档生成", "metadata": {"category": "backend"}},
{"id": "doc5", "text": "PostgreSQL 是关系型数据库", "metadata": {"category": "database"}}
]
# 批量添加
for doc in documents:
embedding = get_embedding(doc["text"])
collection.add(
embeddings=[embedding],
documents=[doc["text"]],
metadatas=[doc["metadata"]],
ids=[doc["id"]]
)
print(f"已添加 {len(documents)} 个文档到向量库")
# 2. 语义搜索
query = "前端框架性能优化"
query_embedding = get_embedding(query)
# 搜索最相似的文档
results = collection.query(
query_embeddings=[query_embedding],
n_results=3,
where={"category": "frontend"} # 可选:元数据过滤
)
print(f"\n查询: {query}")
print("搜索结果:")
for i, (doc, dist) in enumerate(zip(results['documents'][0], results['distances'][0])):
print(f" {i+1}. 相似度: {1-dist:.4f}")
print(f" 文档: {doc}")
# 3. 更新和删除
# 更新文档
collection.update(
ids=["doc1"],
embeddings=[get_embedding("Vue 3 提供组合式API")],
documents=["Vue 3 提供组合式API"]
)
# 删除文档
collection.delete(ids=["doc5"])
# 4. 持久化
client.persist()开源方案
- • Chroma - 轻量易用
- • Weaviate - 功能丰富
- • Milvus - 高性能
- • Qdrant - Rust实现
云服务
- • Pinecone - 全托管
- • Zilliz Cloud - Milvus云版
- • Supabase Vector
- • MongoDB Atlas Vector
选择建议
- • 开发测试: Chroma
- • 生产环境: Pinecone
- • 大规模: Milvus
- • 混合搜索: Weaviate
四、RAG 系统实现
完整 RAG 流程
import openai
from typing import List, Dict
import chromadb
from chromadb.utils import embedding_functions
class RAGSystem:
def __init__(self, api_key: str, collection_name: str = "knowledge_base"):
# 配置 OpenAI
openai.api_key = api_key
openai.api_base = "https://api.n1n.ai/v1"
# 初始化向量数据库
self.client = chromadb.PersistentClient(path="./rag_db")
# 使用 OpenAI 嵌入函数
self.embedding_function = embedding_functions.OpenAIEmbeddingFunction(
api_key=api_key,
api_base="https://api.n1n.ai/v1",
model_name="text-embedding-3-small"
)
self.collection = self.client.get_or_create_collection(
name=collection_name,
embedding_function=self.embedding_function
)
def add_documents(self, documents: List[Dict[str, str]]):
"""添加文档到知识库"""
self.collection.add(
documents=[doc["content"] for doc in documents],
metadatas=[{"source": doc.get("source", "unknown")} for doc in documents],
ids=[doc["id"] for doc in documents]
)
return f"已添加 {len(documents)} 个文档"
def search(self, query: str, n_results: int = 3) -> List[Dict]:
"""语义搜索相关文档"""
results = self.collection.query(
query_texts=[query],
n_results=n_results
)
return [{
"content": doc,
"distance": dist,
"metadata": meta
} for doc, dist, meta in zip(
results['documents'][0],
results['distances'][0],
results['metadatas'][0]
)]
def generate_answer(self, query: str, context_docs: List[str]) -> str:
"""基于检索的文档生成答案"""
context = "\n\n".join(context_docs)
prompt = f"""基于以下文档回答问题。如果文档中没有相关信息,请说"我无法根据提供的文档回答这个问题"。
文档内容:
{context}
问题: {query}
答案:"""
response = openai.ChatCompletion.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "你是一个基于文档的问答助手"},
{"role": "user", "content": prompt}
],
temperature=0.3
)
return response.choices[0].message.content
def ask(self, question: str) -> Dict:
"""完整的 RAG 流程"""
# 1. 检索相关文档
relevant_docs = self.search(question, n_results=3)
# 2. 生成答案
doc_contents = [doc["content"] for doc in relevant_docs]
answer = self.generate_answer(question, doc_contents)
return {
"question": question,
"answer": answer,
"sources": relevant_docs
}
# 使用示例
rag = RAGSystem(api_key="your-api-key")
# 添加知识文档
documents = [
{"id": "1", "content": "Python 3.12 引入了更好的错误信息", "source": "python_docs"},
{"id": "2", "content": "TypeScript 5.0 支持装饰器", "source": "ts_docs"},
{"id": "3", "content": "React 18 引入了并发特性", "source": "react_docs"}
]
rag.add_documents(documents)
# 提问
result = rag.ask("Python 最新版本有什么新特性?")
print(f"问题: {result['question']}")
print(f"答案: {result['answer']}")
print(f"来源: {[s['metadata']['source'] for s in result['sources']]}")五、文本聚类与可视化
聚类分析
import numpy as np
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import openai
openai.api_base = "https://api.n1n.ai/v1"
openai.api_key = "your-api-key"
def get_embeddings(texts):
response = openai.Embedding.create(
model="text-embedding-3-small",
input=texts
)
return np.array([item['embedding'] for item in response['data']])
# 文本数据
texts = [
# 技术类
"Python 是一种编程语言",
"JavaScript 用于网页开发",
"机器学习算法很强大",
"深度学习模型需要训练",
# 动物类
"猫是独立的宠物",
"狗是忠诚的朋友",
"鸟类可以飞翔",
"鱼在水中游泳",
# 食物类
"披萨是意大利美食",
"寿司来自日本",
"汉堡是快餐",
"沙拉很健康"
]
# 获取向量
embeddings = get_embeddings(texts)
# K-Means 聚类
n_clusters = 3
kmeans = KMeans(n_clusters=n_clusters, random_state=42)
clusters = kmeans.fit_predict(embeddings)
# 打印聚类结果
for i in range(n_clusters):
print(f"\n聚类 {i+1}:")
cluster_texts = [texts[j] for j, c in enumerate(clusters) if c == i]
for text in cluster_texts:
print(f" - {text}")
# 降维可视化
pca = PCA(n_components=2)
embeddings_2d = pca.fit_transform(embeddings)
# 绘制聚类图
plt.figure(figsize=(10, 8))
colors = ['red', 'blue', 'green']
for i in range(n_clusters):
cluster_points = embeddings_2d[clusters == i]
plt.scatter(cluster_points[:, 0], cluster_points[:, 1],
c=colors[i], label=f'聚类 {i+1}', alpha=0.6)
# 添加文本标签
for i, txt in enumerate(texts):
plt.annotate(txt, (embeddings_2d[i, 0], embeddings_2d[i, 1]),
fontsize=8, alpha=0.7)
plt.xlabel('第一主成分')
plt.ylabel('第二主成分')
plt.title('文本向量聚类可视化')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()六、性能优化技巧
优化策略
import openai
import time
import asyncio
from concurrent.futures import ThreadPoolExecutor
import numpy as np
openai.api_base = "https://api.n1n.ai/v1"
openai.api_key = "your-api-key"
# 1. 批量处理优化
def batch_embeddings(texts, batch_size=100):
"""分批处理大量文本"""
all_embeddings = []
for i in range(0, len(texts), batch_size):
batch = texts[i:i+batch_size]
response = openai.Embedding.create(
model="text-embedding-3-small",
input=batch
)
batch_embeddings = [item['embedding'] for item in response['data']]
all_embeddings.extend(batch_embeddings)
# 避免速率限制
if i + batch_size < len(texts):
time.sleep(0.1)
return all_embeddings
# 2. 并发处理
async def async_get_embedding(text, semaphore):
"""异步获取单个文本的向量"""
async with semaphore:
response = await openai.Embedding.acreate(
model="text-embedding-3-small",
input=text
)
return response['data'][0]['embedding']
async def concurrent_embeddings(texts, max_concurrent=5):
"""并发处理多个文本"""
semaphore = asyncio.Semaphore(max_concurrent)
tasks = [async_get_embedding(text, semaphore) for text in texts]
return await asyncio.gather(*tasks)
# 3. 缓存策略
class EmbeddingCache:
def __init__(self, cache_size=1000):
self.cache = {}
self.cache_size = cache_size
def get_embedding(self, text, model="text-embedding-3-small"):
# 检查缓存
cache_key = f"{model}:{text}"
if cache_key in self.cache:
return self.cache[cache_key]
# 获取新的向量
response = openai.Embedding.create(
model=model,
input=text
)
embedding = response['data'][0]['embedding']
# 更新缓存(简单的LRU实现)
if len(self.cache) >= self.cache_size:
# 删除最旧的项
oldest_key = list(self.cache.keys())[0]
del self.cache[oldest_key]
self.cache[cache_key] = embedding
return embedding
# 4. 向量压缩(降维)
def compress_embeddings(embeddings, target_dim=256):
"""使用 PCA 压缩向量维度"""
from sklearn.decomposition import PCA
pca = PCA(n_components=target_dim)
compressed = pca.fit_transform(embeddings)
print(f"压缩比: {embeddings.shape[1]} -> {compressed.shape[1]}")
print(f"保留方差: {sum(pca.explained_variance_ratio_):.2%}")
return compressed, pca
# 5. 模型选择策略
def smart_embedding(text, use_large=False):
"""根据文本长度选择模型"""
text_length = len(text)
if text_length > 8000 or use_large:
# 长文本或需要高精度时使用大模型
model = "text-embedding-3-large"
else:
# 短文本使用小模型,更快更便宜
model = "text-embedding-3-small"
response = openai.Embedding.create(
model=model,
input=text
)
return {
"embedding": response['data'][0]['embedding'],
"model": model,
"tokens": response['usage']['total_tokens']
}
# 使用示例
cache = EmbeddingCache()
texts = ["示例文本1", "示例文本2", "示例文本1"] # 注意重复
# 带缓存的处理
for text in texts:
embedding = cache.get_embedding(text)
print(f"处理: {text[:20]}...")⚡ 性能优化
- ✅ 批量处理减少API调用
- ✅ 并发请求提高吞吐量
- ✅ 缓存避免重复计算
- ✅ 向量压缩节省存储
- ✅ 智能模型选择
💰 成本控制
- ✅ 使用 small 模型处理大部分任务
- ✅ 文本预处理去除冗余
- ✅ 合理设置缓存策略
- ✅ 定期清理无用向量
- ✅ 监控API使用量