赞
踩
【2024最全最细Lanchain教程-9】Langchain互联网查询-CSDN博客
上节课我们介绍了如何利用langchain去加载互联网页面内容(中文信息)、向量化和利用大语言模型进行查询,这节课我们讲一下Langchain的记忆模块。
我们利用langchain构造最多的就是聊天机器人,而要进行聊天的业务功能,就必须使得大语言模型能够获得上下文,这样对话才能继续。我们注意一下,这句话非常关键:
记忆组件会将处理过的聊天信息数据注入提示词模板中,将模板传给大语言模型来实现记忆功能。
也就是说,记忆的功能其实是通过prompt模板来实现的,在prompt中要给memory组件预留好一个位置并告诉模板,这个是记忆内容,并在加载模板的时候把上下文注入进去传给大模型,大模型才能够知道你上文说的是啥。
ConversationBufferMemory是一个最简单的记忆组件,他不对数据结构和获取算法做任何讲过,就是简单的原进原出,我们来看他的代码:
- from langchain.memory import ConversationBufferMemory
-
- memory = ConversationBufferMemory()
- memory.load_memory_variables({})
运行load_memory_variables方法(注意要加载一个空的字典),不出意外可以得到空的一个memory:
我们可以加载一些数据给memory再看一下:
- memory.chat_memory.add_user_message("hi!")
- memory.chat_memory.add_ai_message("what's up?")
- memory.load_memory_variables({})
再加载一下,就可以看到刚才加载的数据了:
我们尝试在LLMChain里,加入memory功能,下面是完整的可直接运行代码:
- import os
-
- from langchain_openai import OpenAI
- from langchain.prompts import PromptTemplate
- from langchain.chains import LLMChain
- from langchain.memory import ConversationBufferMemory
-
-
- llm = OpenAI(
- temperature=0,
- openai_api_key = os.getenv("OPENAI_API_KEY"),
- base_url = os.getenv("OPENAI_BASE_URL")
- )
-
- # 注意,在模板里,要给聊天记录留下位置,聊天记录是通过注入给模板来实现的
-
- template = """You are a nice chatbot having a conversation with a human.
- Previous conversation:
- {chat_history}
- New human question: {question}
- Response:"""
-
-
- prompt = PromptTemplate.from_template(template)
-
- # `memory_key`要和模板里的参数保持一致
-
- memory = ConversationBufferMemory(memory_key="chat_history")
- conversation = LLMChain(
- llm=llm,
- prompt=prompt,
- verbose=True,
- memory=memory
- )
-
- conversation.invoke({"question":"hi"})
- conversation.invoke({"question":"你最喜欢什么动物?"})
- conversation.invoke({"question":"那么它最爱吃什么?"})
-
- memory.load_memory_variables({})
注意几个要点:
1. 模板里要预留好memory参数的位置,且要和构造memory时,设置的memory_key保持一致,如果不一致,会报错。
2. 在LLMChain的设置里,可以选择verbose=True,会把创建链的一些中间过程给体现出来,方便理解业务,我们来看代码的运行结果:
通过运行结果可以看到每次每次prompt模板加载的内容都有不同,就是每次在调用的时候memory的数据注入进了模板导致的。
我们尝试在LCEL语法的chain中加入memory功能,下面是hi代码实现:
- import langchain
- import os
-
- from operator import itemgetter
-
- from langchain_openai import ChatOpenAI
- from langchain_core.prompts import ChatPromptTemplate,MessagesPlaceholder
- from langchain_core.runnables import RunnableLambda, RunnablePassthrough
- from langchain.memory import ConversationBufferMemory
-
-
-
- llm = ChatOpenAI(
- temperature=0,
- openai_api_key = os.getenv("OPENAI_API_KEY"),
- base_url = os.getenv("OPENAI_BASE_URL")
- )
这块是引入必要的包、构建好模型,然后继续:
- memory = ConversationBufferMemory(return_messages=True)
-
- prompt = ChatPromptTemplate.from_messages([
- ("system", "你是一个中国历史专家."),
- MessagesPlaceholder(variable_name="history"),
- ("user", "{input}")
- ])
-
- memory.load_memory_variables({})
这里注意,因为我们用的是ChatOpenAI聊天模型包装器,所以return_messages 要选择True,否则memory的输出会是str。
然后我们在构造提示词的时候,需要用这个占位符来实现memory的插入,注意这里的variable_name是memory默认的history,如果你要改成chat_history,在memory构造的时候就要把key重新声明一下,这里我们就不改了,就用默认的history:
MessagesPlaceholder(variable_name="history"),
我们继续:
- chain = (
- RunnablePassthrough.assign(
- history=RunnableLambda(memory.load_memory_variables) | itemgetter("history")
- )
- | prompt
- | llm
- )
-
-
- input = {"input":"中国改革开放的总设计师是谁?"}
- response = chain.invoke(input)
- print(response)
-
- memory.save_context(input, {"output": response.content})
- memory.load_memory_variables({})
这一行的难点在于:
- RunnablePassthrough.assign(
- history=RunnableLambda(memory.load_memory_variables) | itemgetter("history")
- )
这里用RunnablePassthrough把用户输入的input传入,同时使用RunnableLambda方法将memory做加载(第一轮是空的,不过没关系,第二次调用就有数据里),RunnableLambda把memory加载获得数据(字典)赋值给history,构造了一个字典{“history”:"{}"},然后传给itemgetter,itemgetter把键值对里的值取出来然后再传给 prompt,大体的流程就是这样的。
我们进行一下调用看一下结果:
注意我的第二个问题,“他是什么时候去世的?”如果不联系上文,大模型是不知道如何回答你的,我们做一下对比实验:
我们重新构造一下memory,然后在第一次invoke之后不加载input和output,然后继续:
如果之前你不把聊天记录加载到memory里,大模型就无法回答你的问题。
有更多类型的memory组件,我们就不一一介绍了,大家可以去官网上去看,或者简要看一下这个图就行了:
需要用到更细的memory的时候再去学也来得及。
视频教学:【2024最全最细】LangChain之记忆模块_哔哩哔哩_bilibili
本教学演示代码已上传github: https://github.com/jerry1900/jupyter
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。