从零开始用LangChain、Pinecone和LLMs搭建你自己的文档问答系统
AI魔法学院
2023-06-18
分享海报

一、简介

今天我们将深入探讨使用LangChainPinecone创建基于文档的问答系统的过程,利用最新的大文本语言模型(LLMs),如OpenAI GPT-4和ChatGPT。

LangChain 是一个强大的框架,专为开发由语言模型驱动的应用程序而设计,而 Pinecone 则是一个高效的向量数据库,用于构建高性能的向量搜索应用程序。我们的用例重点是在特定的文档上回答问题,仅依赖于文档中的信息来生成准确和符合上下文的答案。

通过将语义搜索的能力与GPT等LLM的卓越能力相结合,我们将演示如何构建一种利用尖端人工智能技术的先进文档问答系统。

二、为什么语义搜索+GPT问答比微调GPT更好?

在深入实现之前,我们先来了解一下使用语义搜索+GPT问答相比微调GPT的优势:

2.1、更广泛的知识覆盖:

语义搜索 + GPT 问答主要包括两个核心步骤,首先从大量的文档中找到相关的段落,然后根据这些段落生成答案。这种方法可以提供更准确和最新的信息,利用来自各种来源的最新信息。而微调GPT则依赖于模型在训练期间编码的知识,这些知识随着时间的推移可能变得过时或不完整。

2.2、特定于上下文的答案:

语义搜索+GPT问答可以通过将答案基于相关文档中的特定段落来生成更具上下文的、更精确的答案。然而,微调的GPT模型可能会根据模型中嵌入的通用知识生成答案,这些答案可能不够准确或与问题的上下文无关。

2.3、适应性

语义搜索组件可以轻松更新新的信息源或调整到不同的领域,使其更适应特定的用例或行业。相比之下,微调GPT需要重新训练模型,这可能耗时且计算成本高昂。

2.4、更好地处理模糊查询

语义搜索可以通过识别与问题相关的最相关段落来消除查询的歧义。与没有适当上下文的微调GPT模型相比,这可以带来更准确和相关的答案。

三、LangChain 模块

LangChain 提供了对几个主要模块的支持:

模型:LangChain 支持的各种模型类型和模型集成。

索引:当结合你自己的文本数据时,语言模型通常更加强大 - 这个模块涵盖了这样做的最佳实践。

:链不仅仅是一个单一的 LLM 调用,而是一系列的调用(无论是对 LLM 还是其他工具)。LangChain 提供了一个标准的链接口,许多与其他工具的集成,以及针对常见应用的端到端链。

四、设置环境

首先,我们需要安装所需的包并导入必要的库。

安装所需的包:

!pip install --upgrade langchain openai -q
!pip install unstructured -q
!pip install unstructured[local-inference] -q
!pip install detectron2@git+https://github.com/facebookresearch/detectron2.git@v0.6#egg=detectron2 -q
!apt-get install poppler-utils

导入必要的库:

import os
import openai
import pinecone
from langchain.document_loaders import DirectoryLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Pinecone
from langchain.llms import OpenAI
from langchain.chains.question_answering import load_qa_chain

五、加载文档

导入文档之前,请确保pillow <= 6.2.2,否则会抛出下面的异常:

ImportError: cannot import name 'is_directory' from 'PIL._util' (/usr/local/lib/python3.10/dist-packages/PIL/_util.py)

检查pillow的版本,重新安装6.2.2版本,安装完成后需要重启Colab Runtime环境。

!pip show pillow
!pip uninstall pillow 
!pip install --upgrade pillow==6.2.2

首先,我们需要使用 LangChain 的 DirectoryLoader 从一个目录中加载文档。在这个例子中,我们假设文档存储在一个叫做 'data' 的目录中。

directory = '/content/data'

def load_docs(directory):
  loader = DirectoryLoader(directory)
  documents = loader.load()
  return documents

documents = load_docs(directory)
len(documents)

六、分割文档

现在,我们需要将文档分割成更小的块进行处理。我们将使用 LangChain 的 RecursiveCharacterTextSplitter,它默认尝试在字符 ["\n\n", "\n", " ", ""] 上进行分割。

