From bf22f566f1abdc387af75b6264074944e4858e22 Mon Sep 17 00:00:00 2001 From: Sebastian Husch Lee Date: Fri, 22 May 2026 09:23:24 +0200 Subject: [PATCH 1/2] Update cookbook --- notebooks/memory_store_mem0.ipynb | 264 +++++++++--------------------- 1 file changed, 76 insertions(+), 188 deletions(-) diff --git a/notebooks/memory_store_mem0.ipynb b/notebooks/memory_store_mem0.ipynb index 29357fa..c7274f1 100644 --- a/notebooks/memory_store_mem0.ipynb +++ b/notebooks/memory_store_mem0.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Using Mem0 Memory Store with Haystack Agents\n", + "# Using Mem0 Memory with Haystack Agents\n", "\n", "[Mem0](https://mem0.ai/) is a managed memory layer for AI agents. Instead of passing entire conversation histories to an LLM on every turn, Mem0 intelligently extracts and compresses key facts from conversations into optimized memory representations.\n", "\n", @@ -14,15 +14,15 @@ "\n", "1. Set up a `Mem0MemoryStore` and add memories about a user\n", "2. Inspect what Mem0 actually stored\n", - "3. Create a Haystack Agent that uses the memory store\n", - "4. Ask the Agent personalized questions and see how it leverages stored memories" + "3. Create a Haystack Agent with Mem0 memory tools\n", + "4. Ask the Agent personalized questions and see how it leverages stored memories\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "> **Note:** The Mem0 integration with Haystack lives in the [`haystack-experimental`](https://github.com/deepset-ai/haystack-experimental) package and is currently **experimental**. The API may change in future releases. For the latest status, check the [haystack-experimental repository](https://github.com/deepset-ai/haystack-experimental)." + "> **Note:** The Mem0 integration now lives in the [`mem0-haystack`](https://pypi.org/project/mem0-haystack/) package in [Haystack Core Integrations](https://github.com/deepset-ai/haystack-core-integrations/tree/main/integrations/mem0). The integration provides `Mem0MemoryStore`, `Mem0MemoryRetriever`, `Mem0MemoryWriter`, and ready-made Agent tools.\n" ] }, { @@ -31,7 +31,7 @@ "source": [ "## Install the required dependencies\n", "\n", - "We need `haystack-ai` for the core framework, `haystack-experimental` for the Mem0 memory store integration and the experimental Agent, and `mem0ai` as the underlying Mem0 client library." + "We need `haystack-ai` for the core framework and `mem0-haystack` for the Mem0 memory store, pipeline components, and Agent tools.\n" ] }, { @@ -40,7 +40,7 @@ "metadata": {}, "outputs": [], "source": [ - "!pip install haystack-ai haystack-experimental mem0ai" + "!pip install haystack-ai mem0-haystack\n" ] }, { @@ -56,7 +56,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -78,35 +78,19 @@ "\n", "The `Mem0MemoryStore` connects to the [Mem0 Platform](https://app.mem0.ai/) using the `MEM0_API_KEY` environment variable. Each memory is associated with a `user_id`, which allows Mem0 to maintain separate memory spaces for different users.\n", "\n", - "We will add several facts about a user - their preferences, background, and work context. Mem0 will extract the key facts from these messages and store them as structured memories. When the Agent later queries the memory store, only the most relevant memories will be retrieved rather than replaying the full conversation history." + "We will add several facts about a user - their preferences, background, and work context. Mem0 will extract the key facts from these messages and store them as structured memories. When the Agent later queries the memory store, only the most relevant memories will be retrieved rather than replaying the full conversation history.\n" ] }, { "cell_type": "code", - "execution_count": 31, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[{'memory_id': '31eb96d0-c679-4a2c-8b65-ec617c3d7e17',\n", - " 'memory': 'User likes listening to Russian pop music.'},\n", - " {'memory_id': '503f44b3-45ed-4a7d-bb0b-d5cfaf536e32',\n", - " 'memory': 'User enjoyed a cold Spanish latte with oat milk.'},\n", - " {'memory_id': '7f757c93-c00e-4972-a9b5-ce20a8f47efd',\n", - " 'memory': 'User lives in Florence, Italy, and loves mountains.'},\n", - " {'memory_id': 'f68058f0-93ef-471d-9092-f78c155c0f07',\n", - " 'memory': 'User is a software engineer and CEO of a startup with 10 people, building a platform for small businesses to manage customers and sales, and prefers Python and the Haystack framework for NLP and LLM agent projects.'}]" - ] - }, - "execution_count": 31, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "from haystack.dataclasses import ChatMessage\n", - "from haystack_experimental.memory_stores.mem0 import Mem0MemoryStore\n", + "from haystack_integrations.memory_stores.mem0 import Mem0MemoryStore\n", + "\n", + "USER_ID = \"agent_example\"\n", "\n", "memory_store = Mem0MemoryStore()\n", "\n", @@ -126,7 +110,7 @@ " ),\n", "]\n", "\n", - "memory_store.add_memories(user_id=\"agent_example\", messages=messages)" + "memory_store.add_memories(user_id=USER_ID, messages=messages)\n" ] }, { @@ -140,28 +124,18 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User is a software engineer and CEO of a startup with 10 people, building a platform for small businesses to manage customers and sales, and prefers Python and the Haystack framework for NLP and LLM agent projects.\n", - "User likes listening to Russian pop music.\n", - "User enjoyed a cold Spanish latte with oat milk.\n" - ] - } - ], + "outputs": [], "source": [ "results = memory_store.search_memories(\n", " query=\"What programming tools does this person use?\",\n", - " user_id=\"agent_example\",\n", + " user_id=USER_ID,\n", " top_k=3,\n", ")\n", "\n", "for message in results:\n", - " print(message.text)" + " print(message.text)\n" ] }, { @@ -175,40 +149,45 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Create the Agent with Memory\n", + "## Create the Agent with Memory Tools\n", "\n", - "Now we create a Haystack Agent that uses an `OpenAIChatGenerator` as its LLM and the `Mem0MemoryStore` as its memory.\n", + "Now we create a Haystack Agent that uses an `OpenAIChatGenerator` as its LLM and two Mem0 tools:\n", "\n", - "When the Agent runs, it will:\n", - "1. Search the memory store using the user's message as a query\n", - "2. Inject relevant memories into the conversation as context\n", - "3. Generate a response that takes those memories into account\n", - "4. Save new messages back to the memory store automatically" + "1. `retrieve_memories` searches for relevant memories, or retrieves all memories when no query is provided.\n", + "2. `store_memory` writes durable user facts, preferences, and context back to Mem0.\n", + "\n", + "The `user_id` is passed through Agent State. This lets a single Agent instance serve multiple users while keeping each user's memories scoped correctly.\n" ] }, { "cell_type": "code", - "execution_count": 33, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "No tools provided to the Agent. The Agent will behave like a ChatGenerator and only return text responses. To enable tool usage, pass tools directly to the Agent, not to the chat_generator.\n" - ] - } - ], + "outputs": [], "source": [ + "from haystack.components.agents import Agent\n", "from haystack.components.generators.chat.openai import OpenAIChatGenerator\n", - "from haystack_experimental.components.agents.agent import Agent\n", + "from haystack.components.generators.utils import print_streaming_chunk\n", + "from haystack_integrations.tools.mem0 import Mem0MemoryRetrieverTool, Mem0MemoryWriterTool\n", "\n", - "chat_generator = OpenAIChatGenerator(model=\"gpt-5-mini\")\n", + "retriever_tool = Mem0MemoryRetrieverTool(memory_store=memory_store, top_k=10)\n", + "writer_tool = Mem0MemoryWriterTool(memory_store=memory_store)\n", "\n", "agent = Agent(\n", - " chat_generator=chat_generator,\n", - " memory_store=memory_store,\n", - ")" + " chat_generator=OpenAIChatGenerator(model=\"gpt-5.4\"),\n", + " tools=[retriever_tool, writer_tool],\n", + " system_prompt=\"\"\"You are a helpful assistant with long-term memory.\n", + "\n", + "Use the memory tools deliberately:\n", + "- At the beginning of every turn, first call retrieve_memories without a query to inspect all scoped memories.\n", + "- Use the retrieved memories to answer, decide whether a focused memory search is still needed, and decide whether anything new should be stored.\n", + "- When the user shares durable, user-specific facts or preferences, call store_memory before your final answer.\n", + "- Before storing, compare the proposed memory with the memories you just retrieved. Do not store duplicate facts.\n", + "- Do not store transient requests or facts that are only useful inside the current conversation.\n", + "\"\"\",\n", + " streaming_callback=print_streaming_chunk,\n", + " state_schema={\"user_id\": {\"type\": str}},\n", + ")\n" ] }, { @@ -219,81 +198,23 @@ "\n", "Let's ask the Agent a question that it can only answer well if it remembers the user's preferences. Based on the stored memories, the Agent knows the user is a Python developer who uses Haystack and works on NLP/LLM projects - so it should tailor its recommendation accordingly.\n", "\n", - "Note the `memory_store_kwargs` parameter: this is where we pass the `user_id` so the Agent knows which user's memories to search. Behind the scenes, the Agent will query Mem0 with the user's message, retrieve relevant memories, inject them into the prompt as additional context, and then generate a response." + "Note the `user_id` runtime parameter: this is how the Agent State passes the user scope into the Mem0 tools. Behind the scenes, the Agent can call `retrieve_memories`, inject the retrieved memories into the conversation as context, and then generate a response.\n" ] }, { "cell_type": "code", - "execution_count": 34, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Short answer: given that you're a Python-preferring engineer who already likes Haystack, use Haystack as the primary framework — and complement it with a vector DB (managed if you want to move fast), an LLM provider (OpenAI or a local LLM), and small orchestration pieces (FastAPI, background workers, connectors to booking APIs). Haystack maps directly to the retrieval + generation + multi‑turn needs of a travel agent and lets you build production pipelines in Python.\n", - "\n", - "Why Haystack fits you (based on what I know about you)\n", - "- You prefer Python and already like Haystack for NLP/LLM projects — so lower ramp-up time and predictable productivity.\n", - "- Haystack is built around retriever/reader/generation pipelines and conversational state, which matches travel agent needs (knowledge retrieval, multi‑turn booking dialogs, guided form filling).\n", - "- It’s modular, so you can replace components (vector DB, LLM) as you scale.\n", - "\n", - "Recommended architecture and components\n", - "- Frontend: React / mobile UI talking to a FastAPI backend.\n", - "- API & orchestration (Python): FastAPI + Celery/RQ for long-running tasks (ticket search, booking).\n", - "- Retrieval layer: Haystack DocumentStore + EmbeddingRetriever. DocumentStore options:\n", - " - Elasticsearch / OpenSearch (good for hybrid search + scale)\n", - " - Milvus / Pinecone / Weaviate (managed vector DB for fast iteration)\n", - " - FAISS (local, good for prototyping)\n", - "- Embeddings/LLM:\n", - " - Managed (OpenAI, Anthropic) for fastest reliable quality.\n", - " - Or self‑hosted LLMs (Llama 2 / Mistral via Hugging Face or TGI) if you want cost/control.\n", - "- Conversational pipeline: Haystack ConversationalPipeline / GenerativeQAPipeline for multi‑turn QA and context-aware responses.\n", - "- Tooling & action execution:\n", - " - Implement booking/payment connectors as custom Haystack nodes or as separate microservices called by the orchestration layer.\n", - " - For tool-like behavior (calling flight/hotel APIs, calendar, payments), either use LLM function-calling (OpenAI) or orchestrate actions server-side based on parsed intents/entities.\n", - "- NLU extras: use NER and slot-filling to extract traveler info (dates, origins, passport info), or integrate a light Rasa-style dialogue policy if you want explicit state machines.\n", - "- Monitoring & safety: logging, prompt/response auditing, input validation, rate limiting, and consent/privacy handling for PII.\n", - "\n", - "How to prototype quickly (MVP path)\n", - "1. Ingest relevant documents: FAQs, travel policies, vendor docs, sample itineraries into Haystack DocumentStore.\n", - "2. Plug an EmbeddingRetriever and a generative LLM (OpenAI/gpt-4o or local model) via Haystack.\n", - "3. Build a simple ConversationalPipeline that keeps context and can answer queries and ask clarifying questions.\n", - "4. Add an action node or endpoint that converts validated slots into an API call to a test booking API (or a mocked service).\n", - "5. Iterate on prompts, retrieval settings (top_k), and add a vector DB if you need scale.\n", - "\n", - "When to consider alternatives or complements\n", - "- If you want heavy agentic tool chaining out of the box, LangChain has a more mature “agent” ecosystem — but you can integrate LangChain agents with your Python/Harstack stack or implement minimal agent behavior via Haystack nodes.\n", - "- If you need rich dialogue policies across many flows, consider combining Haystack for knowledge/RAG with Rasa for fine-grained dialog management.\n", - "- If document ingestion/metadata indexing is your main focus, LlamaIndex can simplify some ingestion tasks; you can still use Haystack for runtime pipelines.\n", - "\n", - "Scaling and production tips\n", - "- Start with managed vector DB (Pinecone, Weaviate Cloud, Milvus Cloud) to avoid ops overhead.\n", - "- Cache common queries/itineraries and batch embedding calls.\n", - "- Use a hybrid retriever (sparse + dense) for precision and recall.\n", - "- Separate “tell me” flows (informational) from “do” flows (bookings) and require stronger validation/consent for the latter.\n", - "- Instrument for user feedback and fine-tune prompts/response reranking based on logs.\n", - "\n", - "If you want, I can:\n", - "- Sketch a minimal Haystack-based project structure and sample pipeline code.\n", - "- Recommend specific vector DB + LLM combos based on budget and latency requirements.\n", - "- Provide a checklist for PII/booking compliance and testing.\n", - "\n", - "Which of those follow-ups would you like next?\n" - ] - } - ], + "outputs": [], "source": [ - "result = agent.run(\n", + "agent.run(\n", " messages=[\n", " ChatMessage.from_user(\n", " \"Based on what you know about me, which framework should I use to design an AI travel agent?\"\n", " )\n", " ],\n", - " memory_store_kwargs={\"user_id\": \"agent_example\"},\n", - ")\n", - "\n", - "print(result[\"last_message\"].text)" + " user_id=USER_ID,\n", + ")\n" ] }, { @@ -302,53 +223,24 @@ "source": [ "## Ask a Follow-Up Question\n", "\n", - "Let's try a different kind of question. This time about personal preferences rather than technical skills." + "Let's try a different kind of question. This time, the user shares a new durable fact about vacation timing and asks for a recommendation based on personal preferences.\n" ] }, { "cell_type": "code", - "execution_count": 37, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Sure — I can help. A few quick questions so I can make better suggestions:\n", - "- How long is your trip (long weekend, 1 week, 2+ weeks)?\n", - "- Where will you be traveling from / how far do you want to fly?\n", - "- What's your budget range (economy, mid, luxury)?\n", - "- What kind of trip do you prefer: beach, city & culture, nature/hiking, food/wine, relaxation, active/adventure, family-friendly?\n", - "- Who are you traveling with (solo, couple, friends, kids)?\n", - "- Any health/visa/other constraints I should know about?\n", - "\n", - "If you want ideas now, here are several good June options across tastes and budgets, with why June is a good time to go:\n", - "\n", - "- Santorini or Crete, Greece — warm weather, sunny beaches, great food and island vibes. Early–mid June is before peak late‑July crowds and still reliably sunny.\n", - "- Dubrovnik & Hvar, Croatia — beautiful coast, historic Old Town, island hopping and clear seas. June has pleasant temperatures and long daylight.\n", - "- Iceland (Ring Road / Golden Circle) — near‑24‑hour daylight, waterfalls, glaciers and dramatic landscapes; ideal for road trips and outdoor photography.\n", - "- Norwegian fjords (Bergen, Aurland, Geiranger) — hiking and scenic drives with mild weather and the midnight sun; fewer mosquitoes than later summer.\n", - "- Canadian Rockies (Banff / Jasper) — turquoise lakes, alpine hiking, wildlife viewing with snow mostly melted at higher trails by June.\n", - "- Azores, Portugal — lush landscapes, whale/sea life watching, hiking and geothermal baths; cooler, green and less crowded than mainland Portugal.\n", - "- Hokkaido, Japan — pleasant cool weather, great seafood and outdoor activities; avoids Japan’s main rainy season which hits Honshu in June.\n", - "- Algarve (Portugal) or Amalfi Coast (Italy) — classic June sun/beach + coastal villages; book lodging early as tourism ramps up.\n", - "\n", - "If you tell me your answers to the questions above, I’ll recommend 2–3 tailored destinations and can suggest a sample itinerary, best neighborhoods, and packing tips. Which direction do you want to go?\n" - ] - } - ], + "outputs": [], "source": [ - "result = agent.run(\n", + "agent.run(\n", " messages=[\n", " ChatMessage.from_user(\n", - " \"Can you suggest a vacation destination for me? \"\n", - " \"I plan to have some time off in June this year.\"\n", + " \"Please remember that I plan to have some time off in June this year. \"\n", + " \"Can you suggest a vacation destination for me?\"\n", " )\n", " ],\n", - " memory_store_kwargs={\"user_id\": \"agent_example\"},\n", - ")\n", - "\n", - "print(result[\"last_message\"].text)" + " user_id=USER_ID,\n", + ")\n" ] }, { @@ -357,33 +249,28 @@ "source": [ "The Agent should reference the user's love of mountains and their location in Florence, Italy, demonstrating that Mem0 retrieves different memories depending on the query context. A question about frameworks surfaces technical memories, while a question about vacations surfaces lifestyle memories.\n", "\n", - "Moreover, new messages are automatically passed to the memory store, so now it should also remember when the user plans their vacation." + "Because the Agent has access to `store_memory`, it can also store new durable user facts. Mem0 may need a few seconds to make newly written memories searchable, so we wait briefly before inspecting the vacation-related memories.\n" ] }, { "cell_type": "code", - "execution_count": 38, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "User plans to have time off in June 2026\n", - "User is a software engineer and CEO of a startup with 10 people, building a platform for small businesses to manage customers and sales, and prefers Python and the Haystack framework for NLP and LLM agent projects.\n", - "User lives in Florence, Italy, and loves mountains.\n" - ] - } - ], + "outputs": [], "source": [ + "import time\n", + "\n", + "print(\"Waiting for Mem0 to make new memories searchable...\")\n", + "time.sleep(10)\n", + "\n", "results = memory_store.search_memories(\n", " query=\"What are the vacation plans?\",\n", - " user_id=\"agent_example\",\n", + " user_id=USER_ID,\n", " top_k=3,\n", ")\n", "\n", "for message in results:\n", - " print(message.text)" + " print(message.text)\n" ] }, { @@ -394,11 +281,11 @@ "\n", "If you have used Haystack for RAG, you might wonder how a memory store differs from a document retriever. While both supply additional context to the LLM, they serve different purposes:\n", "\n", - "- **What is stored** - A retriever pulls chunks from a knowledge base built on top of your documents. A memory store holds distilled facts learned from conversations, like user preferences, past decisions, stated goals, but not raw documents.\n", - "- **Who it belongs to** - Retrieved documents are typically shared across all users. Memories are scoped to a specific user, agent, or session, enabling personalization.\n", - "- **How it evolves** - A document store changes only when you explicitly index new content. A memory store evolves automatically as the agent converses: new facts are extracted, conflicting ones are updated, and low-relevance memories decay over time.\n", + "- **What is stored** - A retriever pulls chunks from a knowledge base built on top of your documents. A memory store holds distilled facts learned from conversations, like user preferences, past decisions, and stated goals, but not raw documents.\n", + "- **Who it belongs to** - Retrieved documents are typically shared across all users. Memories are scoped to a specific user, agent, app, or run, enabling personalization.\n", + "- **How it evolves** - A document store changes only when you explicitly index new content. A memory store evolves as the agent converses: new facts can be extracted, conflicting ones can be updated, and low-relevance memories can decay over time.\n", "\n", - "In practice, the two are complementary. A Haystack Agent can use a retriever to answer factual questions from your knowledge base while using a memory store to remember who it is talking to and what they care about." + "In practice, the two are complementary. A Haystack Agent can use a retriever to answer factual questions from your knowledge base while using Mem0 to remember who it is talking to and what they care about.\n" ] }, { @@ -407,7 +294,7 @@ "source": [ "## Clean Up\n", "\n", - "Since memories are stored in your Mem0 account, let's clean up the memories we created in this notebook to avoid leaving orphaned data." + "Since memories are stored in your Mem0 account, let's clean up the memories we created in this notebook to avoid leaving orphaned data. The Haystack memory store exposes the underlying Mem0 client, which supports scoped deletion by `user_id`.\n" ] }, { @@ -416,7 +303,8 @@ "metadata": {}, "outputs": [], "source": [ - "memory_store.delete_all_memories(user_id=\"agent_example\")" + "memory_store.client.delete_all(user_id=USER_ID)\n", + "print(f\"Deleted memories for {USER_ID}.\")\n" ] } ], From 37f1a4aea1e4358eb7ecbc6788921eb0296350e4 Mon Sep 17 00:00:00 2001 From: Sebastian Husch Lee Date: Tue, 26 May 2026 11:32:10 +0200 Subject: [PATCH 2/2] Update mem0 cookbook --- notebooks/memory_store_mem0.ipynb | 216 +++++++++++++++++++++++++----- 1 file changed, 183 insertions(+), 33 deletions(-) diff --git a/notebooks/memory_store_mem0.ipynb b/notebooks/memory_store_mem0.ipynb index c7274f1..9ac8b96 100644 --- a/notebooks/memory_store_mem0.ipynb +++ b/notebooks/memory_store_mem0.ipynb @@ -40,7 +40,7 @@ "metadata": {}, "outputs": [], "source": [ - "!pip install haystack-ai mem0-haystack\n" + "!pip install haystack-ai mem0-haystack" ] }, { @@ -56,9 +56,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdin", + "output_type": "stream", + "text": [ + "Enter your OpenAI API key: ········\n", + "Enter your Mem0 API key: ········\n" + ] + } + ], "source": [ "import os\n", "from getpass import getpass\n", @@ -83,9 +92,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "from haystack.dataclasses import ChatMessage\n", "from haystack_integrations.memory_stores.mem0 import Mem0MemoryStore\n", @@ -110,7 +130,7 @@ " ),\n", "]\n", "\n", - "memory_store.add_memories(user_id=USER_ID, messages=messages)\n" + "memory_store.add_memories(user_id=USER_ID, messages=messages, infer=True)" ] }, { @@ -119,14 +139,29 @@ "source": [ "## Inspect Stored Memories\n", "\n", - "Before connecting the memory store to an Agent, let's see what Mem0 actually stored. The `search_memories` method lets us query the memory store and see which memories are retrieved for a given query. This is useful for understanding how Mem0 extracts and condenses information from raw messages." + "Before connecting the memory store to an Agent, let's see what Mem0 actually stored. The `search_memories` method lets us query the memory store and see which memories are retrieved for a given query. This is useful for understanding how Mem0 extracts and condenses information from raw messages.\n", + "\n", + "**NOTE**: We may need to wait some time for the inferred memories to become available (usually no longer than 1 minute)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "- User works as a software engineer specializing in Python, focusing on natural language processing and large language model agents, and prefers using the Haystack framework to develop these projects.\n", + "\n", + "- User is the CEO of a startup, leading a team of ten people to build a platform that helps small businesses manage their customers and sales.\n", + "\n", + "- User enjoys listening to Russian pop music, often seeking upbeat tracks that reflect contemporary Russian pop culture.\n", + "\n" + ] + } + ], "source": [ "results = memory_store.search_memories(\n", " query=\"What programming tools does this person use?\",\n", @@ -135,7 +170,7 @@ ")\n", "\n", "for message in results:\n", - " print(message.text)\n" + " print(f\"- {message.text}\\n\")" ] }, { @@ -161,7 +196,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -187,7 +222,7 @@ "\"\"\",\n", " streaming_callback=print_streaming_chunk,\n", " state_schema={\"user_id\": {\"type\": str}},\n", - ")\n" + ")" ] }, { @@ -203,9 +238,64 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[TOOL CALL]\n", + "Tool: retrieve_memories \n", + "Arguments: {\"top_k\":50}\n", + "\n", + "[TOOL RESULT]\n", + "- User resides in Florence, Italy, and has a strong affection for mountains, often expressing a desire to explore alpine landscapes nearby.\n", + "- User enjoys listening to Russian pop music, often seeking upbeat tracks that reflect contemporary Russian pop culture.\n", + "- User works as a software engineer specializing in Python, focusing on natural language processing and large language model agents, and prefers using the Haystack framework to develop these projects.\n", + "- User is the CEO of a startup, leading a team of ten people to build a platform that helps small businesses manage their customers and sales.\n", + "- User liked a cold Spanish latte made with oat milk, appreciating its refreshing flavor and dairy‑free profile.\n", + "\n", + "[ASSISTANT]\n", + "Given what I know about you, I’d recommend **Haystack** first.\n", + "\n", + "Why:\n", + "- You’re a **Python engineer** working on **NLP and LLM agents**.\n", + "- You already **prefer Haystack** for this kind of work.\n", + "- An AI travel agent is a strong fit for **retrieval + tools + orchestration**, which Haystack handles well.\n", + "\n", + "Why Haystack fits a travel agent:\n", + "- **RAG pipelines** for destination info, policies, guides, reviews, and internal travel data\n", + "- **Agent/tool calling** for search, itinerary building, booking APIs, maps, weather, and pricing\n", + "- **Good Python ecosystem fit**, which matches your background\n", + "- Easier to move from prototype to a structured production pipeline\n", + "\n", + "A practical stack for you:\n", + "- **Haystack** as the core orchestration framework\n", + "- **FastAPI** for the backend/API\n", + "- **Postgres + pgvector** or another vector store for travel knowledge\n", + "- External tools/APIs for:\n", + " - flights/hotels\n", + " - maps/geocoding\n", + " - weather\n", + " - calendars\n", + " - payments/booking if needed\n", + "\n", + "When I would *not* choose Haystack:\n", + "- If you want a very lightweight, code-first agent loop with minimal framework abstractions, you might prefer **LangGraph**.\n", + "- If your main need is multi-step deterministic workflow control with complex state machines, **LangGraph** can be stronger.\n", + "\n", + "My bottom line:\n", + "- **Use Haystack** if you want the framework most aligned with your existing skills and preferences.\n", + "- **Use LangGraph** only if the travel agent is going to be highly workflow-heavy, with lots of branching, approvals, and long-running stateful sessions.\n", + "\n", + "If you want, I can also give you:\n", + "1. a **Haystack-based architecture** for an AI travel agent, or \n", + "2. a **Haystack vs LangGraph comparison** specifically for your startup context.\n", + "\n" + ] + } + ], "source": [ "agent.run(\n", " messages=[\n", @@ -214,7 +304,7 @@ " )\n", " ],\n", " user_id=USER_ID,\n", - ")\n" + ");" ] }, { @@ -228,9 +318,58 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[TOOL CALL]\n", + "Tool: retrieve_memories \n", + "Arguments: {\"query\":null}\n", + "\n", + "[TOOL RESULT]\n", + "- User resides in Florence, Italy, and has a strong affection for mountains, often expressing a desire to explore alpine landscapes nearby.\n", + "- User enjoys listening to Russian pop music, often seeking upbeat tracks that reflect contemporary Russian pop culture.\n", + "- User works as a software engineer specializing in Python, focusing on natural language processing and large language model agents, and prefers using the Haystack framework to develop these projects.\n", + "- User is the CEO of a startup, leading a team of ten people to build a platform that helps small businesses manage their customers and sales.\n", + "- User liked a cold Spanish latte made with oat milk, appreciating its refreshing flavor and dairy‑free profile.\n", + "\n", + "[TOOL CALL]\n", + "Tool: store_memory \n", + "Arguments: {\"text\":\"The user plans to have some time off in June this year.\",\"infer\":false}\n", + "\n", + "[TOOL RESULT]\n", + "Stored 1 memory item(s).\n", + "\n", + "[ASSISTANT]\n", + "Since you’re in Florence and love the mountains, I’d suggest the **Dolomites** for a June vacation.\n", + "\n", + "Why it fits:\n", + "- **Easy enough from Florence** compared with more faraway trips\n", + "- **Great in June**: pleasant weather, green valleys, wildflowers, and usually fewer crowds than peak summer\n", + "- **Perfect for mountain lovers**: dramatic alpine scenery, hiking, cable cars, mountain huts, and beautiful villages\n", + "\n", + "A few especially nice areas:\n", + "- **Val Gardena** – great base, scenic, lots of hikes\n", + "- **Alta Badia** – beautiful and slightly more relaxed feel\n", + "- **Cortina d’Ampezzo** – iconic views and a bit more upscale\n", + "- **Alpe di Siusi** – amazing meadows and gentler walking routes\n", + "\n", + "If you want something more relaxing than hiking-heavy, you could also consider:\n", + "- **Lake Bled + Julian Alps, Slovenia**\n", + "- **South Tyrol**\n", + "- **Aosta Valley**\n", + "\n", + "If you want, I can give you:\n", + "1. a **mountain-focused recommendation**, \n", + "2. a **relaxing nature getaway**, or \n", + "3. a **3–5 day June itinerary** from Florence.\n", + "\n" + ] + } + ], "source": [ "agent.run(\n", " messages=[\n", @@ -240,7 +379,7 @@ " )\n", " ],\n", " user_id=USER_ID,\n", - ")\n" + ");" ] }, { @@ -254,23 +393,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "- The user plans to have some time off in June this year.\n" + ] + } + ], "source": [ - "import time\n", - "\n", - "print(\"Waiting for Mem0 to make new memories searchable...\")\n", - "time.sleep(10)\n", - "\n", "results = memory_store.search_memories(\n", - " query=\"What are the vacation plans?\",\n", + " query=\"When do I have planned vacation?\",\n", " user_id=USER_ID,\n", - " top_k=3,\n", + " top_k=1,\n", ")\n", "\n", "for message in results:\n", - " print(message.text)\n" + " print(f\"- {message.text}\")" ] }, { @@ -299,18 +441,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Deleted memories for agent_example.\n" + ] + } + ], "source": [ "memory_store.client.delete_all(user_id=USER_ID)\n", - "print(f\"Deleted memories for {USER_ID}.\")\n" + "print(f\"Deleted memories for {USER_ID}.\")" ] } ], "metadata": { "kernelspec": { - "display_name": "3.12.12", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -324,7 +474,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.12" + "version": "3.12.11" } }, "nbformat": 4,