| from dotenv import load_dotenv |
| import uuid |
| from langgraph.store.memory import InMemoryStore |
| from langchain_openai import ChatOpenAI |
| from IPython.display import Image, display |
|
|
| from langgraph.checkpoint.memory import MemorySaver |
| from langgraph.graph import StateGraph, MessagesState, START, END |
| from langgraph.store.base import BaseStore |
|
|
| from langchain_core.messages import HumanMessage, SystemMessage |
| from langchain_core.runnables.config import RunnableConfig |
|
|
|
|
| load_dotenv() |
| model = ChatOpenAI(model="gpt-4.1-mini", temperature=0) |
|
|
|
|
| in_memory_store = InMemoryStore() |
| |
| user_id = "1" |
| namespace_for_memory = (user_id, "memories") |
|
|
| |
| key = str(uuid.uuid4()) |
|
|
| |
| value = {"food_preference" : "I like pizza"} |
|
|
| |
| in_memory_store.put(namespace_for_memory, key, value) |
|
|
| |
| memories = in_memory_store.search(namespace_for_memory) |
| |
| print("--------------") |
| print("Memories:") |
| print(memories[0].key, memories[0].value) |
| |
| memory = in_memory_store.get(namespace_for_memory, key) |
| print("--------------") |
| print("Memory by key:") |
| print(memory.dict()) |
|
|
| |
|
|
| |
| MODEL_SYSTEM_MESSAGE = """You 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_MEMORY_INSTRUCTION = """"You 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:""" |
|
|
| def call_model(state: MessagesState, config: RunnableConfig, store: BaseStore): |
|
|
| """Load memory from the store and use it to personalize the chatbot's response.""" |
|
|
| |
| user_id = config["configurable"]["user_id"] |
|
|
| |
| namespace = ("memory", user_id) |
| key = "user_memory" |
| existing_memory = store.get(namespace, key) |
|
|
| |
| if existing_memory: |
| |
| existing_memory_content = existing_memory.value.get('memory') |
| else: |
| existing_memory_content = "No existing memory found." |
|
|
| |
| system_msg = MODEL_SYSTEM_MESSAGE.format(memory=existing_memory_content) |
|
|
| |
| response = model.invoke([SystemMessage(content=system_msg)]+state["messages"]) |
|
|
| return {"messages": response} |
|
|
| def write_memory(state: MessagesState, config: RunnableConfig, store: BaseStore): |
|
|
| """Reflect on the chat history and save a memory to the store.""" |
|
|
| |
| user_id = config["configurable"]["user_id"] |
|
|
| |
| namespace = ("memory", user_id) |
| existing_memory = store.get(namespace, "user_memory") |
|
|
| |
| if existing_memory: |
| existing_memory_content = existing_memory.value.get('memory') |
| else: |
| existing_memory_content = "No existing memory found." |
|
|
| |
| system_msg = CREATE_MEMORY_INSTRUCTION.format(memory=existing_memory_content) |
| new_memory = model.invoke([SystemMessage(content=system_msg)]+state['messages']) |
|
|
| |
| key = "user_memory" |
|
|
| |
| store.put(namespace, key, {"memory": new_memory.content}) |
|
|
| |
| builder = StateGraph(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) |
|
|
| |
| across_thread_memory = InMemoryStore() |
|
|
| |
| within_thread_memory = MemorySaver() |
|
|
| |
| graph = builder.compile(checkpointer=within_thread_memory, store=across_thread_memory) |
|
|
| |
| |
|
|
| |
| |
| config = {"configurable": {"thread_id": "1", "user_id": "1"}} |
|
|
|
|
| print("-------------------") |
| print("Mensaje 1") |
| print("-------------------") |
| |
| input_messages = [HumanMessage(content="Hi, my name is Lance")] |
|
|
| |
| for chunk in graph.stream({"messages": input_messages}, config, stream_mode="values"): |
| chunk["messages"][-1].pretty_print() |
|
|
| print("-------------------") |
| print("Mensaje 2") |
| print("-------------------") |
| |
| input_messages = [HumanMessage(content="I like to bike around San Francisco")] |
|
|
| |
| for chunk in graph.stream({"messages": input_messages}, config, stream_mode="values"): |
| chunk["messages"][-1].pretty_print() |
|
|
| print("-------------------") |
| print("Mensaje Hilo") |
| print("-------------------") |
| thread = {"configurable": {"thread_id": "1"}} |
| state = graph.get_state(thread).values |
| for m in state["messages"]: |
| m.pretty_print() |
|
|
| print("-------------------") |
| print("user memory") |
| print("-------------------") |
| |
| user_id = "1" |
| namespace = ("memory", user_id) |
| existing_memory = across_thread_memory.get(namespace, "user_memory") |
| print(existing_memory.dict()) |
|
|
| print("-------------------") |
| print("thread_id 2") |
| print("-------------------") |
| |
| config = {"configurable": {"thread_id": "2", "user_id": "1"}} |
|
|
| |
| input_messages = [HumanMessage(content="Hi! Where would you recommend that I go biking?")] |
|
|
| |
| for chunk in graph.stream({"messages": input_messages}, config, stream_mode="values"): |
| chunk["messages"][-1].pretty_print() |
|
|
| print("-------------------") |
| print("Last") |
| print("-------------------") |
| |
| input_messages = [HumanMessage(content="Great, are there any bakeries nearby that I can check out? I like a croissant after biking.")] |
|
|
| |
| for chunk in graph.stream({"messages": input_messages}, config, stream_mode="values"): |
| chunk["messages"][-1].pretty_print() |
|
|