def split_docs(documents, chunk_size=1000, chunk_overlap=20):
  text_splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap)
  docs = text_splitter.split_documents(documents)
  return docs

docs = split_docs(documents)
print(len(docs))

七、使用 OpenAI 嵌入文档

一旦文档被分割,我们需要使用 OpenAI 的语言模型来嵌入它们。首先,我们需要安装 tiktoken 库。

!pip install tiktoken -q

现在,我们可以使用 LangChain 的 OpenAIEmbeddings 类来嵌入文档。

import openai
from langchain.embeddings.openai import OpenAIEmbeddings

embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")

query_result = embeddings.embed_query("记忆内存")
len(query_result)

八、使用 Pinecone 进行向量搜索

接下来,我们将使用 Pinecone 为我们的文档创建一个索引。首先,我们需要安装 pinecone-client。

!pip install pinecone-client -q

在初始化之前,我们需要在Pinecone控制台创建一个Index索引,Dimensions的值为我们前面计算的嵌入维度大小,这里为1536,具体需要根据你的实际计算结果来配置。

然后,我们可以初始化 Pinecone 并创建一个 Pinecone 索引。

pinecone.init(
    api_key="pinecone api key",
    environment="env"
)

index_name = "langchain-demo"

index = Pinecone.from_documents(docs, embeddings, index_name=index_name)

我们使用方法创建了一个新的 Pinecone 向量索引。这个方法接受三个参数:Pinecone.from_documents()

1、docs: 一个由 RecursiveCharacterTextSplitter 分割成更小块的文档列表。这些更小的块将被索引到 Pinecone 中,以便以后更容易地搜索和检索相关的文档。

2、embeddings: OpenAIEmbeddings 类的一个实例,它负责使用 OpenAI 的语言模型将文本数据转换为嵌入(即数值表示)。这些嵌入将被存储在 Pinecone 索引中,并用于相似性搜索。

3、index_name: 一个表示 Pinecone 索引名称的字符串。这个名称用于在 Pinecone 的数据库中识别索引,并且应该是唯一的,以避免与其他索引冲突。

此方法用于处理输入文档,使用提供的 OpenAIEmbeddings 实例生成嵌入,并用指定的名称创建一个新的 Pinecone 索引。生成的索引对象可以执行相似性搜索,并根据用户查询检索相关的文档。Pinecone.from_documents()

九、查找相似的文档

现在,我们可以定义一个函数,根据给定的查询找到相似的文档。

def get_similiar_docs(query, k=2, score=False):
  if score:
    similar_docs = index.similarity_search_with_score(query, k=k)
  else:
    similar_docs = index.similarity_search(query, k=k)
  return similar_docs

查询结果

十、使用 LangChain 和 OpenAI LLM 进行问答

有了必要的组件,我们现在可以使用 LangChain 的 OpenAI 类和一个预构建的问答链来创建一个问答系统。

# model_name = "text-davinci-003"
# model_name = "gpt-3.5-turbo"
model_name = "gpt-4"
llm = OpenAI(model_name=model_name)

chain = load_qa_chain(llm, chain_type="stuff")

def get_answer(query):
  similar_docs = get_similiar_docs(query)
  answer = chain.run(input_documents=similar_docs, question=query)
  return answer

十一、示例查询和答案

最后,让我们用一些示例查询来测试我们的问答系统。

query = "如何安装LangChain?"
answer = get_answer(query)
print(answer)

query = "管理LLM的提示?"
answer = get_answer(query)
print(answer)

十二、结论

在这篇博客文章中,我们演示了如何使用 LangChain 和 Pinecone 构建一个基于文档的问答系统。通过利用语义搜索和大型语言模型,这种方法提供了一个强大而灵活的解决方案,用于从大量的文档中提取信息。你可以进一步定制这个系统,以适应你的特定需求或领域。

Google Colab Notebook:

github.com/Crossme0809/

原文:从零开始用LangChain、Pinecone和LLMs搭建你自己的文档问答系统 - 知乎 (zhihu.com)

© THE END

转载请联系本网站获得授权

投稿或版权问题请加微信:skillupvip