Skip to content

向量数据库

向量数据库概述

向量数据库是专门用于存储和检索高维向量的数据库,在RAG系统中负责存储文档的向量表示并提供高效的相似度搜索能力。

┌─────────────────────────────────────────────────────────────┐
│                    向量数据库工作原理                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  文本输入              存储到向量数据库                       │
│     │                                                      │
│     ▼                                                      │
│  ┌─────────┐                                                │
│  │Embedding│  "人工智能是..." → [0.12, -0.34, 0.56...]     │
│  │  模型   │                                                │
│  └─────────┘                                                │
│                                                             │
│  查询输入              相似度搜索                           │
│     │                                                      │
│     ▼                                                      │
│  ┌─────────┐                                                │
│  │Embedding│  "什么是AI?" → [0.15, -0.30, 0.52...]        │
│  │  模型   │                                                │
│  └─────────┘                                                │
│     │                                                      │
│     ▼                                                      │
│  ┌─────────┐                                                │
│  │ 相似度  │─────────▶ 返回最相似的K个结果                  │
│  │ 计算    │                                                │
│  └─────────┘                                                │
│                                                             │
└─────────────────────────────────────────────────────────────┘

主流向量数据库对比

数据库特点适用场景部署方式
Milvus功能全面,性能强生产环境,大规模云/私有
Pinecone托管服务,零运维快速上线云服务
Chroma轻量级,易用原型开发,小规模本地
Weaviate原生多模态多模态应用云/私有
QdrantRust实现,高性能生产环境云/私有
FAISSFacebook开源研究,学术本地
Milvus Lite轻量版Milvus快速原型本地

Chroma(推荐入门)

安装

bash
# Python
pip install chromadb

# Node.js
npm install chromadb

基本使用

python
import chromadb

# 创建客户端
client = chromadb.Client()

# 创建集合
collection = client.create_collection(
    name="documents",
    metadata={"hnsw:space": "cosine"}  # cosine/Manhattan/L2
)

# 添加文档
collection.add(
    documents=[
        "人工智能是计算机科学的一个分支",
        "机器学习是人工智能的子领域",
        "深度学习是机器学习的一个分支"
    ],
    ids=["doc1", "doc2", "doc3"],
    metadatas=[
        {"source": "ai-intro", "category": "AI"},
        {"source": "ml-intro", "category": "ML"},
        {"source": "dl-intro", "category": "DL"}
    ]
)

# 查询
results = collection.query(
    query_texts=["什么是机器学习?"],
    n_results=2
)

print(results)

Milvus(生产环境推荐)

安装

bash
pip install pymilvus

Python使用

python
from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType, utility

# 连接Milvus
connections.connect(host="localhost", port="19530")

# 定义schema
fields = [
    FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=True),
    FieldSchema(name="content", dtype=DataType.VARCHAR, max_length=65535),
    FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=1536)
]

schema = CollectionSchema(fields=fields, description="文档集合")

# 创建collection
collection = Collection(name="documents", schema=schema)

# 创建索引
index_params = {
    "index_type": "IVF_FLAT",
    "metric_type": "IP",  # 内积相似度
    "params": {"nlist": 128}
}
collection.create_index(field_name="embedding", index_params=index_params)

# 插入数据
data = [
    ["人工智能简介"],  # content
    [[0.1, 0.2, ...]]  # embedding, 1536维
]
collection.insert(data)

# 搜索
search_params = {"metric_type": "IP", "params": {"nprobe": 10}}
results = collection.search(
    data=[[0.1, 0.2, ...]],
    anns_field="embedding",
    param=search_params,
    limit=5
)

Embedding模型

选择Embedding模型

模型维度中文支持特点
OpenAI text-embedding-3-small1536高性价比
OpenAI text-embedding-3-large3072效果最好
BGE-small-zh512✅ 优秀国产开源
M3E1536✅ 优秀国产开源

使用示例

python
from langchain_community.embeddings import HuggingFaceBgeEmbeddings

# 使用BGE中文Embedding
embeddings = HuggingFaceBgeEmbeddings(
    model_name="BAAI/bge-small-zh-v1.5",
    model_kwargs={'device': 'cpu'},
    encode_kwargs={'normalize_embeddings': True}
)

