从零开始学习 langchain 之实现带有记忆功能的 chatbot

1,046 阅读3分钟

大家好,我是雨飞。今天给大家介绍下,如何使用 langchain 实现一个带有记忆功能的 chatbot。

采用的大模型,依旧是之前的 Yi-34B,毕竟 token 挺多的,不能浪费。

记忆功能 Memory

langchain 内置了 memory 的模块,可以存储我们和大模型的历史对话,这样就可以让大模型记住和我们的聊天记录了。下图就是 langchain 中对 memory 模块的示意图,

memory 主要实现两个步骤,在收到用户初始输入后,但在执行核心逻辑之前,langchian 会从内存系统中读取历史信息并增加用户输入。在执行核心逻辑后、返回答案前,langchian 会将当前运行的输入和输出写入内存,以便在以后的运行中参考。

一、手动聊天记录管理

我们采用占位符 MessagePlaceholder 去作为用户输入的占位符。然后使用 langchain 的 LCEL语法去实现一个 llm chain。

使用 invoke 方法就可以调用 llm 了,这个时候,我们手动把历史信息放在一个 list 里面,然后去获取最后结果。

完整代码如下:

from langchain_core.messages import AIMessage, HumanMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

# 手动聊天记录管理
prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "You are a helpful assistant. Answer all questions to the best of your ability.",
        ),
        MessagesPlaceholder(variable_name="messages"),
    ]
)

chain = prompt | yi_llm

result = chain.invoke(
    {
        "messages": [
            HumanMessage(
                content="Translate this sentence from English to French: I love programming."
            ),
            AIMessage(content="J'adore la programmation."),
            HumanMessage(content="What did you just say?"),
        ],
    }
)

print(result)

二、ChatMessageHistory 手动调用

ChatMessageHistory 是 langchain 中自己封装的 memory 的一个类,可以手动将对话信息添加到这个类里面并进行调用。

我们可以调用这个类的 add_ai_message 和 add_user_message 去分别把 AI 和用户输出的信息添加到内存记忆中。

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "You are a helpful assistant. Answer all questions to the best of your ability.",
        ),
        MessagesPlaceholder(variable_name="messages"),
    ]
)

chain = prompt | yi_llm

from langchain.memory import ChatMessageHistory
demo_ephemeral_chat_history = ChatMessageHistory()

input1 = "Translate this sentence from English to French: I love programming."

demo_ephemeral_chat_history.add_user_message(input1)

response = chain.invoke(
    {
        "messages": demo_ephemeral_chat_history.messages,
    }
)

demo_ephemeral_chat_history.add_ai_message(response)

input2 = "What did I just ask you?"

demo_ephemeral_chat_history.add_user_message(input2)

result = chain.invoke(
    {
        "messages": demo_ephemeral_chat_history.messages,
    }
)

print(response)
print(result)

三、 ChatMessageHistory 自动调用

前面两种方法都需要自己管理历史的对话信息,非常麻烦,langchain 也提供了自己的管理机制可以帮助我们更好的管理历史对话。这样就使用 RunnableWithMessageHistory 对原始的 llm 进行封装。

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.memory import ChatMessageHistory
prompt = ChatPromptTemplate.from_messages(
    [
        (
            "system",
            "You are a helpful assistant. Answer all questions to the best of your ability.",
        ),
        MessagesPlaceholder(variable_name="chat_history"),
        ("human", "{input}"),
    ]
)

chain = prompt | yi_llm

from langchain_core.runnables.history import RunnableWithMessageHistory

demo_ephemeral_chat_history_for_chain = ChatMessageHistory()

chain_with_message_history = RunnableWithMessageHistory(
    chain,
    lambda session_id: demo_ephemeral_chat_history_for_chain,
    input_messages_key="input",
    history_messages_key="chat_history",
)

result =chain_with_message_history.invoke(
    {"input": "Translate this sentence from English to French: I love programming."},
    {"configurable": {"session_id": "unused"}},
)
print(result)

result =chain_with_message_history.invoke(
    {"input": "What did you just say?"},
    {"configurable": {"session_id": "unused"}},
)
print(result)
print(demo_ephemeral_chat_history_for_chain.messages)

好了,这篇文章到此结束,如果对你有所感悟,欢迎点赞,评论 。

雨飞同行

  • 雨飞
  • 主业是推荐算法
  • 希望通过自媒体开启自己不上班只工作的美好愿景
  • 微信:1060687688
  • 欢迎和我交朋友🫰