引言
在人工智能和大语言模型应用中,向量数据库已成为构建智能应用的核心基础设施。本教程将深入探讨向量存储的底层原理,并详细介绍几种主流向量数据库的使用方法,帮助开发者选择和优化适合自己项目的向量管理解决方案。
1. 向量存储底层原理
向量存储基本概念
向量存储(Vector Stores)是一种专门设计用于存储和检索向量嵌入(Vector Embeddings)的数据库系统。在AI应用中,非结构化数据(如文本、图像、音频)通常会被转换为高维向量,这些向量可以在向量空间中进行相似性比较。
向量存储的基本工作流程如下:
- 将非结构化数据转换为向量嵌入
- 存储这些向量及其相关元数据
- 在查询时,将查询内容同样转换为向量
- 检索与查询向量"最相似"的存储向量
向量存储与检索器
在LangChain中,向量存储和检索器是两个相关但不同的概念:
- 向量存储(Vector Stores):负责存储嵌入向量和执行向量搜索
- 检索器(Retrievers):更通用的接口,根据非结构化查询返回文档
检索器可以基于向量存储创建,但也可以基于其他技术(如Wikipedia搜索或Amazon Kendra)。检索器接受字符串查询作为输入,并返回文档列表作为输出。
python
# 向量存储转换为检索器的基本方式
retriever = vector_store.as_retriever()
向量嵌入原理
向量嵌入(Vector Embeddings)是将非结构化数据转换为高维数值向量的过程。与传统数据库基于精确匹配的搜索不同,向量嵌入能够捕捉数据的语义关系。
传统数据库搜索的局限性:
- 基于B Tree、倒排索引等结构
- 使用精确匹配和排序算法(如BM25、TF-IDF)
- 只能进行关键字匹配,无法理解语义关系
例如,搜索"小狗"时,传统数据库无法返回"柯基"、"金毛"等相关结果,因为它们是不同的关键词。传统应用需要人工创建特征标签来关联这些词,这个过程被称为特征工程(Feature Engineering)。
向量嵌入解决了这个问题:
- 由AI模型(如大型语言模型LLM)生成
- 生成高维度向量数据,代表数据的不同特征
- 自动捕捉语义关系,无需手动标注
例如,使用OpenAI的text-embedding-ada-002模型将文本转换为1536维向量:
python
# 文本向量嵌入示例
text = "Your text string goes here"
embedding = openai.Embedding.create(
model="text-embedding-ada-002",
input=text
)
# 结果是1536维向量:[-0.006929283495992422, -0.005336422007530928, ... -0.024047505110502243]
特征和向量的关系
向量可以理解为多维空间中的点,每个维度代表一个特征。在这个空间中,语义相似的内容会彼此靠近。
以狗的分类为例:
- 单一特征(如体型大小):可以在一维空间排列,但无法区分体型相似的不同品种
- 两个特征(体型+毛发长度):形成二维空间,可以更好地区分不同品种
- 三个及更多特征:形成高维空间,能够更精确地区分所有品种
在高维空间中,相似事物的向量会彼此靠近,这就是相似性搜索(Similarity Search)的基础。通过计算向量之间的距离(如欧氏距离、余弦相似度),我们可以找到语义上相似的内容。
2. Chroma向量管理
Chroma是一个开源的向量数据库,专注于开发者的生产力和体验。它使用Apache 2.0许可证,可以在多种模式下运行。
安装与基本设置
python
# 安装Chroma
pip install chromadb langchain-community
Chroma可以在以下模式运行:
- 内存模式:适合测试和实验
- 持久化内存模式:在内存中运行但可保存/加载到磁盘
- 容器模式:作为服务器运行在本地或云端
基本操作
Chroma支持以下基本操作:
.add
:添加文档和向量.get
:获取文档和向量.update
:更新文档和向量.upsert
:如果存在则更新,否则添加.delete
:删除文档和向量.peek
:查看集合中的前几个条目.query
:执行相似性搜索
基本示例
下面是一个使用Chroma存储和检索文档的基本示例:
python
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
# 1. 加载文档
loader = TextLoader("./jobs_speech.txt")
documents = loader.load()
# 2. 分割文档
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(documents)
# 3. 创建向量存储
embedding_function = OpenAIEmbeddings()
db = Chroma.from_documents(docs, embedding_function)
# 4. 执行相似性搜索
query = "乔布斯对创新的看法是什么?"
docs = db.similarity_search(query)
print(docs[0].page_content)
持久化存储
如果需要将数据保存到磁盘,可以指定持久化目录:
python
# 创建持久化的Chroma客户端
db = Chroma.from_documents(
docs,
embedding_function,
persist_directory="./chroma_db"
)
# 持久化数据
db.persist()
# 稍后加载数据
db = Chroma(
persist_directory="./chroma_db",
embedding_function=embedding_function
)
更新和删除
在实际应用中,我们经常需要更新和删除数据。Chroma要求提供唯一标识符(ids)来跟踪文档:
python
# 添加带有ID的文档
db.add_documents(
documents=[doc1, doc2, doc3],
ids=["doc1", "doc2", "doc3"]
)
# 更新文档
db.update_document(
document_id="doc1",
document=updated_doc
)
# 删除文档
db.delete_document(document_id="doc2")
使用OpenAI嵌入模型
许多开发者喜欢使用OpenAI的嵌入模型,以下是设置方法:
python
import os
from langchain_openai import OpenAIEmbeddings
# 设置API密钥
os.environ["OPENAI_API_KEY"] = "你的OpenAI API密钥"
# 创建嵌入模型
embedding_model = OpenAIEmbeddings()
# 使用嵌入模型创建向量存储
db = Chroma.from_documents(docs, embedding_model)
高级检索选项
带分数的相似性搜索
可以返回相似度分数,帮助评估检索结果的质量:
python
# 带分数的相似性搜索
docs_and_scores = db.similarity_search_with_score(query)
for doc, score in docs_and_scores:
print(f"Score: {score}")
print(f"Content: {doc.page_content}\n")
最大边际相关性(MMR)检索
MMR算法在选择结果时平衡相关性和多样性,避免返回过于相似的文档:
python
# 使用MMR检索
retriever = db.as_retriever(
search_type="mmr",
search_kwargs={"k": 5, "fetch_k": 10}
)
docs = retriever.get_relevant_documents(query)
MMR的作用:
- 提高结果的多样性,避免重复信息
- 平衡相关性和新颖性
- 减少冗余,提高信息利用效率
3. Weaviate向量云存储
Weaviate是一个开源的向量数据库,允许存储数据对象和向量嵌入,并能无缝扩展到数十亿个数据对象。
安装与基本设置
python
# 安装Weaviate客户端
pip install weaviate-client langchain-weaviate
Weaviate可以通过多种方式部署:
连接到Weaviate
python
import weaviate
from weaviate.embedded import EmbeddedOptions
# 本地运行Weaviate(嵌入式模式)
client = weaviate.Client(
embedded_options=EmbeddedOptions()
)
# 或连接到远程Weaviate实例
client = weaviate.Client(
url="http://localhost:8080"
)
# 连接到Weaviate云服务
client = weaviate.Client(
url="https://your-cluster-url.weaviate.cloud",
auth_client_secret=weaviate.auth.AuthApiKey(api_key="your-api-key")
)
使用Weaviate与LangChain
以下是一个使用Weaviate存储和检索文档的完整示例:
python
import os
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_weaviate import Weaviate
import weaviate
# 设置OpenAI API密钥
os.environ["OPENAI_API_KEY"] = "你的OpenAI API密钥"
# 连接到Weaviate
client = weaviate.Client(
url="http://localhost:8080"
)
# 加载文档
loader = TextLoader("./data.txt")
documents = loader.load()
# 分割文档
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(documents)
# 创建嵌入模型
embedding_model = OpenAIEmbeddings()
# 创建Weaviate向量存储
vectorstore = Weaviate.from_documents(
client=client,
documents=docs,
embedding=embedding_model,
by_text=False,
index_name="LangChain_Documents"
)
# 执行相似性搜索
query = "人工智能的应用场景"
docs = vectorstore.similarity_search(query)
print(docs[0].page_content)
量化结果相似性
可以检索相关性"分数",这是一个相对分数,表示特定搜索结果在搜索结果池中的好坏程度:
python
# 带分数的相似性搜索
docs_and_scores = vectorstore.similarity_search_with_score(query)
for doc, score in docs_and_scores:
print(f"Score: {score}")
print(f"Content: {doc.page_content}\n")
需要注意的是,这是相对分数,不应用于确定相关性的阈值,但可用于比较整个搜索结果集中不同搜索结果的相关性。
4. Qdrant相似性检索
Qdrant(读作:quadrant)是一个向量相似度搜索引擎,提供生产就绪的服务,具有方便的API来存储、搜索和管理向量数据。Qdrant专门支持扩展过滤功能,使其对各种神经网络或基于语义的匹配、分面搜索和其他应用非常有用。
安装与基本设置
python
# 安装Qdrant客户端
pip install qdrant-client langchain-community
Qdrant有多种运行模式:
- 本地模式,无需服务器
- Qdrant云服务
本地模式
Python客户端允许在本地模式下运行,无需Qdrant服务器,适合测试和调试:
python
from qdrant_client import QdrantClient
from langchain_community.vectorstores import Qdrant
# 内存中模式
client = QdrantClient(":memory:")
# 或持久化到磁盘
client = QdrantClient(path="./qdrant_db")
使用Qdrant与LangChain
以下是一个使用Qdrant存储和检索文档的完整示例:
python
import os
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Qdrant
from qdrant_client import QdrantClient
# 设置OpenAI API密钥
os.environ["OPENAI_API_KEY"] = "你的OpenAI API密钥"
# 创建Qdrant客户端
client = QdrantClient(path="./qdrant_db")
# 加载文档
loader = TextLoader("./data.txt")
documents = loader.load()
# 分割文档
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(documents)
# 创建嵌入模型
embedding_model = OpenAIEmbeddings()
# 创建Qdrant向量存储
collection_name = "document_collection"
vectorstore = Qdrant.from_documents(
docs,
embedding_model,
location=":memory:", # 使用内存模式
collection_name=collection_name,
)
# 执行相似性搜索
query = "量子计算的应用"
docs = vectorstore.similarity_search(query)
print(docs[0].page_content)
Qdrant云服务
如果不想管理基础设施,可以选择在Qdrant云上设置托管集群:
python
# 连接到Qdrant云
client = QdrantClient(
url="https://your-cluster-url.qdrant.io",
api_key="your-api-key"
)
# 使用云客户端创建向量存储
vectorstore = Qdrant.from_documents(
docs,
embedding_model,
url="https://your-cluster-url.qdrant.io",
api_key="your-api-key",
collection_name=collection_name,
)
5. Milvus向量检索
Milvus是一个专为嵌入相似性搜索和人工智能应用设计的向量数据库,用于存储、索引和管理由深度神经网络和其他机器学习模型生成的大规模嵌入向量。
安装与基本设置
python
# 安装Milvus客户端
pip install pymilvus langchain-community
要使用Milvus,需要先启动一个Milvus实例。
使用Milvus与LangChain
以下是一个使用Milvus存储和检索文档的完整示例:
python
import os
from langchain_community.document_loaders import TextLoader
from langchain.text_splitter import CharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Milvus
# 设置OpenAI API密钥
os.environ["OPENAI_API_KEY"] = "你的OpenAI API密钥"
# 加载文档
loader = TextLoader("./data.txt")
documents = loader.load()
# 分割文档
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.split_documents(documents)
# 创建嵌入模型
embedding_model = OpenAIEmbeddings()
# 创建Milvus向量存储
vectorstore = Milvus.from_documents(
docs,
embedding_model,
connection_args={"host": "localhost", "port": "19530"},
collection_name="document_collection"
)
# 执行相似性搜索
query = "深度学习在医疗领域的应用"
docs = vectorstore.similarity_search(query)
print(docs[0].page_content)
使用Zilliz云服务
Zilliz Cloud是Milvus的托管云服务:
python
# 设置Zilliz云环境变量
os.environ["MILVUS_API_URL"] = "https://your-instance-url.zilliz.cloud"
os.environ["MILVUS_API_KEY"] = "your-api-key"
# 使用环境变量连接到Zilliz云
vectorstore = Milvus.from_documents(
docs,
embedding_model,
collection_name="document_collection"
)
6. 向量数据库功能对比
以下是Chroma、Weaviate、Qdrant和Milvus四个向量数据库的功能对比:
功能/特性 | Chroma | Weaviate | Qdrant | Milvus |
---|---|---|---|---|
数据模型 | 向量 + 元数据 | 向量 + 元数据 | 向量 + 元数据 | 向量 + 元数据 |
支持的索引类型 | HNSW | HNSW, IVF, Flat | HNSW | IVF, HNSW, ANNOY, Flat |
扩展性 | 高 | 高 | 高 | 高 |
实时性 | 实时更新 | 实时更新 | 实时更新 | 实时更新 |
多样化查询 | 向量相似性搜索 | 向量相似性搜索 + 混合查询 | 向量相似性搜索 | 向量相似性搜索 + 混合查询 |
分布式架构 | 是 | 是 | 是 | 是 |
支持的语言 | Python, JavaScript | Python, Java, Go, TypeScript | Python, Go | Python, Java, Go, Node.js |
社区支持 | 活跃 | 活跃 | 活跃 | 活跃 |
开源许可证 | Apache 2.0 | BSD-3-Clause | Apache 2.0 | Apache 2.0 |
部署选项 | 本地, 云 | 本地, 云 | 本地, 云 | 本地, 云 |
额外功能 | 数据版本控制 | 知识图谱集成, 模型管理 | 集成向量处理工具 | 数据管理工具, 集成分析工具 |
总结与最佳实践
选择向量数据库的考虑因素
- 数据规模:如果处理的是小规模数据,Chroma的内存模式可能足够;对于大规模数据,Milvus或Weaviate可能更合适
- 查询复杂度:如果需要复杂的混合查询,Weaviate或Milvus提供更强大的功能
- 部署环境:考虑是本地部署还是云部署,以及团队的技术栈
- 特殊需求:如知识图谱集成(Weaviate)或高级数据管理(Milvus)
向量管理最佳实践
-
合理的文档分割:
- 太小的块会丢失上下文
- 太大的块会降低检索精度
- 根据应用场景调整chunk_size和chunk_overlap
-
选择合适的嵌入模型:
- 通用场景:OpenAI的text-embedding-ada-002
- 特定领域:考虑领域特定的嵌入模型
- 本地部署:可考虑开源模型如BERT、Sentence-Transformers等
-
优化检索策略:
- 使用MMR提高结果多样性
- 结合关键词搜索和向量搜索
- 实现混合检索策略
-
定期更新和维护:
- 定期重新嵌入和更新向量
- 监控检索性能
- 根据用户反馈调整系统
通过深入理解向量存储的原理和各种向量数据库的特点,开发者可以为自己的AI应用选择最合适的向量管理解决方案,构建高效、准确的检索增强生成(RAG)系统。