LangChain向量存储模块架构与数据操作源码深度剖析(80)

部署运行你感兴趣的模型镜像

LangChain向量存储模块架构与数据操作源码深度剖析

一、向量存储模块概述

LangChain的向量存储模块是连接文本数据与语言模型的关键桥梁,主要负责将文本转换为向量形式并进行高效存储,为语义检索、相似性匹配等任务提供底层支持。该模块采用高度抽象化和模块化设计,通过统一接口兼容多种向量数据库,如FAISS、Chroma、Milvus等。其核心目标是实现文本数据的快速检索与匹配,支撑智能问答、文档分析等复杂应用场景。

从整体架构来看,向量存储模块包含三个核心层次:

  1. 抽象基类层:定义统一接口规范
  2. 具体存储实现层:对接各类向量数据库
  3. 工具集成层:与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())))
        ]

核心实现逻辑:

  1. 初始化:创建FAISS索引,存储文本和元数据
  2. 添加文本:计算嵌入向量并添加到索引
  3. 检索:通过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方法内部流程:

  1. 调用embeddings.embed_documents生成向量
  2. 将向量添加到FAISS索引
  3. 存储原始文本和元数据

5.2 检索时的向量计算

在执行检索时,嵌入模块再次发挥作用:

query = "量子技术的应用场景"
results = vector_store.similarity_search(query, k=2)

具体步骤:

  1. 使用embeddings.embed_query计算查询向量
  2. 在向量存储中执行相似度匹配
  3. 返回相关文档

六、向量存储的高级功能实现

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("分布式系统")

核心逻辑:

  1. 先进行关键词匹配获取候选集
  2. 对候选集执行语义检索
  3. 合并返回结果

七、向量存储的性能优化策略

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为例,步骤如下:

  1. 安装pymilvus
  2. 继承VectorStore实现核心方法
  3. 适配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 隐私增强

研究隐私保护技术,如联邦学习、同态加密,确保向量数据在存储和检索过程中的安全性。

您可能感兴趣的与本文相关的镜像

Qwen3-VL-30B

Qwen3-VL-30B

图文对话
Qwen3-VL

Qwen3-VL是迄今为止 Qwen 系列中最强大的视觉-语言模型,这一代在各个方面都进行了全面升级:更优秀的文本理解和生成、更深入的视觉感知和推理、扩展的上下文长度、增强的空间和视频动态理解能力,以及更强的代理交互能力

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Android 小码蜂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值