Please enable Javascript to view the contents

 ·  ☕ 6 分钟
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from langchain.llms import Ollama
from langchain.embeddings import OllamaEmbeddings
from langchain.chains import RetrievalQA
from langchain.vectorstores import FAISS
from langchain.text_splitter import CharacterTextSplitter
from langchain.document_loaders import TextLoader

# 加载本地模型
llm = Ollama(model="llama2")
embeddings = OllamaEmbeddings(model="llama2")

# 加载文档
loader = TextLoader("your_knowledge_base.txt")
documents = loader.load()

# 切分文本
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
texts = text_splitter.split_documents(documents)

# 创建向量数据库
db = FAISS.from_documents(texts, embeddings)

# 创建问答链
qa = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=db.as_retriever())

# 提问
query = "你的问题是什么?"
result = qa.run(query)

print(result)

FAISS.from_documents()

上面程序中,FAISS.from_documents 是什么作用?

在上面的 LangChain + Ollama 示例程序中,FAISS.from_documents() 的作用是使用 FAISS(Facebook AI Similarity Search)库创建一个向量数据库,并将文档数据存储到该数据库中。下面我将详细解释这个过程:

1. 向量数据库 (Vector Database)

在构建基于 LLM 的问答系统时,我们需要存储和检索大量的文本信息。传统的关系型数据库不适合存储和查询文本的语义信息,因此我们需要使用向量数据库。

向量数据库将文本转换为高维向量(也称为嵌入向量),这些向量捕捉了文本的语义信息。通过计算向量之间的相似度,我们可以找到与用户查询最相关的文本片段。

2. FAISS 库

FAISS 是 Facebook AI Research 开发的一个用于高效相似性搜索和密集向量聚类的库。它提供了各种索引方法,可以加速向量的搜索速度,并支持大规模数据集。

3. FAISS.from_documents() 的作用

FAISS.from_documents() 是 LangChain 中用于创建 FAISS 向量数据库的便捷方法。它的主要功能包括:

  • 接收文档列表: 它接收一个包含 Document 对象的列表作为输入。每个 Document 对象包含文本内容和元数据。
  • 创建嵌入向量: 它使用指定的 Embeddings 对象(在示例代码中是 OllamaEmbeddings)将文档中的文本转换为向量。
  • 构建 FAISS 索引: 它使用转换后的向量构建 FAISS 索引,以便进行高效的相似性搜索。
  • 返回 FAISS 数据库对象: 它返回一个 FAISS 对象,该对象可以用于执行相似性搜索。

具体步骤分解

  1. 文档加载和分割: 首先,我们使用 Document Loaders(例如 TextLoader)加载知识库文档,然后使用 Text Splitters(例如 CharacterTextSplitter)将文档分割成较小的文本块。这样做是为了提高检索的精度和效率。
  2. 创建嵌入向量: 对于每个文本块,FAISS.from_documents() 会使用 OllamaEmbeddings 将其转换为一个向量。OllamaEmbeddings 会调用 Ollama 运行的语言模型来生成这些向量。这些向量捕捉了文本块的语义信息。
  3. 构建 FAISS 索引: FAISS 提供了多种索引方法,可以根据数据集的大小和性能要求选择合适的索引。FAISS.from_documents() 会根据向量的维度和数量自动选择一个合适的索引。这个索引会加速后续的相似性搜索。
  4. 存储到 FAISS 数据库: 创建好的索引和向量数据会被存储在 FAISS 数据库中,以便后续的检索。

示例代码解释

Python

db = FAISS.from_documents(texts, embeddings)

这行代码的含义是:

  • texts:是一个包含分割后的文本块的 Document 对象列表。
  • embeddings:是一个 OllamaEmbeddings 对象,用于将文本转换为向量。
  • FAISS.from_documents(texts, embeddings):使用 texts 中的文本块和 embeddings 创建一个 FAISS 数据库,并将数据库对象赋值给 db 变量。

总结

FAISS.from_documents() 简化了使用 FAISS 创建向量数据库的过程。它将文本转换为向量,并构建高效的索引,为后续的相似性搜索提供了基础。通过使用 FAISS,我们可以快速找到与用户查询相关的文本片段,从而提高问答系统的性能。

