|
129 | 129 | "from langchain_openai import ChatOpenAI\n", |
130 | 130 | "from langchain_openai import ChatOpenAI\n", |
131 | 131 | "from langchain_core.messages import SystemMessage, HumanMessage, AIMessage, ToolMessage\n", |
132 | | - "from langchain_core.tools import tool\n", |
133 | | - "from typing import List, Optional\n", |
134 | | - "from agent_memory_client import MemoryAPIClient as MemoryClient, MemoryClientConfig\n", |
135 | | - "import json\n", |
| 132 | + "from agent_memory_client import create_memory_client\n", |
| 133 | + "from agent_memory_client.integrations.langchain import get_memory_tools\n", |
136 | 134 | "import asyncio\n", |
| 135 | + "import os\n", |
137 | 136 | "\n", |
138 | 137 | "# Initialize\n", |
139 | 138 | "student_id = \"student_memory_tools\"\n", |
140 | 139 | "session_id = \"tool_demo\"\n", |
141 | 140 | "\n", |
142 | | - "# Initialize memory client with proper config\n", |
143 | | - "import os\n", |
144 | | - "config = MemoryClientConfig(\n", |
145 | | - " base_url=os.getenv(\"AGENT_MEMORY_URL\", \"http://localhost:8000\"),\n", |
146 | | - " default_namespace=\"redis_university\"\n", |
147 | | - ")\n", |
148 | | - "memory_client = MemoryClient(config=config)\n", |
| 141 | + "# Initialize memory client using the new async factory\n", |
| 142 | + "base_url = os.getenv(\"AGENT_MEMORY_URL\", \"http://localhost:8000\")\n", |
| 143 | + "memory_client = await create_memory_client(base_url)\n", |
149 | 144 | "\n", |
150 | 145 | "llm = ChatOpenAI(model=\"gpt-4o\", temperature=0.7)\n", |
151 | 146 | "\n", |
|
165 | 160 | "cell_type": "markdown", |
166 | 161 | "metadata": {}, |
167 | 162 | "source": [ |
168 | | - "### Getting Memory Tools from the Client\n", |
| 163 | + "### Getting Memory Tools with LangChain Integration\n", |
169 | 164 | "\n", |
170 | | - "The memory client provides built-in tool schemas that are ready to use with LLMs. You don't need to manually define tools - the client handles this for you!" |
| 165 | + "The memory client now has built-in LangChain/LangGraph integration! Just call `get_memory_tools()` and you get ready-to-use LangChain tools." |
171 | 166 | ] |
172 | 167 | }, |
173 | 168 | { |
|
176 | 171 | "metadata": {}, |
177 | 172 | "outputs": [], |
178 | 173 | "source": [ |
179 | | - "# Get all memory tool schemas from the client\n", |
180 | | - "# The memory client provides OpenAI-format tool schemas\n", |
181 | | - "memory_tool_schemas = memory_client.get_all_memory_tool_schemas()\n", |
182 | | - "\n", |
183 | | - "print(\"Available memory tools from client:\")\n", |
184 | | - "for tool_schema in memory_tool_schemas:\n", |
185 | | - " print(f\" - {tool_schema['function']['name']}: {tool_schema['function']['description'][:80]}...\")\n", |
| 174 | + "# Get LangChain-compatible memory tools from the client\n", |
| 175 | + "# This returns a list of StructuredTool objects ready to use with LangChain/LangGraph\n", |
| 176 | + "memory_tools = get_memory_tools(\n", |
| 177 | + " memory_client=memory_client,\n", |
| 178 | + " session_id=session_id,\n", |
| 179 | + " user_id=student_id\n", |
| 180 | + ")\n", |
186 | 181 | "\n", |
187 | | - "# Create LangChain tools that wrap the memory client's resolve_function_call\n", |
188 | | - "# This allows us to use LangChain's tool calling while leveraging the client's built-in tools\n", |
| 182 | + "print(\"Available memory tools:\")\n", |
| 183 | + "for tool in memory_tools:\n", |
| 184 | + " print(f\" - {tool.name}: {tool.description[:80]}...\")\n", |
189 | 185 | "\n", |
190 | | - "@tool\n", |
191 | | - "async def create_long_term_memory(memories: List[dict]) -> str:\n", |
192 | | - " \"\"\"\n", |
193 | | - " Store important information in long-term memory.\n", |
194 | | - " \n", |
195 | | - " Args:\n", |
196 | | - " memories: List of memory objects with 'text', 'memory_type', 'topics', and 'entities'\n", |
197 | | - " \n", |
198 | | - " Use this when students share preferences, goals, or important facts.\n", |
199 | | - " \"\"\"\n", |
200 | | - " result = await memory_client.resolve_function_call(\n", |
201 | | - " function_name=\"create_long_term_memory\",\n", |
202 | | - " args={\"memories\": memories},\n", |
203 | | - " session_id=session_id,\n", |
204 | | - " user_id=student_id\n", |
205 | | - " )\n", |
206 | | - " return f\"✅ Stored {len(memories)} memory(ies): {result}\"\n", |
207 | | - "\n", |
208 | | - "@tool\n", |
209 | | - "async def search_long_term_memory(text: str, limit: int = 5) -> str:\n", |
210 | | - " \"\"\"\n", |
211 | | - " Search for relevant memories using semantic search.\n", |
212 | | - " \n", |
213 | | - " Args:\n", |
214 | | - " text: What to search for in memories\n", |
215 | | - " limit: Maximum number of memories to retrieve (default: 5)\n", |
216 | | - " \n", |
217 | | - " Use this when you need to recall information about the student.\n", |
218 | | - " \"\"\"\n", |
219 | | - " result = await memory_client.resolve_function_call(\n", |
220 | | - " function_name=\"search_long_term_memory\",\n", |
221 | | - " args={\"text\": text, \"limit\": limit},\n", |
222 | | - " session_id=session_id,\n", |
223 | | - " user_id=student_id\n", |
224 | | - " )\n", |
225 | | - " return str(result)\n", |
226 | | - "\n", |
227 | | - "print(\"\\n✅ LangChain tools created that wrap memory client's built-in tools\")" |
| 186 | + "print(f\"\\n✅ Got {len(memory_tools)} LangChain tools from memory client\")" |
228 | 187 | ] |
229 | 188 | }, |
230 | 189 | { |
231 | 190 | "cell_type": "markdown", |
232 | 191 | "metadata": {}, |
233 | 192 | "source": [ |
234 | | - "### Key Insight: Wrapping the Memory Client\n", |
| 193 | + "### Key Insight: Built-in LangChain Integration\n", |
235 | 194 | "\n", |
236 | | - "Our LangChain tools are thin wrappers around `memory_client.resolve_function_call()`. This gives us:\n", |
237 | | - "- LangChain's tool calling interface (familiar to LangGraph users)\n", |
238 | | - "- Memory client's built-in tool implementations (no need to reimplement)\n", |
239 | | - "- Best of both worlds!" |
| 195 | + "The `get_memory_tools()` function returns LangChain `StructuredTool` objects that:\n", |
| 196 | + "- Work seamlessly with LangChain's `llm.bind_tools()` and LangGraph agents\n", |
| 197 | + "- Handle all the memory client API calls internally\n", |
| 198 | + "- Are pre-configured with your session_id and user_id\n", |
| 199 | + "\n", |
| 200 | + "No manual wrapping needed - just use them like any other LangChain tool!" |
240 | 201 | ] |
241 | 202 | }, |
242 | 203 | { |
|
254 | 215 | "metadata": {}, |
255 | 216 | "outputs": [], |
256 | 217 | "source": [ |
257 | | - "# Configure agent with our LangChain memory tools\n", |
258 | | - "memory_tools = [create_long_term_memory, search_long_term_memory]\n", |
| 218 | + "# Configure agent with memory tools\n", |
259 | 219 | "llm_with_tools = llm.bind_tools(memory_tools)\n", |
260 | 220 | "\n", |
261 | 221 | "system_prompt = \"\"\"You are a class scheduling agent for Redis University.\n", |
|
310 | 270 | " print(f\" Tool: {tool_call['name']}\")\n", |
311 | 271 | " print(f\" Args: {tool_call['args']}\")\n", |
312 | 272 | " \n", |
313 | | - " # Execute the tool (LangChain handles calling our wrapped function)\n", |
314 | | - " if tool_call['name'] == 'create_long_term_memory':\n", |
315 | | - " result = await create_long_term_memory.ainvoke(tool_call['args'])\n", |
| 273 | + " # Find and execute the tool\n", |
| 274 | + " tool = next((t for t in memory_tools if t.name == tool_call['name']), None)\n", |
| 275 | + " if tool:\n", |
| 276 | + " result = await tool.ainvoke(tool_call['args'])\n", |
316 | 277 | " print(f\" Result: {result}\")\n", |
317 | 278 | " \n", |
318 | 279 | " # Add tool result to messages\n", |
319 | 280 | " messages.append(response)\n", |
320 | 281 | " messages.append(ToolMessage(\n", |
321 | | - " content=result,\n", |
| 282 | + " content=str(result),\n", |
322 | 283 | " tool_call_id=tool_call['id']\n", |
323 | 284 | " ))\n", |
324 | 285 | " \n", |
|
370 | 331 | " print(f\" Tool: {tool_call['name']}\")\n", |
371 | 332 | " print(f\" Args: {tool_call['args']}\")\n", |
372 | 333 | " \n", |
373 | | - " # Execute the tool\n", |
374 | | - " if tool_call['name'] == 'search_long_term_memory':\n", |
375 | | - " result = await search_long_term_memory.ainvoke(tool_call['args'])\n", |
| 334 | + " # Find and execute the tool\n", |
| 335 | + " tool = next((t for t in memory_tools if t.name == tool_call['name']), None)\n", |
| 336 | + " if tool:\n", |
| 337 | + " result = await tool.ainvoke(tool_call['args'])\n", |
376 | 338 | " print(f\"\\n Retrieved memories:\")\n", |
377 | 339 | " print(f\" {result}\")\n", |
378 | 340 | " \n", |
379 | 341 | " # Add tool result to messages\n", |
380 | 342 | " messages.append(response)\n", |
381 | 343 | " messages.append(ToolMessage(\n", |
382 | | - " content=result,\n", |
| 344 | + " content=str(result),\n", |
383 | 345 | " tool_call_id=tool_call['id']\n", |
384 | 346 | " ))\n", |
385 | 347 | " \n", |
|
0 commit comments