共计 2162 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点:为什么需要向量数据库
传统全文检索技术(如 Elasticsearch)依赖关键词匹配,面临两个核心问题:

- 语义鸿沟:无法理解 ” 汽车 ” 和 ” 机动车 ” 的等价性
- 语境缺失:搜索 ”Python” 时难以区分编程语言与蟒蛇
技术选型:向量数据库对比
| 方案 | 适用场景 | 免费额度 |
|---|---|---|
| Faiss | 本地部署 / 千万级数据 | 完全开源 |
| Pinecone | 云服务 / 自动扩展 | 免费 5GB |
| Chroma | 快速原型开发 | 完全开源 |
核心实现步骤
1. 文本向量化
from openai import OpenAI
from typing import List
client = OpenAI()
def get_embedding(text: str, model="text-embedding-3-small") -> List[float]:
"""调用 OpenAI Embedding API 生成文本向量"""
return client.embeddings.create(input=[text],
model=model
).data[0].embedding
2. 数据分块处理
from langchain.text_splitter import RecursiveCharacterTextSplitter
def chunk_document(text: str, chunk_size=500) -> List[str]:
"""
文本分块处理
:param text: 原始文本
:param chunk_size: 单块 token 数
:return: 文本块列表
"""
splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size,
chunk_overlap=50
)
return splitter.split_text(text)
3. 混合检索系统实现
import numpy as np
from typing import Tuple
class HybridRetriever:
def __init__(self, vector_db, bm25_weight=0.3):
self.vector_db = vector_db
self.bm25_weight = bm25_weight
def search(self, query: str, top_k=5) -> List[Tuple[str, float]]:
"""
混合检索实现
:return: (文本, 综合得分) 元组列表
"""
# 获取向量相似度得分
vector_results = self.vector_db.similarity_search(query, k=top_k*2)
# 获取 BM25 关键词得分
bm25_results = bm25_search(query)
# 融合得分计算
combined = {}
for doc, score in vector_results:
combined[doc] = score * (1 - self.bm25_weight)
for doc, score in bm25_results:
combined[doc] = combined.get(doc, 0) + score * self.bm25_weight
return sorted(combined.items(), key=lambda x: -x[1])[:top_k]
性能优化技巧
API 限流规避策略
- 实现指数退避重试机制
- 使用异步请求批量处理
- 本地缓存已处理文本的 embedding
import backoff
import asyncio
@backoff.on_exception(backoff.expo, Exception, max_tries=3)
async def batch_embed(texts: List[str]) -> List[List[float]]:
"""批量处理文本向量化"""
return await asyncio.gather(*[get_embedding(text) for text in texts
])
向量索引优化
import faiss
def train_quantized_index(embeddings: np.ndarray) -> faiss.Index:
"""训练量化压缩索引"""
d = embeddings.shape[1] # 向量维度
quantizer = faiss.IndexFlatL2(d)
index = faiss.IndexIVFPQ(quantizer, d, 100, 8, 4) # 100 个聚类中心, 8 位编码
index.train(embeddings)
index.add(embeddings)
return index
避坑指南
非结构化数据处理
- PDF 解析使用
pdfminer.six而非 PyPDF2(解决编码问题) - PPT 文件先转换为 PDF 再处理
- 表格数据保留 HTML 标签保持结构
中文文本处理
- 优先使用 jieba 分词而非字符分割
- 移除停用词但保留否定词(如 ” 不 ”)
- 长段落按标点符号二次切分
进阶思考
- 冷启动问题:如何在没有用户查询数据时优化检索?
- 多模态扩展:如何处理图像、表格等非文本数据?
- 动态更新:如何实现知识库的增量更新机制?
结语
通过向量数据库构建的知识库系统,在语义理解方面相比传统方案有显著提升。建议从小型 POC 项目开始,逐步验证各组件效果后再扩展规模。实际部署时需特别注意中文处理的特有挑战,建议建立自动化测试用例验证检索质量。
正文完
