LangChain入门1 构建大模型对话与RAG

概述:

本文主要对langchain 的官网内容进行翻译以及进行验证与注释。
希望可以对langchain 的学习给到帮助。
官网链接,有兴趣也可以直接阅读官网。

一、构建基础的对话

LangChain支持构建将外部数据和计算源连接到LLM的应用程序。在这个快速入门中,我们将介绍几种不同的方法。我们将从一个简单的LLM链开始,它只依赖于提示模板中的信息来响应。接下来,我们将构建一个检索链,它从一个单独的数据库中获取数据,并将其传递到提示模板中。然后,我们将添加聊天历史记录,以创建一个会话检索链。这允许您以聊天的方式与此LLM进行交互,因此它可以记住以前的问题。

构建一个简单的对话

#加载ollama
from langchain_community.llms import Ollama
#加载模型
llm = Ollama(model="llama2")

学习加载模型可以参考链接

#构建最简单的对话 invoke 直接在实例化的大模型中添加需要对话的内容
return_=llm.invoke("how can langsmith help with testing?")
#使用 print 和没有print 在结果的输出上会出现格式的一些不一样后续都采用print的方式做对比
print(return_)

返回内容:
在这里插入图片描述
这里整个对话的内容长度在2459个。

添加提示词模版ChatPromptTemplate

from langchain_core.prompts import ChatPromptTemplate
#这里作为一个对话的提示词
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a world class technical documentation writer."),
    ("user", "{input}")
])
#changchain 的管道 这里是langchain的特点
chain = prompt | llm 
#添加一个提示词模版后相同问题的比对
return_=chain.invoke({"input": "how can langsmith help with testing?"})
print(return_)

返回
在这里插入图片描述
从上面的返回中看,返回的内容已经有点类似和人对话的样子。总体的长度在2138,添加模版后对输出的内容长度上没有明显的变化。

添加一个输出解释器 StrOutputParser

输出解析器通常用于将模型生成的原始输出转换成更易于理解和使用的格式。

#添加输出解释器
from langchain_core.output_parsers import StrOutputParser
#实例化
output_parser = StrOutputParser()

现在可以引用它并提出同样的问题。
可以调整成 {“str”: StrOutputParser()}

#将输出的结果添加output_parser 这里没有对具体的格式有做调整
chain = prompt | llm | output_parser

# 提出相同的问题
return_=chain.invoke({"input": "how can langsmith help with testing?"})

print(return_)

返回:
在这里插入图片描述
总体的文字内容长度在2861,

#查看添加样式后的结果输出
chain = prompt | llm | {"str": StrOutputParser()}
return_=chain.invoke({"input": "how can langsmith help with testing?"})
print(return_)

返回
在这里插入图片描述
这里输出的结果的格式变成了str。

构建一个RAG

为了正确回答最初的问题(“langsmith如何帮助测试?”),我们需要为LLM提供额外的上下文。我们可以通过检索来做到这一点。当您有太多的数据要直接传递给LLM时,检索非常有用。然后,您可以使用检索器只提取最相关的片段并将其传递进去。
在这个过程中,我们将从Retriever中查找相关文档,然后将它们传递到提示符中。Retriever可以由任何东西支持——SQL表、互联网等——但在这种情况下,我们将填充一个向量存储,并将其用作Retriever。

#加载依赖 document_loaders 下载需要做RAG的内容
from langchain_community.document_loaders import WebBaseLoader
#数据实例化
loader = WebBaseLoader("https://docs.smith.langchain.com/user_guide")
#数据下载
docs = loader.load()

print(docs)

返回
在这里插入图片描述
这里给到的是一个list

FAISS 向量库

#添加ollama 的向量化
from langchain_community.embeddings import OllamaEmbeddings
#添加向量化
embeddings = OllamaEmbeddings()

from langchain_community.vectorstores import FAISS #用于访问嵌入向量
from langchain_text_splitters import RecursiveCharacterTextSplitter

#通过递归地查看字符来拆分文本。
#递归地尝试按不同的字符进行拆分,以找到一个有效的字符。
#创建一个新的TextSplitter
#通过递归的方式来拆分文本
text_splitter = RecursiveCharacterTextSplitter()#实例化
documents = text_splitter.split_documents(docs)#拆分文档
vector = FAISS.from_documents(documents, embeddings)#灌库

create_stuff_documents_chain格式化提示

这个链获取一个文档列表,并将它们全部格式化为一个提示,然后将该提示传递给LLM。它传递所有文档

from langchain.chains.combine_documents import create_stuff_documents_chain
#创建几个链将文档传递给模型
#仅根据提供的上下文回答以下问题
prompt = ChatPromptTemplate.from_template("""Answer the following question based only on the provided context:

<context>
{context}
</context>

Question: {input}""")
#加载模型和提示词模版后的构建兑换链条
document_chain = create_stuff_documents_chain(llm, prompt)

