LangChain核心模块 Retrieval——文本嵌入模型、Vector stores

Text embedding models

  • 文本嵌入模型

检索的另一个关键部分是为文档创建嵌入。

Embeddings 类是设计用于与文本嵌入模型交互的类。

Embeddings创建一段文本的矢量表示,这样我们就可以在向量空间中思考文本,并执行语义搜索之类的操作,在向量空间中查找最相似的文本片段。

LangChain中的Embeddings基类提供了两种方法:

  • 用于嵌入文档,采用多个文本作为输入
  • 用于嵌入查询,采用单个文本作为输入

将它们作为两种单独方法的原因是,某些嵌入提供程序对文档(要搜索的)与查询(搜索查询本身)有不同的嵌入方法。

from langchain_openai import OpenAIEmbeddings

embeddings_model = OpenAIEmbeddings()
  1. embed_documents

    嵌入文本列表

    embeddings = embeddings_model.embed_documents(
        [
            "Hi there!",
            "Oh, hello!",
            "What's your name?",
            "My friends call me World",
            "Hello World!"
        ]
    )
    len(embeddings), len(embeddings[0])
    
  2. embed_query

    嵌入单个查询,嵌入一段文本是为了与其他嵌入的文本进行比较。

    embedded_query = embeddings_model.embed_query("What was the name mentioned in the conversation?")
    embedded_query[:5]
    

CacheBackedEmbeddings

embeddings可以被存储或临时缓存以避免需要重新计算它们。

缓存embeddings可以使用 CacheBackedEmbeddings 来完成。支持缓存的嵌入器是嵌入器的包装器,它将嵌入缓存在键值存储中。对文本进行哈希处理,并将哈希值用作缓存中的密钥。

初始化 CacheBackedEmbeddings 的主要支持方式是 from_bytes_store。它需要以下参数:

  • underlying_embedder(底层嵌入器):用于嵌入的嵌入器。
  • document_embedding_cache(文档嵌入缓存):任何用于缓存文档嵌入的 ByteStore
  • batch_size:(optional, defaults to None)要更新嵌入的文档数量。
  • namespace:(optional, defaults to "") 用于文档缓存的命名空间,该命名空间用于避免与其他缓存发生冲突。例如,将其设置为所使用的嵌入模型的名称。

请务必设置命名空间参数,以避免使用不同嵌入模型嵌入的相同文本发生冲突。

from langchain.embeddings import CacheBackedEmbeddings
Using with a Vector Store

首先,让我们看一个使用本地文件系统存储嵌入并使用 FAISS 矢量存储进行检索的示例。

%pip install --upgrade --quiet  langchain-openai faiss-cpu
from langchain.storage import LocalFileStore
from langchain_community.document_loaders import TextLoader
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings
from langchain_text_splitters import CharacterTextSplitter

underlying_embeddings = OpenAIEmbeddings()

store = LocalFileStore("./cache/")

cached_embedder = CacheBackedEmbeddings.from_bytes_store(
    underlying_embeddings, store, namespace=underlying_embeddings.model
)

嵌入之前缓存为空:

list(store.yield_keys())
[]

加载文档,将其分割成块,嵌入每个块并将其加载到向量存储中。

raw_documents = TextLoader("../../state_of_the_union.txt").load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
documents = text_splitter.split_documents(raw_documents)

创建向量存储:

%%time
db = FAISS.from_documents(documents, cached_embedder)
CPU times: user 218 ms, sys: 29.7 ms, total: 248 ms
Wall time: 1.02 s

如果我们尝试再次创建向量存储,它会快得多,因为它不需要重新计算任何嵌入。

%%time
db2 = FAISS.from_documents(documents, cached_embedder)
CPU times: user 15.7 ms, sys: 2.22 ms, total: 18 ms
Wall time: 17.2 ms

以下是创建的一些嵌入:

list(store.yield_keys())[:5]
['text-embedding-ada-00217a6727d-8916-54eb-b196-ec9c9d6ca472',
 'text-embedding-ada-0025fc0d904-bd80-52da-95c9-441015bfb438',
 'text-embedding-ada-002e4ad20ef-dfaa-5916-9459-f90c6d8e8159',
 'text-embedding-ada-002ed199159-c1cd-5597-9757-f80498e8f17b',
 'text-embedding-ada-0021297d37a-2bc1-5e19-bf13-6c950f075062']
Swapping the ByteStore
  • 交换字节存储

为了使用不同的 ByteStore,只需在创建 CacheBackedEmbeddings 时使用它即可。下面,我们创建一个等效的缓存嵌入对象,但使用非持久性InMemoryByteStore代替:

from langchain.embeddings import CacheBackedEmbeddings
from langchain.storage import InMemoryByteStore

store = InMemoryByteStore()

cached_embedder = CacheBackedEmbeddings.from_bytes_store(
    underlying_embeddings, store, namespace=underlying_embeddings.model
)