希望以上解释能够帮助你理解 FAISS.from_documents() 的作用。如果还有其他问题,欢迎继续提问。

RetrievalQA.from_chain_type()

在 LangChain 的示例代码中,RetrievalQA.from_chain_type() 的作用是创建一个“检索问答”(RetrievalQA)链。这个链专门用于处理需要从外部数据源检索信息的问答任务。它将检索步骤和语言模型生成答案的步骤结合在一起,形成一个完整的问答流程。

为什么需要 RetrievalQA 链?

单独使用大型语言模型(LLM)回答问题时,它只能依靠其训练数据中的知识。如果问题涉及到特定领域或最新的信息,LLM 可能无法给出准确或相关的答案。因此,我们需要一个机制来让 LLM 访问外部的知识库,并在回答问题时参考这些信息。RetrievalQA 链就是为了解决这个问题而设计的。

RetrievalQA.from_chain_type() 的作用分解

RetrievalQA.from_chain_type() 方法主要执行以下步骤:

  1. 检索 (Retrieval): 首先,它接收用户的查询,并使用“检索器”(Retriever)从向量数据库中检索相关的文本片段。检索器根据查询与向量数据库中存储的文本向量之间的相似度来查找最相关的文档。在你的代码中,db.as_retriever() 创建了一个基于 FAISS 数据库的检索器。
  2. 组合上下文 (Context): 它将检索到的文本片段作为上下文信息传递给 LLM。这些上下文信息为 LLM 提供了回答问题所需的背景知识。
  3. 生成答案 (Generation): 它使用指定的 LLM(在你的代码中是 Ollama(model="llama2"))根据用户查询和上下文信息生成答案。LLM 会利用上下文信息来提供更准确、更相关的回答。

from_chain_type() 的参数

RetrievalQA.from_chain_type() 方法接受几个重要的参数:

  • llm:要使用的语言模型。

  • chain_type
    

    :要使用的链的类型。常用的类型有:

    • "stuff":将所有检索到的文档“塞入”到提示中。这种方法简单直接,但如果检索到的文档过多,可能会超出 LLM 的上下文窗口限制。
    • "map_reduce":将每个检索到的文档单独传递给 LLM,并生成一个中间答案,然后将这些中间答案“归约”成一个最终答案。这种方法适用于处理大量文档,但可能会比较慢。
    • "refine":迭代地处理检索到的文档,逐步完善答案。这种方法可以提高答案的质量,但计算成本也较高。
    • "map_rerank": 类似于map_reduce, 但使用单独的LLM进行重新排序,选择最优解。
  • retriever:用于检索文档的检索器。

  • chain_type_kwargs:传递给链类型的其他参数。例如,你可以使用 chain_type_kwargs={"prompt": PROMPT} 来自定义提示。

示例代码解释

Python

qa = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=db.as_retriever())

这行代码的含义是:

  • llm:使用之前定义的 llm 对象(Ollama 运行的 llama2 模型)。
  • chain_type="stuff":使用 “stuff” 类型的链,即将所有检索到的文档塞入提示中。
  • retriever=db.as_retriever():使用基于 db(FAISS 数据库)的检索器。
  • 整个语句创建一个 RetrievalQA 链,并将其赋值给 qa 变量。

总结

RetrievalQA.from_chain_type() 是 LangChain 中一个非常有用的工具,它可以将检索和生成答案的步骤结合在一起,构建强大的问答系统。通过选择合适的 chain_typeretriever,你可以根据不同的应用场景进行优化,提高问答系统的性能和效率。

结合之前关于 FAISS.from_documents() 的解释,现在你应该对整个代码片段的功能有了更全面的理解:

  1. 使用 FAISS.from_documents() 创建向量数据库,存储知识库的向量表示。
  2. 使用 RetrievalQA.from_chain_type() 创建问答链,该链负责检索相关文档并使用 LLM 生成答案。

希望以上解释对你有所帮助。如有任何疑问,请随时提出。

分享

Mark Zhu
作者
Mark Zhu
An old developer