现在我们已经在向量库中对这些数据进行了索引,我们将创建一个检索链。该链将接受一个传入的问题,查找相关文档,然后将这些文档与原始问题一起传递到LLM中,并要求其回答原始问题。

from langchain_core.documents import Document
#Document用于存储一段文本和相关联的元数据。
#将page_content作为位置参数或命名参数传入。
return_=document_chain.invoke({
    "input": "how can langsmith help with testing?",
    "context": [Document(page_content="langsmith can let you visualize test results")]
})
print(return_)

返回

Langsmith can help with testing by providing a platform for
visualizing and analyzing test results. This allows developers to
quickly identify issues and areas of improvement, making the testing
process more efficient and effective.

这里的回答非常的简单。

添加RAG并回答

from langchain.chains import create_retrieval_chain
#实例化向量检索器
retriever = vector.as_retriever()
#创建检索链,用于检索文档并将其传递出去。
retrieval_chain = create_retrieval_chain(retriever, document_chain)

我们现在可以调用这个链。这将返回一个字典-LLM的响应在答案键中

#检索链中添加回答
response = retrieval_chain.invoke({"input": "how can langsmith help with testing?"})
#print(response)

#查看向量的内容,response是一个字典
for key in response:
    print(key)

input
context
answer

#输入
response['input']

‘how can langsmith help with testing?’

#向量的检索内容
response['context'][0]

返回
在这里插入图片描述

#回答
response['answer']

返回
在这里插入图片描述

Conversation Retrieval Chain 会话检索链

到目前为止,我们创建的链只能回答单个问题。人们正在构建的LLM应用程序的主要类型之一是聊天机器人。那么,我们如何将这条链转化为一条可以回答后续问题的链呢? 我们仍然可以使用create_retrieval_chain函数,但我们需要更改两件事:

  • 检索方法现在不应该只针对最近的输入,而是应该考虑整个历史。最后的LLM链同样应考虑整个历史
  • 更新检索,我们将创建一个新的链。该链将接收最近的输入(input)和会话历史(chat_history),并使用LLM生成搜索查询。
from langchain.chains import create_history_aware_retriever
from langchain_core.prompts import MessagesPlaceholder

#首先,我们需要一个提示,可以将其传递到LLM中以生成此搜索查询
#这里出现了user 表示输入给大模型开始带入角色
#ChatPromptTemplate仅根据提供的上下文回答以下问题 
prompt = ChatPromptTemplate.from_messages([
    MessagesPlaceholder(variable_name="chat_history"),#加载历史的对话模版
    ("user", "{input}"),
    ("user", "Given the above conversation, generate a search query to look up to get information relevant to the conversation")
])
#创建历史检索 大模型 向量数据库 提示词
retriever_chain = create_history_aware_retriever(llm, retriever, prompt)

create_history_aware_retriever
创建一个获取对话历史记录并返回文档的链。如果没有chat_history,那么输入直接传递给检索器。如果存在chat_history,则提示和LLM将用于生成搜索查询。然后将该搜索查询传递给检索器。

MessagesPlaceholder
用于历史的对话模版加载

对比

我们可以通过传递一个用户提出后续问题的实例来测试这一点。

from langchain_core.messages import HumanMessage, AIMessage
#历史对话
#告知信息的来源
chat_history = [HumanMessage(content="Can LangSmith help test my LLM applications?"), AIMessage(content="Yes!")]

return_=retriever_chain.invoke({
    "chat_history": chat_history,#加载历史对话
    "input": "Tell me how"
})
len(return_)
#返回4个
return_[0]

在这里插入图片描述
应该看到,这会返回有关LangSmith中测试的文档。这是因为LLM生成了一个新的查询,将聊天历史记录与后续问题相结合。现在我们有了这个新的检索器,我们可以创建一个新的链来继续对话。

#ChatPromptTemplate仅根据提供的上下文回答以下问题 
prompt = ChatPromptTemplate.from_messages([
    ("system", "Answer the user's questions based on the below context:\n\n{context}"),
    
    MessagesPlaceholder(variable_name="chat_history"),#加载历史的对话模版
    
    ("user", "{input}"),
])

#加载模型和提示词模版后的构建兑换链条
document_chain = create_stuff_documents_chain(llm, prompt)
#创建检索
retrieval_chain = create_retrieval_chain(retriever_chain, document_chain)
#拆看检修的格式
retrieval_chain

在这里插入图片描述

端到端测试

chat_history = [HumanMessage(content="Can LangSmith help test my LLM applications?"), AIMessage(content="Yes!")]
return_=retrieval_chain.invoke({
    "chat_history": chat_history,
    "input": "Tell me how"
})
print(return_)

在这里插入图片描述
以上是附带了历史对话,校色输入,向量检索后返回的回答。

以上是本文的全部内容,官网中的AGENT相关的内容需要GPT4的key这里暂不做演示。
感谢阅读。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值