ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

(LangGraph教程)5. Long-Term Memory长期记忆——Lesson 1(2):LangGraph Store记忆存储(未索引)

(LangGraph教程)5. Long-Term Memory长期记忆——Lesson 1(2):LangGraph Store记忆存储(未索引) https://academy.langchain.com/courses/intro-to-langgraphhttps://github.com/shangxiang0907/langchain-academy文章目录Chatbot with Memory 带记忆功能的聊天机器人Review 复习Goals 目标Introduction to the LangGraph Store LangGraph Store 简介Chatbot with long-term memory 带长期记忆的聊天机器人Viewing traces in LangSmith 在 LangSmith 中查看追踪记录StudioChatbot with Memory 带记忆功能的聊天机器人Review 复习Memory is a cognitive function that allows people to store, retrieve, and use information to understand their present and future.记忆 是一种认知功能使人们能够存储、检索和使用信息以理解当下与未来。There are various long-term memory types that can be used in AI applications.存在多种长期记忆类型可用于人工智能应用。Goals 目标Here, we’ll introduce the LangGraph Memory Store as a way to save and retrieve long-term memories.此处我们将介绍 LangGraph Memory Store作为一种保存与检索长期记忆的方式。We’ll build a chatbot that uses bothshort-term (within-thread)andlong-term (across-thread)memory.我们将构建一个同时使用短期线程内和长期跨线程记忆的聊天机器人。We’ll focus on long-term semantic memory, which will be facts about the user.我们将重点关注长期语义记忆即关于用户的事实性信息。These long-term memories will be used to create a personalized chatbot that can remember facts about the user.这些长期记忆将用于创建一个个性化聊天机器人使其能够记住有关用户的事实。It will save memory “in the hot path”, as the user is chatting with it.它将在用户与其聊天时“在热路径中” 保存记忆。%%capture--no-stderr%pip install-U langchain_openai langgraph langchain_coreWe’ll use LangSmith for tracing.我们将使用 LangSmith 进行追踪。importos,getpassdef_set_env(var:str):ifnotos.environ.get(var):os.environ[var]getpass.getpass(f{var}: )_set_env(LANGSMITH_API_KEY)os.environ[LANGSMITH_TRACING]trueos.environ[LANGSMITH_PROJECT]langchain-academyIntroduction to the LangGraph Store LangGraph Store 简介The LangGraph Memory Store provides a way to store and retrieve informationacross threadsin LangGraph.LangGraph Memory Store 提供了一种在 LangGraph 中跨线程存储与检索信息的方式。This is an open source base class for persistentkey-valuestores.这是一个开源基类用于持久化的键值key-value存储。importuuidfromlanggraph.store.memoryimportInMemoryStore in_memory_storeInMemoryStore()When storing objects (e.g., memories) in the Store, we provide:向 Store 中存储对象例如记忆时我们需要提供Thenamespacefor the object, a tuple (similar to directories)对象的命名空间namespace为一个元组类似于目录结构the objectkey(similar to filenames)对象的键key类似于文件名the objectvalue(similar to file contents)对象的值value类似于文件内容We use the put method to save an object to the store bynamespaceandkey.我们使用 put 方法按命名空间和键将对象保存至存储中。# Namespace for the memory to saveuser_id1namespace_for_memory(user_id,memories)# Save a memory to namespace as key and valuekeystr(uuid.uuid4())# The value needs to be a dictionaryvalue{food_preference:I like pizza}# Save the memoryin_memory_store.put(namespace_for_memory,key,value)We use search to retrieve objects from the store bynamespace.我们使用 search 方法按命名空间从存储中检索对象。This returns a list.该方法返回一个列表。# Searchmemoriesin_memory_store.search(namespace_for_memory)type(memories)list# Metatdatamemories[0].dict(){value: {food_preference: I like pizza}, key: a754b8c5-e8b7-40ec-834b-c426a9a7c7cc, namespace: [1, memories], created_at: 2024-11-04T22:48:16.72757200:00, updated_at: 2024-11-04T22:48:16.72757400:00}# The key, valueprint(memories[0].key,memories[0].value)a754b8c5-e8b7-40ec-834b-c426a9a7c7cc {food_preference: I like pizza}We can also use get to retrieve an object bynamespaceandkey.我们还可以使用 get 方法按命名空间和键检索单个对象。# Get the memory by namespace and keymemoryin_memory_store.get(namespace_for_memory,key)memory.dict(){value: {food_preference: I like pizza}, key: a754b8c5-e8b7-40ec-834b-c426a9a7c7cc, namespace: [1, memories], created_at: 2024-11-04T22:48:16.72757200:00, updated_at: 2024-11-04T22:48:16.72757400:00}Chatbot with long-term memory 带长期记忆的聊天机器人We want a chatbot that has two types of memory:我们希望构建一个具备两种记忆类型的聊天机器人Short-term (within-thread) memory: Chatbot can persist conversational history and / or allow interruptions in a chat session.短期线程内记忆聊天机器人可在一次聊天会话中持续保存对话历史或支持中断操作。Long-term (cross-thread) memory: Chatbot can remember information about a specific useracross all chat sessions.长期跨线程记忆聊天机器人可跨所有聊天会话记住特定用户的有关信息。fromdotenvimportfind_dotenv,load_dotenv load_dotenv(find_dotenv(usecwdTrue))_set_env(OPENAI_API_KEY)Forshort-term memory, we’ll use a checkpointer.对于短期记忆我们将使用 检查点器checkpointer。See Module 2 and our conceptual docs for more on checkpointers, but in summary:更多关于检查点器的内容请参阅模块 2 及我们的概念文档简而言之They write the graph state at each step to a thread.它们在每一步都将图状态写入线程。They persist the chat history in the thread.它们在线程中持久化聊天历史。They allow the graph to be interrupted and / or resumed from any step in the thread.它们允许图从线程中的任意步骤被中断和/或恢复。And, forlong-term memory, we’ll use the LangGraph Store as introduced above.而对于长期记忆我们将使用上文介绍的 LangGraph Store。# Chat modelimportosfromlangchain_openaiimportChatOpenAI# Initialize the LLMmodelChatOpenAI(modelos.getenv(OPENAI_MODEL,qwen-plus),base_urlos.getenv(OPENAI_BASE_URL,https://dashscope.aliyuncs.com/compatible-mode/v1),temperature0)The chat history will be saved to short-term memory using the checkpointer.聊天历史将通过检查点器保存至短期记忆。The chatbot will reflect on the chat history.聊天机器人将对聊天历史进行反思。It will then create and save a memory to the LangGraph Store.然后它将创建一条记忆并保存至 LangGraph Store。This memory is accessible in future chat sessions to personalize the chatbot’s responses.该记忆可在未来的聊天会话中被访问从而实现聊天机器人响应的个性化。fromIPython.displayimportImage,displayfromlanggraph.checkpoint.memoryimportMemorySaverfromlanggraph.graphimportStateGraph,MessagesState,START,ENDfromlanggraph.store.baseimportBaseStorefromlangchain_core.messagesimportHumanMessage,SystemMessagefromlangchain_core.runnables.configimportRunnableConfig# Chatbot instructionMODEL_SYSTEM_MESSAGEYou are a helpful assistant with memory that provides information about the user. If you have memory for this user, use it to personalize your responses. Here is the memory (it may be empty): {memory}# Create new memory from the chat history and any existing memoryCREATE_MEMORY_INSTRUCTIONYou are collecting information about the user to personalize your responses. CURRENT USER INFORMATION: {memory} INSTRUCTIONS: 1. Review the chat history below carefully 2. Identify new information about the user, such as: - Personal details (name, location) - Preferences (likes, dislikes) - Interests and hobbies - Past experiences - Goals or future plans 3. Merge any new information with existing memory 4. Format the memory as a clear, bulleted list 5. If new information conflicts with existing memory, keep the most recent version Remember: Only include factual information directly stated by the user. Do not make assumptions or inferences. Based on the chat history below, please update the user information:defcall_model(state:MessagesState,config:RunnableConfig,store:BaseStore):Load memory from the store and use it to personalize the chatbots response.# Get the user ID from the configuser_idconfig[configurable][user_id]# Retrieve memory from the storenamespace(memory,user_id)keyuser_memoryexisting_memorystore.get(namespace,key)# Extract the actual memory content if it exists and add a prefixifexisting_memory:# Value is a dictionary with a memory keyexisting_memory_contentexisting_memory.value.get(memory)else:existing_memory_contentNo existing memory found.# Format the memory in the system promptsystem_msgMODEL_SYSTEM_MESSAGE.format(memoryexisting_memory_content)# Respond using memory as well as the chat historyresponsemodel.invoke([SystemMessage(contentsystem_msg)]state[messages])return{messages:response}defwrite_memory(state:MessagesState,config:RunnableConfig,store:BaseStore):Reflect on the chat history and save a memory to the store.# Get the user ID from the configuser_idconfig[configurable][user_id]# Retrieve existing memory from the storenamespace(memory,user_id)existing_memorystore.get(namespace,user_memory)# Extract the memoryifexisting_memory:existing_memory_contentexisting_memory.value.get(memory)else:existing_memory_contentNo existing memory found.# Format the memory in the system promptsystem_msgCREATE_MEMORY_INSTRUCTION.format(memoryexisting_memory_content)new_memorymodel.invoke([SystemMessage(contentsystem_msg)]state[messages])# Overwrite the existing memory in the storekeyuser_memory# Write value as a dictionary with a memory keystore.put(namespace,key,{memory:new_memory.content})# Define the graphbuilderStateGraph(MessagesState)builder.add_node(call_model,call_model)builder.add_node(write_memory,write_memory)builder.add_edge(START,call_model)builder.add_edge(call_model,write_memory)builder.add_edge(write_memory,END)# Store for long-term (across-thread) memoryacross_thread_memoryInMemoryStore()# Checkpointer for short-term (within-thread) memorywithin_thread_memoryMemorySaver()# Compile the graph with the checkpointer fir and storegraphbuilder.compile(checkpointerwithin_thread_memory,storeacross_thread_memory)# Viewdisplay(Image(graph.get_graph(xray1).draw_mermaid_png()))When we interact with the chatbot, we supply two things:当我们与聊天机器人交互时需提供两样东西Short-term (within-thread) memory: Athread IDfor persisting the chat history.短期线程内记忆一个用于持久化聊天历史的线程 ID。Long-term (cross-thread) memory: Auser IDto namespace long-term memories to the user.长期跨线程记忆一个用于将长期记忆按用户命名空间隔离的用户 ID。Let’s see how these work together in practice.让我们在实践中看看它们如何协同工作。# We supply a thread ID for short-term (within-thread) memory# We supply a user ID for long-term (across-thread) memoryconfig{configurable:{thread_id:1,user_id:1}}# User inputinput_messages[HumanMessage(contentHi, my name is Lance)]# Run the graphforchunkingraph.stream({messages:input_messages},config,stream_modevalues):chunk[messages][-1].pretty_print()[1m Human Message [0m Hi, my name is Lance [1m Ai Message [0m Hello, Lance! Its nice to meet you. How can I assist you today?# User inputinput_messages[HumanMessage(contentI like to bike around San Francisco)]# Run the graphforchunkingraph.stream({messages:input_messages},config,stream_modevalues):chunk[messages][-1].pretty_print()[1m Human Message [0m I like to bike around San Francisco [1m Ai Message [0m That sounds like a great way to explore the city, Lance! San Francisco has some beautiful routes and views. Do you have a favorite trail or area you like to bike in?We’re using theMemorySavercheckpointer for within-thread memory.我们正在使用MemorySaver检查点器来处理线程内记忆。This saves the chat history to the thread.该检查点器将聊天历史保存至线程。We can look at the chat history saved to the thread.我们可以查看已保存至线程的聊天历史。thread{configurable:{thread_id:1}}stategraph.get_state(thread).valuesforminstate[messages]:m.pretty_print()[1m Human Message [0m Hi, my name is Lance [1m Ai Message [0m Hello, Lance! Its nice to meet you. How can I assist you today? [1m Human Message [0m I like to bike around San Francisco [1m Ai Message [0m That sounds like a great way to explore the city, Lance! San Francisco has some beautiful routes and views. Do you have a favorite trail or area you like to bike in?Recall that we compiled the graph with our the store:请回顾一下我们已使用该存储编译了图across_thread_memoryInMemoryStore()And, we added a node to the graph (write_memory) that reflects on the chat history and saves a memory to the store.并且我们在图中添加了一个节点write_memory用于反思聊天历史并将记忆保存至存储。We can to see if the memory was saved to the store.我们可以验证该记忆是否已成功保存至存储。# Namespace for the memory to saveuser_id1namespace(memory,user_id)existing_memoryacross_thread_memory.get(namespace,user_memory)existing_memory.dict(){value: {memory: **Updated User Information:**\n- Users name is Lance.\n- Likes to bike around San Francisco.}, key: user_memory, namespace: [memory, 1], created_at: 2024-11-05T00:12:17.38391800:00, updated_at: 2024-11-05T00:12:25.46952800:00}Now, let’s kick off anew threadwith thesame user ID.现在让我们用相同的用户 ID启动一个新线程。We should see that the chatbot remembered the user’s profile and used it to personalize the response.我们应该能看到聊天机器人记住了用户的档案并据此个性化其响应。# We supply a user ID for across-thread memory as well as a new thread IDconfig{configurable:{thread_id:2,user_id:1}}# User inputinput_messages[HumanMessage(contentHi! Where would you recommend that I go biking?)]# Run the graphforchunkingraph.stream({messages:input_messages},config,stream_modevalues):chunk[messages][-1].pretty_print()[1m Human Message [0m Hi! Where would you recommend that I go biking? [1m Ai Message [0m Hi Lance! Since you enjoy biking around San Francisco, there are some fantastic routes you might love. Here are a few recommendations: 1. **Golden Gate Park**: This is a classic choice with plenty of trails and beautiful scenery. You can explore the parks many attractions, like the Conservatory of Flowers and the Japanese Tea Garden. 2. **The Embarcadero**: A ride along the Embarcadero offers stunning views of the Bay Bridge and the waterfront. Its a great way to experience the citys vibrant atmosphere. 3. **Marin Headlands**: If youre up for a bit of a challenge, biking across the Golden Gate Bridge to the Marin Headlands offers breathtaking views of the city and the Pacific Ocean. 4. **Presidio**: This area has a network of trails with varying difficulty levels, and you can enjoy views of the Golden Gate Bridge and the bay. 5. **Twin Peaks**: For a more challenging ride, head up to Twin Peaks. The climb is worth it for the panoramic views of the city. Let me know if you want more details on any of these routes!# User inputinput_messages[HumanMessage(contentGreat, are there any bakeries nearby that I can check out? I like a croissant after biking.)]# Run the graphforchunkingraph.stream({messages:input_messages},config,stream_modevalues):chunk[messages][-1].pretty_print()[1m Human Message [0m Great, are there any bakeries nearby that I can check out? I like a croissant after biking. [1m Ai Message [0m Absolutely, Lance! Here are a few bakeries in San Francisco where you can enjoy a delicious croissant after your ride: 1. **Tartine Bakery**: Located in the Mission District, Tartine is famous for its pastries, and their croissants are a must-try. 2. **Arsicault Bakery**: This bakery in the Richmond District has been praised for its buttery, flaky croissants. Its a bit of a detour, but worth it! 3. **b. Patisserie**: Situated in Lower Pacific Heights, b. Patisserie offers a variety of pastries, and their croissants are particularly popular. 4. **Le Marais Bakery**: With locations in the Marina and Castro, Le Marais offers a charming French bakery experience with excellent croissants. 5. **Neighbor Bakehouse**: Located in the Dogpatch, this bakery is known for its creative pastries, including some fantastic croissants. These spots should provide a delightful treat after your biking adventures. Enjoy your ride and your croissant!Viewing traces in LangSmith 在 LangSmith 中查看追踪记录We can see that the memories are retrieved from the store and supplied as part of the system prompt, as expected:我们可以看到记忆已按预期从存储中检索并作为系统提示的一部分提供https://smith.langchain.com/public/10268d64-82ff-434e-ac02-4afa5cc15432/rhttps://smith.langchain.com/public/10268d64-82ff-434e-ac02-4afa5cc15432/rStudioWe can also interact with our chatbot in Studio.我们还可以在 Studio 中与我们的聊天机器人进行交互。
返回列表