Vector stores

  • 矢量仓库

存储和搜索非结构化数据的最常见方法之一是将其嵌入,并存储生成的嵌入向量,然后在查询时嵌入非结构化查询并检索与嵌入查询“最相似”的嵌入向量。

矢量存储负责存储嵌入数据并执行矢量搜索。

在这里插入图片描述

使用向量存储的一个关键部分是创建要放入其中的向量,这通常是通过嵌入创建的。

Asynchronous operations

  • 异步操作

矢量存储通常作为需要一些 I/O 操作的单独服务运行,因此它们可能会被异步调用。这样会带来性能优势,因为不会浪费时间等待外部服务的响应。如果您使用异步框架(例如 FastAPI),这一点也可能很重要。

LangChain支持向量存储的异步操作。所有方法都可以使用其异步对应方法来调用,前缀 a 表示异步。

Qdrant 是一个向量存储,它支持所有异步操作,因此将在下例中使用它。

pip install qdrant-client
from langchain_community.vectorstores import Qdrant
  1. 异步创建向量存储

    db = await Qdrant.afrom_documents(documents, embeddings, "http://localhost:6333")
    
  2. 相似性搜索

    query = "What did the president say about Ketanji Brown Jackson"
    docs = await db.asimilarity_search(query)
    print(docs[0].page_content)
    
  3. 通过vector进行相似性搜索

    embedding_vector = embeddings.embed_query(query)
    docs = await db.asimilarity_search_by_vector(embedding_vector)
    

Maximum marginal relevance search (MMR)

  • 最大边际相关性搜索

最大边际相关性优化了所选文档之间查询的相似性和多样性。异步 API 也支持它。

query = "What did the president say about Ketanji Brown Jackson"
found_docs = await qdrant.amax_marginal_relevance_search(query, k=2, fetch_k=10)
for i, doc in enumerate(found_docs):
    print(f"{i + 1}.", doc.page_content, "\n")
### LangChain 使用教程 #### 链的定义与应用 链是 LangChain 中的任务组合机制,旨在管理和协调数据流以及执行复杂的操作流程。不同类型的链适用于不同的应用场景: - **LLMChain**: 基础链结构,适合简单的任务处理[^1]。 ```python from langchain import LLMChain, PromptTemplate template = "What is a good name for a company that makes {product}?" prompt = PromptTemplate(input_variables=["product"], template=template) llm_chain = LLMChain(prompt=prompt) print(llm_chain.run(product="colorful socks")) ``` - **RefineChain**: 设计用于涉及多个步骤的任务,能够逐步细化结果. ```python from langchain.chains.refine import RefineDocumentsChain refine_chain = RefineDocumentsChain() # Example usage would involve passing documents and prompts to refine the output iteratively. ``` - **MapReduceChain**: 支持并行化处理大量数据集,在提高效率方面表现出色. ```python from langchain.chains.mapreduce import MapReduceDocumentsChain map_reduce_chain = MapReduceDocumentsChain() # This chain can be used to process large datasets by splitting them into chunks, # processing each chunk independently (map), then combining results (reduce). ``` #### 检索器(Retriever) 检索器组件负责从大量的文档集合中高效地提取最相关的片段或全文本。这在面对海量信息源时尤为有用,可以显著提升响应速度和准确性. #### 文档相似度搜索实例 利用 Elasticsearch 结合 LangChain 实现高效的文档相似度搜索功能。此方法特别适用于需要迅速定位到大型文档库内相关内容的情况。例如在一个包含多年份体育赛事报道的数据集中寻找有关2023年环法自行车赛的信息[^2]: ```python import elasticsearch from langchain.retrievers.elastic_search_retriever import ElasticSearchRetriever es_client = elasticsearch.Elasticsearch(hosts=['http://localhost:9200']) retriever = ElasticSearchRetriever(es_client) query = "Who won the Tour de France in 2023?" results = retriever.retrieve(query=query) for result in results: print(result['_source']['content']) ``` #### 文档问答系统构建 借助于强大的语言模型(LLMs),可以通过解析PDF、HTML页面或是企业内部资料等方式获取知识,并据此建立交互式的问答平台。LangChain 提供了一系列工具帮助开发者轻松搭建这样的应用程序,包括但不限于嵌入(embeddings)技术和向量数据库(vector stores)[^3]. ```python from langchain.document_loaders import PyMuPDFLoader from langchain.embeddings.openai import OpenAIEmbeddings from langchain.vectorstores import Chroma loader = PyMuPDFLoader("path/to/document.pdf") documents = loader.load() embeddings = OpenAIEmbeddings(openai_api_key='your-api-key') vector_store = Chroma.from_documents(documents, embeddings) qa_system = vector_store.as_retrieval_qa() response = qa_system({"question": "What was discussed on page 5?"}) print(response['answer']) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值