From 2beb767ae588fac1ab020fe348c8dba4583704e0 Mon Sep 17 00:00:00 2001 From: Daniel Chalef <131175+danielchalef@users.noreply.github.com> Date: Tue, 17 Oct 2023 16:35:11 -0700 Subject: [PATCH] zep: Memory Retriever MMR Support & Docs Updates (#11954) - Update Zep Memory and Retriever docstrings - Zep Memory Retriever: Add support for native MMR - Add MMR example to existing ZepRetriever Notebook @baskaryan --- .../retrievers/zep_memorystore.ipynb | 170 +++++++++++++++--- libs/langchain/langchain/memory/zep_memory.py | 10 +- libs/langchain/langchain/retrievers/zep.py | 65 +++++-- 3 files changed, 203 insertions(+), 42 deletions(-) diff --git a/docs/docs/integrations/retrievers/zep_memorystore.ipynb b/docs/docs/integrations/retrievers/zep_memorystore.ipynb index 85b753709c..2f91fd2b0f 100644 --- a/docs/docs/integrations/retrievers/zep_memorystore.ipynb +++ b/docs/docs/integrations/retrievers/zep_memorystore.ipynb @@ -1,15 +1,18 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Zep\n", - "## Retriever Example for [Zep](https://docs.getzep.com/) - A long-term memory store for LLM applications.\n", + "## Retriever Example for [Zep](https://docs.getzep.com/) - Fast, scalable building blocks for LLM Apps\n", "\n", "### More on Zep:\n", "\n", - "Zep stores, summarizes, embeds, indexes, and enriches conversational AI chat histories, and exposes them via simple, low-latency APIs.\n", + "Zep is an open source platform for productionizing LLM apps. Go from a prototype\n", + "built in LangChain or LlamaIndex, or a custom app, to production in minutes without\n", + "rewriting code.\n", "\n", "Key Features:\n", "\n", @@ -26,6 +29,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -44,11 +48,11 @@ "cell_type": "code", "execution_count": 1, "metadata": { - "collapsed": false, "ExecuteTime": { "end_time": "2023-08-11T20:31:12.231459Z", "start_time": "2023-08-11T20:31:11.211176Z" - } + }, + "collapsed": false }, "outputs": [], "source": [ @@ -56,7 +60,7 @@ "import time\n", "from uuid import uuid4\n", "\n", - "from langchain.memory import ZepMemory, CombinedMemory, VectorStoreRetrieverMemory\n", + "from langchain.memory import ZepMemory\n", "from langchain.schema import HumanMessage, AIMessage\n", "\n", "# Set this to your Zep server URL\n", @@ -64,6 +68,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -95,31 +100,38 @@ "cell_type": "code", "execution_count": 3, "metadata": { - "collapsed": false, "ExecuteTime": { "end_time": "2023-08-11T20:31:12.342790Z", "start_time": "2023-08-11T20:31:12.235291Z" - } + }, + "collapsed": false }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/danielchalef/dev/langchain/.venv/lib/python3.11/site-packages/zep_python/zep_client.py:86: Warning: You are using an incompatible Zep server version. Please upgrade to {MINIMUM_SERVER_VERSION} or later.\n", + " self._healthcheck(base_url)\n" + ] + } + ], "source": [ "session_id = str(uuid4()) # This is a unique identifier for the user/session\n", "\n", "# Initialize the Zep Memory Class\n", - "zep_memory = ZepMemory(\n", - " session_id=session_id, url=ZEP_API_URL, api_key=zep_api_key\n", - ")" + "zep_memory = ZepMemory(session_id=session_id, url=ZEP_API_URL, api_key=zep_api_key)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { - "collapsed": false, "ExecuteTime": { "end_time": "2023-08-11T20:31:14.455269Z", "start_time": "2023-08-11T20:31:12.345635Z" - } + }, + "collapsed": false }, "outputs": [], "source": [ @@ -189,11 +201,12 @@ " if msg[\"role\"] == \"human\"\n", " else AIMessage(content=msg[\"content\"])\n", " )\n", - " \n", + "\n", "time.sleep(2) # Wait for the messages to be embedded" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -208,16 +221,22 @@ "cell_type": "code", "execution_count": 5, "metadata": { - "collapsed": false, "ExecuteTime": { "end_time": "2023-08-11T20:31:14.758738Z", "start_time": "2023-08-11T20:31:14.458850Z" - } + }, + "collapsed": false }, "outputs": [ { "data": { - "text/plain": "[Document(page_content='Who was Octavia Butler?', metadata={'score': 0.7758688965570713, 'uuid': 'b3322d28-f589-48c7-9daf-5eb092d65976', 'created_at': '2023-08-11T20:31:12.3856Z', 'role': 'human', 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 22, 'Start': 8, 'Text': 'Octavia Butler'}], 'Name': 'Octavia Butler'}]}}, 'token_count': 8}),\n Document(page_content=\"Octavia Butler's contemporaries included Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ.\", metadata={'score': 0.7602672137411663, 'uuid': '756b7136-0b4c-4664-ad33-c4431670356c', 'created_at': '2023-08-11T20:31:12.420717Z', 'role': 'ai', 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 16, 'Start': 0, 'Text': \"Octavia Butler's\"}], 'Name': \"Octavia Butler's\"}, {'Label': 'ORG', 'Matches': [{'End': 58, 'Start': 41, 'Text': 'Ursula K. Le Guin'}], 'Name': 'Ursula K. Le Guin'}, {'Label': 'PERSON', 'Matches': [{'End': 76, 'Start': 60, 'Text': 'Samuel R. Delany'}], 'Name': 'Samuel R. Delany'}, {'Label': 'PERSON', 'Matches': [{'End': 93, 'Start': 82, 'Text': 'Joanna Russ'}], 'Name': 'Joanna Russ'}]}}, 'token_count': 27}),\n Document(page_content='You might want to read Ursula K. Le Guin or Joanna Russ.', metadata={'score': 0.7596040989115522, 'uuid': '166d9556-2d48-4237-8a84-5d8a1024d5f4', 'created_at': '2023-08-11T20:31:12.434522Z', 'role': 'ai', 'metadata': {'system': {'entities': [{'Label': 'ORG', 'Matches': [{'End': 40, 'Start': 23, 'Text': 'Ursula K. Le Guin'}], 'Name': 'Ursula K. Le Guin'}, {'Label': 'PERSON', 'Matches': [{'End': 55, 'Start': 44, 'Text': 'Joanna Russ'}], 'Name': 'Joanna Russ'}]}}, 'token_count': 18}),\n Document(page_content='Who were her contemporaries?', metadata={'score': 0.7575531381951208, 'uuid': 'c6a16691-4012-439f-b223-84fd4e79c4cf', 'created_at': '2023-08-11T20:31:12.410336Z', 'role': 'human', 'token_count': 8}),\n Document(page_content='Octavia Estelle Butler (June 22, 1947 – February 24, 2006) was an American science fiction author.', metadata={'score': 0.7546476914454683, 'uuid': '7c093a2a-0099-415a-95c5-615a8026a894', 'created_at': '2023-08-11T20:31:12.399979Z', 'role': 'ai', 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 22, 'Start': 0, 'Text': 'Octavia Estelle Butler'}], 'Name': 'Octavia Estelle Butler'}, {'Label': 'DATE', 'Matches': [{'End': 37, 'Start': 24, 'Text': 'June 22, 1947'}], 'Name': 'June 22, 1947'}, {'Label': 'DATE', 'Matches': [{'End': 57, 'Start': 40, 'Text': 'February 24, 2006'}], 'Name': 'February 24, 2006'}, {'Label': 'NORP', 'Matches': [{'End': 74, 'Start': 66, 'Text': 'American'}], 'Name': 'American'}]}}, 'token_count': 31})]" + "text/plain": [ + "[Document(page_content='Parable of the Sower is a science fiction novel by Octavia Butler, published in 1993. It follows the story of Lauren Olamina, a young woman living in a dystopian future where society has collapsed due to environmental disasters, poverty, and violence.', metadata={'score': 0.8897589445114136, 'uuid': 'f99ecec3-f778-4bfd-8bb7-c3c00ae919c0', 'created_at': '2023-10-17T22:53:08.664849Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'ai', 'metadata': {'system': {'entities': [{'Label': 'GPE', 'Matches': [{'End': 20, 'Start': 15, 'Text': 'Sower'}], 'Name': 'Sower'}, {'Label': 'PERSON', 'Matches': [{'End': 65, 'Start': 51, 'Text': 'Octavia Butler'}], 'Name': 'Octavia Butler'}, {'Label': 'DATE', 'Matches': [{'End': 84, 'Start': 80, 'Text': '1993'}], 'Name': '1993'}, {'Label': 'PERSON', 'Matches': [{'End': 124, 'Start': 110, 'Text': 'Lauren Olamina'}], 'Name': 'Lauren Olamina'}]}}, 'token_count': 56}),\n", + " Document(page_content=\"Write a short synopsis of Butler's book, Parable of the Sower. What is it about?\", metadata={'score': 0.8856973648071289, 'uuid': 'f6aba470-f15f-4b22-84ef-1c0d315a31de', 'created_at': '2023-10-17T22:53:08.642659Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'human', 'metadata': {'system': {'entities': [{'Label': 'ORG', 'Matches': [{'End': 32, 'Start': 26, 'Text': 'Butler'}], 'Name': 'Butler'}, {'Label': 'WORK_OF_ART', 'Matches': [{'End': 61, 'Start': 41, 'Text': 'Parable of the Sower'}], 'Name': 'Parable of the Sower'}]}}, 'token_count': 23}),\n", + " Document(page_content='Who was Octavia Butler?', metadata={'score': 0.7759557962417603, 'uuid': '26aab7b5-34b1-4aff-9be0-7834a7702be4', 'created_at': '2023-10-17T22:53:08.585297Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'human', 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 22, 'Start': 8, 'Text': 'Octavia Butler'}], 'Name': 'Octavia Butler'}], 'intent': 'The subject is asking for information about Octavia Butler, a specific person.'}}, 'token_count': 8}),\n", + " Document(page_content=\"Octavia Butler's contemporaries included Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ.\", metadata={'score': 0.760245680809021, 'uuid': 'ee4aa8e9-9913-4e69-a2a5-77a85294d24e', 'created_at': '2023-10-17T22:53:08.611466Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'ai', 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 16, 'Start': 0, 'Text': \"Octavia Butler's\"}], 'Name': \"Octavia Butler's\"}, {'Label': 'ORG', 'Matches': [{'End': 58, 'Start': 41, 'Text': 'Ursula K. Le Guin'}], 'Name': 'Ursula K. Le Guin'}, {'Label': 'PERSON', 'Matches': [{'End': 76, 'Start': 60, 'Text': 'Samuel R. Delany'}], 'Name': 'Samuel R. Delany'}, {'Label': 'PERSON', 'Matches': [{'End': 93, 'Start': 82, 'Text': 'Joanna Russ'}], 'Name': 'Joanna Russ'}]}}, 'token_count': 27}),\n", + " Document(page_content='You might want to read Ursula K. Le Guin or Joanna Russ.', metadata={'score': 0.7596070170402527, 'uuid': '9fa630e6-0b17-4d77-80b0-ba99249850c0', 'created_at': '2023-10-17T22:53:08.630731Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'ai', 'metadata': {'system': {'entities': [{'Label': 'ORG', 'Matches': [{'End': 40, 'Start': 23, 'Text': 'Ursula K. Le Guin'}], 'Name': 'Ursula K. Le Guin'}, {'Label': 'PERSON', 'Matches': [{'End': 55, 'Start': 44, 'Text': 'Joanna Russ'}], 'Name': 'Joanna Russ'}]}}, 'token_count': 18})]" + ] }, "execution_count": 5, "metadata": {}, @@ -226,6 +245,7 @@ ], "source": [ "from langchain.retrievers import ZepRetriever\n", + "from langchain.retrievers.zep import SearchType\n", "\n", "zep_retriever = ZepRetriever(\n", " session_id=session_id, # Ensure that you provide the session_id when instantiating the Retriever\n", @@ -238,6 +258,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -248,16 +269,22 @@ "cell_type": "code", "execution_count": 6, "metadata": { - "collapsed": false, "ExecuteTime": { "end_time": "2023-08-11T20:31:14.922838Z", "start_time": "2023-08-11T20:31:14.751737Z" - } + }, + "collapsed": false }, "outputs": [ { "data": { - "text/plain": "[Document(page_content=\"Write a short synopsis of Butler's book, Parable of the Sower. What is it about?\", metadata={'score': 0.8857504413268114, 'uuid': '82f07ab5-9d4b-4db6-aaae-6028e6fd836b', 'created_at': '2023-08-11T20:31:12.437365Z', 'role': 'human', 'metadata': {'system': {'entities': [{'Label': 'ORG', 'Matches': [{'End': 32, 'Start': 26, 'Text': 'Butler'}], 'Name': 'Butler'}, {'Label': 'WORK_OF_ART', 'Matches': [{'End': 61, 'Start': 41, 'Text': 'Parable of the Sower'}], 'Name': 'Parable of the Sower'}]}}, 'token_count': 23}),\n Document(page_content='Who was Octavia Butler?', metadata={'score': 0.7758688965570713, 'uuid': 'b3322d28-f589-48c7-9daf-5eb092d65976', 'created_at': '2023-08-11T20:31:12.3856Z', 'role': 'human', 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 22, 'Start': 8, 'Text': 'Octavia Butler'}], 'Name': 'Octavia Butler'}]}}, 'token_count': 8}),\n Document(page_content=\"Octavia Butler's contemporaries included Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ.\", metadata={'score': 0.7602672137411663, 'uuid': '756b7136-0b4c-4664-ad33-c4431670356c', 'created_at': '2023-08-11T20:31:12.420717Z', 'role': 'ai', 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 16, 'Start': 0, 'Text': \"Octavia Butler's\"}], 'Name': \"Octavia Butler's\"}, {'Label': 'ORG', 'Matches': [{'End': 58, 'Start': 41, 'Text': 'Ursula K. Le Guin'}], 'Name': 'Ursula K. Le Guin'}, {'Label': 'PERSON', 'Matches': [{'End': 76, 'Start': 60, 'Text': 'Samuel R. Delany'}], 'Name': 'Samuel R. Delany'}, {'Label': 'PERSON', 'Matches': [{'End': 93, 'Start': 82, 'Text': 'Joanna Russ'}], 'Name': 'Joanna Russ'}]}}, 'token_count': 27}),\n Document(page_content='You might want to read Ursula K. Le Guin or Joanna Russ.', metadata={'score': 0.7596040989115522, 'uuid': '166d9556-2d48-4237-8a84-5d8a1024d5f4', 'created_at': '2023-08-11T20:31:12.434522Z', 'role': 'ai', 'metadata': {'system': {'entities': [{'Label': 'ORG', 'Matches': [{'End': 40, 'Start': 23, 'Text': 'Ursula K. Le Guin'}], 'Name': 'Ursula K. Le Guin'}, {'Label': 'PERSON', 'Matches': [{'End': 55, 'Start': 44, 'Text': 'Joanna Russ'}], 'Name': 'Joanna Russ'}]}}, 'token_count': 18}),\n Document(page_content='Who were her contemporaries?', metadata={'score': 0.7575531381951208, 'uuid': 'c6a16691-4012-439f-b223-84fd4e79c4cf', 'created_at': '2023-08-11T20:31:12.410336Z', 'role': 'human', 'token_count': 8})]" + "text/plain": [ + "[Document(page_content='Parable of the Sower is a science fiction novel by Octavia Butler, published in 1993. It follows the story of Lauren Olamina, a young woman living in a dystopian future where society has collapsed due to environmental disasters, poverty, and violence.', metadata={'score': 0.8897120952606201, 'uuid': 'f99ecec3-f778-4bfd-8bb7-c3c00ae919c0', 'created_at': '2023-10-17T22:53:08.664849Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'ai', 'metadata': {'system': {'entities': [{'Label': 'GPE', 'Matches': [{'End': 20, 'Start': 15, 'Text': 'Sower'}], 'Name': 'Sower'}, {'Label': 'PERSON', 'Matches': [{'End': 65, 'Start': 51, 'Text': 'Octavia Butler'}], 'Name': 'Octavia Butler'}, {'Label': 'DATE', 'Matches': [{'End': 84, 'Start': 80, 'Text': '1993'}], 'Name': '1993'}, {'Label': 'PERSON', 'Matches': [{'End': 124, 'Start': 110, 'Text': 'Lauren Olamina'}], 'Name': 'Lauren Olamina'}]}}, 'token_count': 56}),\n", + " Document(page_content=\"Write a short synopsis of Butler's book, Parable of the Sower. What is it about?\", metadata={'score': 0.8857351541519165, 'uuid': 'f6aba470-f15f-4b22-84ef-1c0d315a31de', 'created_at': '2023-10-17T22:53:08.642659Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'human', 'metadata': {'system': {'entities': [{'Label': 'ORG', 'Matches': [{'End': 32, 'Start': 26, 'Text': 'Butler'}], 'Name': 'Butler'}, {'Label': 'WORK_OF_ART', 'Matches': [{'End': 61, 'Start': 41, 'Text': 'Parable of the Sower'}], 'Name': 'Parable of the Sower'}]}}, 'token_count': 23}),\n", + " Document(page_content='Who was Octavia Butler?', metadata={'score': 0.7759560942649841, 'uuid': '26aab7b5-34b1-4aff-9be0-7834a7702be4', 'created_at': '2023-10-17T22:53:08.585297Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'human', 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 22, 'Start': 8, 'Text': 'Octavia Butler'}], 'Name': 'Octavia Butler'}], 'intent': 'The subject is asking for information about Octavia Butler, a specific person.'}}, 'token_count': 8}),\n", + " Document(page_content=\"Octavia Butler's contemporaries included Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ.\", metadata={'score': 0.7602507472038269, 'uuid': 'ee4aa8e9-9913-4e69-a2a5-77a85294d24e', 'created_at': '2023-10-17T22:53:08.611466Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'ai', 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 16, 'Start': 0, 'Text': \"Octavia Butler's\"}], 'Name': \"Octavia Butler's\"}, {'Label': 'ORG', 'Matches': [{'End': 58, 'Start': 41, 'Text': 'Ursula K. Le Guin'}], 'Name': 'Ursula K. Le Guin'}, {'Label': 'PERSON', 'Matches': [{'End': 76, 'Start': 60, 'Text': 'Samuel R. Delany'}], 'Name': 'Samuel R. Delany'}, {'Label': 'PERSON', 'Matches': [{'End': 93, 'Start': 82, 'Text': 'Joanna Russ'}], 'Name': 'Joanna Russ'}], 'intent': \"The subject is stating a fact about Octavia Butler's contemporaries, including Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ.\"}}, 'token_count': 27}),\n", + " Document(page_content='You might want to read Ursula K. Le Guin or Joanna Russ.', metadata={'score': 0.7595934867858887, 'uuid': '9fa630e6-0b17-4d77-80b0-ba99249850c0', 'created_at': '2023-10-17T22:53:08.630731Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'ai', 'metadata': {'system': {'entities': [{'Label': 'ORG', 'Matches': [{'End': 40, 'Start': 23, 'Text': 'Ursula K. Le Guin'}], 'Name': 'Ursula K. Le Guin'}, {'Label': 'PERSON', 'Matches': [{'End': 55, 'Start': 44, 'Text': 'Joanna Russ'}], 'Name': 'Joanna Russ'}]}}, 'token_count': 18})]" + ] }, "execution_count": 6, "metadata": {}, @@ -268,18 +295,109 @@ "zep_retriever.get_relevant_documents(\"Who wrote Parable of the Sower?\")" ] }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Reranking using MMR (Maximal Marginal Relevance)\n", + "\n", + "Zep has native, SIMD-accelerated support for reranking results using MMR. This is useful for removing redundancy in results." + ] + }, { "cell_type": "code", - "execution_count": 6, - "outputs": [], - "source": [], + "execution_count": 7, "metadata": { - "collapsed": false, "ExecuteTime": { "end_time": "2023-08-11T20:31:14.923032Z", "start_time": "2023-08-11T20:31:14.918181Z" + }, + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/danielchalef/dev/langchain/.venv/lib/python3.11/site-packages/zep_python/zep_client.py:86: Warning: You are using an incompatible Zep server version. Please upgrade to {MINIMUM_SERVER_VERSION} or later.\n", + " self._healthcheck(base_url)\n" + ] + }, + { + "data": { + "text/plain": [ + "[Document(page_content='Parable of the Sower is a science fiction novel by Octavia Butler, published in 1993. It follows the story of Lauren Olamina, a young woman living in a dystopian future where society has collapsed due to environmental disasters, poverty, and violence.', metadata={'score': 0.8897120952606201, 'uuid': 'f99ecec3-f778-4bfd-8bb7-c3c00ae919c0', 'created_at': '2023-10-17T22:53:08.664849Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'ai', 'metadata': {'system': {'entities': [{'Label': 'GPE', 'Matches': [{'End': 20, 'Start': 15, 'Text': 'Sower'}], 'Name': 'Sower'}, {'Label': 'PERSON', 'Matches': [{'End': 65, 'Start': 51, 'Text': 'Octavia Butler'}], 'Name': 'Octavia Butler'}, {'Label': 'DATE', 'Matches': [{'End': 84, 'Start': 80, 'Text': '1993'}], 'Name': '1993'}, {'Label': 'PERSON', 'Matches': [{'End': 124, 'Start': 110, 'Text': 'Lauren Olamina'}], 'Name': 'Lauren Olamina'}]}}, 'token_count': 56}),\n", + " Document(page_content='Which books of hers were made into movies?', metadata={'score': 0.7496200799942017, 'uuid': '1047ff15-96f1-4101-bb0f-9ed073b8081d', 'created_at': '2023-10-17T22:53:08.596614Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'human', 'metadata': {'system': {'intent': 'The subject is inquiring about the books of the person referred to as \"hers\" that have been made into movies.'}}, 'token_count': 11}),\n", + " Document(page_content=\"Write a short synopsis of Butler's book, Parable of the Sower. What is it about?\", metadata={'score': 0.8857351541519165, 'uuid': 'f6aba470-f15f-4b22-84ef-1c0d315a31de', 'created_at': '2023-10-17T22:53:08.642659Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'human', 'metadata': {'system': {'entities': [{'Label': 'ORG', 'Matches': [{'End': 32, 'Start': 26, 'Text': 'Butler'}], 'Name': 'Butler'}, {'Label': 'WORK_OF_ART', 'Matches': [{'End': 61, 'Start': 41, 'Text': 'Parable of the Sower'}], 'Name': 'Parable of the Sower'}]}}, 'token_count': 23}),\n", + " Document(page_content='You might want to read Ursula K. Le Guin or Joanna Russ.', metadata={'score': 0.7595934867858887, 'uuid': '9fa630e6-0b17-4d77-80b0-ba99249850c0', 'created_at': '2023-10-17T22:53:08.630731Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'ai', 'metadata': {'system': {'entities': [{'Label': 'ORG', 'Matches': [{'End': 40, 'Start': 23, 'Text': 'Ursula K. Le Guin'}], 'Name': 'Ursula K. Le Guin'}, {'Label': 'PERSON', 'Matches': [{'End': 55, 'Start': 44, 'Text': 'Joanna Russ'}], 'Name': 'Joanna Russ'}]}}, 'token_count': 18}),\n", + " Document(page_content='Who were her contemporaries?', metadata={'score': 0.7575579881668091, 'uuid': 'b2dfd1f7-cac6-4e37-94ea-7c15b0a5af2c', 'created_at': '2023-10-17T22:53:08.606283Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'human', 'metadata': {'system': {'intent': 'The subject is asking about the people who were contemporaries of someone else.'}}, 'token_count': 8})]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" } - } + ], + "source": [ + "zep_retriever = ZepRetriever(\n", + " session_id=session_id, # Ensure that you provide the session_id when instantiating the Retriever\n", + " url=ZEP_API_URL,\n", + " top_k=5,\n", + " api_key=zep_api_key,\n", + " search_type=SearchType.mmr,\n", + " mmr_lambda=0.5,\n", + ")\n", + "\n", + "await zep_retriever.aget_relevant_documents(\"Who wrote Parable of the Sower?\")" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Using metadata filters to refine search results\n", + "\n", + "Zep supports filtering results by metadata. This is useful for filtering results by entity type, or other metadata.\n", + "\n", + "More information here: https://docs.getzep.com/sdk/search_query/" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[Document(page_content='Parable of the Sower is a science fiction novel by Octavia Butler, published in 1993. It follows the story of Lauren Olamina, a young woman living in a dystopian future where society has collapsed due to environmental disasters, poverty, and violence.', metadata={'score': 0.8897120952606201, 'uuid': 'f99ecec3-f778-4bfd-8bb7-c3c00ae919c0', 'created_at': '2023-10-17T22:53:08.664849Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'ai', 'metadata': {'system': {'entities': [{'Label': 'GPE', 'Matches': [{'End': 20, 'Start': 15, 'Text': 'Sower'}], 'Name': 'Sower'}, {'Label': 'PERSON', 'Matches': [{'End': 65, 'Start': 51, 'Text': 'Octavia Butler'}], 'Name': 'Octavia Butler'}, {'Label': 'DATE', 'Matches': [{'End': 84, 'Start': 80, 'Text': '1993'}], 'Name': '1993'}, {'Label': 'PERSON', 'Matches': [{'End': 124, 'Start': 110, 'Text': 'Lauren Olamina'}], 'Name': 'Lauren Olamina'}], 'intent': 'None'}}, 'token_count': 56}),\n", + " Document(page_content='Which books of hers were made into movies?', metadata={'score': 0.7496200799942017, 'uuid': '1047ff15-96f1-4101-bb0f-9ed073b8081d', 'created_at': '2023-10-17T22:53:08.596614Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'human', 'metadata': {'system': {'intent': 'The subject is inquiring about the books of the person referred to as \"hers\" that have been made into movies.'}}, 'token_count': 11}),\n", + " Document(page_content=\"Write a short synopsis of Butler's book, Parable of the Sower. What is it about?\", metadata={'score': 0.8857351541519165, 'uuid': 'f6aba470-f15f-4b22-84ef-1c0d315a31de', 'created_at': '2023-10-17T22:53:08.642659Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'human', 'metadata': {'system': {'entities': [{'Label': 'ORG', 'Matches': [{'End': 32, 'Start': 26, 'Text': 'Butler'}], 'Name': 'Butler'}, {'Label': 'WORK_OF_ART', 'Matches': [{'End': 61, 'Start': 41, 'Text': 'Parable of the Sower'}], 'Name': 'Parable of the Sower'}], 'intent': 'The subject is requesting a brief summary or description of Butler\\'s book, \"Parable of the Sower.\"'}}, 'token_count': 23}),\n", + " Document(page_content='You might want to read Ursula K. Le Guin or Joanna Russ.', metadata={'score': 0.7595934867858887, 'uuid': '9fa630e6-0b17-4d77-80b0-ba99249850c0', 'created_at': '2023-10-17T22:53:08.630731Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'ai', 'metadata': {'system': {'entities': [{'Label': 'ORG', 'Matches': [{'End': 40, 'Start': 23, 'Text': 'Ursula K. Le Guin'}], 'Name': 'Ursula K. Le Guin'}, {'Label': 'PERSON', 'Matches': [{'End': 55, 'Start': 44, 'Text': 'Joanna Russ'}], 'Name': 'Joanna Russ'}], 'intent': 'The subject is providing a suggestion or recommendation for the person to read Ursula K. Le Guin or Joanna Russ.'}}, 'token_count': 18}),\n", + " Document(page_content='Who were her contemporaries?', metadata={'score': 0.7575579881668091, 'uuid': 'b2dfd1f7-cac6-4e37-94ea-7c15b0a5af2c', 'created_at': '2023-10-17T22:53:08.606283Z', 'updated_at': '0001-01-01T00:00:00Z', 'role': 'human', 'metadata': {'system': {'intent': 'The subject is asking about the people who were contemporaries of someone else.'}}, 'token_count': 8})]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "filter = {\"where\": {\"jsonpath\": '$[*] ? (@.Label == \"WORK_OF_ART\")'}}\n", + "\n", + "await zep_retriever.aget_relevant_documents(\n", + " \"Who wrote Parable of the Sower?\", metadata=filter\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -298,7 +416,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.4" + "version": "3.11.5" } }, "nbformat": 4, diff --git a/libs/langchain/langchain/memory/zep_memory.py b/libs/langchain/langchain/memory/zep_memory.py index 6e2a7ec823..0c276c69bf 100644 --- a/libs/langchain/langchain/memory/zep_memory.py +++ b/libs/langchain/langchain/memory/zep_memory.py @@ -7,7 +7,7 @@ from langchain.memory.chat_message_histories import ZepChatMessageHistory class ZepMemory(ConversationBufferMemory): - """Persist your chain history to the Zep Memory Server. + """Persist your chain history to the Zep MemoryStore. The number of messages returned by Zep and when the Zep server summarizes chat histories is configurable. See the Zep documentation for more details. @@ -36,11 +36,11 @@ class ZepMemory(ConversationBufferMemory): in the call to `self.memory.save_context`. - About Zep + Zep - Fast, scalable building blocks for LLM Apps ========= - Zep provides long-term conversation storage for LLM apps. The server stores, - summarizes, embeds, indexes, and enriches conversational AI chat - histories, and exposes them via simple, low-latency APIs. + Zep is an open source platform for productionizing LLM apps. Go from a prototype + built in LangChain or LlamaIndex, or a custom app, to production in minutes without + rewriting code. For server installation instructions and more, see: https://docs.getzep.com/deployment/quickstart/ diff --git a/libs/langchain/langchain/retrievers/zep.py b/libs/langchain/langchain/retrievers/zep.py index 39dd855636..ae53aaf254 100644 --- a/libs/langchain/langchain/retrievers/zep.py +++ b/libs/langchain/langchain/retrievers/zep.py @@ -1,5 +1,6 @@ from __future__ import annotations +from enum import Enum from typing import TYPE_CHECKING, Any, Dict, List, Optional from langchain.callbacks.manager import ( @@ -13,28 +14,58 @@ if TYPE_CHECKING: from zep_python import MemorySearchResult +class SearchType(str, Enum): + """Enumerator of the types of search to perform.""" + + similarity = "similarity" + """Similarity search.""" + mmr = "mmr" + """Maximal Marginal Relevance reranking of similarity search.""" + + class ZepRetriever(BaseRetriever): - """`Zep` long-term memory store retriever. + """`Zep` MemoryStore Retriever. Search your user's long-term chat history with Zep. + Zep offers both simple semantic search and Maximal Marginal Relevance (MMR) + reranking of search results. + Note: You will need to provide the user's `session_id` to use this retriever. - More on Zep: - Zep provides long-term conversation storage for LLM apps. The server stores, - summarizes, embeds, indexes, and enriches conversational AI chat - histories, and exposes them via simple, low-latency APIs. + Args: + url: URL of your Zep server (required) + api_key: Your Zep API key (optional) + session_id: Identifies your user or a user's session (required) + top_k: Number of documents to return (default: 3, optional) + search_type: Type of search to perform (similarity / mmr) (default: similarity, + optional) + mmr_lambda: Lambda value for MMR search. Defaults to 0.5 (optional) + + Zep - Fast, scalable building blocks for LLM Apps + ========= + Zep is an open source platform for productionizing LLM apps. Go from a prototype + built in LangChain or LlamaIndex, or a custom app, to production in minutes without + rewriting code. For server installation instructions, see: https://docs.getzep.com/deployment/quickstart/ """ - zep_client: Any + zep_client: Optional[Any] = None """Zep client.""" + url: str + """URL of your Zep server.""" + api_key: Optional[str] = None + """Your Zep API key.""" session_id: str """Zep session ID.""" top_k: Optional[int] - """Number of documents to return.""" + """Number of items to return.""" + search_type: SearchType = SearchType.similarity + """Type of search to perform (similarity / mmr)""" + mmr_lambda: Optional[float] = None + """Lambda value for MMR search.""" @root_validator(pre=True) def create_client(cls, values: dict) -> dict: @@ -68,12 +99,18 @@ class ZepRetriever(BaseRetriever): query: str, *, run_manager: CallbackManagerForRetrieverRun, - metadata: Optional[Dict] = None, + metadata: Optional[Dict[str, Any]] = None, ) -> List[Document]: from zep_python import MemorySearchPayload + if not self.zep_client: + raise RuntimeError("Zep client not initialized.") + payload: MemorySearchPayload = MemorySearchPayload( - text=query, metadata=metadata + text=query, + metadata=metadata, + search_type=self.search_type, + mmr_lambda=self.mmr_lambda, ) results: List[MemorySearchResult] = self.zep_client.memory.search_memory( @@ -87,12 +124,18 @@ class ZepRetriever(BaseRetriever): query: str, *, run_manager: AsyncCallbackManagerForRetrieverRun, - metadata: Optional[Dict] = None, + metadata: Optional[Dict[str, Any]] = None, ) -> List[Document]: from zep_python import MemorySearchPayload + if not self.zep_client: + raise RuntimeError("Zep client not initialized.") + payload: MemorySearchPayload = MemorySearchPayload( - text=query, metadata=metadata + text=query, + metadata=metadata, + search_type=self.search_type, + mmr_lambda=self.mmr_lambda, ) results: List[MemorySearchResult] = await self.zep_client.memory.asearch_memory(