LangChain向量存储模块架构与数据操作源码深度剖析
一、向量存储模块概述
LangChain的向量存储模块是连接文本数据与语言模型的关键桥梁,主要负责将文本转换为向量形式并进行高效存储,为语义检索、相似性匹配等任务提供底层支持。该模块采用高度抽象化和模块化设计,通过统一接口兼容多种向量数据库,如FAISS、Chroma、Milvus等。其核心目标是实现文本数据的快速检索与匹配,支撑智能问答、文档分析等复杂应用场景。
从整体架构来看,向量存储模块包含三个核心层次:
- 抽象基类层:定义统一接口规范
- 具体存储实现层:对接各类向量数据库
- 工具集成层:与LangChain其他模块协同工作
这种分层架构设计保证了模块的扩展性和可维护性,开发者可根据需求灵活替换底层存储方案。
二、向量存储基类设计
2.1 VectorStore抽象基类
VectorStore基类位于langchain.vectorstores.base.py,定义了向量存储的核心接口:
from abc import ABC, abstractmethod
from typing import Any, List, Optional, Tuple
from langchain.schema import Document
class VectorStore(ABC):
"""所有向量存储类的基类"""
@abstractmethod
def add_texts(
self, texts: List[str], metadatas: Optional[List[dict]] = None, **kwargs: Any
) -> List[str]:
"""将文本列表及其元数据添加到存储中,返回唯一标识符列表"""
pass
@abstractmethod
def similarity_search(
self, query: str, k: int = 4, **kwargs: Any
) -> List[Document]:
"""基于余弦相似度执行语义检索,返回最相似的k个文档"""
pass
@abstractmethod
def similarity_search_with_score(
self, query: str, k: int = 4, **kwargs: Any
) -> List[Tuple[Document, float]]:
"""返回包含相似度得分的检索结果"""
pass
@classmethod
@abstractmethod
def from_texts(
cls, texts: List[str], embedding: Any, metadatas: Optional[List[dict]] = None, **kwargs: Any
) -> "VectorStore":
"""从文本列表直接创建向量存储实例"""
pass
该基类通过四个抽象方法规范了向量存储的核心操作:
add_texts:批量添加文本数据similarity_search:执行语义检索similarity_search_with_score:带得分的检索from_texts:快速初始化存储实例
2.2 VectorStoreRetriever接口
VectorStoreRetriever接口进一步扩展了检索功能,位于langchain.retrievers:
from abc import ABC, abstractmethod
from typing import Any, List
from langchain.schema import Document
class VectorStoreRetriever(ABC):
"""向量存储检索器接口"""
@abstractmethod
def get_relevant_documents(self, query: str) -> List[Document]:
"""获取相关文档列表"""
pass
async def aget_relevant_documents(self, query: str) -> List[Document]:
"""异步获取相关文档(默认同步调用)"""
return self.get_relevant_documents(query)
此接口将检索逻辑抽象化,便于与LangChain的链(Chain)和代理(Agent)模块集成。
三、具体向量存储实现:FAISS
3.1 FAISS向量存储类
FAISS类位于langchain.vectorstores.faiss.py,实现了基于FAISS库的向量存储:
import faiss
import numpy as np
from langchain.vectorstores.base import VectorStore
from langchain.embeddings.base import Embeddings
class FAISS(VectorStore):
def __init__(self, embedding_function: Embeddings, index: faiss.Index, texts: List[str], metadatas: List[dict]):
self.embedding_function = embedding_function
self.index = index
self.texts = texts
self.metadatas = metadatas or [{}] * len(texts)
@classmethod
def from_texts(
cls, texts: List[str], embedding: Embeddings, metadatas: Optional[List[dict]] = None, **kwargs: Any
) -> "FAISS":
"""从文本列表创建FAISS实例"""
embeddings = embedding.embed_documents(texts)
embedding_size = len(embeddings[0])
index = faiss.IndexFlatL2(embedding_size) # 创建L2距离索引
index.add(np.array(embeddings).astype('float32'))
return cls(embedding, index, texts, metadatas)
def add_texts(
self, texts: List[str], metadatas: Optional[List[dict]] = None, **kwargs: Any
) -> List[str]:
"""添加文本到FAISS索引"""
embeddings = self.embedding_function.embed_documents(texts)
self.index.add(np.array(embeddings).astype('float32'))
self.texts.extend(texts)
if metadatas:
self.metadatas.extend(metadatas)
else:
self.metadatas.extend([{}] * len(texts))
return [str(i) for i in range(len(self.texts) - len(texts), len(self.texts))]
def similarity_search(
self, query: str, k: int = 4, **kwargs: Any
) -> List[Document]:
"""执行相似度检索"""
embedding = np.array(self.embedding_function.embed_query(query)).astype('float32').reshape(1, -1)
distances, indices = self.index.search(embedding, k)
return [
Document(page_content=self.texts[i], metadata=self.metadatas[i])
for i in indices.flatten()
]
def similarity_search_with_score(
self, query: str, k: int = 4, **kwargs: Any
) -> List[Tuple[Document, float]]:
"""返回带得分的检索结果"""
embedding = np.array(self.embedding_function.embed_query(query)).astype('float32').reshape(1, -1)
distances, indices = self.index.search(embedding, k)
return [
(Document(page_content=self.texts[i], metadata=self.metadatas[i]), float(distances[0][j]))
for i, j in zip(indices.flatten(), range(len(indices.flatten())))
]
核心实现逻辑:
- 初始化:创建FAISS索引,存储文本和元数据
- 添加文本:计算嵌入向量并添加到索引
- 检索:通过L2距离计算相似度,返回相关文档
四、具体向量存储实现:Chroma
4.1 Chroma向量存储类
Chroma类位于langchain.vectorstores.chroma.py,基于Chroma数据库实现:
from typing import Any, List, Optional
from langchain.vectorstores.base import VectorStore
from langchain.embeddings.base import Embeddings
import chromadb
class Chroma(VectorStore):
def __init__(
self,
embedding_function: Embeddings,
client: chromadb.Client,
collection_name: str
):
self.embedding_function = embedding_function
self.client = client
self.collection = client.get_or_create_collection(collection_name)
@classmethod
def from_texts(
cls, texts: List[str], embedding: Embeddings, metadatas: Optional[List[dict]] = None, **kwargs: Any
) -> "Chroma":
"""从文本列表创建Chroma实例"""
client = chromadb.Client()
collection_name = "langchain_collection"
collection = client.create_collection(
name=collection_name,
embedding_function=embedding.embed_query
)
collection.add(
documents=texts,
metadatas=metadatas or [{}] * len(texts),
ids=[str(i) for i in range(len(texts))]
)
return cls(embedding, client, collection_name)
def add_texts(
self, texts: List[str], metadatas: Optional[List[dict]] = None, **kwargs: Any
) -> List[str]:
"""添加文本到Chroma集合"""
ids = [str(len(self.collection.get()['ids']) + i) for i in range(len(texts))]
self.collection.add(
documents=texts,
metadatas=metadatas or [{}] * len(texts),
ids=ids
)
return ids
def similarity_search(
self, query: str, k: int = 4, **kwargs: Any
) -> List[Document]:
"""执行相似度检索"""
results = self.collection.query(
query_texts=[query],
n_results=k
)
return [
Document(page_content=doc, metadata=meta)
for doc, meta in zip(results['documents'][0], results['metadatas'][0])
]
def similarity_search_with_score(
self, query: str, k: int = 4, **kwargs: Any
) -> List[Tuple[Document, float]]:
"""返回带得分的检索结果"""
results = self.collection.query(
query_texts=[query],
n_results=k
)
return [
(Document(page_content=doc, metadata=meta), score)
for doc, meta, score in zip(results['documents'][0], results['metadatas'][0], results['distances'][0])
]
关键特性:
- 使用Chroma原生API进行数据操作
- 支持动态创建和管理集合
- 封装相似度计算逻辑
五、向量存储与嵌入模块的协同
5.1 嵌入向量生成流程
向量存储依赖嵌入模块将文本转换为向量:
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS
# 初始化嵌入模型
embeddings = OpenAIEmbeddings()
# 示例文本
texts = [
"量子计算是未来科技的重要方向",
"人工智能改变了生活方式",
"区块链技术实现去中心化信任"
]
# 创建FAISS向量存储实例
vector_store = FAISS.from_texts(texts, embeddings)
from_texts方法内部流程:
- 调用
embeddings.embed_documents生成向量 - 将向量添加到FAISS索引
- 存储原始文本和元数据
5.2 检索时的向量计算
在执行检索时,嵌入模块再次发挥作用:
query = "量子技术的应用场景"
results = vector_store.similarity_search(query, k=2)
具体步骤:
- 使用
embeddings.embed_query计算查询向量 - 在向量存储中执行相似度匹配
- 返回相关文档
六、向量存储的高级功能实现
6.1 过滤检索(Filtered Retrieval)
部分向量存储支持按元数据过滤,以Chroma为例:
# 添加带元数据的文本
vector_store.add_texts(
texts=["Python编程教程", "Java开发指南"],
metadatas=[{"language": "python"}, {"language": "java"}]
)
# 按元数据过滤检索
filtered_results = vector_store.similarity_search(
query="编程语言",
k=1,
where={"language": "python"}
)
Chroma通过where参数实现元数据过滤,在similarity_search方法中解析并应用过滤条件。
6.2 混合检索(Hybrid Retrieval)
混合检索结合关键词匹配与语义检索,LangChain通过HybridSearchRetriever实现:
from langchain.retrievers import HybridSearchRetriever
# 初始化混合检索器
retriever = HybridSearchRetriever(
vector_store=vector_store,
embedding=embeddings,
search_keyword_threshold=0.3
)
# 执行混合检索
hybrid_results = retriever.get_relevant_documents("分布式系统")
核心逻辑:
- 先进行关键词匹配获取候选集
- 对候选集执行语义检索
- 合并返回结果
七、向量存储的性能优化策略
7.1 批量操作优化
在添加数据时,批量处理可显著提升效率:
# 错误示例:逐条添加
for text in large_text_list:
vector_store.add_texts([text])
# 正确示例:批量添加
vector_store.add_texts(large_text_list)
add_texts方法内部通过一次计算和插入操作减少开销,如FAISS的index.add和Chroma的collection.add均支持批量数据。
7.2 索引优化
不同向量数据库提供索引优化手段:
- FAISS:支持创建层次化索引(如HNSW、IVFFlat),适合大规模数据
# 创建HNSW索引
index = faiss.HNSW(embedding_size, faiss.METRIC_L2)
- Chroma:自动管理索引,支持通过
persist_directory参数持久化数据
八、向量存储与其他模块的集成
8.1 与智能代理(Agent)集成
向量存储可作为代理的知识库,以RetrievalAgent为例:
from langchain.agents import RetrievalAgent
from langchain.chat_models import ChatOpenAI
# 创建检索器
retriever = vector_store.as_retriever()
# 初始化代理
agent = RetrievalAgent.from_llm_and_retriever(
llm=ChatOpenAI(temperature=0),
retriever=retriever
)
# 执行任务
agent.run("查找量子计算的最新进展")
RetrievalAgent在处理任务时,先通过向量存储检索相关文档,再结合LLM生成答案。
8.2 与工作流链(Chain)集成
向量存储可嵌入到链中实现复杂逻辑,如RetrievalQA链:
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
# 创建问答链
qa_chain = RetrievalQA.from_chain_type(
llm=OpenAI(),
chain_type="stuff",
retriever=vector_store.as_retriever()
)
# 执行问答
answer = qa_chain.run("区块链的核心原理是什么?")
RetrievalQA链先检索相关文档,再将文档内容与问题组合后传递给LLM生成答案。
九、向量存储的扩展与自定义开发
9.1 自定义向量存储类
开发者可通过继承VectorStore基类创建自定义存储:
class CustomVectorStore(VectorStore):
def __init__(self, custom_backend: Any):
self.backend = custom_backend
def add_texts(
self, texts: List[str], metadatas: Optional[List[dict]] = None, **kwargs: Any
) -> List[str]:
# 实现自定义添加逻辑
pass
def similarity_search(
self, query: str, k: int = 4, **kwargs: Any
) -> List[Document]:
# 实现自定义检索逻辑
pass
# 其他抽象方法实现...
需完整实现基类的抽象方法,并适配底层存储系统。
9.2 集成新的向量数据库
以集成Milvus为例,步骤如下:
- 安装
pymilvus库 - 继承
VectorStore实现核心方法 - 适配Milvus的API接口
import pymilvus
from langchain.vectorstores.base import VectorStore
class MilvusStore(VectorStore):
def __init__(self, collection_name: str, embedding_function: Any):
self.client = pymilvus.MilvusClient(uri="localhost", port="19530")
self.collection_name = collection_name
self.embedding_function = embedding_function
# 实现add_texts, similarity_search等方法...
十、向量存储模块的未来发展方向
10.1 多模态支持
未来将扩展支持图像、音频等多模态数据的向量存储,需要解决跨模态嵌入和统一检索问题。
10.2 分布式存储
针对大规模数据场景,开发分布式向量存储方案,提升存储容量和检索性能。
10.3 智能索引优化
结合AI技术实现索引的动态优化,根据数据特征和查询模式自动调整存储结构。
10.4 隐私增强
研究隐私保护技术,如联邦学习、同态加密,确保向量数据在存储和检索过程中的安全性。
3982

被折叠的 条评论
为什么被折叠?



