280 lines
No EOL
12 KiB
Text
280 lines
No EOL
12 KiB
Text
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Memora-LangMem: Drop-in Semantic Memory for LangGraph\n",
|
|
"\n",
|
|
"Replace your LangGraph memory store in one line and get advanced semantic capabilities."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## What is Memora-LangMem?\n",
|
|
"\n",
|
|
"`memora-langmem` implements LangGraph's `BaseStore` interface using Memora as the backend.\n",
|
|
"\n",
|
|
"### What You Get vs Standard LangGraph Memory\n",
|
|
"\n",
|
|
"| Feature | Standard Memory | Memora-LangMem |\n",
|
|
"|---------|-----------------|----------------|\n",
|
|
"| Basic Key-Value Storage | ✅ | ✅ |\n",
|
|
"| Semantic Search | ✅ Basic | ✅ **Enhanced with spreading activation** |\n",
|
|
"| Namespace Support | ✅ | ✅ |\n",
|
|
"| **Personality-Driven Retrieval** | ❌ | ✅ |\n",
|
|
"| **Automatic Fact Extraction** | ❌ | ✅ |\n",
|
|
"| **Entity Recognition** | ❌ | ✅ |\n",
|
|
"| **Temporal Reasoning** | ❌ | ✅ |\n",
|
|
"| **Opinion Formation** | ❌ | ✅ |\n",
|
|
"| **Background Knowledge** | ❌ | ✅ |\n",
|
|
"| **Thinking/Reasoning API** | ❌ | ✅ |\n",
|
|
"\n",
|
|
"### When to Use\n",
|
|
"- Conversational agents needing long-term memory\n",
|
|
"- Personalized AI with context-aware responses \n",
|
|
"- Multi-agent systems with distinct personalities\n",
|
|
"- Knowledge management with semantic search"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": "## Installation\n\nRun this cell to install dependencies:",
|
|
"metadata": {}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"source": "!pip install langgraph langmem",
|
|
"metadata": {},
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": "Make sure Memora API is running at `http://localhost:8000`",
|
|
"metadata": {}
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": "## Setup API Keys\n\nSet up your OpenAI API key and Memora URL:",
|
|
"metadata": {}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"source": "import os\nimport getpass\n\n# Set OpenAI API key\nif \"OPENAI_API_KEY\" not in os.environ:\n os.environ[\"OPENAI_API_KEY\"] = getpass.getpass(\"Enter your OpenAI API key: \")\n\n# Set Memora API URL\nif \"MEMORA_API_URL\" not in os.environ:\n os.environ[\"MEMORA_API_URL\"] = input(\"Enter Memora API URL (default: http://localhost:8000): \") or \"http://localhost:8000\"\n\nprint(\"✅ API keys configured\")",
|
|
"metadata": {},
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## The Drop-in Replacement\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": "### Before: Standard LangGraph Memory",
|
|
"metadata": {}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"source": "from langmem import create_manage_memory_tool, create_search_memory_tool\nfrom langgraph.prebuilt import create_react_agent\nfrom langgraph.store.memory import InMemoryStore\n\n# Standard store - basic key-value with optional vector search\nstore = InMemoryStore()\n\nagent = create_react_agent(\n \"openai:gpt-4o\",\n tools=[\n create_manage_memory_tool(namespace=(\"memories\",)),\n create_search_memory_tool(namespace=(\"memories\",)),\n ],\n store=store\n)",
|
|
"metadata": {},
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": "### After: With Memora-LangMem\n\n**Just change one line!**",
|
|
"metadata": {},
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {},
|
|
"source": "import os\nfrom langmem import create_manage_memory_tool, create_search_memory_tool\nfrom langgraph.prebuilt import create_react_agent\nfrom memora_langmem import MemoraStore # ← Only import change!\n\n# Replace InMemoryStore with MemoraStore\nbase_url = os.getenv(\"MEMORA_API_URL\", \"http://localhost:8000\")\nstore = MemoraStore(base_url=base_url, default_agent_id=\"my_agent\") # ← One line change!\n\n# Everything else stays exactly the same\nagent = create_react_agent(\n \"openai:gpt-4o\", # ← Use OpenAI\n tools=[\n create_manage_memory_tool(namespace=(\"memories\",)),\n create_search_memory_tool(namespace=(\"memories\",)),\n ],\n store=store # ← Now using Memora with enhanced capabilities!\n)\n\nprint(\"✅ Agent created with Memora-powered memory\")"
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"ename": "ModuleNotFoundError",
|
|
"evalue": "No module named 'langmem'",
|
|
"output_type": "error",
|
|
"traceback": [
|
|
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
|
|
"\u001b[31mModuleNotFoundError\u001b[39m Traceback (most recent call last)",
|
|
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[1]\u001b[39m\u001b[32m, line 2\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;28;01mimport\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mos\u001b[39;00m\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mlangmem\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m create_manage_memory_tool, create_search_memory_tool\n\u001b[32m 3\u001b[39m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mlanggraph\u001b[39;00m\u001b[34;01m.\u001b[39;00m\u001b[34;01mprebuilt\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m create_react_agent\n\u001b[32m 4\u001b[39m \u001b[38;5;28;01mfrom\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[34;01mmemora_langmem\u001b[39;00m\u001b[38;5;250m \u001b[39m\u001b[38;5;28;01mimport\u001b[39;00m MemoraStore \u001b[38;5;66;03m# ← Only import change!\u001b[39;00m\n",
|
|
"\u001b[31mModuleNotFoundError\u001b[39m: No module named 'langmem'"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"import os\n",
|
|
"from langmem import create_manage_memory_tool, create_search_memory_tool\n",
|
|
"from langgraph.prebuilt import create_react_agent\n",
|
|
"from memora_langmem import MemoraStore # ← Only import change!\n",
|
|
"\n",
|
|
"# Replace InMemoryStore with MemoraStore\n",
|
|
"base_url = os.getenv(\"MEMORA_API_URL\", \"http://localhost:8080\")\n",
|
|
"store = MemoraStore(base_url=base_url, default_agent_id=\"my_agent\") # ← One line change!\n",
|
|
"\n",
|
|
"# Everything else stays exactly the same\n",
|
|
"agent = create_react_agent(\n",
|
|
" \"anthropic:claude-3-5-sonnet-latest\",\n",
|
|
" tools=[\n",
|
|
" create_manage_memory_tool(namespace=(\"memories\",)),\n",
|
|
" create_search_memory_tool(namespace=(\"memories\",)),\n",
|
|
" ],\n",
|
|
" store=store # ← Now using Memora with enhanced capabilities!\n",
|
|
")\n",
|
|
"\n",
|
|
"print(\"✅ Agent created with Memora-powered memory\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Example: Conversational Memory in Action"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import time\n",
|
|
"\n",
|
|
"# Store information\n",
|
|
"result1 = agent.invoke({\n",
|
|
" \"messages\": [{\n",
|
|
" \"role\": \"user\",\n",
|
|
" \"content\": \"\"\"Remember: I'm David, a software engineer working on AI projects. \n",
|
|
" I love Python and machine learning. Currently building a chatbot with LangGraph.\"\"\"\n",
|
|
" }]\n",
|
|
"})\n",
|
|
"print(\"Agent:\", result1[\"messages\"][-1].content)\n",
|
|
"\n",
|
|
"time.sleep(2)\n",
|
|
"\n",
|
|
"# Recall information\n",
|
|
"result2 = agent.invoke({\n",
|
|
" \"messages\": [{\"role\": \"user\", \"content\": \"What do you remember about me?\"}]\n",
|
|
"})\n",
|
|
"print(\"\\nAgent:\", result2[\"messages\"][-1].content)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## What Happens Behind the Scenes\n",
|
|
"\n",
|
|
"When your agent stores memories with Memora, automatically:\n",
|
|
"\n",
|
|
"1. **Fact Extraction**: Natural language → structured facts\n",
|
|
"2. **Entity Recognition**: Identifies people, places, concepts\n",
|
|
"3. **Semantic Indexing**: Spreading activation for better retrieval\n",
|
|
"4. **Temporal Awareness**: Event dates tracked for time queries\n",
|
|
"5. **Opinion Formation**: Agent develops perspectives over time\n",
|
|
"6. **Personality Influence**: Memory retrieval shaped by personality traits\n",
|
|
"\n",
|
|
"**You use the standard LangGraph API - Memora does the rest!**"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"metadata": {},
|
|
"source": "# Different agents with different personalities\ncreative_store = MemoraStore(base_url=base_url, default_agent_id=\"creative_writer\")\nanalyst_store = MemoraStore(base_url=base_url, default_agent_id=\"data_analyst\")\n\ncreative_agent = create_react_agent(\n \"openai:gpt-4o\",\n tools=[\n create_manage_memory_tool(namespace=(\"creative\",)),\n create_search_memory_tool(namespace=(\"creative\",))\n ],\n store=creative_store\n)\n\nanalyst_agent = create_react_agent(\n \"openai:gpt-4o\",\n tools=[\n create_manage_memory_tool(namespace=(\"analysis\",)),\n create_search_memory_tool(namespace=(\"analysis\",))\n ],\n store=analyst_store\n)\n\nprint(\"✅ Two agents with isolated memories and distinct personalities\")"
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Different agents with different personalities\n",
|
|
"creative_store = MemoraStore(base_url=base_url, default_agent_id=\"creative_writer\")\n",
|
|
"analyst_store = MemoraStore(base_url=base_url, default_agent_id=\"data_analyst\")\n",
|
|
"\n",
|
|
"creative_agent = create_react_agent(\n",
|
|
" \"anthropic:claude-3-5-sonnet-latest\",\n",
|
|
" tools=[\n",
|
|
" create_manage_memory_tool(namespace=(\"creative\",)),\n",
|
|
" create_search_memory_tool(namespace=(\"creative\",))\n",
|
|
" ],\n",
|
|
" store=creative_store\n",
|
|
")\n",
|
|
"\n",
|
|
"analyst_agent = create_react_agent(\n",
|
|
" \"anthropic:claude-3-5-sonnet-latest\",\n",
|
|
" tools=[\n",
|
|
" create_manage_memory_tool(namespace=(\"analysis\",)),\n",
|
|
" create_search_memory_tool(namespace=(\"analysis\",))\n",
|
|
" ],\n",
|
|
" store=analyst_store\n",
|
|
")\n",
|
|
"\n",
|
|
"print(\"✅ Two agents with isolated memories and distinct personalities\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Summary\n",
|
|
"\n",
|
|
"### The Change\n",
|
|
"```python\n",
|
|
"# Before\n",
|
|
"store = InMemoryStore()\n",
|
|
"\n",
|
|
"# After \n",
|
|
"store = MemoraStore(base_url=\"http://localhost:8000\", default_agent_id=\"my_agent\")\n",
|
|
"```\n",
|
|
"\n",
|
|
"### What You Get\n",
|
|
"- ✅ Semantic search with spreading activation\n",
|
|
"- ✅ Automatic fact extraction from conversations\n",
|
|
"- ✅ Entity recognition and linking\n",
|
|
"- ✅ Temporal reasoning (time-aware queries)\n",
|
|
"- ✅ Personality-driven memory retrieval\n",
|
|
"- ✅ Opinion formation over time\n",
|
|
"- ✅ Multi-agent support with isolated memories\n",
|
|
"\n",
|
|
"**Same LangGraph API. Smarter memory. Zero code changes (except the store line).**"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3 (ipykernel)",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.11.10"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
} |