LangChain向量存储与检索器快速入门指南

使用LangChain的向量存储和检索器

准备好体验LangChain的魔力了吗?今天我们要探索的是向量存储和检索器抽象,这是LLM工作流中不可或缺的一部分。我们将揭开它们的神秘面纱,并看看它们如何帮助我们从数据库和其他数据源中检索数据,特别是在需要进行检索增强生成(RAG)时。这不仅是技术上的飞跃,也是让你的应用程序更智能、更高效的关键一步。

核心概念

在这个教程中,我们将主要关注文本数据的检索。首先,我们需要了解以下几个关键概念:

  • 文档:文本数据的基本单位。
  • 向量存储:用于存储和检索文本数据的向量表示。
  • 检索器:用于从向量存储中检索相关数据的工具。
  • 让我们从安装和设置开始,然后深入了解每一个概念。

    设置

    Jupyter Notebook

    本教程及其他教程都推荐在Jupyter Notebook中运行。具体安装步骤请参阅这里。

    安装

    你需要安装langchainlangchain-chromalangchain-openai包:

    pip install langchain langchain-chroma langchain-openai
    

    更多详细信息,请参阅我们的安装指南。

    LangSmith

    随着你构建的LangChain应用程序变得越来越复杂,能够检查链或代理内部发生的情况变得至关重要。最好的方法是使用LangSmith。

    注册后,设置环境变量以开始记录跟踪:

    export LANGCHAIN_TRACING_V2="true"
    export LANGCHAIN_API_KEY="..."
    

    或者在notebook中,可以这样设置:

    import getpass
    import os
    
    os.environ["LANGCHAIN_TRACING_V2"] = "true"
    os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()
    

    文档

    LangChain实现了一个文档抽象,代表一个文本单元及其相关的元数据。它有两个属性:

  • page_content:表示内容的字符串;
  • metadata:包含任意元数据的字典。
  • 元数据属性可以捕捉文档的来源、与其他文档的关系等信息。通常,一个文档对象代表一个更大文档的片段。

    来生成一些示例文档吧:

    from langchain_core.documents import Document
    
    documents = [
        Document(
            page_content="狗是忠诚且友好的伴侣。",
            metadata={"source": "mammal-pets-doc"},
        ),
        Document(
            page_content="猫是独立的宠物,喜欢自己的空间。",
            metadata={"source": "mammal-pets-doc"},
        ),
        Document(
            page_content="金鱼是新手的理想宠物,养护简单。",
            metadata={"source": "fish-pets-doc"},
        ),
        Document(
            page_content="鹦鹉是聪明的鸟类,能够模仿人类说话。",
            metadata={"source": "bird-pets-doc"},
        ),
        Document(
            page_content="兔子是社交动物,需要足够的空间跳跃。",
            metadata={"source": "mammal-pets-doc"},
        ),
    ]
    

    向量存储

    向量搜索是一种常见的存储和搜索非结构化数据(如文本)的方式。基本思路是将文本存储为数值向量,给定查询时,可以将其嵌入为相同维度的向量,并使用向量相似度度量来识别存储中相关的数据。

    LangChain的VectorStore对象包含添加文本和文档对象到存储中的方法,并使用各种相似度度量进行查询。它们通常会与嵌入模型一起初始化,这决定了文本数据如何转换为数值向量。

    LangChain包括一套与不同向量存储技术的集成。一些向量存储由提供商托管(如各种云提供商),需要特定凭据使用;一些(如Postgres)在单独的基础设施上运行,可以本地或通过第三方运行;另一些可以在内存中运行,适合轻量级工作负载。这里我们将展示如何使用Chroma实现的LangChain VectorStores。

    要实例化向量存储,我们通常需要提供一个嵌入模型来指定文本应如何转换为数值向量。这里我们将使用OpenAI嵌入模型。

    from langchain_chroma import Chroma
    from langchain_openai import OpenAIEmbeddings
    
    vectorstore = Chroma.from_documents(
        documents,
        embedding=OpenAIEmbeddings(),
    )
    

    调用.from_documents会将文档添加到向量存储中。VectorStore实现了添加文档的方法,可以在对象实例化后调用。大多数实现允许你连接到现有的向量存储,例如,通过提供客户端、索引名称或其他信息。有关特定集成的更多详细信息,请参阅文档。

    一旦我们实例化了包含文档的VectorStore,我们可以查询它。VectorStore包括查询方法:

  • 同步和异步;
  • 通过字符串查询和向量查询;
  • 是否返回相似度分数;
  • 按相似度和最大边际相关性(以在相似度和检索结果的多样性之间平衡)。
  • 这些方法的输出通常包含一个文档对象列表。

    示例

    根据与字符串查询的相似度返回文档:

    vectorstore.similarity_search("cat")
    
    # 输出示例:
    [
        Document(page_content='猫是独立的宠物,喜欢自己的空间。', metadata={'source': 'mammal-pets-doc'}),
        Document(page_content='狗是忠诚且友好的伴侣。', metadata={'source': 'mammal-pets-doc'}),
        Document(page_content='兔子是社交动物,需要足够的空间跳跃。', metadata={'source': 'mammal-pets-doc'}),
        Document(page_content='鹦鹉是聪明的鸟类,能够模仿人类说话。', metadata={'source': 'bird-pets-doc'})
    ]
    

    异步查询:

    await vectorstore.asimilarity_search("cat")
    
    # 输出示例:
    [
        Document(page_content='猫是独立的宠物,喜欢自己的空间。', metadata={'source': 'mammal-pets-doc'}),
        Document(page_content='狗是忠诚且友好的伴侣。', metadata={'source': 'mammal-pets-doc'}),
        Document(page_content='兔子是社交动物,需要足够的空间跳跃。', metadata={'source': 'mammal-pets-doc'}),
        Document(page_content='鹦鹉是聪明的鸟类,能够模仿人类说话。', metadata={'source': 'bird-pets-doc'})
    ]
    

    返回分数:

    vectorstore.similarity_search_with_score("cat")
    
    # 输出示例:
    [
        (Document(page_content='猫是独立的宠物,喜欢自己的空间。', metadata={'source': 'mammal-pets-doc'}), 0.3751849830150604),
        (Document(page_content='狗是忠诚且友好的伴侣。', metadata={'source': 'mammal-pets-doc'}), 0.48316916823387146),
        (Document(page_content='兔子是社交动物,需要足够的空间跳跃。', metadata={'source': 'mammal-pets-doc'}), 0.49601367115974426),
        (Document(page_content='鹦鹉是聪明的鸟类,能够模仿人类说话。', metadata={'source': 'bird-pets-doc'}), 0.4972994923591614)
    ]
    

    基于嵌入查询返回文档:

    embedding = OpenAIEmbeddings().embed_query("cat")
    
    vectorstore.similarity_search_by_vector(embedding)
    
    # 输出示例:
    [
        Document(page_content='猫是独立的宠物,喜欢自己的空间。', metadata={'source': 'mammal-pets-doc'}),
        Document(page_content='狗是忠诚且友好的伴侣。', metadata={'source': 'mammal-pets-doc'}),
        Document(page_content='兔子是社交动物,需要足够的空间跳跃。', metadata={'source': 'mammal-pets-doc'}),
        Document(page_content='鹦鹉是聪明的鸟类,能够模仿人类说话。', metadata={'source': 'bird-pets-doc'})
    ]
    

    了解更多:

  • API参考
  • 指南
  • 集成文档
  • 检索器

    LangChain的VectorStore对象不继承Runnable,因此不能直接集成到LangChain表达语言链中。

    LangChain的检索器是可运行的,因此实现了一套标准方法(如同步和异步调用和批处理操作),并设计为可以集成到LCEL链中。

    我们可以自己创建一个

    简单版本,而不需要继承Retriever。选择我们希望使用的检索文档的方法,可以很容易地创建一个可运行的。下面我们将围绕similarity_search方法构建一个:

    from typing import List
    from langchain_core.documents import Document
    from langchain_core.runnables import RunnableLambda
    
    retriever = RunnableLambda(vectorstore.similarity_search).bind(k=1)  # 选择最优结果
    
    retriever.batch(["cat", "shark"])
    

    向量存储实现了一个as_retriever方法,该方法将生成一个检索器,特别是一个VectorStoreRetriever。这些检索器包括特定的search_typesearch_kwargs属性,标识调用底层向量存储的哪些方法以及如何参数化它们。例如,我们可以复制上面的内容:

    retriever = vectorstore.as_retriever(
        search_type="similarity",
        search_kwargs={"k": 1},
    )
    
    retriever.batch(["cat", "shark"])
    
    # 输出示例:
    [
        [Document(page_content='猫是独立的宠物,喜欢自己的空间。', metadata={'source': 'mammal-pets-doc'})],
        [Document(page_content='金鱼是新手的理想宠物,养护简单。', metadata={'source': 'fish-pets-doc'})]
    ]
    

    VectorStoreRetriever支持“相似性”(默认)、“mmr”(最大边际相关性)和“相似性分数阈值”的搜索类型。我们可以使用后者通过相似性分数阈值来筛选检索器输出的文档。

    检索器可以轻松集成到更复杂的应用程序中,例如将检索到的上下文与问题结合形成LLM提示的检索增强生成(RAG)应用程序。下面是一个最小示例。

    pip install -qU langchain-openai
    
    import getpass
    import os
    
    os.environ["OPENAI_API_KEY"] = getpass.getpass()
    
    from langchain_openai import ChatOpenAI
    llm = ChatOpenAI(model="gpt-4o-mini")
    
    from langchain_core.prompts import ChatPromptTemplate
    from langchain_core.runnables import RunnablePassthrough
    
    message = """
    使用提供的上下文回答以下问题。
    
    {question}
    
    上下文:
    {context}
    """
    
    prompt = ChatPromptTemplate.from_messages([("human", message)])
    
    rag_chain = {"context": retriever, "question": RunnablePassthrough()} | prompt | llm
    
    response = rag_chain.invoke("告诉我关于猫的知识")
    
    print(response.content)
    

    输出示例:

    猫是独立的宠物,喜欢自己的空间。
    

    恭喜你!你现在已经掌握了使用LangChain的向量存储和检索器的基础知识。继续探索,打造更智能、更强大的应用程序吧!

    作者:数字沉思

    物联沃分享整理
    物联沃-IOTWORD物联网 » LangChain向量存储与检索器快速入门指南

    发表回复