Spaces:
Sleeping
Sleeping
| import uuid | |
| from datetime import datetime | |
| from abc import ABC, abstractmethod | |
| from langgraph.store.base import BaseStore | |
| from langchain_core.runnables import RunnableConfig | |
| class BaseMemoryAgent(ABC): | |
| """Base class for agents with memory capabilities. | |
| Extracts shared logic from therapist_agent and logical_agent: | |
| - Memory retrieval from store | |
| - Automatic storage of all conversations (user + assistant messages) | |
| - Message construction with system prompt + memories | |
| - LLM invocation and response formatting | |
| """ | |
| def __init__(self, llm): | |
| self.llm = llm | |
| def system_prompt(self) -> str: | |
| """Each agent defines its own personality/system prompt.""" | |
| pass | |
| async def retrieve_memories(self, store: BaseStore, user_id: str, query: str) -> str: | |
| """Fetch relevant memories for this user.""" | |
| namespace = ("memories", user_id) | |
| memories = await store.asearch(namespace, query=query) | |
| return "\n".join([d.value.get("data", "") for d in memories]) | |
| async def store_message(self, store: BaseStore, user_id: str, content: str, role: str): | |
| """Store every message to Supabase automatically. | |
| Args: | |
| store: The LangGraph store instance | |
| user_id: User identifier for namespacing | |
| content: The message content | |
| role: Either 'user' or 'assistant' | |
| """ | |
| memory_id = str(uuid.uuid4()) | |
| namespace = ("memories", user_id) | |
| await store.aput(namespace, memory_id, { | |
| "data": content, | |
| "role": role, | |
| "timestamp": datetime.now().isoformat() | |
| }) | |
| async def __call__(self, state: dict, config: RunnableConfig, *, store: BaseStore) -> dict: | |
| """Make the agent callable for LangGraph node compatibility.""" | |
| last_message = state["messages"][-1] | |
| user_id = config["configurable"].get("user_id", "default_user") | |
| # Get memories | |
| memory_info = await self.retrieve_memories(store, user_id, str(last_message.content)) | |
| # Build prompt with memories injected | |
| full_prompt = f"""{self.system_prompt} | |
| User information from previous sessions: | |
| {memory_info}""" | |
| messages = [ | |
| {"role": "system", "content": full_prompt}, | |
| {"role": "user", "content": last_message.content} | |
| ] | |
| # Store user message automatically | |
| await self.store_message(store, user_id, last_message.content, "user") | |
| # Get response from LLM | |
| reply = self.llm.invoke(messages) | |
| # Store assistant response automatically | |
| await self.store_message(store, user_id, reply.content, "assistant") | |
| return {"messages": [{"role": "assistant", "content": reply.content}]} | |