# 向量化文本
vector = embeddings.embed_query("这是一个测试文本")
print(f"向量维度: {len(vector)}")

Node.js使用

javascript
import { HNSWLib } from '@langchain/community/vectorstores/hnswlib';
import { OpenAIEmbeddings } from '@langchain/openai';
import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';

// 初始化
const embeddings = new OpenAIEmbeddings({
  model: 'text-embedding-3-small'
});

// 创建向量存储
const vectorStore = await HNSWLib.fromTexts(
  ['人工智能是未来的趋势', '机器学习是AI的重要分支'],
  [{ id: 1 }, { id: 2 }],
  embeddings,
  { docStore: 'docstore.json', indexStore: 'index.bin' }
);

// 相似度搜索
const results = await vectorStore.similaritySearchVectorWithScore(
  await embeddings.embedQuery('什么是AI'),
  2
);

相似度计算

常用距离度量

┌─────────────────────────────────────────────────────────────┐
│                    相似度计算方法                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  📐 余弦相似度 (Cosine Similarity)                          │
│     cos(θ) = A·B / (|A| × |B|)                             │
│     范围: [-1, 1],值越大越相似                              │
│                                                             │
│  📏 欧氏距离 (L2 Distance)                                  │
│     d = √(Σ(Ai-Bi)²)                                       │
│     越小越相似                                              │
│                                                             │
│  📊 内积 (Inner Product)                                    │
│     A·B = ΣAi×Bi                                            │
│     值越大越相似(需先归一化)                               │
│                                                             │
└─────────────────────────────────────────────────────────────┘

选择建议

场景推荐度量
通用文本相似度余弦相似度
关注向量长度余弦相似度
关注绝对距离欧氏距离
高维向量内积(配合归一化)

向量数据库最佳实践

1. 合理的Chunk策略

python
from langchain.text_splitter import RecursiveCharacterTextSplitter

# 按段落和token数切分
text_splitter = RecursiveCharacterTextSplitter(
    separators=["\n\n", "\n", "。", "!", "?", " "],
    chunk_size=500,        # 目标chunk大小(token)
    chunk_overlap=50,      # 重叠大小,保持上下文连续性
    length_function=len,   # 按字符数计算
    is_separator_regex=False
)

chunks = text_splitter.split_text(long_document)

2. 元数据利用

python
# 添加丰富的元数据
collection.add(
    documents=[chunk],
    ids=[chunk_id],
    metadatas=[{
        "source": "product_manual",      # 来源
        "category": "usage",              # 类别
        "page": 5,                         # 页码
        "created_at": "2024-01-01",       # 创建时间
        "author": "技术部"                 # 作者
    }]
)

# 利用元数据过滤检索
results = collection.query(
    query_texts=["如何使用产品"],
    where={"category": "usage"},  # 元数据过滤
    n_results=5
)

3. 索引优化

python
# Milvus索引配置
index_params = {
    "index_type": "HNSW",  # HNSW: 召回率高,速度快
    "metric_type": "COSINE",
    "params": {
        "M": 16,           # 构建质量,值越大质量越高
        "efConstruction": 200  # 构建参数
    }
}

4. 混合检索

python
async def hybrid_search(query, top_k=5):
    # 1. 语义搜索
    semantic_results = await vector_search(query, top_k * 2)
    
    # 2. 关键词搜索
    keyword_results = await keyword_search(query, top_k * 2)
    
    # 3. RRF融合(Reciprocal Rank Fusion)
    fused_scores = {}
    for rank, (doc, score) in enumerate(semantic_results):
        fused_scores[doc.id] = fused_scores.get(doc.id, 0) + score / (60 + rank)
    
    for rank, (doc, score) in enumerate(keyword_results):
        fused_scores[doc.id] = fused_scores.get(doc.id, 0) + score / (60 + rank)
    
    # 4. 返回融合后结果
    sorted_results = sorted(fused_scores.items(), key=lambda x: x[1], reverse=True)
    return sorted_results[:top_k]

Released under the MIT License.