向量数据库(Vector Database)
概念
ai用的数据库就是向量数据库 向量数据库(Vector Database)是一种专门用于存储、索引和检索高维向量数据的数据库系统。
传统数据库通过精确匹配来查询(WHERE name = 'Alice')
向量数据库通过相似度来查询(找到和这张图最相似的 10 张图)。
嵌入
嵌入(Embedding)是将现实世界的对象(文字、图片、音频等)转换成向量的过程和结果。
这个转换由嵌入模型完成,其核心思想是:语义相近的对象,其向量在空间中的距离也更近。
主流向量数据库
算法
相似度计算
向量数据库(Vector Database) | 菜鸟教程
余弦相似度(Cosine Similarity)
余弦相似度衡量两个向量的方向角,忽略长度。这是最常用的方法,尤其适合文本场景
结果范围:-1 到 1,值越大越相似
适用场景:文本语义搜索、文档相似度
欧氏距离(Euclidean Distance)
欧氏距离衡量两点之间的直线距离,距离越小越相似。
结果范围:0 到 ∞,值越小越相似
适用场景:图像检索、地理位置相关应用
点积(Dot Product)
点积是向量相乘求和,结合了方向和长度信息。
适用场景:推荐系统(向量已归一化时等价于余弦相似度)
PYTHON代码实现
import numpy as np # 余弦相似度:衡量方向相似性 def cosine_similarity(a, b): return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)) # 欧氏距离:衡量绝对位置差异 def euclidean_distance(a, b): return np.linalg.norm(a - b) # 点积:结合方向与长度 def dot_product(a, b): return np.dot(a, b) # 示例向量 v1 = np.array([0.12, -0.54, 0.87, 0.03]) v2 = np.array([0.10, -0.50, 0.90, 0.05]) v3 = np.array([-0.80, 0.20, -0.30, 0.70]) print(f"v1 vs v2 余弦相似度: {cosine_similarity(v1, v2):.4f}") # 约 0.9997(非常相似) print(f"v1 vs v3 余弦相似度: {cosine_similarity(v1, v3):.4f}") # 约 -0.55(不相似)v1 vs v2 余弦相似度: 0.9997 v1 vs v3 余弦相似度: -0.5512
向量索引算法
数据量大时(百万、亿级),对每一条数据做相似度计算(暴力检索)太慢。向量数据库使用专门的索引算法来加速查询。
暴力检索(Flat / Brute-force)
暴力检索遍历所有向量,逐一计算相似度。
| 维度 | 说明 |
|---|---|
| 原理 | 遍历所有向量,逐一计算相似度 |
| 优点 | 结果 100% 精确 |
| 缺点 | 数据量大时极慢,O(n) 复杂度 |
| 适用 | 数据量小于 10 万,对精度要求极高 |
IVF(倒排文件索引)
IVF 索引原理:先聚类,再在桶内搜索
VF 执行步骤:
训练阶段:用 K-Means 将所有向量聚成 N 个簇,记录每个簇的中心
查询阶段:先找出距离最近的几个簇的中心,再只在这些簇内做精确搜索
HNSW(分层导航小世界图)
HNSW 是目前最主流的向量索引算法,兼顾速度和精度。
HNSW 核心思路:
构建多层图结构,顶层稀疏,底层密集
查询时从顶层入口开始,做"跳格游戏":每层贪心地往更近的节点跳,再下探到下一层
大幅减少需要比较的节点数,时间复杂度近似 O(log n)
其他索引算法
| 索引类型 | 特点 | 适用场景 |
|---|---|---|
| Flat(暴力) | 精确但慢 | 小数据集、精度优先 |
| IVF_Flat | 聚类后精确搜索,速度快 | 中大规模,内存充足 |
| IVF_PQ | 量化压缩,节省内存 | 超大规模,内存受限 |
| HNSW | 速度快、精度高,内存占用高 | 最常用,推荐首选 |
| ScaNN | Google 出品,优化吞吐量 | 高并发生产环境 |
构建一个文档语义搜索系统
用 Chroma(最易入门)演示完整的增删改查流程。
1. ChromaDB(AI 领域最常用,简称 Chroma) 轻量级开源向量数据库,专门用于大模型 RAG、语义检索。 Chroma RAG架构 作用:存储文本 / 图片生成的Embedding 嵌入向量,快速做相似度搜索; 特点:开箱即用,Python 一行安装,支持内存模式 / 本地持久化 / 服务端部署; 安装:pip install chromadb 典型场景:本地知识库问答、LLM 外挂记忆、文档检索; 定位:新手做 RAG 首选,对比 Milvus、Pinecone 更轻量化。
1.安装
pip install chromadb openai
第三方嵌入api
2.文件内容
import chromadb from chromadb.utils import embedding_functions # ─── 1. 初始化客户端 ─────────────────────────────────────────── # 持久化到本地(推荐) client = chromadb.PersistentClient(path="./my_vector_db") # 使用 OpenAI 嵌入模型(也可换成本地模型) openai_ef = embedding_functions.OpenAIEmbeddingFunction( api_key="your-openai-api-key", # 必填:替换为你的 API Key //api的配置 model_name="text-embedding-3-small" # 1536 维,性价比高 ) # ─── 2. 创建集合(类似关系库里的"表")──────────────────────── collection = client.get_or_create_collection( name="my_documents", # 集合名称 embedding_function=openai_ef, # 绑定嵌入函数 metadata={"hnsw:space": "cosine"} # 使用余弦相似度 ) # ─── 3. 插入文档 ────────────────────────────────────────────── documents = [ "Python 是一种面向对象的解释型编程语言,广泛用于数据科学和 AI 开发", #//这里放文档内容 "机器学习是人工智能的子领域,让计算机从数据中学习规律", "深度学习使用多层神经网络,在图像识别和 NLP 任务中表现优异", "向量数据库专门存储高维向量,支持语义相似度搜索", "PostgreSQL 是功能强大的开源关系型数据库", "Redis 是基于内存的高性能键值数据库,常用于缓存", "Docker 容器化技术让应用可以在任何环境中一致运行", "Git 是分布式版本控制系统,是现代软件开发的基础工具", ] ids = [f"doc_{i}" for i in range(len(documents))] # 批量插入(Chroma 自动调用嵌入模型转为向量后存储) collection.add( documents=documents, ids=ids, metadatas=[{"source": "tutorial", "index": i} for i in range(len(documents))] ) print(f"已插入 {len(documents)} 条文档") # //已插入 8 条文档 # ─── 4. 语义搜索 ────────────────────────────────────────────── query = "如何用 Python 做人工智能" results = collection.query( query_texts=[query], n_results=3, # 返回最相似的 3 条 include=["documents", "distances", "metadatas"] ) print(f"\n查询:{query}") print("-" * 50) for i, (doc, dist) in enumerate(zip( results["documents"][0], results["distances"][0] )): similarity = 1 - dist # 余弦距离转相似度 #//查询:如何用 Python 做人工智能 print(f"第 {i+1} 名(相似度 {similarity:.4f}):") --------------------------------- print(f" {doc}") #第 1 名(相似度 0.9231):Python 是一种面向对象的解释型编程语言... print() #第 2 名(相似度 0.8874):机器学习是人工智能的子领域... # ─── 5. 带过滤条件的搜索(元数据过滤)─────────────────────── # 第 3 名(相似度 0.8612):深度学习使用多层神经网络... results_filtered = collection.query( query_texts=["数据库技术"], n_results=2, where={"source": "tutorial"}, # 只在 source=tutorial 的文档里搜索 include=["documents", "distances"] ) # ─── 6. 更新文档 ────────────────────────────────────────────── collection.update( ids=["doc_0"], documents=["Python 是目前最流行的编程语言,在 AI、数据分析、Web 开发中均有广泛应用"], metadatas=[{"source": "tutorial", "index": 0, "updated": True}] ) # ─── 7. 删除文档 ────────────────────────────────────────────── collection.delete(ids=["doc_7"]) # 删除 Git 相关文档 # ─── 8. 查看集合统计 ────────────────────────────────────────── print(f"当前集合文档数:{collection.count()}")本地嵌入模型离线运行
或者不使用第三方嵌入 API,只使用本地嵌入模型完全离线运行:
import chromadb from sentence_transformers import SentenceTransformer # 使用本地嵌入模型(无需 API Key,完全离线) model = SentenceTransformer("paraphrase-multilingual-MiniLM-L12-v2") # 支持中文 client = chromadb.Client() collection = client.create_collection("local_demo") texts = ["今天天气很好", "阳光明媚,适合出门", "股市大涨了", "明天可能会下雨"] # 手动生成向量后插入 embeddings = model.encode(texts).tolist() collection.add( embeddings=embeddings, documents=texts, ids=[f"id_{i}" for i in range(len(texts))] ) # 查询 query_embedding = model.encode(["今天天气怎么样"]).tolist() results = collection.query(query_embeddings=query_embedding, n_results=2) print(results["documents"]) # 输出: [['今天天气很好', '阳光明媚,适合出门']]PostgreSQL轻量接入
还有一种方式,使用PostgreSQL,pgvector 是最轻量的接入方式,适用于PostgreSQL 用户
-- 安装扩展 CREATE EXTENSION IF NOT EXISTS vector; -- 建表:存储文章标题及其向量(1536维) CREATE TABLE articles ( id SERIAL PRIMARY KEY, title TEXT NOT NULL, content TEXT, embedding vector(1536) -- 向量列,1536 维 ); -- 创建 HNSW 索引加速查询 CREATE INDEX ON articles USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 64); -- 插入数据(向量由应用层生成后传入) INSERT INTO articles (title, embedding) VALUES ('Python 入门指南', '[0.12, -0.54, 0.87, ...]'::vector); -- 语义搜索:找最相似的 5 篇文章 SELECT id, title, 1 - (embedding <=> '[0.10, -0.50, 0.90, ...]'::vector) AS similarity FROM articles ORDER BY embedding <=> '[0.10, -0.50, 0.90, ...]'::vector LIMIT 5;应用场景
性能优化技巧
1. 批量插入:
一次插入多条,避免频繁单条写入
# 推荐:批量插入 collection.add(documents=docs_list, ids=ids_list) # 不推荐:循环单条(每次都重新索引,效率极低) # for doc, id in zip(docs_list, ids_list): # collection.add(documents=[doc], ids=[id])
2.向量归一化:
使用余弦相似度前,提前归一化向量可加速计算。
import numpy as np def normalize(v): """对向量做 L2 归一化,使模长为 1""" return v / np.linalg.norm(v)
3. 合理设置 n_results
不要无脑设置很大的 top_k,一般 RAG 场景 3~10 条足够
4..善用元数据过滤
在搜索时配合 where 条件,缩小搜索范围。
# 只在"技术文档"分类里搜索,缩小范围提升精度 collection.query( query_texts=["Python 异常处理"], where={"category": "tech_doc"}, n_results=5 )5.定期重建索引
数据量增长后,适时重建 HNSW 索引以维持查询性能。
实例
选择
向量数据库的选择
你的情况是什么? │ ├─── 已有 PostgreSQL,且数据量 < 500 万 │ └──> 用 pgvector,无缝集成,零额外运维 │ ├─── 做 AI/LLM 应用原型,快速验证 │ └──> 用 Chroma,几行代码跑起来 │ ├─── 需要生产级部署,性能优先,数据量 500 万 ~ 1 亿 │ └──> 用 Qdrant,Rust 实现,性能强 │ ├─── 超大规模(> 1 亿),有 K8s 运维能力 │ └──> 用 Milvus,分布式,功能最全 │ └─── 团队没有运维能力,愿意付费 └──> 用 Pinecone 云服务,开箱即用
嵌入模型的选择
| 需求 | 推荐模型 |
|---|---|
| 中英文文本(高质量) | OpenAItext-embedding-3-small |
| 中文文本(本地离线) | BAAI/bge-large-zh-v1.5 |
| 多语言通用 | paraphrase-multilingual-MiniLM-L12-v2 |
| 图文多模态 | OpenAICLIP系列 |
常见问题与解决方案
| 问题 | 说明 | 解决方案 |
|---|---|---|
| 嵌入模型要统一 | 插入和查询必须用同一个模型 | 在配置文件中固定模型版本 |
| 维度不匹配 | 换了模型但没重建集合 | 换模型时删除重建集合 |
| 文本过长 | 大多数模型有 token 限制(512~8192) | 超长文本先分块(chunking) |
| 相似度不准确 | 文本没有分块,语义被稀释 | 按段落或固定长度切分文档 |
| 冷启动慢 | 数据量大时首次加载索引耗时 | 提前预热,或使用持久索引 |