Press "Enter" to skip to content

利用LangChain和OpenAI提升文件理解能力

使用DAAL-E生成的图片

随着生成型人工智能和语言模型在理解和提取文档信息方面的巨大增长,我们正见证着一个新时代,在这个时代,像GPT这样的机器正在帮助人类更好地提取、解释和提取知识。

在本博客文章中,我们将讨论一个类似的用例,在其中我们利用OpenAI API和LangChain构建了一个能够从文档中提取信息并回答问题的系统。让我们开始吧。

步骤0:设置环境

为了本文的目的,我们将使用Jupyter Notebook和OpenAI API。

以下是我们在本教程中需要的模块。

pip install openai tiktoken chromadb langchain BeautifulSoup4

我们还需要设置OpenAI API凭据

import osos.environ["OPENAI_API_KEY"] = "sk-xxxx"

一旦这些都解决了,我们就可以开始了。

步骤1:获取文档内容

我们将使用伯克利人工智能研究博客的一篇文章https://bair.berkeley.edu/blog/2023/07/14/ddpo/

LangChain提供了一种方便的方式,从Web URL中读取数据并将其转换为Document格式。您可以在这里阅读更多关于加载文档的信息。

我们将使用WebBaseLoader如下所示。

from langchain.document_loaders import WebBaseLoaderloader = WebBaseLoader("https://bair.berkeley.edu/blog/2023/07/14/ddpo/")data = loader.load()print(data[0].page_content)> '\n\n\n\n\nTraining Diffusion Models with  Reinforcement Learning – The Berkeley Artificial Intelligence Research Blog\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nSubscribe\nAbout\nArchive\nBAIR\n\n\n\n\n\n\n\n\nTraining Diffusion Models with  Reinforcement Learning\n\n

步骤2:将文档转换为固定长度的块

一旦我们有了文档内容,下一步就是将其转换为固定大小的块,以便文本适应我们选择的模型上下文窗口。我们将使用具有500个块大小的RecursiveCharacterTextSplitter

from langchain.text_splitter import RecursiveCharacterTextSplittertext_splitter = RecursiveCharacterTextSplitter(chunk_size = 500, chunk_overlap = 0)all_splits = text_splitter.split_documents(data)print(all_splits[0])print(all_splits[1])> page_content='Training Diffusion Models with  Reinforcement Learning – The Berkeley Artificial Intelligence Research Blog\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nSubscribe\nAbout\nArchive\nBAIR\n\n\n\n\n\n\n\n\nTraining Diffusion Models with  Reinforcement Learning\n\nKevin Black \xa0\xa0\n  \n  \n  Jul 14, 2023\n  \n  \n\n\n\n\n\n\n\n\n\n\nTraining Diffusion Models with Reinforcement Learning\n\n\n\n\n\n\nreplay' metadata={'source': 'https://bair.berkeley.edu/blog/2023/07/14/ddpo/', 'title': 'Training Diffusion Models with  Reinforcement Learning – The Berkeley Artificial Intelligence Research Blog', 'description': 'The BAIR Blog', 'language': 'No language found.'}page_content='Diffusion models have recently emerged as the de facto standard for generating complex, high-dimensional outputs. You may know them for their ability to produce stunning AI art and hyper-realistic synthetic images, but they have also found success in other applications such as drug design\xa0and continuous control. The key idea behind diffusion models is to iteratively transform random noise into a sample, such as an image or protein structure. This is typically motivated as a maximum likelihood' metadata={'source': 'https://bair.berkeley.edu/blog/2023/07/14/ddpo/', 'title': 'Training Diffusion Models with  Reinforcement Learning – The Berkeley Artificial Intelligence Research Blog', 'description': 'The BAIR Blog', 'language': 'No language found.'}

步骤3:使用向量存储存储文档块

一旦我们将文档拆分成块,下一步是为文本创建嵌入并将其存储在向量存储中。我们可以按以下方式完成。

from langchain.embeddings import OpenAIEmbeddingsfrom langchain.vectorstores import Chromavectorstore = Chroma.from_documents(documents=all_splits, embedding=OpenAIEmbeddings())retriever = vectorstore.as_retriever()

步骤4:根据查询检索相似的文档

在为文本生成嵌入之后,我们可以使用向量相似搜索来获取与查询相关的文档块。

question = "DDPO算法使用了哪些步骤?"docs = vectorstore.similarity_search(question)print(f"检索到 {len(docs)} 个文档")print(docs[0].page_content)> 检索到 4 个文档我们算法的关键洞察,我们称之为去噪扩散策略优化(DDPO),是如果我们关注使最终样本的奖励最大化,我们可以更好地关注带我们到达那里的整个去噪步骤序列。为此,我们将扩散过程重新构建为多步马尔科夫决策过程(MDP)。在MDP术语中:每个去噪步骤都是一个动作,只有在每个去噪轨迹的最后一步生成最终样本时,代理才获得奖励。

步骤5:使用精炼的文档生成响应

现在,我们有了查询的精炼文档,我们可以创建一个LLM链,根据由vectorstore retriever提供的上下文来制定对查询的响应。我们将生成一个提示,指示LLM回答查询,并在不确定情况下指定一个固定的消息。

from langchain.prompts import PromptTemplate
template = """使用以下上下文内容回答最后的问题。如果你不知道答案,只需说不知道,不要编造答案。用最多三句话解释答案。简明扼要。最后要说“完成!”。{context}问题:{question}回答:""" 
prompt = PromptTemplate.from_template(template)

使用这个提示,我们将创建如下的LLM链

from langchain.schema.runnable import RunnablePassthrough
from langchain.chat_models import ChatOpenAI
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0)
qa_chain = ({"context": retriever, "question": RunnablePassthrough()} | prompt | llm)

在上述代码中,我们有一个新术语 — RunnablePassThrough。它是一个协议,可以更轻松地创建定制的LLM链,允许我们像上面那样将组件连接在一起。

现在我们可以使用我们的LLM链来回答我们的查询。

qa_chain.invoke("DDPO算法使用哪些步骤?").content> 'DDPO算法使用一系列去噪步骤来最大化最终样本的奖励。每个去噪步骤被视为多步马尔可夫决策过程(MDP)中的一个动作。只有当产生最终样本时,智能体才会在每个去噪轨迹的最后一步上获得奖励。完成!'qa_chain.invoke("文章讨论的主要思想是什么?").content> '文章讨论的主要思想是过度优化的问题以及对一种通用方法的需求来防止它。完成!'

Python笔记本的完整代码可以在这里找到。

通过这样,我们拥有了一个功能齐全的系统,可以轻松地帮助我们解释和理解文档。

如果你对使用生成AI和LangChain的其他奇妙能力感到好奇,敬请关注即将发布的文章,我们将深入探讨几个其他的用例。

Leave a Reply

Your email address will not be published. Required fields are marked *