【LangChain】检索器(Retrievers)

检索器

  • 概要
  • 开始
  • 一行(代码)创建索引
  • 演示
  • 总结

概要

检索器是一个接口,它根据非结构化查询返回文档。它比向量存储更通用。检索器不需要能够存储文档,只需返回(或检索)它。向量存储可以用作检索器的骨干,但也有其他类型的检索器。

开始

LangChainBaseRetriever类的公共API如下:

from abc import ABC, abstractmethod
from typing import Any, List
from langchain.schema import Document
from langchain.callbacks.manager import Callbacks

class BaseRetriever(ABC):
    ...
    def get_relevant_documents(
        self, query: str, *, callbacks: Callbacks = None, **kwargs: Any
    ) -> List[Document]:
        """Retrieve documents relevant to a query.
        Args:
            query: string to find relevant documents for
            callbacks: Callback manager or list of callbacks
        Returns:
            List of relevant documents
        """
        ...

    async def aget_relevant_documents(
        self, query: str, *, callbacks: Callbacks = None, **kwargs: Any
    ) -> List[Document]:
        """Asynchronously get documents relevant to a query.
        Args:
            query: string to find relevant documents for
            callbacks: Callback manager or list of callbacks
        Returns:
            List of relevant documents
        """
        ...

就这么简单!您可以调用 get_relevant_documents异步 get_relevant_documents 方法来检索与查询相关的文档,其中“相关性”由您调用的特定检索器对象定义。

当然,我们也帮助构建我们认为有用的检索器。我们关注的主要检索器类型是 Vectorstore 检索器。我们将在本指南的其余部分重点讨论这一点。

为了了解什么是向量存储检索器,了解什么是向量存储,这非常重要。那么让我们看看这个。

pip install chromadb

此示例展示了针对文档的问答。我们选择这个作为入门示例,因为它很好地结合了许多不同的元素(文本分割器、嵌入、向量存储),然后还展示了如何在链中使用它们。

针对文档的问答包括四个步骤:

  1. 创建索引
  2. 从该索引创建一个检索器
  3. 创建问答链
  4. 问问题!

每个步骤都有多个子步骤和潜在的配置。在本笔记本中,我们将主要关注 (1)。
我们将首先展示这样做的简短说明,然后分解实际发生的情况。

首先,让我们导入一些无论如何都会用到的通用类。

from langchain.chains import RetrievalQA
from langchain.llms import OpenAI

接下来在通用设置中,我们指定要使用的文档加载器。您可以在此处下载 state_of_the_union.txt 文件。

from langchain.document_loaders import TextLoader
loader = TextLoader('../state_of_the_union.txt', encoding='utf8')

一行(代码)创建索引

为了尽快开始,我们可以使用 VectorstoreIndexCreator

from langchain.indexes import VectorstoreIndexCreator
index = VectorstoreIndexCreator().from_loaders([loader])

结果:

使用直接本地 API 运行 Chroma。
使用内存中的 DuckDB 作为数据库。数据将是暂时的。

现在索引已创建,我们可以使用它来询问数据问题!请注意,在幕后,这实际上也执行了几个步骤,我们将在本指南的后面部分介绍这些步骤。

query = "总统对科坦吉·布朗·杰克逊说了些什么"
index.query(query)

结果:

总统表示,科坦吉·布朗·杰克逊是美国顶尖的法律专家之一、前私人执业顶级诉讼律师、前联邦公设辩护律师,出身于公立学校教育工作者和警察家庭。他还表示,她是共识的缔造者,得到了从警察兄弟会到民主党和共和党任命的前法官的广泛支持。
query = "总统对科坦吉·布朗·杰克逊说了些什么"
# 注意这里方法不一样啦
index.query_with_sources(query)

结果:

    {'question': '总统对科坦吉·布朗·杰克逊说了些什么',
     'answer': " 总统表示,他提名美国顶尖法律专家之一的巡回上诉法院法官科坦吉·布朗·杰克逊(Ketanji Brown Jackson)继承布雷耶大法官的卓越遗产,她得到了警察兄弟会以及民主党和共和党任命的前法官的广泛支持。\n",
     'sources': '../state_of_the_union.txt'}

VectorstoreIndexCreator 返回的是 VectorStoreIndexWrapper,它提供了很好的查询和 query_with_sources 功能。如果我们只是想直接访问向量库,我们也可以这样做。

index.vectorstore

结果:

    <langchain.vectorstores.chroma.Chroma at 0x119aa5940>

如果我们想访问 VectorstoreRetriever,我们可以这样做:

index.vectorstore.as_retriever()

结果:

    VectorStoreRetriever(vectorstore=<langchain.vectorstores.chroma.Chroma object at 0x119aa5940>, search_kwargs={})

演示

好吧,现在我们可能会有很多疑问:到底发生了什么?这个索引是如何创建的?
很多神奇之处都隐藏在这个 VectorstoreIndexCreator 中。这是在做什么?
加载文档后 将执行下面三个主要步骤:

  1. 将文档分割成块
  2. 为每个文档创建嵌入
  3. 在向量存储中存储文档和嵌入

让我们用代码来演示一下:

加载文档:

documents = loader.load()

接下来,我们将把文档分成块。

from langchain.text_splitter import CharacterTextSplitter
# 拆分器
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
# 将文档分成块
texts = text_splitter.split_documents(documents)

然后我们将选择要使用的嵌入。

from langchain.embeddings import OpenAIEmbeddings
# 创建嵌入
embeddings = OpenAIEmbeddings()

我们现在创建向量存储来用作索引。

from langchain.vectorstores import Chroma
# 向量存储,这也就意味着,创建了一个索引
db = Chroma.from_documents(texts, embeddings)

结果

    Running Chroma using direct local API.
    Using DuckDB in-memory for database. Data will be transient.

这就是创建索引。然后,我们在检索器接口中公开该索引。

# 公开该索引
retriever = db.as_retriever()

然后,像以前一样,我们创建一条链并用它来回答问题!

qa = RetrievalQA.from_chain_type(llm=OpenAI(), chain_type="stuff", retriever=retriever)
query = "总统对科坦吉·布朗·杰克逊说了些什么"
qa.run(query)

结果:

总统表示,科坦吉·布朗·杰克逊法官是美国顶尖的法律专家之一、前私人执业顶级诉讼律师、前联邦公设辩护律师,出身于公立学校教育工作者和警察家庭。他说,她是共识的缔造者,并得到了警察兄弟会等组织以及民主党和共和党任命的前法官的广泛支持。

VectorstoreIndexCreator 是所有这些逻辑的包装器。它可以在它使用的文本分割器、嵌入以及向量存储中进行配置。例如,您可以如下配置:

index_creator = VectorstoreIndexCreator(
    vectorstore_cls=Chroma,
    embedding=OpenAIEmbeddings(),
    text_splitter=CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
)

希望能帮助我们了解 VectorstoreIndexCreator 背后发生的事情。

总结

如何创建检索器

  1. 加载文档documents = loader.load()
  2. 创建拆分器,拆分文档
  3. 创建嵌入
  4. 构建向量存储(利用拆分后的文档和嵌入)得到索引:db = Chroma.from_documents(texts, embeddings)
  5. 利用索引得到检索器:retriever = db.as_retriever()

参考地址:

https://python.langchain.com/docs/modules/data_connection/retrievers/

你可能感兴趣的:(LangChain,AI,langchain)