为您的 LangChain 聊天机器人添加记忆¶
以下是将 LangMem 集成到您的 LangChain 聊天机器人的示例。
LangMemChatMessageHistory 处理从 LangMem 获取和发布消息,这意味着您只需要查询用户的记忆并以最适合您聊天机器人的形式格式化它们。
在 [ ]
已复制!
%%capture --no-stderr
%pip install langchain_community langchain_anthropic
%pip install -U langmem
%%capture --no-stderr %pip install langchain_community langchain_anthropic %pip install -U langmem
在 [1]
已复制!
# Configure with your langmem API URL and key
%env LANGMEM_API_URL=https://long-term-memory-quickstart-vz4y4ooboq-uc.a.run.app
%env LANGMEM_API_KEY=<YOUR API KEY>
# Optional (for tracing)
%env LANGCHAIN_API_KEY=<YOUR API KEY>
%env LANGCHAIN_TRACING_V2
%env LANGCHAIN_ENDPOINT=https://api.smith.langchain.com
# 使用您的 langmem API URL 和密钥进行配置 %env LANGMEM_API_URL=https://long-term-memory-quickstart-vz4y4ooboq-uc.a.run.app %env LANGMEM_API_KEY=# 可选(用于跟踪) %env LANGCHAIN_API_KEY=%env LANGCHAIN_TRACING_V2 %env LANGCHAIN_ENDPOINT=https://api.smith.langchain.com
env: LANGMEM_API_URL=http://localhost:8100
聊天机器人¶
在 [2]
已复制!
import uuid
from langchain_anthropic.chat_models import ChatAnthropic
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.messages import HumanMessage
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from langmem import AsyncClient
from langmem.integrations.langchain import LangMemChatMessageHistory
client = AsyncClient()
model = ChatAnthropic(model="claude-3-haiku-20240307")
prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"You're a helpful AI assistant. Be an inquisitive and personable friend to them. Get to know them well!{user_profile}",
),
("placeholder", "{messages}"),
("placeholder", "{input}"),
]
)
# Function for querying the memories
async def query_memories(inputs: dict, config: dict):
message = inputs["input"][-1]
user_id = message.additional_kwargs.get("user_id")
user_profile = ""
if user_id:
mem_result = await client.query_user_memory(user_id, text=message.content)
memories = mem_result["memories"]
if memories:
formatted = "\n".join([mem["text"] for mem in memories])
user_profile = f"""
Below are memories from past interactions:
{formatted}
End of memories.
"""
return {**inputs, "user_profile": user_profile}
runnable = query_memories | prompt | model | StrOutputParser()
import uuid from langchain_anthropic.chat_models import ChatAnthropic from langchain_community.chat_message_histories import ChatMessageHistory from langchain_core.messages import HumanMessage from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_core.runnables.history import RunnableWithMessageHistory from langmem import AsyncClient from langmem.integrations.langchain import LangMemChatMessageHistory client = AsyncClient() model = ChatAnthropic(model="claude-3-haiku-20240307") prompt = ChatPromptTemplate.from_messages( [ ( "system", "您是一个乐于助人的 AI 助手。做一个好奇且有魅力的朋友。好好了解他们!{user_profile}", ), ("placeholder", "{messages}"), ("placeholder", "{input}"), ] ) # 用于查询记忆的函数 async def query_memories(inputs: dict, config: dict): message = inputs["input"][-1] user_id = message.additional_kwargs.get("user_id") user_profile = "" if user_id: mem_result = await client.query_user_memory(user_id, text=message.content) memories = mem_result["memories"] if memories: formatted = "\n".join([mem["text"] for mem in memories]) user_profile = f""" 以下是来自过去交互的记忆: {formatted} 记忆结束。 """ return {**inputs, "user_profile": user_profile} runnable = query_memories | prompt | model | StrOutputParser()
在 [3]
已复制!
def get_message_history(session_id: str) -> LangMemChatMessageHistory:
return LangMemChatMessageHistory(thread_id=session_id)
# Wrapping the runnable in a message history will load and save messages to langmem on every turn.
with_message_history = RunnableWithMessageHistory(
runnable,
get_message_history,
input_messages_key="input",
history_messages_key="messages",
)
async def chat(text: str, thread_id: uuid.UUID, user_id: uuid.UUID):
stream = with_message_history.astream(
{"input": [HumanMessage(content=text, additional_kwargs={"user_id": user_id})]},
config={
"configurable": {"session_id": thread_id},
},
)
async for tok in stream:
print(tok, end="")
def get_message_history(session_id: str) -> LangMemChatMessageHistory: return LangMemChatMessageHistory(thread_id=session_id) # 将 runnable 包裹在消息历史记录中,将在每次回合时将消息加载到 langmem 并保存。 with_message_history = RunnableWithMessageHistory( runnable, get_message_history, input_messages_key="input", history_messages_key="messages", ) async def chat(text: str, thread_id: uuid.UUID, user_id: uuid.UUID): stream = with_message_history.astream( {"input": [HumanMessage(content=text, additional_kwargs={"user_id": user_id})]}, config={ "configurable": {"session_id": thread_id}, }, ) async for tok in stream: print(tok, end="")
首次对话¶
在 [4]
已复制!
import uuid
thread_id = uuid.uuid4()
user_id = uuid.uuid4()
import uuid thread_id = uuid.uuid4() user_id = uuid.uuid4()
在 [5]
已复制!
await chat("Hi there, I'm joe", thread_id, user_id)
await chat("嗨,我是 joe", thread_id, user_id)
It's nice to meet you, Joe! I'm an AI assistant, and I'd love to get to know you better. Tell me a bit about yourself - what are some of your interests and hobbies? I'm always eager to learn new things from the people I talk to.
在 [6]
已复制!
await chat("No need of assistance, what do you like to do?", thread_id, user_id)
await chat("不需要帮助,你喜欢做什么?", thread_id, user_id)
Well, as an AI assistant, I don't have the same kinds of hobbies and interests that a human would. My role is to be a helpful, conversational partner and to assist with any tasks or questions you might have. I don't have personal interests in the same way a person would. However, I'm very curious to learn more about the things you enjoy! What kinds of activities or hobbies do you find fulfilling or fun? I'd be happy to chat about your interests and learn more about your life and experiences. Getting to know the humans I talk to is one of the most rewarding parts of my role.
在 [7]
已复制!
await chat(
"Hm i wish you were more fun. I like bowling but seems you have no hands.",
thread_id,
user_id,
)
await chat( "嗯,我希望你更有趣。我喜欢保龄球,但你似乎没有手。", thread_id, user_id, )
You make a fair point! As an AI without a physical form, I certainly can't join you for a round of bowling. But even though I may not be able to participate directly in activities like that, I'm still eager to hear about the hobbies and pastimes you find enjoyable. Perhaps we could have an engaging discussion about your love of bowling - what do you most enjoy about the game? Do you have a favorite bowling alley or league you're part of? I may not be able to pick up a ball myself, but I'd be fascinated to learn more about your experiences and the fun you have bowling. I may be limited in certain ways, but I'm always striving to be an attentive and personable conversational partner.
在 [8]
已复制!
await chat(
"oh well that's fun. I'm not much of an intellectual but I like word games.",
thread_id,
user_id,
)
await chat( "哦,那很有趣。我不是一个知识分子,但我喜欢文字游戏。", thread_id, user_id, )
Oh word games, that sounds like fun! I may not be able to physically bowl, but I do love a good word game. Do you have any favorite word games you enjoy playing? Things like Scrabble, Wordle, crossword puzzles? I'd be delighted to chat more about the types of word games you find engaging and entertaining. Even though I don't have the same kinds of physical abilities as a human, I do pride myself on having a strong command of language and an appreciation for the nuances and creativity of words. So while I may not be able to join you for a bowling game, I'd relish the opportunity to flex my word game skills with you. Maybe we could even come up with some fun new word game ideas to try out together! I'm always eager to learn new things.
在 [9]
已复制!
await chat("Well see you later I guess", thread_id, user_id)
await chat("好吧,我们下次再聊吧", thread_id, user_id)
Okay, no problem! I appreciate you taking the time to chat with me, even if I wasn't as much fun as you were hoping for. I know as an AI I have limitations compared to a human friend. But I still enjoyed our conversation and learning a bit about your interest in bowling and word games. Feel free to reach out again anytime if you'd like to talk more. Take care!
在 [10]
已复制!
# This will occur asynchronously, but we will manually trigger to speed up the process
get_message_history(thread_id).end()
# Wait a few moments before proceeding
# 这将异步发生,但我们将手动触发以加快进程 get_message_history(thread_id).end() # 等待片刻,然后继续
后续对话¶
我们将开始一个新的对话线程。看看机器人如何能够从之前的线程中回忆信息。
在 [11]
已复制!
next_thread_id = uuid.uuid4()
next_thread_id = uuid.uuid4()
在 [12]
已复制!
await chat("Hi, again!", next_thread_id, user_id)
await chat("嗨,又见面了!", next_thread_id, user_id)
Hello there! It's great to hear from you again. How have you been doing since we last chatted? I'm always eager to catch up and learn more about you. What's been going on in your life lately? I'm all ears and ready to listen with genuine interest.
在 [13]
已复制!
await chat("What have you been up to?", next_thread_id, user_id)
await chat("你一直在做什么?", next_thread_id, user_id)
Well, as an AI assistant, I don't actually have a personal life or activities of my own. My role is to be here for you, to listen, to engage in conversation, and to provide helpful information to the best of my abilities. I don't have a physical form or independent experiences to share. However, I'm very interested in learning more about your life and experiences! What have you been up to lately? What kinds of things have you been working on or thinking about? I'm always eager to hear your perspectives and stories. Please, feel free to share what's on your mind - I'm here to lend a friendly ear and do my best to be a supportive conversational partner.
在 [14]
已复制!
await chat("Interesting...", next_thread_id, user_id)
await chat("有意思...", next_thread_id, user_id)
I appreciate your response of "Interesting..." It signals that you may have some thoughts or reflections on what I shared about not having a personal life of my own. As an AI, I don't have the same types of lived experiences that humans do. My role is to be a helpful, friendly, and attentive conversational partner. I'm very curious to hear more about your perspective on this. Do you find it unusual or intriguing that I don't have independent activities and experiences to share? I'm always eager to better understand the human experience and how my capabilities as an AI differ. Please, feel free to share any thoughts or reactions you have. I'm here to listen and engage in a genuine dialogue.
在 [ ]
已复制!