diff --git a/docs/extras/modules/memory/integrations/zep_memory.ipynb b/docs/extras/modules/memory/integrations/zep_memory.ipynb index dfe5829cfb..aa4d668665 100644 --- a/docs/extras/modules/memory/integrations/zep_memory.ipynb +++ b/docs/extras/modules/memory/integrations/zep_memory.ipynb @@ -40,12 +40,15 @@ "cell_type": "code", "execution_count": 1, "metadata": { - "is_executing": true + "ExecuteTime": { + "end_time": "2023-07-09T19:20:49.003167Z", + "start_time": "2023-07-09T19:20:47.446370Z" + } }, "outputs": [], "source": [ - "from langchain.memory.chat_message_histories import ZepChatMessageHistory\n", - "from langchain.memory import ConversationBufferMemory\n", + "from langchain.memory import ZepMemory\n", + "from langchain.retrievers import ZepRetriever\n", "from langchain import OpenAI\n", "from langchain.schema import HumanMessage, AIMessage\n", "from langchain.utilities import WikipediaAPIWrapper\n", @@ -64,19 +67,11 @@ "execution_count": 2, "metadata": { "ExecuteTime": { - "end_time": "2023-05-25T15:09:41.762056Z", - "start_time": "2023-05-25T15:09:41.755238Z" + "end_time": "2023-07-09T19:23:14.378234Z", + "start_time": "2023-07-09T19:20:49.005041Z" } }, - "outputs": [ - { - "name": "stdin", - "output_type": "stream", - "text": [ - " ········\n" - ] - } - ], + "outputs": [], "source": [ "# Provide your OpenAI key\n", "import getpass\n", @@ -87,16 +82,13 @@ { "cell_type": "code", "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdin", - "output_type": "stream", - "text": [ - " ········\n" - ] + "metadata": { + "ExecuteTime": { + "end_time": "2023-07-09T19:23:16.329934Z", + "start_time": "2023-07-09T19:23:14.345580Z" } - ], + }, + "outputs": [], "source": [ "# Provide your Zep API key. Note that this is optional. See https://docs.getzep.com/deployment/auth\n", "\n", @@ -116,8 +108,8 @@ "execution_count": 4, "metadata": { "ExecuteTime": { - "end_time": "2023-05-25T15:09:41.840440Z", - "start_time": "2023-05-25T15:09:41.762277Z" + "end_time": "2023-07-09T19:23:16.528212Z", + "start_time": "2023-07-09T19:23:16.279045Z" } }, "outputs": [], @@ -132,15 +124,11 @@ "]\n", "\n", "# Set up Zep Chat History\n", - "zep_chat_history = ZepChatMessageHistory(\n", + "memory = ZepMemory(\n", " session_id=session_id,\n", " url=ZEP_API_URL,\n", - " api_key=zep_api_key\n", - ")\n", - "\n", - "# Use a standard ConversationBufferMemory to encapsulate the Zep chat history\n", - "memory = ConversationBufferMemory(\n", - " memory_key=\"chat_history\", chat_memory=zep_chat_history\n", + " api_key=zep_api_key,\n", + " memory_key=\"chat_history\",\n", ")\n", "\n", "# Initialize the agent\n", @@ -167,8 +155,8 @@ "execution_count": 5, "metadata": { "ExecuteTime": { - "end_time": "2023-05-25T15:09:41.960661Z", - "start_time": "2023-05-25T15:09:41.842656Z" + "end_time": "2023-07-09T19:23:16.659484Z", + "start_time": "2023-07-09T19:23:16.532090Z" } }, "outputs": [], @@ -230,14 +218,16 @@ " \" living in a dystopian future where society has collapsed due to\"\n", " \" environmental disasters, poverty, and violence.\"\n", " ),\n", + " \"metadata\": {\"foo\": \"bar\"},\n", " },\n", "]\n", "\n", "for msg in test_history:\n", - " zep_chat_history.add_message(\n", + " memory.chat_memory.add_message(\n", " HumanMessage(content=msg[\"content\"])\n", " if msg[\"role\"] == \"human\"\n", - " else AIMessage(content=msg[\"content\"])\n", + " else AIMessage(content=msg[\"content\"]),\n", + " metadata=msg.get(\"metadata\", {}),\n", " )" ] }, @@ -256,8 +246,8 @@ "execution_count": 6, "metadata": { "ExecuteTime": { - "end_time": "2023-05-25T15:09:50.485377Z", - "start_time": "2023-05-25T15:09:41.962287Z" + "end_time": "2023-07-09T19:23:19.348822Z", + "start_time": "2023-07-09T19:23:16.660130Z" } }, "outputs": [ @@ -269,16 +259,14 @@ "\n", "\u001B[1m> Entering new chain...\u001B[0m\n", "\u001B[32;1m\u001B[1;3mThought: Do I need to use a tool? No\n", - "AI: Parable of the Sower is a prescient novel that speaks to the challenges facing contemporary society, such as climate change, economic inequality, and the rise of authoritarianism. It is a cautionary tale that warns of the dangers of ignoring these issues and the importance of taking action to address them.\u001B[0m\n", + "AI: Parable of the Sower is a prescient novel that speaks to the challenges facing contemporary society, such as climate change, inequality, and violence. It is a cautionary tale that warns of the dangers of unchecked greed and the need for individuals to take responsibility for their own lives and the lives of those around them.\u001B[0m\n", "\n", "\u001B[1m> Finished chain.\u001B[0m\n" ] }, { "data": { - "text/plain": [ - "'Parable of the Sower is a prescient novel that speaks to the challenges facing contemporary society, such as climate change, economic inequality, and the rise of authoritarianism. It is a cautionary tale that warns of the dangers of ignoring these issues and the importance of taking action to address them.'" - ] + "text/plain": "'Parable of the Sower is a prescient novel that speaks to the challenges facing contemporary society, such as climate change, inequality, and violence. It is a cautionary tale that warns of the dangers of unchecked greed and the need for individuals to take responsibility for their own lives and the lives of those around them.'" }, "execution_count": 6, "metadata": {}, @@ -287,7 +275,7 @@ ], "source": [ "agent_chain.run(\n", - " input=\"WWhat is the book's relevance to the challenges facing contemporary society?\"\n", + " input=\"What is the book's relevance to the challenges facing contemporary society?\",\n", ")" ] }, @@ -305,11 +293,11 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 9, "metadata": { "ExecuteTime": { - "end_time": "2023-05-25T15:09:50.493438Z", - "start_time": "2023-05-25T15:09:50.479230Z" + "end_time": "2023-07-09T19:23:41.042254Z", + "start_time": "2023-07-09T19:23:41.016815Z" } }, "outputs": [ @@ -317,29 +305,39 @@ "name": "stdout", "output_type": "stream", "text": [ - "The human asks about Octavia Butler and the AI identifies her as an American science fiction author. They continue to discuss her works and the fact that the FX series Kindred is based on one of her novels. The AI also lists Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ as Butler's contemporaries.\n", + "The human inquires about Octavia Butler. The AI identifies her as an American science fiction author. The human then asks which books of hers were made into movies. The AI responds by mentioning the FX series Kindred, based on her novel of the same name. The human then asks about her contemporaries, and the AI lists Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ.\n", "\n", "\n", - "{'role': 'human', 'content': 'What awards did she win?', 'uuid': 'a4bdc592-71a5-47d0-9c64-230b882aab48', 'created_at': '2023-06-26T23:37:56.383953Z', 'token_count': 8, 'metadata': {'system': {'entities': [], 'intent': 'The subject is asking about the awards someone won, likely referring to a specific individual.'}}}\n", - "{'role': 'ai', 'content': 'Octavia Butler won the Hugo Award, the Nebula Award, and the MacArthur Fellowship.', 'uuid': '60cc6e6b-7cd4-4a81-aebc-72ef997286b4', 'created_at': '2023-06-26T23:37:56.389935Z', 'token_count': 21, 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 14, 'Start': 0, 'Text': 'Octavia Butler'}], 'Name': 'Octavia Butler'}, {'Label': 'WORK_OF_ART', 'Matches': [{'End': 33, 'Start': 19, 'Text': 'the Hugo Award'}], 'Name': 'the Hugo Award'}, {'Label': 'EVENT', 'Matches': [{'End': 81, 'Start': 57, 'Text': 'the MacArthur Fellowship'}], 'Name': 'the MacArthur Fellowship'}], 'intent': 'The subject is stating the accomplishments and awards received by Octavia Butler.'}}}\n", - "{'role': 'human', 'content': 'Which other women sci-fi writers might I want to read?', 'uuid': 'b189fc60-1510-4a4b-a503-899481d652de', 'created_at': '2023-06-26T23:37:56.395722Z', 'token_count': 14, 'metadata': {'system': {'entities': [], 'intent': 'The subject is looking for recommendations on women science fiction writers to read.'}}}\n", - "{'role': 'ai', 'content': 'You might want to read Ursula K. Le Guin or Joanna Russ.', 'uuid': '4be1ccbb-a915-45d6-9f18-7a0c1cbd9907', 'created_at': '2023-06-26T23:37:56.403596Z', 'token_count': 18, '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 suggesting reading material and making a literary recommendation.'}}}\n", - "{'role': 'human', 'content': \"Write a short synopsis of Butler's book, Parable of the Sower. What is it about?\", 'uuid': 'ac3c5e3e-26a7-4f3b-aeb0-bba084e22753', 'created_at': '2023-06-26T23:37:56.410662Z', 'token_count': 23, '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 asking for a brief overview or summary of the book \"Parable of the Sower\" written by Butler.'}}}\n", - "{'role': 'ai', '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.', 'uuid': '4a463b4c-bcab-473c-bed1-fc56a7a20ae2', 'created_at': '2023-06-26T23:37:56.41764Z', 'token_count': 56, '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'}]}}}\n", - "{'role': 'human', 'content': \"WWhat is the book's relevance to the challenges facing contemporary society?\", 'uuid': '41bab0c7-5e20-40a4-9303-f82069977c91', 'created_at': '2023-06-26T23:38:03.559642Z', 'token_count': 16, 'metadata': {'system': {'entities': [{'Label': 'ORG', 'Matches': [{'End': 5, 'Start': 0, 'Text': 'WWhat'}], 'Name': 'WWhat'}]}}}\n", - "{'role': 'ai', 'content': 'Parable of the Sower is a prescient novel that speaks to the challenges facing contemporary society, such as climate change, economic inequality, and the rise of authoritarianism. It is a cautionary tale that warns of the dangers of ignoring these issues and the importance of taking action to address them.', 'uuid': 'bfd8146a-4632-4c8c-98b6-9468bb624339', 'created_at': '2023-06-26T23:38:03.589312Z', 'token_count': 62, 'metadata': {'system': {'entities': [{'Label': 'GPE', 'Matches': [{'End': 20, 'Start': 15, 'Text': 'Sower'}], 'Name': 'Sower'}]}}}\n" + "system :\n", + " {'content': 'The human inquires about Octavia Butler. The AI identifies her as an American science fiction author. The human then asks which books of hers were made into movies. The AI responds by mentioning the FX series Kindred, based on her novel of the same name. The human then asks about her contemporaries, and the AI lists Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ.', 'additional_kwargs': {}}\n", + "human :\n", + " {'content': 'What awards did she win?', 'additional_kwargs': {'uuid': '6b733f0b-6778-49ae-b3ec-4e077c039f31', 'created_at': '2023-07-09T19:23:16.611232Z', 'token_count': 8, 'metadata': {'system': {'entities': [], 'intent': 'The subject is inquiring about the awards that someone, whose identity is not specified, has won.'}}}, 'example': False}\n", + "ai :\n", + " {'content': 'Octavia Butler won the Hugo Award, the Nebula Award, and the MacArthur Fellowship.', 'additional_kwargs': {'uuid': '2f6d80c6-3c08-4fd4-8d4e-7bbee341ac90', 'created_at': '2023-07-09T19:23:16.618947Z', 'token_count': 21, 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 14, 'Start': 0, 'Text': 'Octavia Butler'}], 'Name': 'Octavia Butler'}, {'Label': 'WORK_OF_ART', 'Matches': [{'End': 33, 'Start': 19, 'Text': 'the Hugo Award'}], 'Name': 'the Hugo Award'}, {'Label': 'EVENT', 'Matches': [{'End': 81, 'Start': 57, 'Text': 'the MacArthur Fellowship'}], 'Name': 'the MacArthur Fellowship'}], 'intent': 'The subject is stating that Octavia Butler received the Hugo Award, the Nebula Award, and the MacArthur Fellowship.'}}}, 'example': False}\n", + "human :\n", + " {'content': 'Which other women sci-fi writers might I want to read?', 'additional_kwargs': {'uuid': 'ccdcc901-ea39-4981-862f-6fe22ab9289b', 'created_at': '2023-07-09T19:23:16.62678Z', 'token_count': 14, 'metadata': {'system': {'entities': [], 'intent': 'The subject is seeking recommendations for additional women science fiction writers to explore.'}}}, 'example': False}\n", + "ai :\n", + " {'content': 'You might want to read Ursula K. Le Guin or Joanna Russ.', 'additional_kwargs': {'uuid': '7977099a-0c62-4c98-bfff-465bbab6c9c3', 'created_at': '2023-07-09T19:23:16.631721Z', 'token_count': 18, '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 suggesting that the person should consider reading the works of Ursula K. Le Guin or Joanna Russ.'}}}, 'example': False}\n", + "human :\n", + " {'content': \"Write a short synopsis of Butler's book, Parable of the Sower. What is it about?\", 'additional_kwargs': {'uuid': 'e439b7e6-286a-4278-a8cb-dc260fa2e089', 'created_at': '2023-07-09T19:23:16.63623Z', 'token_count': 23, '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 explanation of the book \"Parable of the Sower\" by Butler.'}}}, 'example': False}\n", + "ai :\n", + " {'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.', 'additional_kwargs': {'uuid': '6760489b-19c9-41aa-8b45-fae6cb1d7ee6', 'created_at': '2023-07-09T19:23:16.647524Z', 'token_count': 56, 'metadata': {'foo': 'bar', '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': 'The subject is providing information about the novel \"Parable of the Sower\" by Octavia Butler, including its genre, publication date, and a brief summary of the plot.'}}}, 'example': False}\n", + "human :\n", + " {'content': \"What is the book's relevance to the challenges facing contemporary society?\", 'additional_kwargs': {'uuid': '7dbbbb93-492b-4739-800f-cad2b6e0e764', 'created_at': '2023-07-09T19:23:19.315182Z', 'token_count': 15, 'metadata': {'system': {'entities': [], 'intent': 'The subject is asking about the relevance of a book to the challenges currently faced by society.'}}}, 'example': False}\n", + "ai :\n", + " {'content': 'Parable of the Sower is a prescient novel that speaks to the challenges facing contemporary society, such as climate change, inequality, and violence. It is a cautionary tale that warns of the dangers of unchecked greed and the need for individuals to take responsibility for their own lives and the lives of those around them.', 'additional_kwargs': {'uuid': '3e14ac8f-b7c1-4360-958b-9f3eae1f784f', 'created_at': '2023-07-09T19:23:19.332517Z', 'token_count': 66, 'metadata': {'system': {'entities': [{'Label': 'GPE', 'Matches': [{'End': 20, 'Start': 15, 'Text': 'Sower'}], 'Name': 'Sower'}], 'intent': 'The subject is providing an analysis and evaluation of the novel \"Parable of the Sower\" and highlighting its relevance to contemporary societal challenges.'}}}, 'example': False}\n" ] } ], "source": [ "def print_messages(messages):\n", " for m in messages:\n", - " print(m.to_dict())\n", + " print(m.type, \":\\n\", m.dict())\n", "\n", "\n", - "print(zep_chat_history.zep_summary)\n", + "print(memory.chat_memory.zep_summary)\n", "print(\"\\n\")\n", - "print_messages(zep_chat_history.zep_messages)" + "print_messages(memory.chat_memory.messages)" ] }, { @@ -349,16 +347,18 @@ "source": [ "### Vector search over the Zep memory\n", "\n", - "Zep provides native vector search over historical conversation memory. Embedding happens automatically.\n" + "Zep provides native vector search over historical conversation memory via the `ZepRetriever`.\n", + "\n", + "You can use the `ZepRetriever` with chains that support passing in a Langchain `Retriever` object.\n" ] }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 11, "metadata": { "ExecuteTime": { - "end_time": "2023-05-25T15:09:50.751203Z", - "start_time": "2023-05-25T15:09:50.495050Z" + "end_time": "2023-07-09T19:24:30.781893Z", + "start_time": "2023-07-09T19:24:30.595650Z" } }, "outputs": [ @@ -366,38 +366,36 @@ "name": "stdout", "output_type": "stream", "text": [ - "{'uuid': 'b189fc60-1510-4a4b-a503-899481d652de', 'created_at': '2023-06-26T23:37:56.395722Z', 'role': 'human', 'content': 'Which other women sci-fi writers might I want to read?', 'metadata': {'system': {'entities': [], 'intent': 'The subject is looking for recommendations on women science fiction writers to read.'}}, 'token_count': 14} 0.9119619869747062\n", - "{'uuid': '4be1ccbb-a915-45d6-9f18-7a0c1cbd9907', 'created_at': '2023-06-26T23:37:56.403596Z', 'role': 'ai', 'content': 'You might want to read Ursula K. Le Guin or Joanna Russ.', '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 suggesting reading material and making a literary recommendation.'}}, 'token_count': 18} 0.8534346954749745\n", - "{'uuid': '76ec2a3d-b908-4c23-a55d-71ff92865a7a', 'created_at': '2023-06-26T23:37:56.378345Z', 'role': 'ai', 'content': \"Octavia Butler's contemporaries included Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ.\", '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 the contemporaries of Octavia Butler, who are also science fiction writers.'}}, 'token_count': 27} 0.8523930955780226\n", - "{'uuid': '1feb02c7-63c9-4616-854d-0d97fb590ea5', 'created_at': '2023-06-26T23:37:56.313009Z', 'role': 'human', 'content': 'Who was Octavia Butler?', 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 22, 'Start': 8, 'Text': 'Octavia Butler'}], 'Name': 'Octavia Butler'}], 'intent': 'The subject is asking about the identity of Octavia Butler, likely seeking information about her background or accomplishments.'}}, 'token_count': 8} 0.8236355436055457\n", - "{'uuid': 'ebe4696d-b5fa-4ca0-88c9-da794d9611ab', 'created_at': '2023-06-26T23:37:56.332247Z', 'role': 'ai', 'content': 'Octavia Estelle Butler (June 22, 1947 – February 24, 2006) was an American science fiction author.', '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'}], 'intent': 'The subject is making a statement about the background and profession of Octavia Estelle Butler, an American author.'}}, 'token_count': 31} 0.8206687242257686\n", - "{'uuid': '60cc6e6b-7cd4-4a81-aebc-72ef997286b4', 'created_at': '2023-06-26T23:37:56.389935Z', 'role': 'ai', 'content': 'Octavia Butler won the Hugo Award, the Nebula Award, and the MacArthur Fellowship.', 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 14, 'Start': 0, 'Text': 'Octavia Butler'}], 'Name': 'Octavia Butler'}, {'Label': 'WORK_OF_ART', 'Matches': [{'End': 33, 'Start': 19, 'Text': 'the Hugo Award'}], 'Name': 'the Hugo Award'}, {'Label': 'EVENT', 'Matches': [{'End': 81, 'Start': 57, 'Text': 'the MacArthur Fellowship'}], 'Name': 'the MacArthur Fellowship'}], 'intent': 'The subject is stating the accomplishments and awards received by Octavia Butler.'}}, 'token_count': 21} 0.8194249796585193\n", - "{'uuid': '0fa4f336-909d-4880-b01a-8e80e91fa8f2', 'created_at': '2023-06-26T23:37:56.344552Z', 'role': 'human', 'content': 'Which books of hers were made into movies?', 'metadata': {'system': {'entities': [], 'intent': 'The subject is inquiring about which books written by an unknown female author were adapted into movies.'}}, 'token_count': 11} 0.7955105671310818\n", - "{'uuid': 'f91de7f2-4b84-4c5a-8a33-a71f38f3a59c', 'created_at': '2023-06-26T23:37:56.368146Z', 'role': 'human', 'content': 'Who were her contemporaries?', 'metadata': {'system': {'entities': [], 'intent': 'The subject is asking about the people who lived during the same time period as a specific individual.'}}, 'token_count': 8} 0.7942358617914813\n", - "{'uuid': '4a463b4c-bcab-473c-bed1-fc56a7a20ae2', 'created_at': '2023-06-26T23:37:56.41764Z', 'role': 'ai', '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': {'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} 0.7816448549236643\n", - "{'uuid': '6161d934-a629-4ba2-8bba-0b0996c93964', 'created_at': '2023-06-26T23:37:56.358632Z', 'role': 'ai', 'content': \"The most well-known adaptation of Octavia Butler's work is the FX series Kindred, based on her novel of the same name.\", 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 50, 'Start': 34, 'Text': \"Octavia Butler's\"}], 'Name': \"Octavia Butler's\"}, {'Label': 'ORG', 'Matches': [{'End': 65, 'Start': 63, 'Text': 'FX'}], 'Name': 'FX'}, {'Label': 'GPE', 'Matches': [{'End': 80, 'Start': 73, 'Text': 'Kindred'}], 'Name': 'Kindred'}], 'intent': \"The subject is discussing Octavia Butler's work being adapted into a TV series called Kindred.\"}}, 'token_count': 29} 0.7815841371388998\n" + "{'uuid': 'ccdcc901-ea39-4981-862f-6fe22ab9289b', 'created_at': '2023-07-09T19:23:16.62678Z', 'role': 'human', 'content': 'Which other women sci-fi writers might I want to read?', 'metadata': {'system': {'entities': [], 'intent': 'The subject is seeking recommendations for additional women science fiction writers to explore.'}}, 'token_count': 14} 0.9119619869747062\n", + "{'uuid': '7977099a-0c62-4c98-bfff-465bbab6c9c3', 'created_at': '2023-07-09T19:23:16.631721Z', 'role': 'ai', 'content': 'You might want to read Ursula K. Le Guin or Joanna Russ.', '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 suggesting that the person should consider reading the works of Ursula K. Le Guin or Joanna Russ.'}}, 'token_count': 18} 0.8534346954749745\n", + "{'uuid': 'b05e2eb5-c103-4973-9458-928726f08655', 'created_at': '2023-07-09T19:23:16.603098Z', 'role': 'ai', 'content': \"Octavia Butler's contemporaries included Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ.\", '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 that Octavia Butler's contemporaries included Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ.\"}}, 'token_count': 27} 0.8523831524040919\n", + "{'uuid': 'e346f02b-f854-435d-b6ba-fb394a416b9b', 'created_at': '2023-07-09T19:23:16.556587Z', 'role': 'human', 'content': 'Who was Octavia Butler?', 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 22, 'Start': 8, 'Text': 'Octavia Butler'}], 'Name': 'Octavia Butler'}], 'intent': 'The subject is asking for information about the identity or background of Octavia Butler.'}}, 'token_count': 8} 0.8236355436055457\n", + "{'uuid': '42ff41d2-c63a-4d5b-b19b-d9a87105cfc3', 'created_at': '2023-07-09T19:23:16.578022Z', 'role': 'ai', 'content': 'Octavia Estelle Butler (June 22, 1947 – February 24, 2006) was an American science fiction author.', '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'}], 'intent': 'The subject is providing information about Octavia Estelle Butler, who was an American science fiction author.'}}, 'token_count': 31} 0.8206687242257686\n", + "{'uuid': '2f6d80c6-3c08-4fd4-8d4e-7bbee341ac90', 'created_at': '2023-07-09T19:23:16.618947Z', 'role': 'ai', 'content': 'Octavia Butler won the Hugo Award, the Nebula Award, and the MacArthur Fellowship.', 'metadata': {'system': {'entities': [{'Label': 'PERSON', 'Matches': [{'End': 14, 'Start': 0, 'Text': 'Octavia Butler'}], 'Name': 'Octavia Butler'}, {'Label': 'WORK_OF_ART', 'Matches': [{'End': 33, 'Start': 19, 'Text': 'the Hugo Award'}], 'Name': 'the Hugo Award'}, {'Label': 'EVENT', 'Matches': [{'End': 81, 'Start': 57, 'Text': 'the MacArthur Fellowship'}], 'Name': 'the MacArthur Fellowship'}], 'intent': 'The subject is stating that Octavia Butler received the Hugo Award, the Nebula Award, and the MacArthur Fellowship.'}}, 'token_count': 21} 0.8199012397683285\n" ] } ], "source": [ - "search_results = zep_chat_history.search(\"who are some famous women sci-fi authors?\")\n", + "retriever = ZepRetriever(\n", + " session_id=session_id,\n", + " url=ZEP_API_URL,\n", + " api_key=zep_api_key,\n", + ")\n", + "\n", + "search_results = memory.chat_memory.search(\"who are some famous women sci-fi authors?\")\n", "for r in search_results:\n", - " print(r.message, r.dist)" + " if r.dist > 0.8: # Only print results with similarity of 0.8 or higher\n", + " print(r.message, r.dist)" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] + "source": [], + "metadata": { + "collapsed": false + } } ], "metadata": { diff --git a/langchain/memory/__init__.py b/langchain/memory/__init__.py index 8e0c5b82d9..4c28f61814 100644 --- a/langchain/memory/__init__.py +++ b/langchain/memory/__init__.py @@ -31,6 +31,7 @@ from langchain.memory.summary import ConversationSummaryMemory from langchain.memory.summary_buffer import ConversationSummaryBufferMemory from langchain.memory.token_buffer import ConversationTokenBufferMemory from langchain.memory.vectorstore import VectorStoreRetrieverMemory +from langchain.memory.zep_memory import ZepMemory __all__ = [ "CassandraChatMessageHistory", @@ -60,4 +61,5 @@ __all__ = [ "SimpleMemory", "VectorStoreRetrieverMemory", "ZepChatMessageHistory", + "ZepMemory", ] diff --git a/langchain/memory/chat_message_histories/zep.py b/langchain/memory/chat_message_histories/zep.py index 58dc26bdc4..e468369ac8 100644 --- a/langchain/memory/chat_message_histories/zep.py +++ b/langchain/memory/chat_message_histories/zep.py @@ -1,12 +1,17 @@ from __future__ import annotations import logging -from typing import TYPE_CHECKING, Dict, List, Optional +from typing import TYPE_CHECKING, Any, Dict, List, Optional from langchain.schema import ( BaseChatMessageHistory, ) -from langchain.schema.messages import AIMessage, BaseMessage, HumanMessage +from langchain.schema.messages import ( + AIMessage, + BaseMessage, + HumanMessage, + SystemMessage, +) if TYPE_CHECKING: from zep_python import Memory, MemorySearchResult, Message, NotFoundError @@ -75,14 +80,24 @@ class ZepChatMessageHistory(BaseChatMessageHistory): # Extract summary, if present, and messages if zep_memory.summary: if len(zep_memory.summary.content) > 0: - messages.append(HumanMessage(content=zep_memory.summary.content)) + messages.append(SystemMessage(content=zep_memory.summary.content)) if zep_memory.messages: msg: Message for msg in zep_memory.messages: + metadata: Dict = { + "uuid": msg.uuid, + "created_at": msg.created_at, + "token_count": msg.token_count, + "metadata": msg.metadata, + } if msg.role == "ai": - messages.append(AIMessage(content=msg.content)) + messages.append( + AIMessage(content=msg.content, additional_kwargs=metadata) + ) else: - messages.append(HumanMessage(content=msg.content)) + messages.append( + HumanMessage(content=msg.content, additional_kwargs=metadata) + ) return messages @@ -117,16 +132,37 @@ class ZepChatMessageHistory(BaseChatMessageHistory): return None return zep_memory - def add_message(self, message: BaseMessage) -> None: + def add_user_message( + self, message: str, metadata: Optional[Dict[str, Any]] = None + ) -> None: + """Convenience method for adding a human message string to the store. + + Args: + message: The string contents of a human message. + metadata: Optional metadata to attach to the message. + """ + self.add_message(HumanMessage(content=message), metadata=metadata) + + def add_ai_message( + self, message: str, metadata: Optional[Dict[str, Any]] = None + ) -> None: + """Convenience method for adding an AI message string to the store. + + Args: + message: The string contents of an AI message. + metadata: Optional metadata to attach to the message. + """ + self.add_message(AIMessage(content=message), metadata=metadata) + + def add_message( + self, message: BaseMessage, metadata: Optional[Dict[str, Any]] = None + ) -> None: """Append the message to the Zep memory history""" from zep_python import Memory, Message - zep_message: Message - if isinstance(message, HumanMessage): - zep_message = Message(content=message.content, role="human") - else: - zep_message = Message(content=message.content, role="ai") - + zep_message = Message( + content=message.content, role=message.type, metadata=metadata + ) zep_memory = Memory(messages=[zep_message]) self.zep_client.add_memory(self.session_id, zep_memory) diff --git a/langchain/memory/zep_memory.py b/langchain/memory/zep_memory.py new file mode 100644 index 0000000000..8e56eb4773 --- /dev/null +++ b/langchain/memory/zep_memory.py @@ -0,0 +1,124 @@ +from __future__ import annotations + +from typing import Any, Dict, Optional + +from langchain.memory import ConversationBufferMemory +from langchain.memory.chat_message_histories import ZepChatMessageHistory + + +class ZepMemory(ConversationBufferMemory): + """Persist your chain history to the Zep Long-term Memory Server + + The number of messages returned by Zep and when the Zep server summarizes chat + histories is configurable. See the Zep documentation for more details. + + Documentation: https://docs.getzep.com + + Example: + .. code-block:: python + + memory = ZepMemory( + session_id=session_id, # Identifies your user or a user's session + url=ZEP_API_URL, # Your Zep server's URL + api_key=, # Optional + memory_key="history", # Ensure this matches the key used in + # chain's prompt template + return_messages=True, # Does your prompt template expect a string + # or a list of Messages? + ) + chain = LLMChain(memory=memory,...) # Configure your chain to use the ZepMemory + instance + + + Note: + To persist metadata alongside your chat history, your will need to create a + custom Chain class that overrides the `prep_outputs` method to include the metadata + in the call to `self.memory.save_context`. + + + About 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. + + For server installation instructions and more, see: + https://docs.getzep.com/deployment/quickstart/ + + For more information on the zep-python package, see: + https://github.com/getzep/zep-python + + """ + + chat_memory: ZepChatMessageHistory + + def __init__( + self, + session_id: str, + url: str = "http://localhost:8000", + api_key: Optional[str] = None, + output_key: Optional[str] = None, + input_key: Optional[str] = None, + return_messages: bool = False, + human_prefix: str = "Human", + ai_prefix: str = "AI", + memory_key: str = "history", + ): + """Initialize ZepMemory. + + Args: + session_id (str): Identifies your user or a user's session + url (str, optional): Your Zep server's URL. Defaults to + "http://localhost:8000". + api_key (Optional[str], optional): Your Zep API key. Defaults to None. + output_key (Optional[str], optional): The key to use for the output message. + Defaults to None. + input_key (Optional[str], optional): The key to use for the input message. + Defaults to None. + return_messages (bool, optional): Does your prompt template expect a string + or a list of Messages? Defaults to False + i.e. return a string. + human_prefix (str, optional): The prefix to use for human messages. + Defaults to "Human". + ai_prefix (str, optional): The prefix to use for AI messages. + Defaults to "AI". + memory_key (str, optional): The key to use for the memory. + Defaults to "history". + Ensure that this matches the key used in + chain's prompt template. + """ + chat_message_history = ZepChatMessageHistory( + session_id=session_id, + url=url, + api_key=api_key, + ) + super().__init__( + chat_memory=chat_message_history, + output_key=output_key, + input_key=input_key, + return_messages=return_messages, + human_prefix=human_prefix, + ai_prefix=ai_prefix, + memory_key=memory_key, + ) + + def save_context( + self, + inputs: Dict[str, Any], + outputs: Dict[str, str], + metadata: Optional[Dict[str, Any]] = None, + ) -> None: + """Save context from this conversation to buffer. + + Args: + inputs (Dict[str, Any]): The inputs to the chain. + outputs (Dict[str, str]): The outputs from the chain. + metadata (Optional[Dict[str, Any]], optional): Any metadata to save with + the context. Defaults to None + + Returns: + None + """ + input_str, output_str = self._get_input_output(inputs, outputs) + self.chat_memory.add_user_message(input_str, metadata=metadata) + self.chat_memory.add_ai_message(output_str, metadata=metadata) diff --git a/tests/unit_tests/memory/chat_message_histories/test_zep.py b/tests/unit_tests/memory/chat_message_histories/test_zep.py index 78967657ed..9eda5d929c 100644 --- a/tests/unit_tests/memory/chat_message_histories/test_zep.py +++ b/tests/unit_tests/memory/chat_message_histories/test_zep.py @@ -4,7 +4,7 @@ import pytest from pytest_mock import MockerFixture from langchain.memory.chat_message_histories import ZepChatMessageHistory -from langchain.schema.messages import AIMessage, HumanMessage +from langchain.schema.messages import AIMessage, HumanMessage, SystemMessage if TYPE_CHECKING: from zep_python import ZepClient @@ -39,7 +39,7 @@ def test_messages(mocker: MockerFixture, zep_chat: ZepChatMessageHistory) -> Non result = zep_chat.messages assert len(result) == 3 - assert isinstance(result[0], HumanMessage) # summary + assert isinstance(result[0], SystemMessage) # summary assert isinstance(result[1], AIMessage) assert isinstance(result[2], HumanMessage)