mirror of
https://github.com/hwchase17/langchain.git
synced 2025-08-02 01:23:07 +00:00
community[minor]: Add Zep Cloud components + docs + examples (#21671)
Thank you for contributing to LangChain! - [x] **PR title**: community: Add Zep Cloud components + docs + examples - [x] **PR message**: We have recently released our new zep-cloud sdks that are compatible with Zep Cloud (not Zep Open Source). We have also maintained our Cloud version of langchain components (ChatMessageHistory, VectorStore) as part of our sdks. This PRs goal is to port these components to langchain community repo, and close the gap with the existing Zep Open Source components already present in community repo (added ZepCloudMemory,ZepCloudVectorStore,ZepCloudRetriever). Also added a ZepCloudChatMessageHistory components together with an expression language example ported from our repo. We have left the original open source components intact on purpose as to not introduce any breaking changes. - **Issue:** - - **Dependencies:** Added optional dependency of our new cloud sdk `zep-cloud` - **Twitter handle:** @paulpaliychuk51 - [x] **Add tests and docs** - [x] **Lint and test**: Run `make format`, `make lint` and `make test` from the root of the package(s) you've modified. See contribution guidelines for more: https://python.langchain.com/docs/contributing/ Additional guidelines: - Make sure optional dependencies are imported within a function. - Please do not add dependencies to pyproject.toml files (even optional ones) unless they are required for unit tests. - Most PRs should not touch more than one package. - Changes should be backwards compatible. - If you are adding something to community, do not re-import it in langchain. If no one reviews your PR within a few days, please @-mention one of baskaryan, efriis, eyurtsev, hwchase17.
This commit is contained in:
parent
cccc8fbe2f
commit
342df7cf83
@ -0,0 +1,337 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "1cdd080f9ea3e0b",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# ZepCloudChatMessageHistory\n",
|
||||
"> Recall, understand, and extract data from chat histories. Power personalized AI experiences.\n",
|
||||
"\n",
|
||||
">[Zep](https://www.getzep.com) is a long-term memory service for AI Assistant apps.\n",
|
||||
"> With Zep, you can provide AI assistants with the ability to recall past conversations, no matter how distant,\n",
|
||||
"> while also reducing hallucinations, latency, and cost.\n",
|
||||
"\n",
|
||||
"> See [Zep Cloud Installation Guide](https://help.getzep.com/sdks) and more [Zep Cloud Langchain Examples](https://github.com/getzep/zep-python/tree/main/examples)\n",
|
||||
"\n",
|
||||
"## Example\n",
|
||||
"\n",
|
||||
"This notebook demonstrates how to use [Zep](https://www.getzep.com/) to persist chat history and use Zep Memory with your chain.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"id": "82fb8484eed2ee9a",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-05-10T05:20:12.069045Z",
|
||||
"start_time": "2024-05-10T05:20:12.062518Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from uuid import uuid4\n",
|
||||
"\n",
|
||||
"from langchain_community.chat_message_histories import ZepCloudChatMessageHistory\n",
|
||||
"from langchain_community.memory.zep_cloud_memory import ZepCloudMemory\n",
|
||||
"from langchain_core.messages import AIMessage, HumanMessage\n",
|
||||
"from langchain_core.output_parsers import StrOutputParser\n",
|
||||
"from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
|
||||
"from langchain_core.runnables import (\n",
|
||||
" RunnableParallel,\n",
|
||||
")\n",
|
||||
"from langchain_core.runnables.history import RunnableWithMessageHistory\n",
|
||||
"from langchain_openai import ChatOpenAI\n",
|
||||
"\n",
|
||||
"session_id = str(uuid4()) # This is a unique identifier for the session"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "d79e0e737db426ac",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Provide your OpenAI key"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"id": "7430ea2341ecd227",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-05-10T05:20:17.983314Z",
|
||||
"start_time": "2024-05-10T05:20:13.805729Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import getpass\n",
|
||||
"\n",
|
||||
"openai_key = getpass.getpass()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "81a87004bc92c3e2",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Provide your Zep API key. See https://help.getzep.com/projects#api-keys\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"id": "c21632a2c7223170",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-05-10T05:20:24.694643Z",
|
||||
"start_time": "2024-05-10T05:20:22.174681Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"zep_api_key = getpass.getpass()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "436de864fe0000",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Preload some messages into the memory. The default message window is 4 messages. We want to push beyond this to demonstrate auto-summarization."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"id": "e8fb07edd965ef1f",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-05-10T05:20:38.657289Z",
|
||||
"start_time": "2024-05-10T05:20:26.981492Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"test_history = [\n",
|
||||
" {\"role\": \"human\", \"content\": \"Who was Octavia Butler?\"},\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"Octavia Estelle Butler (June 22, 1947 – February 24, 2006) was an American\"\n",
|
||||
" \" science fiction author.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\"role\": \"human\", \"content\": \"Which books of hers were made into movies?\"},\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"The most well-known adaptation of Octavia Butler's work is the FX series\"\n",
|
||||
" \" Kindred, based on her novel of the same name.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\"role\": \"human\", \"content\": \"Who were her contemporaries?\"},\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"Octavia Butler's contemporaries included Ursula K. Le Guin, Samuel R.\"\n",
|
||||
" \" Delany, and Joanna Russ.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\"role\": \"human\", \"content\": \"What awards did she win?\"},\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"Octavia Butler won the Hugo Award, the Nebula Award, and the MacArthur\"\n",
|
||||
" \" Fellowship.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"human\",\n",
|
||||
" \"content\": \"Which other women sci-fi writers might I want to read?\",\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"content\": \"You might want to read Ursula K. Le Guin or Joanna Russ.\",\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"human\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"Write a short synopsis of Butler's book, Parable of the Sower. What is it\"\n",
|
||||
" \" about?\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"Parable of the Sower is a science fiction novel by Octavia Butler,\"\n",
|
||||
" \" published in 1993. It follows the story of Lauren Olamina, a young woman\"\n",
|
||||
" \" 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",
|
||||
"zep_memory = ZepCloudMemory(\n",
|
||||
" session_id=session_id,\n",
|
||||
" api_key=zep_api_key,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"for msg in test_history:\n",
|
||||
" zep_memory.chat_memory.add_message(\n",
|
||||
" HumanMessage(content=msg[\"content\"])\n",
|
||||
" if msg[\"role\"] == \"human\"\n",
|
||||
" else AIMessage(content=msg[\"content\"])\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"import time\n",
|
||||
"\n",
|
||||
"time.sleep(\n",
|
||||
" 10\n",
|
||||
") # Wait for the messages to be embedded and summarized, this happens asynchronously."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "bfa6b19f0b501aea",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"**MessagesPlaceholder** - We’re using the variable name chat_history here. This will incorporate the chat history into the prompt.\n",
|
||||
"It’s important that this variable name aligns with the history_messages_key in the RunnableWithMessageHistory chain for seamless integration.\n",
|
||||
"\n",
|
||||
"**question** must match input_messages_key in `RunnableWithMessageHistory“ chain."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"id": "2b12eccf9b4908eb",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-05-10T05:20:46.592163Z",
|
||||
"start_time": "2024-05-10T05:20:46.464326Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"template = \"\"\"Be helpful and answer the question below using the provided context:\n",
|
||||
" \"\"\"\n",
|
||||
"answer_prompt = ChatPromptTemplate.from_messages(\n",
|
||||
" [\n",
|
||||
" (\"system\", template),\n",
|
||||
" MessagesPlaceholder(variable_name=\"chat_history\"),\n",
|
||||
" (\"user\", \"{question}\"),\n",
|
||||
" ]\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "7d6014d6fe7f2d22",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We use RunnableWithMessageHistory to incorporate Zep’s Chat History into our chain. This class requires a session_id as a parameter when you activate the chain."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"id": "83ea7322638f8ead",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-05-10T05:20:49.681754Z",
|
||||
"start_time": "2024-05-10T05:20:49.663404Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"inputs = RunnableParallel(\n",
|
||||
" {\n",
|
||||
" \"question\": lambda x: x[\"question\"],\n",
|
||||
" \"chat_history\": lambda x: x[\"chat_history\"],\n",
|
||||
" },\n",
|
||||
")\n",
|
||||
"chain = RunnableWithMessageHistory(\n",
|
||||
" inputs | answer_prompt | ChatOpenAI(openai_api_key=openai_key) | StrOutputParser(),\n",
|
||||
" lambda s_id: ZepCloudChatMessageHistory(\n",
|
||||
" session_id=s_id, # This uniquely identifies the conversation, note that we are getting session id as chain configurable field\n",
|
||||
" api_key=zep_api_key,\n",
|
||||
" memory_type=\"perpetual\",\n",
|
||||
" ),\n",
|
||||
" input_messages_key=\"question\",\n",
|
||||
" history_messages_key=\"chat_history\",\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"id": "db8bdc1d0d7bb672",
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-05-10T05:20:54.966758Z",
|
||||
"start_time": "2024-05-10T05:20:52.117440Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Parent run 622c6f75-3e4a-413d-ba20-558c1fea0d50 not found for run af12a4b1-e882-432d-834f-e9147465faf6. Treating as a root run.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'\"Parable of the Sower\" is relevant to the challenges facing contemporary society as it explores themes of environmental degradation, economic inequality, social unrest, and the search for hope and community in the face of chaos. The novel\\'s depiction of a dystopian future where society has collapsed due to environmental and economic crises serves as a cautionary tale about the potential consequences of our current societal and environmental challenges. By addressing issues such as climate change, social injustice, and the impact of technology on humanity, Octavia Butler\\'s work prompts readers to reflect on the pressing issues of our time and the importance of resilience, empathy, and collective action in building a better future.'"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"chain.invoke(\n",
|
||||
" {\n",
|
||||
" \"question\": \"What is the book's relevance to the challenges facing contemporary society?\"\n",
|
||||
" },\n",
|
||||
" config={\"configurable\": {\"session_id\": session_id}},\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "1d9c609652110db3",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
"collapsed": false
|
||||
},
|
||||
"source": [
|
||||
"# Zep\n",
|
||||
"# Zep Open Source Memory\n",
|
||||
"> Recall, understand, and extract data from chat histories. Power personalized AI experiences.\n",
|
||||
"\n",
|
||||
">[Zep](https://www.getzep.com) is a long-term memory service for AI Assistant apps.\n",
|
||||
@ -36,11 +36,11 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2023-07-09T19:20:49.003167Z",
|
||||
"start_time": "2023-07-09T19:20:47.446370Z"
|
||||
"end_time": "2024-05-10T03:25:26.191166Z",
|
||||
"start_time": "2024-05-10T03:25:25.641520Z"
|
||||
}
|
||||
},
|
||||
"outputs": [],
|
||||
|
428
docs/docs/integrations/memory/zep_memory_cloud.ipynb
Normal file
428
docs/docs/integrations/memory/zep_memory_cloud.ipynb
Normal file
@ -0,0 +1,428 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"source": [
|
||||
"# Zep Cloud Memory\n",
|
||||
"> Recall, understand, and extract data from chat histories. Power personalized AI experiences.\n",
|
||||
"\n",
|
||||
">[Zep](https://www.getzep.com) is a long-term memory service for AI Assistant apps.\n",
|
||||
"> With Zep, you can provide AI assistants with the ability to recall past conversations, no matter how distant,\n",
|
||||
"> while also reducing hallucinations, latency, and cost.\n",
|
||||
"\n",
|
||||
"> See [Zep Cloud Installation Guide](https://help.getzep.com/sdks) and more [Zep Cloud Langchain Examples](https://github.com/getzep/zep-python/tree/main/examples)\n",
|
||||
"\n",
|
||||
"## Example\n",
|
||||
"\n",
|
||||
"This notebook demonstrates how to use [Zep](https://www.getzep.com/) as memory for your chatbot.\n",
|
||||
"\n",
|
||||
"We'll demonstrate:\n",
|
||||
"\n",
|
||||
"1. Adding conversation history to Zep.\n",
|
||||
"2. Running an agent and having message automatically added to the store.\n",
|
||||
"3. Viewing the enriched messages.\n",
|
||||
"4. Vector search over the conversation history."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-05-14T17:25:10.779451Z",
|
||||
"start_time": "2024-05-14T17:25:10.375249Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "AttributeError",
|
||||
"evalue": "'FieldInfo' object has no attribute 'deprecated'",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
||||
"\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
|
||||
"Cell \u001b[0;32mIn[3], line 8\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mlangchain_community\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mutilities\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m WikipediaAPIWrapper\n\u001b[1;32m 7\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mlangchain_core\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmessages\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m AIMessage, HumanMessage\n\u001b[0;32m----> 8\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mlangchain_openai\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m OpenAI\n\u001b[1;32m 10\u001b[0m session_id \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mstr\u001b[39m(uuid4()) \u001b[38;5;66;03m# This is a unique identifier for the session\u001b[39;00m\n",
|
||||
"File \u001b[0;32m~/job/integrations/langchain/libs/partners/openai/langchain_openai/__init__.py:1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mlangchain_openai\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mchat_models\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m (\n\u001b[1;32m 2\u001b[0m AzureChatOpenAI,\n\u001b[1;32m 3\u001b[0m ChatOpenAI,\n\u001b[1;32m 4\u001b[0m )\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mlangchain_openai\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01membeddings\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m (\n\u001b[1;32m 6\u001b[0m AzureOpenAIEmbeddings,\n\u001b[1;32m 7\u001b[0m OpenAIEmbeddings,\n\u001b[1;32m 8\u001b[0m )\n\u001b[1;32m 9\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mlangchain_openai\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mllms\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m AzureOpenAI, OpenAI\n",
|
||||
"File \u001b[0;32m~/job/integrations/langchain/libs/partners/openai/langchain_openai/chat_models/__init__.py:1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mlangchain_openai\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mchat_models\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mazure\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m AzureChatOpenAI\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mlangchain_openai\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mchat_models\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mbase\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m ChatOpenAI\n\u001b[1;32m 4\u001b[0m __all__ \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 5\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mChatOpenAI\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 6\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mAzureChatOpenAI\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 7\u001b[0m ]\n",
|
||||
"File \u001b[0;32m~/job/integrations/langchain/libs/partners/openai/langchain_openai/chat_models/azure.py:8\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\n\u001b[1;32m 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtyping\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Any, Callable, Dict, List, Optional, Union\n\u001b[0;32m----> 8\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mopenai\u001b[39;00m\n\u001b[1;32m 9\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mlangchain_core\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01moutputs\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m ChatResult\n\u001b[1;32m 10\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mlangchain_core\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpydantic_v1\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Field, SecretStr, root_validator\n",
|
||||
"File \u001b[0;32m~/job/zep-proprietary/venv/lib/python3.11/site-packages/openai/__init__.py:8\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01m_os\u001b[39;00m\n\u001b[1;32m 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtyping_extensions\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m override\n\u001b[0;32m----> 8\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m types\n\u001b[1;32m 9\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_types\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m NOT_GIVEN, NoneType, NotGiven, Transport, ProxiesTypes\n\u001b[1;32m 10\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_utils\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m file_from_path\n",
|
||||
"File \u001b[0;32m~/job/zep-proprietary/venv/lib/python3.11/site-packages/openai/types/__init__.py:5\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.\u001b[39;00m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m__future__\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m annotations\n\u001b[0;32m----> 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mbatch\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Batch \u001b[38;5;28;01mas\u001b[39;00m Batch\n\u001b[1;32m 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mimage\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Image \u001b[38;5;28;01mas\u001b[39;00m Image\n\u001b[1;32m 7\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodel\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Model \u001b[38;5;28;01mas\u001b[39;00m Model\n",
|
||||
"File \u001b[0;32m~/job/zep-proprietary/venv/lib/python3.11/site-packages/openai/types/batch.py:7\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtyping\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m List, Optional\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtyping_extensions\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Literal\n\u001b[0;32m----> 7\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01m_models\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m BaseModel\n\u001b[1;32m 8\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mbatch_error\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m BatchError\n\u001b[1;32m 9\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mbatch_request_counts\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m BatchRequestCounts\n",
|
||||
"File \u001b[0;32m~/job/zep-proprietary/venv/lib/python3.11/site-packages/openai/_models.py:667\u001b[0m\n\u001b[1;32m 662\u001b[0m json_data: Body\n\u001b[1;32m 663\u001b[0m extra_json: AnyMapping\n\u001b[1;32m 666\u001b[0m \u001b[38;5;129;43m@final\u001b[39;49m\n\u001b[0;32m--> 667\u001b[0m \u001b[38;5;28;43;01mclass\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;21;43;01mFinalRequestOptions\u001b[39;49;00m\u001b[43m(\u001b[49m\u001b[43mpydantic\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mBaseModel\u001b[49m\u001b[43m)\u001b[49m\u001b[43m:\u001b[49m\n\u001b[1;32m 668\u001b[0m \u001b[43m \u001b[49m\u001b[43mmethod\u001b[49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mstr\u001b[39;49m\n\u001b[1;32m 669\u001b[0m \u001b[43m \u001b[49m\u001b[43murl\u001b[49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mstr\u001b[39;49m\n",
|
||||
"File \u001b[0;32m~/job/zep-proprietary/venv/lib/python3.11/site-packages/pydantic/_internal/_model_construction.py:202\u001b[0m, in \u001b[0;36m__new__\u001b[0;34m(mcs, cls_name, bases, namespace, __pydantic_generic_metadata__, __pydantic_reset_parent_namespace__, _create_model_module, **kwargs)\u001b[0m\n\u001b[1;32m 199\u001b[0m super(cls, cls).__pydantic_init_subclass__(**kwargs) # type: ignore[misc]\n\u001b[1;32m 200\u001b[0m return cls\n\u001b[1;32m 201\u001b[0m else:\n\u001b[0;32m--> 202\u001b[0m # this is the BaseModel class itself being created, no logic required\n\u001b[1;32m 203\u001b[0m return super().__new__(mcs, cls_name, bases, namespace, **kwargs)\n\u001b[1;32m 205\u001b[0m if not typing.TYPE_CHECKING: # pragma: no branch\n\u001b[1;32m 206\u001b[0m # We put `__getattr__` in a non-TYPE_CHECKING block because otherwise, mypy allows arbitrary attribute access\n",
|
||||
"File \u001b[0;32m~/job/zep-proprietary/venv/lib/python3.11/site-packages/pydantic/_internal/_model_construction.py:539\u001b[0m, in \u001b[0;36mcomplete_model_class\u001b[0;34m(cls, cls_name, config_wrapper, raise_errors, types_namespace, create_model_module)\u001b[0m\n\u001b[1;32m 532\u001b[0m \u001b[38;5;66;03m# debug(schema)\u001b[39;00m\n\u001b[1;32m 533\u001b[0m \u001b[38;5;28mcls\u001b[39m\u001b[38;5;241m.\u001b[39m__pydantic_core_schema__ \u001b[38;5;241m=\u001b[39m schema\n\u001b[1;32m 535\u001b[0m \u001b[38;5;28mcls\u001b[39m\u001b[38;5;241m.\u001b[39m__pydantic_validator__ \u001b[38;5;241m=\u001b[39m create_schema_validator(\n\u001b[1;32m 536\u001b[0m schema,\n\u001b[1;32m 537\u001b[0m \u001b[38;5;28mcls\u001b[39m,\n\u001b[1;32m 538\u001b[0m create_model_module \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mcls\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__module__\u001b[39m,\n\u001b[0;32m--> 539\u001b[0m \u001b[38;5;28mcls\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__qualname__\u001b[39m,\n\u001b[1;32m 540\u001b[0m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mcreate_model\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m create_model_module \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mBaseModel\u001b[39m\u001b[38;5;124m'\u001b[39m,\n\u001b[1;32m 541\u001b[0m core_config,\n\u001b[1;32m 542\u001b[0m config_wrapper\u001b[38;5;241m.\u001b[39mplugin_settings,\n\u001b[1;32m 543\u001b[0m )\n\u001b[1;32m 544\u001b[0m \u001b[38;5;28mcls\u001b[39m\u001b[38;5;241m.\u001b[39m__pydantic_serializer__ \u001b[38;5;241m=\u001b[39m SchemaSerializer(schema, core_config)\n\u001b[1;32m 545\u001b[0m \u001b[38;5;28mcls\u001b[39m\u001b[38;5;241m.\u001b[39m__pydantic_complete__ \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n",
|
||||
"File \u001b[0;32m~/job/zep-proprietary/venv/lib/python3.11/site-packages/pydantic/main.py:626\u001b[0m, in \u001b[0;36m__get_pydantic_core_schema__\u001b[0;34m(cls, source, handler)\u001b[0m\n\u001b[1;32m 611\u001b[0m \u001b[38;5;129m@classmethod\u001b[39m\n\u001b[1;32m 612\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__pydantic_init_subclass__\u001b[39m(\u001b[38;5;28mcls\u001b[39m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs: Any) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 613\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"This is intended to behave just like `__init_subclass__`, but is called by `ModelMetaclass`\u001b[39;00m\n\u001b[1;32m 614\u001b[0m \u001b[38;5;124;03m only after the class is actually fully initialized. In particular, attributes like `model_fields` will\u001b[39;00m\n\u001b[1;32m 615\u001b[0m \u001b[38;5;124;03m be present when this is called.\u001b[39;00m\n\u001b[1;32m 616\u001b[0m \n\u001b[1;32m 617\u001b[0m \u001b[38;5;124;03m This is necessary because `__init_subclass__` will always be called by `type.__new__`,\u001b[39;00m\n\u001b[1;32m 618\u001b[0m \u001b[38;5;124;03m and it would require a prohibitively large refactor to the `ModelMetaclass` to ensure that\u001b[39;00m\n\u001b[1;32m 619\u001b[0m \u001b[38;5;124;03m `type.__new__` was called in such a manner that the class would already be sufficiently initialized.\u001b[39;00m\n\u001b[1;32m 620\u001b[0m \n\u001b[1;32m 621\u001b[0m \u001b[38;5;124;03m This will receive the same `kwargs` that would be passed to the standard `__init_subclass__`, namely,\u001b[39;00m\n\u001b[1;32m 622\u001b[0m \u001b[38;5;124;03m any kwargs passed to the class definition that aren't used internally by pydantic.\u001b[39;00m\n\u001b[1;32m 623\u001b[0m \n\u001b[1;32m 624\u001b[0m \u001b[38;5;124;03m Args:\u001b[39;00m\n\u001b[1;32m 625\u001b[0m \u001b[38;5;124;03m **kwargs: Any keyword arguments passed to the class definition that aren't used internally\u001b[39;00m\n\u001b[0;32m--> 626\u001b[0m \u001b[38;5;124;03m by pydantic.\u001b[39;00m\n\u001b[1;32m 627\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[1;32m 628\u001b[0m \u001b[38;5;28;01mpass\u001b[39;00m\n",
|
||||
"File \u001b[0;32m~/job/zep-proprietary/venv/lib/python3.11/site-packages/pydantic/_internal/_schema_generation_shared.py:82\u001b[0m, in \u001b[0;36mCallbackGetCoreSchemaHandler.__call__\u001b[0;34m(self, source_type)\u001b[0m\n\u001b[1;32m 81\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__call__\u001b[39m(\u001b[38;5;28mself\u001b[39m, __source_type: Any) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m core_schema\u001b[38;5;241m.\u001b[39mCoreSchema:\n\u001b[0;32m---> 82\u001b[0m schema \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_handler(__source_type)\n\u001b[1;32m 83\u001b[0m ref \u001b[38;5;241m=\u001b[39m schema\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mref\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 84\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_ref_mode \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mto-def\u001b[39m\u001b[38;5;124m'\u001b[39m:\n",
|
||||
"File \u001b[0;32m~/job/zep-proprietary/venv/lib/python3.11/site-packages/pydantic/_internal/_generate_schema.py:502\u001b[0m, in \u001b[0;36mgenerate_schema\u001b[0;34m(self, obj, from_dunder_get_core_schema)\u001b[0m\n\u001b[1;32m 498\u001b[0m schema \u001b[38;5;241m=\u001b[39m _add_custom_serialization_from_json_encoders(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_config_wrapper\u001b[38;5;241m.\u001b[39mjson_encoders, obj, schema)\n\u001b[1;32m 500\u001b[0m schema \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_post_process_generated_schema(schema)\n\u001b[0;32m--> 502\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m schema\n",
|
||||
"File \u001b[0;32m~/job/zep-proprietary/venv/lib/python3.11/site-packages/pydantic/_internal/_generate_schema.py:753\u001b[0m, in \u001b[0;36m_generate_schema_inner\u001b[0;34m(self, obj)\u001b[0m\n\u001b[1;32m 749\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mmatch_type\u001b[39m(\u001b[38;5;28mself\u001b[39m, obj: Any) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m core_schema\u001b[38;5;241m.\u001b[39mCoreSchema: \u001b[38;5;66;03m# noqa: C901\u001b[39;00m\n\u001b[1;32m 750\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Main mapping of types to schemas.\u001b[39;00m\n\u001b[1;32m 751\u001b[0m \n\u001b[1;32m 752\u001b[0m \u001b[38;5;124;03m The general structure is a series of if statements starting with the simple cases\u001b[39;00m\n\u001b[0;32m--> 753\u001b[0m \u001b[38;5;124;03m (non-generic primitive types) and then handling generics and other more complex cases.\u001b[39;00m\n\u001b[1;32m 754\u001b[0m \n\u001b[1;32m 755\u001b[0m \u001b[38;5;124;03m Each case either generates a schema directly, calls into a public user-overridable method\u001b[39;00m\n\u001b[1;32m 756\u001b[0m \u001b[38;5;124;03m (like `GenerateSchema.tuple_variable_schema`) or calls into a private method that handles some\u001b[39;00m\n\u001b[1;32m 757\u001b[0m \u001b[38;5;124;03m boilerplate before calling into the user-facing method (e.g. `GenerateSchema._tuple_schema`).\u001b[39;00m\n\u001b[1;32m 758\u001b[0m \n\u001b[1;32m 759\u001b[0m \u001b[38;5;124;03m The idea is that we'll evolve this into adding more and more user facing methods over time\u001b[39;00m\n\u001b[1;32m 760\u001b[0m \u001b[38;5;124;03m as they get requested and we figure out what the right API for them is.\u001b[39;00m\n\u001b[1;32m 761\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[1;32m 762\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m obj \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28mstr\u001b[39m:\n\u001b[1;32m 763\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mstr_schema()\n",
|
||||
"File \u001b[0;32m~/job/zep-proprietary/venv/lib/python3.11/site-packages/pydantic/_internal/_generate_schema.py:580\u001b[0m, in \u001b[0;36m_model_schema\u001b[0;34m(self, cls)\u001b[0m\n\u001b[1;32m 574\u001b[0m inner_schema \u001b[38;5;241m=\u001b[39m new_inner_schema\n\u001b[1;32m 575\u001b[0m inner_schema \u001b[38;5;241m=\u001b[39m apply_model_validators(inner_schema, model_validators, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124minner\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 577\u001b[0m model_schema \u001b[38;5;241m=\u001b[39m core_schema\u001b[38;5;241m.\u001b[39mmodel_schema(\n\u001b[1;32m 578\u001b[0m \u001b[38;5;28mcls\u001b[39m,\n\u001b[1;32m 579\u001b[0m inner_schema,\n\u001b[0;32m--> 580\u001b[0m custom_init\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mgetattr\u001b[39m(\u001b[38;5;28mcls\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m__pydantic_custom_init__\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m),\n\u001b[1;32m 581\u001b[0m root_model\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m,\n\u001b[1;32m 582\u001b[0m post_init\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mgetattr\u001b[39m(\u001b[38;5;28mcls\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m__pydantic_post_init__\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m),\n\u001b[1;32m 583\u001b[0m config\u001b[38;5;241m=\u001b[39mcore_config,\n\u001b[1;32m 584\u001b[0m ref\u001b[38;5;241m=\u001b[39mmodel_ref,\n\u001b[1;32m 585\u001b[0m metadata\u001b[38;5;241m=\u001b[39mmetadata,\n\u001b[1;32m 586\u001b[0m )\n\u001b[1;32m 588\u001b[0m schema \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_apply_model_serializers(model_schema, decorators\u001b[38;5;241m.\u001b[39mmodel_serializers\u001b[38;5;241m.\u001b[39mvalues())\n\u001b[1;32m 589\u001b[0m schema \u001b[38;5;241m=\u001b[39m apply_model_validators(schema, model_validators, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mouter\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
|
||||
"File \u001b[0;32m~/job/zep-proprietary/venv/lib/python3.11/site-packages/pydantic/_internal/_generate_schema.py:580\u001b[0m, in \u001b[0;36m<dictcomp>\u001b[0;34m(.0)\u001b[0m\n\u001b[1;32m 574\u001b[0m inner_schema \u001b[38;5;241m=\u001b[39m new_inner_schema\n\u001b[1;32m 575\u001b[0m inner_schema \u001b[38;5;241m=\u001b[39m apply_model_validators(inner_schema, model_validators, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124minner\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 577\u001b[0m model_schema \u001b[38;5;241m=\u001b[39m core_schema\u001b[38;5;241m.\u001b[39mmodel_schema(\n\u001b[1;32m 578\u001b[0m \u001b[38;5;28mcls\u001b[39m,\n\u001b[1;32m 579\u001b[0m inner_schema,\n\u001b[0;32m--> 580\u001b[0m custom_init\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mgetattr\u001b[39m(\u001b[38;5;28mcls\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m__pydantic_custom_init__\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m),\n\u001b[1;32m 581\u001b[0m root_model\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m,\n\u001b[1;32m 582\u001b[0m post_init\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mgetattr\u001b[39m(\u001b[38;5;28mcls\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m__pydantic_post_init__\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28;01mNone\u001b[39;00m),\n\u001b[1;32m 583\u001b[0m config\u001b[38;5;241m=\u001b[39mcore_config,\n\u001b[1;32m 584\u001b[0m ref\u001b[38;5;241m=\u001b[39mmodel_ref,\n\u001b[1;32m 585\u001b[0m metadata\u001b[38;5;241m=\u001b[39mmetadata,\n\u001b[1;32m 586\u001b[0m )\n\u001b[1;32m 588\u001b[0m schema \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_apply_model_serializers(model_schema, decorators\u001b[38;5;241m.\u001b[39mmodel_serializers\u001b[38;5;241m.\u001b[39mvalues())\n\u001b[1;32m 589\u001b[0m schema \u001b[38;5;241m=\u001b[39m apply_model_validators(schema, model_validators, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mouter\u001b[39m\u001b[38;5;124m'\u001b[39m)\n",
|
||||
"File \u001b[0;32m~/job/zep-proprietary/venv/lib/python3.11/site-packages/pydantic/_internal/_generate_schema.py:916\u001b[0m, in \u001b[0;36m_generate_md_field_schema\u001b[0;34m(self, name, field_info, decorators)\u001b[0m\n\u001b[1;32m 906\u001b[0m common_field \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_common_field_schema(name, field_info, decorators)\n\u001b[1;32m 907\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m core_schema\u001b[38;5;241m.\u001b[39mmodel_field(\n\u001b[1;32m 908\u001b[0m common_field[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mschema\u001b[39m\u001b[38;5;124m'\u001b[39m],\n\u001b[1;32m 909\u001b[0m serialization_exclude\u001b[38;5;241m=\u001b[39mcommon_field[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mserialization_exclude\u001b[39m\u001b[38;5;124m'\u001b[39m],\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 913\u001b[0m metadata\u001b[38;5;241m=\u001b[39mcommon_field[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mmetadata\u001b[39m\u001b[38;5;124m'\u001b[39m],\n\u001b[1;32m 914\u001b[0m )\n\u001b[0;32m--> 916\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_generate_dc_field_schema\u001b[39m(\n\u001b[1;32m 917\u001b[0m \u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 918\u001b[0m name: \u001b[38;5;28mstr\u001b[39m,\n\u001b[1;32m 919\u001b[0m field_info: FieldInfo,\n\u001b[1;32m 920\u001b[0m decorators: DecoratorInfos,\n\u001b[1;32m 921\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m core_schema\u001b[38;5;241m.\u001b[39mDataclassField:\n\u001b[1;32m 922\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Prepare a DataclassField to represent the parameter/field, of a dataclass.\"\"\"\u001b[39;00m\n\u001b[1;32m 923\u001b[0m common_field \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_common_field_schema(name, field_info, decorators)\n",
|
||||
"File \u001b[0;32m~/job/zep-proprietary/venv/lib/python3.11/site-packages/pydantic/_internal/_generate_schema.py:1114\u001b[0m, in \u001b[0;36m_common_field_schema\u001b[0;34m(self, name, field_info, decorators)\u001b[0m\n\u001b[1;32m 1108\u001b[0m json_schema_extra \u001b[38;5;241m=\u001b[39m field_info\u001b[38;5;241m.\u001b[39mjson_schema_extra\n\u001b[1;32m 1110\u001b[0m metadata \u001b[38;5;241m=\u001b[39m build_metadata_dict(\n\u001b[1;32m 1111\u001b[0m js_annotation_functions\u001b[38;5;241m=\u001b[39m[get_json_schema_update_func(json_schema_updates, json_schema_extra)]\n\u001b[1;32m 1112\u001b[0m )\n\u001b[0;32m-> 1114\u001b[0m alias_generator \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_config_wrapper\u001b[38;5;241m.\u001b[39malias_generator\n\u001b[1;32m 1115\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m alias_generator \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 1116\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_apply_alias_generator_to_field_info(alias_generator, field_info, name)\n",
|
||||
"\u001b[0;31mAttributeError\u001b[0m: 'FieldInfo' object has no attribute 'deprecated'"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from uuid import uuid4\n",
|
||||
"\n",
|
||||
"from langchain.agents import AgentType, Tool, initialize_agent\n",
|
||||
"from langchain_community.memory.zep_cloud_memory import ZepCloudMemory\n",
|
||||
"from langchain_community.retrievers import ZepCloudRetriever\n",
|
||||
"from langchain_community.utilities import WikipediaAPIWrapper\n",
|
||||
"from langchain_core.messages import AIMessage, HumanMessage\n",
|
||||
"from langchain_openai import OpenAI\n",
|
||||
"\n",
|
||||
"session_id = str(uuid4()) # This is a unique identifier for the session"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Provide your OpenAI key\n",
|
||||
"import getpass\n",
|
||||
"\n",
|
||||
"openai_key = getpass.getpass()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Provide your Zep API key. See https://help.getzep.com/projects#api-keys\n",
|
||||
"\n",
|
||||
"zep_api_key = getpass.getpass()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Initialize the Zep Chat Message History Class and initialize the Agent\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"search = WikipediaAPIWrapper()\n",
|
||||
"tools = [\n",
|
||||
" Tool(\n",
|
||||
" name=\"Search\",\n",
|
||||
" func=search.run,\n",
|
||||
" description=(\n",
|
||||
" \"useful for when you need to search online for answers. You should ask\"\n",
|
||||
" \" targeted questions\"\n",
|
||||
" ),\n",
|
||||
" ),\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"# Set up Zep Chat History\n",
|
||||
"memory = ZepCloudMemory(\n",
|
||||
" session_id=session_id,\n",
|
||||
" api_key=zep_api_key,\n",
|
||||
" return_messages=True,\n",
|
||||
" memory_key=\"chat_history\",\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"# Initialize the agent\n",
|
||||
"llm = OpenAI(temperature=0, openai_api_key=openai_key)\n",
|
||||
"agent_chain = initialize_agent(\n",
|
||||
" tools,\n",
|
||||
" llm,\n",
|
||||
" agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION,\n",
|
||||
" verbose=True,\n",
|
||||
" memory=memory,\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Add some history data\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Preload some messages into the memory. The default message window is 12 messages. We want to push beyond this to demonstrate auto-summarization.\n",
|
||||
"test_history = [\n",
|
||||
" {\"role\": \"human\", \"content\": \"Who was Octavia Butler?\"},\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"Octavia Estelle Butler (June 22, 1947 – February 24, 2006) was an American\"\n",
|
||||
" \" science fiction author.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\"role\": \"human\", \"content\": \"Which books of hers were made into movies?\"},\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"The most well-known adaptation of Octavia Butler's work is the FX series\"\n",
|
||||
" \" Kindred, based on her novel of the same name.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\"role\": \"human\", \"content\": \"Who were her contemporaries?\"},\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"Octavia Butler's contemporaries included Ursula K. Le Guin, Samuel R.\"\n",
|
||||
" \" Delany, and Joanna Russ.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\"role\": \"human\", \"content\": \"What awards did she win?\"},\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"Octavia Butler won the Hugo Award, the Nebula Award, and the MacArthur\"\n",
|
||||
" \" Fellowship.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"human\",\n",
|
||||
" \"content\": \"Which other women sci-fi writers might I want to read?\",\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"content\": \"You might want to read Ursula K. Le Guin or Joanna Russ.\",\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"human\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"Write a short synopsis of Butler's book, Parable of the Sower. What is it\"\n",
|
||||
" \" about?\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"Parable of the Sower is a science fiction novel by Octavia Butler,\"\n",
|
||||
" \" published in 1993. It follows the story of Lauren Olamina, a young woman\"\n",
|
||||
" \" 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",
|
||||
" memory.chat_memory.add_message(\n",
|
||||
" (\n",
|
||||
" HumanMessage(content=msg[\"content\"])\n",
|
||||
" if msg[\"role\"] == \"human\"\n",
|
||||
" else AIMessage(content=msg[\"content\"])\n",
|
||||
" ),\n",
|
||||
" metadata=msg.get(\"metadata\", {}),\n",
|
||||
" )"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Run the agent\n",
|
||||
"\n",
|
||||
"Doing so will automatically add the input and response to the Zep memory.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-05-10T14:34:37.613049Z",
|
||||
"start_time": "2024-05-10T14:34:35.883359Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\n",
|
||||
"\n",
|
||||
"\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
|
||||
"\u001b[32;1m\u001b[1;3m\n",
|
||||
"AI: Parable of the Sower is highly relevant to contemporary society as it explores themes of environmental degradation, social and economic inequality, and the struggle for survival in a chaotic world. It also delves into issues of race, gender, and religion, making it a thought-provoking and timely read.\u001b[0m\n",
|
||||
"\n",
|
||||
"\u001b[1m> Finished chain.\u001b[0m\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'input': \"What is the book's relevance to the challenges facing contemporary society?\",\n",
|
||||
" 'chat_history': [HumanMessage(content=\"Octavia Butler's contemporaries included Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ.\\nOctavia Butler won the Hugo Award, the Nebula Award, and the MacArthur Fellowship.\\nUrsula K. Le Guin is known for novels like The Left Hand of Darkness and The Dispossessed.\\nJoanna Russ is the author of the influential feminist science fiction novel The Female Man.\\nMargaret Atwood is known for works like The Handmaid's Tale and the MaddAddam trilogy.\\nConnie Willis is an award-winning author of science fiction and fantasy, known for novels like Doomsday Book.\\nOctavia Butler is a pioneering black female science fiction author, known for Kindred and the Parable series.\\nOctavia Estelle Butler was an acclaimed American science fiction author. While none of her books were directly adapted into movies, her novel Kindred was adapted into a TV series on FX. Butler was part of a generation of prominent science fiction writers in the 20th century, including contemporaries such as Ursula K. Le Guin, Samuel R. Delany, Chip Delany, and Nalo Hopkinson.\\nhuman: What awards did she win?\\nai: Octavia Butler won the Hugo Award, the Nebula Award, and the MacArthur Fellowship.\\nhuman: Which other women sci-fi writers might I want to read?\\nai: You might want to read Ursula K. Le Guin or Joanna Russ.\\nhuman: Write a short synopsis of Butler's book, Parable of the Sower. What is it about?\\nai: 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.\")],\n",
|
||||
" 'output': 'Parable of the Sower is highly relevant to contemporary society as it explores themes of environmental degradation, social and economic inequality, and the struggle for survival in a chaotic world. It also delves into issues of race, gender, and religion, making it a thought-provoking and timely read.'}"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"agent_chain.invoke(\n",
|
||||
" input=\"What is the book's relevance to the challenges facing contemporary society?\",\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Inspect the Zep memory\n",
|
||||
"\n",
|
||||
"Note the summary, and that the history has been enriched with token counts, UUIDs, and timestamps.\n",
|
||||
"\n",
|
||||
"Summaries are biased towards the most recent messages.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-05-10T14:35:11.437446Z",
|
||||
"start_time": "2024-05-10T14:35:10.664076Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Octavia Estelle Butler was an acclaimed American science fiction author. While none of her books were directly adapted into movies, her novel Kindred was adapted into a TV series on FX. Butler was part of a generation of prominent science fiction writers in the 20th century, including contemporaries such as Ursula K. Le Guin, Samuel R. Delany, Chip Delany, and Nalo Hopkinson.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"Conversation Facts: \n",
|
||||
"Octavia Butler's contemporaries included Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ.\n",
|
||||
"\n",
|
||||
"Octavia Butler won the Hugo Award, the Nebula Award, and the MacArthur Fellowship.\n",
|
||||
"\n",
|
||||
"Ursula K. Le Guin is known for novels like The Left Hand of Darkness and The Dispossessed.\n",
|
||||
"\n",
|
||||
"Joanna Russ is the author of the influential feminist science fiction novel The Female Man.\n",
|
||||
"\n",
|
||||
"Margaret Atwood is known for works like The Handmaid's Tale and the MaddAddam trilogy.\n",
|
||||
"\n",
|
||||
"Connie Willis is an award-winning author of science fiction and fantasy, known for novels like Doomsday Book.\n",
|
||||
"\n",
|
||||
"Octavia Butler is a pioneering black female science fiction author, known for Kindred and the Parable series.\n",
|
||||
"\n",
|
||||
"Parable of the Sower is a science fiction novel by Octavia Butler, published in 1993.\n",
|
||||
"\n",
|
||||
"The novel 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.\n",
|
||||
"\n",
|
||||
"Parable of the Sower explores themes of environmental degradation, social and economic inequality, and the struggle for survival in a chaotic world.\n",
|
||||
"\n",
|
||||
"The novel also delves into issues of race, gender, and religion, making it a thought-provoking and timely read.\n",
|
||||
"\n",
|
||||
"human :\n",
|
||||
" {'content': \"Octavia Butler's contemporaries included Ursula K. Le Guin, Samuel R. Delany, and Joanna Russ.\\nOctavia Butler won the Hugo Award, the Nebula Award, and the MacArthur Fellowship.\\nUrsula K. Le Guin is known for novels like The Left Hand of Darkness and The Dispossessed.\\nJoanna Russ is the author of the influential feminist science fiction novel The Female Man.\\nMargaret Atwood is known for works like The Handmaid's Tale and the MaddAddam trilogy.\\nConnie Willis is an award-winning author of science fiction and fantasy, known for novels like Doomsday Book.\\nOctavia Butler is a pioneering black female science fiction author, known for Kindred and the Parable series.\\nParable of the Sower is a science fiction novel by Octavia Butler, published in 1993.\\nThe novel 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.\\nParable of the Sower explores themes of environmental degradation, social and economic inequality, and the struggle for survival in a chaotic world.\\nThe novel also delves into issues of race, gender, and religion, making it a thought-provoking and timely read.\\nOctavia Estelle Butler was an acclaimed American science fiction author. While none of her books were directly adapted into movies, her novel Kindred was adapted into a TV series on FX. Butler was part of a generation of prominent science fiction writers in the 20th century, including contemporaries such as Ursula K. Le Guin, Samuel R. Delany, Chip Delany, and Nalo Hopkinson.\\nhuman: Which other women sci-fi writers might I want to read?\\nai: You might want to read Ursula K. Le Guin or Joanna Russ.\\nhuman: Write a short synopsis of Butler's book, Parable of the Sower. What is it about?\\nai: 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.\\nhuman: What is the book's relevance to the challenges facing contemporary society?\\nai: Parable of the Sower is highly relevant to contemporary society as it explores themes of environmental degradation, social and economic inequality, and the struggle for survival in a chaotic world. It also delves into issues of race, gender, and religion, making it a thought-provoking and timely read.\", 'additional_kwargs': {}, 'response_metadata': {}, 'type': 'human', 'name': None, 'id': None, 'example': False}\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"def print_messages(messages):\n",
|
||||
" for m in messages:\n",
|
||||
" print(m.type, \":\\n\", m.dict())\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"print(memory.chat_memory.zep_summary)\n",
|
||||
"print(\"\\n\")\n",
|
||||
"print(\"Conversation Facts: \")\n",
|
||||
"facts = memory.chat_memory.zep_facts\n",
|
||||
"for fact in facts:\n",
|
||||
" print(fact + \"\\n\")\n",
|
||||
"print_messages(memory.chat_memory.messages)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Vector search over the Zep memory\n",
|
||||
"\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": 9,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-05-10T14:35:33.023765Z",
|
||||
"start_time": "2024-05-10T14:35:32.613576Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"content='Which other women sci-fi writers might I want to read?' created_at='2024-05-10T14:34:16.714292Z' metadata=None role='human' role_type=None token_count=12 updated_at='0001-01-01T00:00:00Z' uuid_='64ca1fae-8db1-4b4f-8a45-9b0e57e88af5' 0.8960460126399994\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"retriever = ZepCloudRetriever(\n",
|
||||
" session_id=session_id,\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",
|
||||
" if r.score > 0.8: # Only print results with similarity of 0.8 or higher\n",
|
||||
" print(r.message, r.score)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.12"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
@ -28,38 +28,68 @@ In addition to Zep Open Source's memory management features, Zep Cloud offers:
|
||||
- **Dialog Classification**: Instantly and accurately classify chat dialog. Understand user intent and emotion, segment users, and more. Route chains based on semantic context, and trigger events.
|
||||
- **Structured Data Extraction**: Quickly extract business data from chat conversations using a schema you define. Understand what your Assistant should ask for next in order to complete its task.
|
||||
|
||||
> Interested in Zep Cloud? See [Zep Cloud Installation Guide](https://help.getzep.com/sdks), [Zep Cloud Message History Example](https://help.getzep.com/langchain/examples/messagehistory-example), [Zep Cloud Vector Store Example](https://help.getzep.com/langchain/examples/vectorstore-example)
|
||||
|
||||
## Open Source Installation and Setup
|
||||
|
||||
> Zep Open Source project: [https://github.com/getzep/zep](https://github.com/getzep/zep)
|
||||
>
|
||||
> Zep Open Source Docs: [https://docs.getzep.com/](https://docs.getzep.com/)
|
||||
## Zep Open Source
|
||||
Zep offers an open source version with a self-hosted option.
|
||||
Please refer to the [Zep Open Source](https://github.com/getzep/zep) repo for more information.
|
||||
You can also find Zep Open Source compatible [Retriever](/docs/integrations/retrievers/zep_memorystore), [Vector Store](/docs/integrations/vectorstores/zep) and [Memory](/docs/integrations/memory/zep_memory) examples
|
||||
|
||||
1. Install the Zep service. See the [Zep Quick Start Guide](https://docs.getzep.com/deployment/quickstart/).
|
||||
## Zep Cloud Installation and Setup
|
||||
|
||||
2. Install the Zep Python SDK:
|
||||
[Zep Cloud Docs](https://help.getzep.com)
|
||||
|
||||
1. Install the Zep Cloud SDK:
|
||||
|
||||
```bash
|
||||
pip install zep_python
|
||||
pip install zep_cloud
|
||||
```
|
||||
or
|
||||
```bash
|
||||
poetry add zep_cloud
|
||||
```
|
||||
|
||||
## Memory
|
||||
|
||||
Zep's [Memory API](https://docs.getzep.com/sdk/chat_history/) persists your app's chat history and metadata to a Session, enriches the memory, automatically generates summaries, and enables vector similarity search over historical chat messages and summaries.
|
||||
Zep's Memory API persists your users' chat history and metadata to a [Session](https://help.getzep.com/chat-history-memory/sessions), enriches the memory, and
|
||||
enables vector similarity search over historical chat messages and dialog summaries.
|
||||
|
||||
There are two approaches to populating your prompt with chat history:
|
||||
Zep offers several approaches to populating prompts with context from historical conversations.
|
||||
|
||||
1. Retrieve the most recent N messages (and potentionally a summary) from a Session and use them to construct your prompt.
|
||||
2. Search over the Session's chat history for messages that are relevant and use them to construct your prompt.
|
||||
### Perpetual Memory
|
||||
This is the default memory type.
|
||||
Salient facts from the dialog are extracted and stored in a Fact Table.
|
||||
This is updated in real-time as new messages are added to the Session.
|
||||
Every time you call the Memory API to get a Memory, Zep returns the Fact Table, the most recent messages (per your Message Window setting), and a summary of the most recent messages prior to the Message Window.
|
||||
The combination of the Fact Table, summary, and the most recent messages in a prompts provides both factual context and nuance to the LLM.
|
||||
|
||||
Both of these approaches may be useful, with the first providing the LLM with context as to the most recent interactions with a human. The second approach enables you to look back further in the chat history and retrieve messages that are relevant to the current conversation in a token-efficient manner.
|
||||
### Summary Retriever Memory
|
||||
Returns the most recent messages and a summary of past messages relevant to the current conversation,
|
||||
enabling you to provide your Assistant with helpful context from past conversations
|
||||
|
||||
### Message Window Buffer Memory
|
||||
Returns the most recent N messages from the current conversation.
|
||||
|
||||
Additionally, Zep enables vector similarity searches for Messages or Summaries stored within its system.
|
||||
|
||||
This feature lets you populate prompts with past conversations that are contextually similar to a specific query,
|
||||
organizing the results by a similarity Score.
|
||||
|
||||
`ZepCloudChatMessageHistory` and `ZepCloudMemory` classes can be imported to interact with Zep Cloud APIs.
|
||||
|
||||
`ZepCloudChatMessageHistory` is compatible with `RunnableWithMessageHistory`.
|
||||
```python
|
||||
from langchain.memory import ZepMemory
|
||||
from langchain_community.chat_message_histories import ZepCloudChatMessageHistory
|
||||
```
|
||||
|
||||
See a [RAG App Example here](/docs/integrations/memory/zep_memory).
|
||||
See a [Perpetual Memory Example here](/docs/integrations/memory/zep_cloud_chat_message_history).
|
||||
|
||||
You can use `ZepCloudMemory` together with agents that support Memory.
|
||||
```python
|
||||
from langchain.memory import ZepCloudMemory
|
||||
```
|
||||
|
||||
See a [Memory RAG Example here](/docs/integrations/memory/zep_memory_cloud).
|
||||
|
||||
## Retriever
|
||||
|
||||
@ -67,24 +97,24 @@ Zep's Memory Retriever is a LangChain Retriever that enables you to retrieve mes
|
||||
|
||||
The Retriever supports searching over both individual messages and summaries of conversations. The latter is useful for providing rich, but succinct context to the LLM as to relevant past conversations.
|
||||
|
||||
Zep's Memory Retriever supports both similarity search and [Maximum Marginal Relevance (MMR) reranking](https://docs.getzep.com/sdk/search_query/). MMR search is useful for ensuring that the retrieved messages are diverse and not too similar to each other
|
||||
Zep's Memory Retriever supports both similarity search and [Maximum Marginal Relevance (MMR) reranking](https://help.getzep.com/working-with-search#how-zeps-mmr-re-ranking-works). MMR search is useful for ensuring that the retrieved messages are diverse and not too similar to each other
|
||||
|
||||
See a [usage example](/docs/integrations/retrievers/zep_memorystore).
|
||||
See a [usage example](/docs/integrations/retrievers/zep_cloud_memorystore).
|
||||
|
||||
```python
|
||||
from langchain_community.retrievers import ZepRetriever
|
||||
from langchain_community.retrievers import ZepCloudRetriever
|
||||
```
|
||||
|
||||
## Vector store
|
||||
|
||||
Zep's [Document VectorStore API](https://docs.getzep.com/sdk/documents/) enables you to store and retrieve documents using vector similarity search. Zep doesn't require you to understand
|
||||
Zep's [Document VectorStore API](https://help.getzep.com/document-collections) enables you to store and retrieve documents using vector similarity search. Zep doesn't require you to understand
|
||||
distance functions, types of embeddings, or indexing best practices. You just pass in your chunked documents, and Zep handles the rest.
|
||||
|
||||
Zep supports both similarity search and [Maximum Marginal Relevance (MMR) reranking](https://docs.getzep.com/sdk/search_query/).
|
||||
Zep supports both similarity search and [Maximum Marginal Relevance (MMR) reranking](https://help.getzep.com/working-with-search#how-zeps-mmr-re-ranking-works).
|
||||
MMR search is useful for ensuring that the retrieved documents are diverse and not too similar to each other.
|
||||
|
||||
```python
|
||||
from langchain_community.vectorstores import ZepVectorStore
|
||||
from langchain_community.vectorstores import ZepCloudVectorStore
|
||||
```
|
||||
|
||||
See a [usage example](/docs/integrations/vectorstores/zep).
|
||||
See a [usage example](/docs/integrations/vectorstores/zep_cloud).
|
470
docs/docs/integrations/retrievers/zep_cloud_memorystore.ipynb
Normal file
470
docs/docs/integrations/retrievers/zep_cloud_memorystore.ipynb
Normal file
@ -0,0 +1,470 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"source": [
|
||||
"# Zep Cloud\n",
|
||||
"## Retriever Example for [Zep Cloud](https://docs.getzep.com/)\n",
|
||||
"\n",
|
||||
"> Recall, understand, and extract data from chat histories. Power personalized AI experiences.\n",
|
||||
"\n",
|
||||
"> [Zep](https://www.getzep.com) is a long-term memory service for AI Assistant apps.\n",
|
||||
"> With Zep, you can provide AI assistants with the ability to recall past conversations, no matter how distant,\n",
|
||||
"> while also reducing hallucinations, latency, and cost.\n",
|
||||
"\n",
|
||||
"> See [Zep Cloud Installation Guide](https://help.getzep.com/sdks) and more [Zep Cloud Langchain Examples](https://github.com/getzep/zep-python/tree/main/examples)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Retriever Example\n",
|
||||
"\n",
|
||||
"This notebook demonstrates how to search historical chat message histories using the [Zep Long-term Memory Store](https://www.getzep.com/).\n",
|
||||
"\n",
|
||||
"We'll demonstrate:\n",
|
||||
"\n",
|
||||
"1. Adding conversation history to the Zep memory store.\n",
|
||||
"2. Vector search over the conversation history: \n",
|
||||
" 1. With a similarity search over chat messages\n",
|
||||
" 2. Using maximal marginal relevance re-ranking of a chat message search\n",
|
||||
" 3. Filtering a search using metadata filters\n",
|
||||
" 4. A similarity search over summaries of the chat messages\n",
|
||||
" 5. Using maximal marginal relevance re-ranking of a summary search\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import getpass\n",
|
||||
"import time\n",
|
||||
"from uuid import uuid4\n",
|
||||
"\n",
|
||||
"from langchain_community.memory.zep_cloud_memory import ZepCloudMemory\n",
|
||||
"from langchain_community.retrievers import ZepCloudRetriever\n",
|
||||
"from langchain_core.messages import AIMessage, HumanMessage\n",
|
||||
"\n",
|
||||
"# Provide your Zep API key.\n",
|
||||
"zep_api_key = getpass.getpass()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Initialize the Zep Chat Message History Class and add a chat message history to the memory store\n",
|
||||
"\n",
|
||||
"**NOTE:** Unlike other Retrievers, the content returned by the Zep Retriever is session/user specific. A `session_id` is required when instantiating the Retriever."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"session_id = str(uuid4()) # This is a unique identifier for the user/session\n",
|
||||
"\n",
|
||||
"# Initialize the Zep Memory Class\n",
|
||||
"zep_memory = ZepCloudMemory(session_id=session_id, api_key=zep_api_key)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Preload some messages into the memory. The default message window is 4 messages. We want to push beyond this to demonstrate auto-summarization.\n",
|
||||
"test_history = [\n",
|
||||
" {\"role\": \"human\", \"role_type\": \"user\", \"content\": \"Who was Octavia Butler?\"},\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"role_type\": \"assistant\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"Octavia Estelle Butler (June 22, 1947 – February 24, 2006) was an American\"\n",
|
||||
" \" science fiction author.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"human\",\n",
|
||||
" \"role_type\": \"user\",\n",
|
||||
" \"content\": \"Which books of hers were made into movies?\",\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"role_type\": \"assistant\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"The most well-known adaptation of Octavia Butler's work is the FX series\"\n",
|
||||
" \" Kindred, based on her novel of the same name.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\"role\": \"human\", \"role_type\": \"user\", \"content\": \"Who were her contemporaries?\"},\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"role_type\": \"assistant\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"Octavia Butler's contemporaries included Ursula K. Le Guin, Samuel R.\"\n",
|
||||
" \" Delany, and Joanna Russ.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\"role\": \"human\", \"role_type\": \"user\", \"content\": \"What awards did she win?\"},\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"role_type\": \"assistant\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"Octavia Butler won the Hugo Award, the Nebula Award, and the MacArthur\"\n",
|
||||
" \" Fellowship.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"human\",\n",
|
||||
" \"role_type\": \"user\",\n",
|
||||
" \"content\": \"Which other women sci-fi writers might I want to read?\",\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"role_type\": \"assistant\",\n",
|
||||
" \"content\": \"You might want to read Ursula K. Le Guin or Joanna Russ.\",\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"human\",\n",
|
||||
" \"role_type\": \"user\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"Write a short synopsis of Butler's book, Parable of the Sower. What is it\"\n",
|
||||
" \" about?\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"role_type\": \"assistant\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"Parable of the Sower is a science fiction novel by Octavia Butler,\"\n",
|
||||
" \" published in 1993. It follows the story of Lauren Olamina, a young woman\"\n",
|
||||
" \" living in a dystopian future where society has collapsed due to\"\n",
|
||||
" \" environmental disasters, poverty, and violence.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"human\",\n",
|
||||
" \"role_type\": \"user\",\n",
|
||||
" \"content\": \"What is the setting of the book?\",\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"role_type\": \"assistant\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"The book is set in a dystopian future in the 2020s, where society has\"\n",
|
||||
" \" collapsed due to climate change and economic crises.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\"role\": \"human\", \"role_type\": \"user\", \"content\": \"Who is the protagonist?\"},\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"role_type\": \"assistant\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"The protagonist of the book is Lauren Olamina, a young woman who possesses\"\n",
|
||||
" \" 'hyperempathy', the ability to feel pain and other sensations she\"\n",
|
||||
" \" witnesses.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"human\",\n",
|
||||
" \"role_type\": \"user\",\n",
|
||||
" \"content\": \"What is the main theme of the book?\",\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"role_type\": \"assistant\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"The main theme of the book is survival in the face of drastic societal\"\n",
|
||||
" \" change and collapse. It also explores themes of adaptability, community,\"\n",
|
||||
" \" and the human capacity for change.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"human\",\n",
|
||||
" \"role_type\": \"user\",\n",
|
||||
" \"content\": \"What is the 'Parable of the Sower'?\",\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"role_type\": \"assistant\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"The 'Parable of the Sower' is a biblical parable that Butler uses as a\"\n",
|
||||
" \" metaphor in the book. In the parable, a sower scatters seeds, some of\"\n",
|
||||
" \" which fall on fertile ground and grow, while others fall on rocky ground\"\n",
|
||||
" \" or among thorns and fail to grow. The parable is used to illustrate the\"\n",
|
||||
" \" importance of receptivity and preparedness in the face of change.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"human\",\n",
|
||||
" \"role_type\": \"user\",\n",
|
||||
" \"content\": \"What is Butler's writing style like?\",\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"role_type\": \"assistant\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"Butler's writing style is known for its clarity, directness, and\"\n",
|
||||
" \" psychological insight. Her narratives often involve complex, diverse\"\n",
|
||||
" \" characters and explore themes of race, gender, and power.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"human\",\n",
|
||||
" \"role_type\": \"user\",\n",
|
||||
" \"content\": \"What other books has she written?\",\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"ai\",\n",
|
||||
" \"content\": (\n",
|
||||
" \"In addition to 'Parable of the Sower', Butler has written several other\"\n",
|
||||
" \" notable works, including 'Kindred', 'Dawn', and 'Parable of the Talents'.\"\n",
|
||||
" ),\n",
|
||||
" },\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"for msg in test_history:\n",
|
||||
" zep_memory.chat_memory.add_message(\n",
|
||||
" HumanMessage(content=msg[\"content\"])\n",
|
||||
" if msg[\"role\"] == \"human\"\n",
|
||||
" else AIMessage(content=msg[\"content\"])\n",
|
||||
" )\n",
|
||||
"\n",
|
||||
"time.sleep(\n",
|
||||
" 10\n",
|
||||
") # Wait for the messages to be embedded and summarized, this happens asynchronously."
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Use the Zep Retriever to vector search over the Zep memory\n",
|
||||
"\n",
|
||||
"Zep provides native vector search over historical conversation memory. Embedding happens automatically.\n",
|
||||
"\n",
|
||||
"NOTE: Embedding of messages occurs asynchronously, so the first query may not return results. Subsequent queries will return results as the embeddings are generated."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 8,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-05-10T14:32:06.613100Z",
|
||||
"start_time": "2024-05-10T14:32:06.369301Z"
|
||||
},
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[Document(page_content=\"What is the 'Parable of the Sower'?\", metadata={'score': 0.9333381652832031, 'uuid': 'bebc441c-a32d-44a1-ae61-968e7b3d4956', 'created_at': '2024-05-10T05:02:01.857627Z', 'token_count': 11, 'role': 'human'}),\n",
|
||||
" Document(page_content=\"The 'Parable of the Sower' is a biblical parable that Butler uses as a metaphor in the book. In the parable, a sower scatters seeds, some of which fall on fertile ground and grow, while others fall on rocky ground or among thorns and fail to grow. The parable is used to illustrate the importance of receptivity and preparedness in the face of change.\", metadata={'score': 0.8757256865501404, 'uuid': '193c60d8-2b7b-4eb1-a4be-c2d8afd92991', 'created_at': '2024-05-10T05:02:01.97174Z', 'token_count': 82, 'role': 'ai'}),\n",
|
||||
" Document(page_content=\"Write a short synopsis of Butler's book, Parable of the Sower. What is it about?\", metadata={'score': 0.8641344904899597, 'uuid': 'fc78901d-a625-4530-ba63-1ae3e3b11683', 'created_at': '2024-05-10T05:02:00.942994Z', 'token_count': 21, 'role': 'human'}),\n",
|
||||
" 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.8581685125827789, 'uuid': '91f2cda4-276e-446d-96bf-07d34e5af616', 'created_at': '2024-05-10T05:02:01.05577Z', 'token_count': 54, 'role': 'ai'}),\n",
|
||||
" Document(page_content=\"In addition to 'Parable of the Sower', Butler has written several other notable works, including 'Kindred', 'Dawn', and 'Parable of the Talents'.\", metadata={'score': 0.8076582252979279, 'uuid': 'e3994519-9a90-410c-b14c-2c652f6d184f', 'created_at': '2024-05-10T05:02:02.401682Z', 'token_count': 37, 'role': 'ai'})]"
|
||||
]
|
||||
},
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"zep_retriever = ZepCloudRetriever(\n",
|
||||
" api_key=zep_api_key,\n",
|
||||
" session_id=session_id, # Ensure that you provide the session_id when instantiating the Retriever\n",
|
||||
" top_k=5,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"await zep_retriever.ainvoke(\"Who wrote Parable of the Sower?\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"attachments": {},
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We can also use the Zep sync API to retrieve results:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-05-10T14:31:37.611570Z",
|
||||
"start_time": "2024-05-10T14:31:37.298903Z"
|
||||
},
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[Document(page_content='Parable of the Sower is a science fiction novel by Octavia Butler set in a dystopian future in the 2020s. The story follows Lauren Olamina, a young woman living in a society that has collapsed due to environmental disasters, poverty, and violence. The novel explores themes of societal breakdown, the struggle for survival, and the search for a better future.', metadata={'score': 0.8473024368286133, 'uuid': 'e4689f8e-33be-4a59-a9c2-e5ef5dd70f74', 'created_at': '2024-05-10T05:02:02.713123Z', 'token_count': 76})]"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"zep_retriever.invoke(\"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": null,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"zep_retriever = ZepCloudRetriever(\n",
|
||||
" api_key=zep_api_key,\n",
|
||||
" session_id=session_id, # Ensure that you provide the session_id when instantiating the Retriever\n",
|
||||
" top_k=5,\n",
|
||||
" search_type=\"mmr\",\n",
|
||||
" mmr_lambda=0.5,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"await zep_retriever.ainvoke(\"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://help.getzep.com/document-collections#searching-a-collection-with-hybrid-vector-search"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"filter = {\"where\": {\"jsonpath\": '$[*] ? (@.baz == \"qux\")'}}\n",
|
||||
"\n",
|
||||
"await zep_retriever.ainvoke(\n",
|
||||
" \"Who wrote Parable of the Sower?\", config={\"metadata\": filter}\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Searching over Summaries with MMR Reranking\n",
|
||||
"\n",
|
||||
"Zep automatically generates summaries of chat messages. These summaries can be searched over using the Zep Retriever. Since a summary is a distillation of a conversation, they're more likely to match your search query and offer rich, succinct context to the LLM.\n",
|
||||
"\n",
|
||||
"Successive summaries may include similar content, with Zep's similarity search returning the highest matching results but with little diversity.\n",
|
||||
"MMR re-ranks the results to ensure that the summaries you populate into your prompt are both relevant and each offers additional information to the LLM."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 9,
|
||||
"metadata": {
|
||||
"ExecuteTime": {
|
||||
"end_time": "2024-05-10T14:32:56.877960Z",
|
||||
"start_time": "2024-05-10T14:32:56.517360Z"
|
||||
}
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[Document(page_content='Parable of the Sower is a science fiction novel by Octavia Butler set in a dystopian future in the 2020s. The story follows Lauren Olamina, a young woman living in a society that has collapsed due to environmental disasters, poverty, and violence. The novel explores themes of societal breakdown, the struggle for survival, and the search for a better future.', metadata={'score': 0.8473024368286133, 'uuid': 'e4689f8e-33be-4a59-a9c2-e5ef5dd70f74', 'created_at': '2024-05-10T05:02:02.713123Z', 'token_count': 76}),\n",
|
||||
" Document(page_content='The \\'Parable of the Sower\\' refers to a new religious belief system that the protagonist, Lauren Olamina, develops over the course of the novel. As her community disintegrates due to climate change, economic collapse, and social unrest, Lauren comes to believe that humanity must adapt and \"shape God\" in order to survive. The \\'Parable of the Sower\\' is the foundational text of this new religion, which Lauren calls \"Earthseed\", that emphasizes the inevitability of change and the need for humanity to take an active role in shaping its own future. This parable is a central thematic element of the novel, representing the protagonist\\'s search for meaning and purpose in the face of societal upheaval.', metadata={'score': 0.8466987311840057, 'uuid': '1f1a44eb-ebd8-4617-ac14-0281099bd770', 'created_at': '2024-05-10T05:02:07.541073Z', 'token_count': 146}),\n",
|
||||
" Document(page_content='The dialog discusses the central themes of Octavia Butler\\'s acclaimed science fiction novel \"Parable of the Sower.\" The main theme is survival in the face of drastic societal collapse, and the importance of adaptability, community, and the human capacity for change. The \"Parable of the Sower,\" a biblical parable, serves as a metaphorical framework for the novel, illustrating the need for receptivity and preparedness when confronting transformative upheaval.', metadata={'score': 0.8283970355987549, 'uuid': '4158a750-3ccd-45ce-ab88-fed5ba68b755', 'created_at': '2024-05-10T05:02:06.510068Z', 'token_count': 91})]"
|
||||
]
|
||||
},
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"zep_retriever = ZepCloudRetriever(\n",
|
||||
" api_key=zep_api_key,\n",
|
||||
" session_id=session_id, # Ensure that you provide the session_id when instantiating the Retriever\n",
|
||||
" top_k=3,\n",
|
||||
" search_scope=\"summary\",\n",
|
||||
" search_type=\"mmr\",\n",
|
||||
" mmr_lambda=0.5,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"await zep_retriever.ainvoke(\"Who wrote Parable of the Sower?\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.12"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
"collapsed": false
|
||||
},
|
||||
"source": [
|
||||
"# Zep\n",
|
||||
"# Zep Open Source\n",
|
||||
"## Retriever Example for [Zep](https://docs.getzep.com/)\n",
|
||||
"\n",
|
||||
"> Recall, understand, and extract data from chat histories. Power personalized AI experiences.\n",
|
||||
|
484
docs/docs/integrations/vectorstores/zep_cloud.ipynb
Normal file
484
docs/docs/integrations/vectorstores/zep_cloud.ipynb
Normal file
File diff suppressed because one or more lines are too long
@ -82,6 +82,9 @@ if TYPE_CHECKING:
|
||||
from langchain_community.chat_message_histories.zep import (
|
||||
ZepChatMessageHistory,
|
||||
)
|
||||
from langchain_community.chat_message_histories.zep_cloud import (
|
||||
ZepCloudChatMessageHistory,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"AstraDBChatMessageHistory",
|
||||
@ -105,6 +108,7 @@ __all__ = [
|
||||
"UpstashRedisChatMessageHistory",
|
||||
"XataChatMessageHistory",
|
||||
"ZepChatMessageHistory",
|
||||
"ZepCloudChatMessageHistory",
|
||||
]
|
||||
|
||||
_module_lookup = {
|
||||
@ -129,6 +133,7 @@ _module_lookup = {
|
||||
"UpstashRedisChatMessageHistory": "langchain_community.chat_message_histories.upstash_redis", # noqa: E501
|
||||
"XataChatMessageHistory": "langchain_community.chat_message_histories.xata",
|
||||
"ZepChatMessageHistory": "langchain_community.chat_message_histories.zep",
|
||||
"ZepCloudChatMessageHistory": "langchain_community.chat_message_histories.zep_cloud", # noqa: E501
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,285 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence
|
||||
|
||||
from langchain_core.chat_history import BaseChatMessageHistory
|
||||
from langchain_core.messages import (
|
||||
AIMessage,
|
||||
BaseMessage,
|
||||
HumanMessage,
|
||||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from zep_cloud import (
|
||||
Memory,
|
||||
MemoryGetRequestMemoryType,
|
||||
MemorySearchResult,
|
||||
Message,
|
||||
NotFoundError,
|
||||
RoleType,
|
||||
SearchScope,
|
||||
SearchType,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def condense_zep_memory_into_human_message(zep_memory: Memory) -> BaseMessage:
|
||||
prompt = ""
|
||||
if zep_memory.facts:
|
||||
prompt = "\n".join(zep_memory.facts)
|
||||
if zep_memory.summary and zep_memory.summary.content:
|
||||
prompt += "\n" + zep_memory.summary.content
|
||||
for msg in zep_memory.messages or []:
|
||||
prompt += f"\n{msg.role or msg.role_type}: {msg.content}"
|
||||
return HumanMessage(content=prompt)
|
||||
|
||||
|
||||
def get_zep_message_role_type(role: str) -> RoleType:
|
||||
if role == "human":
|
||||
return "user"
|
||||
elif role == "ai":
|
||||
return "assistant"
|
||||
elif role == "system":
|
||||
return "system"
|
||||
elif role == "function":
|
||||
return "function"
|
||||
elif role == "tool":
|
||||
return "tool"
|
||||
else:
|
||||
return "system"
|
||||
|
||||
|
||||
class ZepCloudChatMessageHistory(BaseChatMessageHistory):
|
||||
"""Chat message history that uses Zep Cloud as a backend.
|
||||
|
||||
Recommended usage::
|
||||
|
||||
# Set up Zep Chat History
|
||||
zep_chat_history = ZepChatMessageHistory(
|
||||
session_id=session_id,
|
||||
api_key=<your_api_key>,
|
||||
)
|
||||
|
||||
# Use a standard ConversationBufferMemory to encapsulate the Zep chat history
|
||||
memory = ConversationBufferMemory(
|
||||
memory_key="chat_history", chat_memory=zep_chat_history
|
||||
)
|
||||
|
||||
Zep - Recall, understand, and extract data from chat histories.
|
||||
Power personalized AI experiences.
|
||||
|
||||
Zep is a long-term memory service for AI Assistant apps.
|
||||
With Zep, you can provide AI assistants with the
|
||||
ability to recall past conversations,
|
||||
no matter how distant,
|
||||
while also reducing hallucinations, latency, and cost.
|
||||
|
||||
see Zep Cloud Docs: https://help.getzep.com
|
||||
|
||||
This class is a thin wrapper around the zep-python package. Additional
|
||||
Zep functionality is exposed via the `zep_summary`, `zep_messages` and `zep_facts`
|
||||
properties.
|
||||
|
||||
For more information on the zep-python package, see:
|
||||
https://github.com/getzep/zep-python
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
session_id: str,
|
||||
api_key: str,
|
||||
*,
|
||||
memory_type: Optional[MemoryGetRequestMemoryType] = None,
|
||||
lastn: Optional[int] = None,
|
||||
ai_prefix: Optional[str] = None,
|
||||
human_prefix: Optional[str] = None,
|
||||
summary_instruction: Optional[str] = None,
|
||||
) -> None:
|
||||
try:
|
||||
from zep_cloud.client import AsyncZep, Zep
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"Could not import zep-cloud package. "
|
||||
"Please install it with `pip install zep-cloud`."
|
||||
)
|
||||
|
||||
self.zep_client = Zep(api_key=api_key)
|
||||
self.zep_client_async = AsyncZep(api_key=api_key)
|
||||
self.session_id = session_id
|
||||
|
||||
self.memory_type = memory_type or "perpetual"
|
||||
self.lastn = lastn
|
||||
self.ai_prefix = ai_prefix or "ai"
|
||||
self.human_prefix = human_prefix or "human"
|
||||
self.summary_instruction = summary_instruction
|
||||
|
||||
@property
|
||||
def messages(self) -> List[BaseMessage]: # type: ignore
|
||||
"""Retrieve messages from Zep memory"""
|
||||
zep_memory: Optional[Memory] = self._get_memory()
|
||||
if not zep_memory:
|
||||
return []
|
||||
|
||||
return [condense_zep_memory_into_human_message(zep_memory)]
|
||||
|
||||
@property
|
||||
def zep_messages(self) -> List[Message]:
|
||||
"""Retrieve summary from Zep memory"""
|
||||
zep_memory: Optional[Memory] = self._get_memory()
|
||||
if not zep_memory:
|
||||
return []
|
||||
|
||||
return zep_memory.messages or []
|
||||
|
||||
@property
|
||||
def zep_summary(self) -> Optional[str]:
|
||||
"""Retrieve summary from Zep memory"""
|
||||
zep_memory: Optional[Memory] = self._get_memory()
|
||||
if not zep_memory or not zep_memory.summary:
|
||||
return None
|
||||
|
||||
return zep_memory.summary.content
|
||||
|
||||
@property
|
||||
def zep_facts(self) -> Optional[List[str]]:
|
||||
"""Retrieve conversation facts from Zep memory"""
|
||||
if self.memory_type != "perpetual":
|
||||
return None
|
||||
zep_memory: Optional[Memory] = self._get_memory()
|
||||
if not zep_memory or not zep_memory.facts:
|
||||
return None
|
||||
|
||||
return zep_memory.facts
|
||||
|
||||
def _get_memory(self) -> Optional[Memory]:
|
||||
"""Retrieve memory from Zep"""
|
||||
from zep_cloud import NotFoundError
|
||||
|
||||
try:
|
||||
zep_memory: Memory = self.zep_client.memory.get(
|
||||
self.session_id, memory_type=self.memory_type, lastn=self.lastn
|
||||
)
|
||||
except NotFoundError:
|
||||
logger.warning(
|
||||
f"Session {self.session_id} not found in Zep. Returning None"
|
||||
)
|
||||
return None
|
||||
return zep_memory
|
||||
|
||||
def add_user_message( # type: ignore[override]
|
||||
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( # type: ignore[override]
|
||||
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_cloud import Message
|
||||
|
||||
self.zep_client.memory.add(
|
||||
self.session_id,
|
||||
messages=[
|
||||
Message(
|
||||
content=str(message.content),
|
||||
role=message.type,
|
||||
role_type=get_zep_message_role_type(message.type),
|
||||
metadata=metadata,
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
def add_messages(self, messages: Sequence[BaseMessage]) -> None:
|
||||
"""Append the messages to the Zep memory history"""
|
||||
from zep_cloud import Message
|
||||
|
||||
zep_messages = [
|
||||
Message(
|
||||
content=str(message.content),
|
||||
role=message.type,
|
||||
role_type=get_zep_message_role_type(message.type),
|
||||
metadata=message.additional_kwargs.get("metadata", None),
|
||||
)
|
||||
for message in messages
|
||||
]
|
||||
|
||||
self.zep_client.memory.add(self.session_id, messages=zep_messages)
|
||||
|
||||
async def aadd_messages(self, messages: Sequence[BaseMessage]) -> None:
|
||||
"""Append the messages to the Zep memory history asynchronously"""
|
||||
from zep_cloud import Message
|
||||
|
||||
zep_messages = [
|
||||
Message(
|
||||
content=str(message.content),
|
||||
role=message.type,
|
||||
role_type=get_zep_message_role_type(message.type),
|
||||
metadata=message.additional_kwargs.get("metadata", None),
|
||||
)
|
||||
for message in messages
|
||||
]
|
||||
|
||||
await self.zep_client_async.memory.add(self.session_id, messages=zep_messages)
|
||||
|
||||
def search(
|
||||
self,
|
||||
query: str,
|
||||
metadata: Optional[Dict] = None,
|
||||
search_scope: SearchScope = "messages",
|
||||
search_type: SearchType = "similarity",
|
||||
mmr_lambda: Optional[float] = None,
|
||||
limit: Optional[int] = None,
|
||||
) -> List[MemorySearchResult]:
|
||||
"""Search Zep memory for messages matching the query"""
|
||||
|
||||
return self.zep_client.memory.search(
|
||||
self.session_id,
|
||||
text=query,
|
||||
metadata=metadata,
|
||||
search_scope=search_scope,
|
||||
search_type=search_type,
|
||||
mmr_lambda=mmr_lambda,
|
||||
limit=limit,
|
||||
)
|
||||
|
||||
def clear(self) -> None:
|
||||
"""Clear session memory from Zep. Note that Zep is long-term storage for memory
|
||||
and this is not advised unless you have specific data retention requirements.
|
||||
"""
|
||||
try:
|
||||
self.zep_client.memory.delete(self.session_id)
|
||||
except NotFoundError:
|
||||
logger.warning(
|
||||
f"Session {self.session_id} not found in Zep. Skipping delete."
|
||||
)
|
||||
|
||||
async def aclear(self) -> None:
|
||||
"""Clear session memory from Zep asynchronously.
|
||||
Note that Zep is long-term storage for memory and this is not advised
|
||||
unless you have specific data retention requirements.
|
||||
"""
|
||||
try:
|
||||
await self.zep_client_async.memory.delete(self.session_id)
|
||||
except NotFoundError:
|
||||
logger.warning(
|
||||
f"Session {self.session_id} not found in Zep. Skipping delete."
|
||||
)
|
124
libs/community/langchain_community/memory/zep_cloud_memory.py
Normal file
124
libs/community/langchain_community/memory/zep_cloud_memory.py
Normal file
@ -0,0 +1,124 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from langchain_community.chat_message_histories import ZepCloudChatMessageHistory
|
||||
|
||||
try:
|
||||
from langchain.memory import ConversationBufferMemory
|
||||
from zep_cloud import MemoryGetRequestMemoryType
|
||||
|
||||
class ZepCloudMemory(ConversationBufferMemory):
|
||||
"""Persist your chain history to the Zep MemoryStore.
|
||||
|
||||
Documentation: https://help.getzep.com
|
||||
|
||||
Example:
|
||||
.. code-block:: python
|
||||
|
||||
memory = ZepCloudMemory(
|
||||
session_id=session_id, # Identifies your user or a user's session
|
||||
api_key=<your_api_key>, # Your Zep Project API key
|
||||
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`.
|
||||
|
||||
|
||||
Zep - Recall, understand, and extract data from chat histories. Power personalized AI experiences.
|
||||
=========
|
||||
Zep is a long-term memory service for AI Assistant apps. With Zep, you can provide AI assistants with the ability to recall past conversations,
|
||||
no matter how distant, while also reducing hallucinations, latency, and cost.
|
||||
|
||||
For more information on the zep-python package, see:
|
||||
https://github.com/getzep/zep-python
|
||||
|
||||
""" # noqa: E501
|
||||
|
||||
chat_memory: ZepCloudChatMessageHistory
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
session_id: str,
|
||||
api_key: str,
|
||||
memory_type: Optional[MemoryGetRequestMemoryType] = None,
|
||||
lastn: Optional[int] = 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
|
||||
api_key (str): Your Zep Project key.
|
||||
memory_type (Optional[MemoryGetRequestMemoryType], optional): Zep Memory Type, defaults to perpetual
|
||||
lastn (Optional[int], optional): Number of messages to retrieve. Will add the last summary generated prior to the nth oldest message. Defaults to 6
|
||||
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.
|
||||
""" # noqa: E501
|
||||
chat_message_history = ZepCloudChatMessageHistory(
|
||||
session_id=session_id,
|
||||
memory_type=memory_type,
|
||||
lastn=lastn,
|
||||
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)
|
||||
except ImportError:
|
||||
# Placeholder object
|
||||
class ZepCloudMemory: # type: ignore[no-redef]
|
||||
pass
|
@ -136,6 +136,9 @@ if TYPE_CHECKING:
|
||||
from langchain_community.retrievers.zep import (
|
||||
ZepRetriever,
|
||||
)
|
||||
from langchain_community.retrievers.zep_cloud import (
|
||||
ZepCloudRetriever,
|
||||
)
|
||||
from langchain_community.retrievers.zilliz import (
|
||||
ZillizRetriever,
|
||||
)
|
||||
@ -183,6 +186,7 @@ _module_lookup = {
|
||||
"WikipediaRetriever": "langchain_community.retrievers.wikipedia",
|
||||
"YouRetriever": "langchain_community.retrievers.you",
|
||||
"ZepRetriever": "langchain_community.retrievers.zep",
|
||||
"ZepCloudRetriever": "langchain_community.retrievers.zep_cloud",
|
||||
"ZillizRetriever": "langchain_community.retrievers.zilliz",
|
||||
"NeuralDBRetriever": "langchain_community.retrievers.thirdai_neuraldb",
|
||||
}
|
||||
@ -238,5 +242,6 @@ __all__ = [
|
||||
"WikipediaRetriever",
|
||||
"YouRetriever",
|
||||
"ZepRetriever",
|
||||
"ZepCloudRetriever",
|
||||
"ZillizRetriever",
|
||||
]
|
||||
|
162
libs/community/langchain_community/retrievers/zep_cloud.py
Normal file
162
libs/community/langchain_community/retrievers/zep_cloud.py
Normal file
@ -0,0 +1,162 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
||||
|
||||
from langchain_core.callbacks import (
|
||||
AsyncCallbackManagerForRetrieverRun,
|
||||
CallbackManagerForRetrieverRun,
|
||||
)
|
||||
from langchain_core.documents import Document
|
||||
from langchain_core.pydantic_v1 import root_validator
|
||||
from langchain_core.retrievers import BaseRetriever
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from zep_cloud import MemorySearchResult, SearchScope, SearchType
|
||||
from zep_cloud.client import AsyncZep, Zep
|
||||
|
||||
|
||||
class ZepCloudRetriever(BaseRetriever):
|
||||
"""`Zep Cloud` 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.
|
||||
|
||||
Args:
|
||||
api_key: Your Zep API key
|
||||
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 - Recall, understand, and extract data from chat histories.
|
||||
Power personalized AI experiences.
|
||||
=========
|
||||
Zep is a long-term memory service for AI Assistant apps.
|
||||
With Zep, you can provide AI assistants with the ability
|
||||
to recall past conversations,
|
||||
no matter how distant, while also reducing hallucinations, latency, and cost.
|
||||
|
||||
see Zep Cloud Docs: https://help.getzep.com
|
||||
"""
|
||||
|
||||
api_key: str
|
||||
"""Your Zep API key."""
|
||||
zep_client: Zep
|
||||
"""Zep client used for making API requests."""
|
||||
zep_client_async: AsyncZep
|
||||
"""Async Zep client used for making API requests."""
|
||||
session_id: str
|
||||
"""Zep session ID."""
|
||||
top_k: Optional[int]
|
||||
"""Number of items to return."""
|
||||
search_scope: SearchScope = "messages"
|
||||
"""Which documents to search. Messages or Summaries?"""
|
||||
search_type: 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:
|
||||
try:
|
||||
from zep_cloud.client import AsyncZep, Zep
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"Could not import zep-cloud package. "
|
||||
"Please install it with `pip install zep-cloud`."
|
||||
)
|
||||
if values.get("api_key") is None:
|
||||
raise ValueError("Zep API key is required.")
|
||||
values["zep_client"] = Zep(api_key=values.get("api_key"))
|
||||
values["zep_client_async"] = AsyncZep(api_key=values.get("api_key"))
|
||||
return values
|
||||
|
||||
def _messages_search_result_to_doc(
|
||||
self, results: List[MemorySearchResult]
|
||||
) -> List[Document]:
|
||||
return [
|
||||
Document(
|
||||
page_content=str(r.message.content),
|
||||
metadata={
|
||||
"score": r.score,
|
||||
"uuid": r.message.uuid_,
|
||||
"created_at": r.message.created_at,
|
||||
"token_count": r.message.token_count,
|
||||
"role": r.message.role or r.message.role_type,
|
||||
},
|
||||
)
|
||||
for r in results or []
|
||||
if r.message
|
||||
]
|
||||
|
||||
def _summary_search_result_to_doc(
|
||||
self, results: List[MemorySearchResult]
|
||||
) -> List[Document]:
|
||||
return [
|
||||
Document(
|
||||
page_content=str(r.summary.content),
|
||||
metadata={
|
||||
"score": r.score,
|
||||
"uuid": r.summary.uuid_,
|
||||
"created_at": r.summary.created_at,
|
||||
"token_count": r.summary.token_count,
|
||||
},
|
||||
)
|
||||
for r in results
|
||||
if r.summary
|
||||
]
|
||||
|
||||
def _get_relevant_documents(
|
||||
self,
|
||||
query: str,
|
||||
*,
|
||||
run_manager: CallbackManagerForRetrieverRun,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
) -> List[Document]:
|
||||
if not self.zep_client:
|
||||
raise RuntimeError("Zep client not initialized.")
|
||||
|
||||
results = self.zep_client.memory.search(
|
||||
self.session_id,
|
||||
text=query,
|
||||
metadata=metadata,
|
||||
search_scope=self.search_scope,
|
||||
search_type=self.search_type,
|
||||
mmr_lambda=self.mmr_lambda,
|
||||
limit=self.top_k,
|
||||
)
|
||||
|
||||
if self.search_scope == "summary":
|
||||
return self._summary_search_result_to_doc(results)
|
||||
|
||||
return self._messages_search_result_to_doc(results)
|
||||
|
||||
async def _aget_relevant_documents(
|
||||
self,
|
||||
query: str,
|
||||
*,
|
||||
run_manager: AsyncCallbackManagerForRetrieverRun,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
) -> List[Document]:
|
||||
if not self.zep_client_async:
|
||||
raise RuntimeError("Zep client not initialized.")
|
||||
|
||||
results = await self.zep_client_async.memory.search(
|
||||
self.session_id,
|
||||
text=query,
|
||||
metadata=metadata,
|
||||
search_scope=self.search_scope,
|
||||
search_type=self.search_type,
|
||||
mmr_lambda=self.mmr_lambda,
|
||||
limit=self.top_k,
|
||||
)
|
||||
|
||||
if self.search_scope == "summary":
|
||||
return self._summary_search_result_to_doc(results)
|
||||
|
||||
return self._messages_search_result_to_doc(results)
|
@ -294,6 +294,9 @@ if TYPE_CHECKING:
|
||||
from langchain_community.vectorstores.zep import (
|
||||
ZepVectorStore,
|
||||
)
|
||||
from langchain_community.vectorstores.zep_cloud import (
|
||||
ZepCloudVectorStore,
|
||||
)
|
||||
from langchain_community.vectorstores.zilliz import (
|
||||
Zilliz,
|
||||
)
|
||||
@ -395,6 +398,7 @@ __all__ = [
|
||||
"Weaviate",
|
||||
"Yellowbrick",
|
||||
"ZepVectorStore",
|
||||
"ZepCloudVectorStore",
|
||||
"Zilliz",
|
||||
]
|
||||
|
||||
@ -495,6 +499,7 @@ _module_lookup = {
|
||||
"Weaviate": "langchain_community.vectorstores.weaviate",
|
||||
"Yellowbrick": "langchain_community.vectorstores.yellowbrick",
|
||||
"ZepVectorStore": "langchain_community.vectorstores.zep",
|
||||
"ZepCloudVectorStore": "langchain_community.vectorstores.zep_cloud",
|
||||
"Zilliz": "langchain_community.vectorstores.zilliz",
|
||||
}
|
||||
|
||||
|
477
libs/community/langchain_community/vectorstores/zep_cloud.py
Normal file
477
libs/community/langchain_community/vectorstores/zep_cloud.py
Normal file
@ -0,0 +1,477 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import warnings
|
||||
from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple
|
||||
|
||||
from langchain_core.documents import Document
|
||||
from langchain_core.embeddings import Embeddings
|
||||
from langchain_core.vectorstores import VectorStore
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from zep_cloud import CreateDocumentRequest, DocumentCollectionResponse, SearchType
|
||||
|
||||
logger = logging.getLogger()
|
||||
|
||||
|
||||
class ZepCloudVectorStore(VectorStore):
|
||||
"""`Zep` vector store.
|
||||
|
||||
It provides methods for adding texts or documents to the store,
|
||||
searching for similar documents, and deleting documents.
|
||||
|
||||
Search scores are calculated using cosine similarity normalized to [0, 1].
|
||||
|
||||
Args:
|
||||
collection_name (str): The name of the collection in the Zep store.
|
||||
api_key (str): The API key for the Zep API.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
collection_name: str,
|
||||
api_key: str,
|
||||
) -> None:
|
||||
super().__init__()
|
||||
if not collection_name:
|
||||
raise ValueError(
|
||||
"collection_name must be specified when using ZepVectorStore."
|
||||
)
|
||||
try:
|
||||
from zep_cloud.client import AsyncZep, Zep
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"Could not import zep-python python package. "
|
||||
"Please install it with `pip install zep-python`."
|
||||
)
|
||||
self._client = Zep(api_key=api_key)
|
||||
self._client_async = AsyncZep(api_key=api_key)
|
||||
|
||||
self.collection_name = collection_name
|
||||
|
||||
self._load_collection()
|
||||
|
||||
@property
|
||||
def embeddings(self) -> Optional[Embeddings]:
|
||||
"""Unavailable for ZepCloud"""
|
||||
return None
|
||||
|
||||
def _load_collection(self) -> DocumentCollectionResponse:
|
||||
"""
|
||||
Load the collection from the Zep backend.
|
||||
"""
|
||||
from zep_cloud import NotFoundError
|
||||
|
||||
try:
|
||||
collection = self._client.document.get_collection(self.collection_name)
|
||||
except NotFoundError:
|
||||
logger.info(
|
||||
f"Collection {self.collection_name} not found. Creating new collection."
|
||||
)
|
||||
collection = self._create_collection()
|
||||
|
||||
return collection
|
||||
|
||||
def _create_collection(self) -> DocumentCollectionResponse:
|
||||
"""
|
||||
Create a new collection in the Zep backend.
|
||||
"""
|
||||
self._client.document.add_collection(self.collection_name)
|
||||
collection = self._client.document.get_collection(self.collection_name)
|
||||
return collection
|
||||
|
||||
def _generate_documents_to_add(
|
||||
self,
|
||||
texts: Iterable[str],
|
||||
metadatas: Optional[List[Dict[Any, Any]]] = None,
|
||||
document_ids: Optional[List[str]] = None,
|
||||
) -> List[CreateDocumentRequest]:
|
||||
from zep_cloud import CreateDocumentRequest as ZepDocument
|
||||
|
||||
documents: List[ZepDocument] = []
|
||||
for i, d in enumerate(texts):
|
||||
documents.append(
|
||||
ZepDocument(
|
||||
content=d,
|
||||
metadata=metadatas[i] if metadatas else None,
|
||||
document_id=document_ids[i] if document_ids else None,
|
||||
)
|
||||
)
|
||||
return documents
|
||||
|
||||
def add_texts(
|
||||
self,
|
||||
texts: Iterable[str],
|
||||
metadatas: Optional[List[Dict[str, Any]]] = None,
|
||||
document_ids: Optional[List[str]] = None,
|
||||
**kwargs: Any,
|
||||
) -> List[str]:
|
||||
"""Run more texts through the embeddings and add to the vectorstore.
|
||||
|
||||
Args:
|
||||
texts: Iterable of strings to add to the vectorstore.
|
||||
metadatas: Optional list of metadatas associated with the texts.
|
||||
document_ids: Optional list of document ids associated with the texts.
|
||||
kwargs: vectorstore specific parameters
|
||||
|
||||
Returns:
|
||||
List of ids from adding the texts into the vectorstore.
|
||||
"""
|
||||
|
||||
documents = self._generate_documents_to_add(texts, metadatas, document_ids)
|
||||
uuids = self._client.document.add_documents(
|
||||
self.collection_name, request=documents
|
||||
)
|
||||
|
||||
return uuids
|
||||
|
||||
async def aadd_texts(
|
||||
self,
|
||||
texts: Iterable[str],
|
||||
metadatas: Optional[List[Dict[str, Any]]] = None,
|
||||
document_ids: Optional[List[str]] = None,
|
||||
**kwargs: Any,
|
||||
) -> List[str]:
|
||||
"""Run more texts through the embeddings and add to the vectorstore."""
|
||||
documents = self._generate_documents_to_add(texts, metadatas, document_ids)
|
||||
uuids = await self._client_async.document.add_documents(
|
||||
self.collection_name, request=documents
|
||||
)
|
||||
|
||||
return uuids
|
||||
|
||||
def search(
|
||||
self,
|
||||
query: str,
|
||||
search_type: SearchType,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
k: int = 3,
|
||||
**kwargs: Any,
|
||||
) -> List[Document]:
|
||||
"""Return docs most similar to query using specified search type."""
|
||||
if search_type == "similarity":
|
||||
return self.similarity_search(query, k=k, metadata=metadata, **kwargs)
|
||||
elif search_type == "mmr":
|
||||
return self.max_marginal_relevance_search(
|
||||
query, k=k, metadata=metadata, **kwargs
|
||||
)
|
||||
else:
|
||||
raise ValueError(
|
||||
f"search_type of {search_type} not allowed. Expected "
|
||||
"search_type to be 'similarity' or 'mmr'."
|
||||
)
|
||||
|
||||
async def asearch(
|
||||
self,
|
||||
query: str,
|
||||
search_type: str,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
k: int = 3,
|
||||
**kwargs: Any,
|
||||
) -> List[Document]:
|
||||
"""Return docs most similar to query using specified search type."""
|
||||
if search_type == "similarity":
|
||||
return await self.asimilarity_search(
|
||||
query, k=k, metadata=metadata, **kwargs
|
||||
)
|
||||
elif search_type == "mmr":
|
||||
return await self.amax_marginal_relevance_search(
|
||||
query, k=k, metadata=metadata, **kwargs
|
||||
)
|
||||
else:
|
||||
raise ValueError(
|
||||
f"search_type of {search_type} not allowed. Expected "
|
||||
"search_type to be 'similarity' or 'mmr'."
|
||||
)
|
||||
|
||||
def similarity_search(
|
||||
self,
|
||||
query: str,
|
||||
k: int = 4,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
**kwargs: Any,
|
||||
) -> List[Document]:
|
||||
"""Return docs most similar to query."""
|
||||
|
||||
results = self._similarity_search_with_relevance_scores(
|
||||
query, k=k, metadata=metadata, **kwargs
|
||||
)
|
||||
return [doc for doc, _ in results]
|
||||
|
||||
def similarity_search_with_score(
|
||||
self,
|
||||
query: str,
|
||||
k: int = 4,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
**kwargs: Any,
|
||||
) -> List[Tuple[Document, float]]:
|
||||
"""Run similarity search with distance."""
|
||||
|
||||
return self._similarity_search_with_relevance_scores(
|
||||
query, k=k, metadata=metadata, **kwargs
|
||||
)
|
||||
|
||||
def _similarity_search_with_relevance_scores(
|
||||
self,
|
||||
query: str,
|
||||
k: int = 4,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
**kwargs: Any,
|
||||
) -> List[Tuple[Document, float]]:
|
||||
"""
|
||||
Default similarity search with relevance scores. Modify if necessary
|
||||
in subclass.
|
||||
Return docs and relevance scores in the range [0, 1].
|
||||
|
||||
0 is dissimilar, 1 is most similar.
|
||||
|
||||
Args:
|
||||
query: input text
|
||||
k: Number of Documents to return. Defaults to 4.
|
||||
metadata: Optional, metadata filter
|
||||
**kwargs: kwargs to be passed to similarity search. Should include:
|
||||
score_threshold: Optional, a floating point value between 0 to 1 and
|
||||
filter the resulting set of retrieved docs
|
||||
|
||||
Returns:
|
||||
List of Tuples of (doc, similarity_score)
|
||||
"""
|
||||
|
||||
results = self._client.document.search(
|
||||
collection_name=self.collection_name,
|
||||
text=query,
|
||||
limit=k,
|
||||
metadata=metadata,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return [
|
||||
(
|
||||
Document(
|
||||
page_content=str(doc.content),
|
||||
metadata=doc.metadata,
|
||||
),
|
||||
doc.score or 0.0,
|
||||
)
|
||||
for doc in results.results or []
|
||||
]
|
||||
|
||||
async def asimilarity_search_with_relevance_scores(
|
||||
self,
|
||||
query: str,
|
||||
k: int = 4,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
**kwargs: Any,
|
||||
) -> List[Tuple[Document, float]]:
|
||||
"""Return docs most similar to query."""
|
||||
|
||||
results = await self._client_async.document.search(
|
||||
collection_name=self.collection_name,
|
||||
text=query,
|
||||
limit=k,
|
||||
metadata=metadata,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return [
|
||||
(
|
||||
Document(
|
||||
page_content=str(doc.content),
|
||||
metadata=doc.metadata,
|
||||
),
|
||||
doc.score or 0.0,
|
||||
)
|
||||
for doc in results.results or []
|
||||
]
|
||||
|
||||
async def asimilarity_search(
|
||||
self,
|
||||
query: str,
|
||||
k: int = 4,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
**kwargs: Any,
|
||||
) -> List[Document]:
|
||||
"""Return docs most similar to query."""
|
||||
|
||||
results = await self.asimilarity_search_with_relevance_scores(
|
||||
query, k, metadata=metadata, **kwargs
|
||||
)
|
||||
|
||||
return [doc for doc, _ in results]
|
||||
|
||||
def similarity_search_by_vector(
|
||||
self,
|
||||
embedding: List[float],
|
||||
k: int = 4,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
**kwargs: Any,
|
||||
) -> List[Document]:
|
||||
"""Unsupported in Zep Cloud"""
|
||||
warnings.warn("similarity_search_by_vector is not supported in Zep Cloud")
|
||||
return []
|
||||
|
||||
async def asimilarity_search_by_vector(
|
||||
self,
|
||||
embedding: List[float],
|
||||
k: int = 4,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
**kwargs: Any,
|
||||
) -> List[Document]:
|
||||
"""Unsupported in Zep Cloud"""
|
||||
warnings.warn("asimilarity_search_by_vector is not supported in Zep Cloud")
|
||||
return []
|
||||
|
||||
def max_marginal_relevance_search(
|
||||
self,
|
||||
query: str,
|
||||
k: int = 4,
|
||||
fetch_k: int = 20,
|
||||
lambda_mult: float = 0.5,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
**kwargs: Any,
|
||||
) -> List[Document]:
|
||||
"""Return docs selected using the maximal marginal relevance.
|
||||
|
||||
Maximal marginal relevance optimizes for similarity to query AND diversity
|
||||
among selected documents.
|
||||
|
||||
Args:
|
||||
query: Text to look up documents similar to.
|
||||
k: Number of Documents to return. Defaults to 4.
|
||||
fetch_k: Number of Documents to fetch to pass to MMR algorithm.
|
||||
Zep determines this automatically and this parameter is
|
||||
ignored.
|
||||
lambda_mult: Number between 0 and 1 that determines the degree
|
||||
of diversity among the results with 0 corresponding
|
||||
to maximum diversity and 1 to minimum diversity.
|
||||
Defaults to 0.5.
|
||||
metadata: Optional, metadata to filter the resulting set of retrieved docs
|
||||
Returns:
|
||||
List of Documents selected by maximal marginal relevance.
|
||||
"""
|
||||
|
||||
results = self._client.document.search(
|
||||
collection_name=self.collection_name,
|
||||
text=query,
|
||||
limit=k,
|
||||
metadata=metadata,
|
||||
search_type="mmr",
|
||||
mmr_lambda=lambda_mult,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return [
|
||||
Document(page_content=str(d.content), metadata=d.metadata)
|
||||
for d in results.results or []
|
||||
]
|
||||
|
||||
async def amax_marginal_relevance_search(
|
||||
self,
|
||||
query: str,
|
||||
k: int = 4,
|
||||
fetch_k: int = 20,
|
||||
lambda_mult: float = 0.5,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
**kwargs: Any,
|
||||
) -> List[Document]:
|
||||
"""Return docs selected using the maximal marginal relevance."""
|
||||
|
||||
results = await self._client_async.document.search(
|
||||
collection_name=self.collection_name,
|
||||
text=query,
|
||||
limit=k,
|
||||
metadata=metadata,
|
||||
search_type="mmr",
|
||||
mmr_lambda=lambda_mult,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return [
|
||||
Document(page_content=str(d.content), metadata=d.metadata)
|
||||
for d in results.results or []
|
||||
]
|
||||
|
||||
def max_marginal_relevance_search_by_vector(
|
||||
self,
|
||||
embedding: List[float],
|
||||
k: int = 4,
|
||||
fetch_k: int = 20,
|
||||
lambda_mult: float = 0.5,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
**kwargs: Any,
|
||||
) -> List[Document]:
|
||||
"""Unsupported in Zep Cloud"""
|
||||
warnings.warn(
|
||||
"max_marginal_relevance_search_by_vector is not supported in Zep Cloud"
|
||||
)
|
||||
return []
|
||||
|
||||
async def amax_marginal_relevance_search_by_vector(
|
||||
self,
|
||||
embedding: List[float],
|
||||
k: int = 4,
|
||||
fetch_k: int = 20,
|
||||
lambda_mult: float = 0.5,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
**kwargs: Any,
|
||||
) -> List[Document]:
|
||||
"""Unsupported in Zep Cloud"""
|
||||
warnings.warn(
|
||||
"amax_marginal_relevance_search_by_vector is not supported in Zep Cloud"
|
||||
)
|
||||
return []
|
||||
|
||||
@classmethod
|
||||
def from_texts(
|
||||
cls,
|
||||
texts: List[str],
|
||||
embedding: Embeddings,
|
||||
metadatas: Optional[List[dict]] = None,
|
||||
collection_name: str = "",
|
||||
api_key: Optional[str] = None,
|
||||
**kwargs: Any,
|
||||
) -> ZepCloudVectorStore:
|
||||
"""
|
||||
Class method that returns a ZepVectorStore instance initialized from texts.
|
||||
|
||||
If the collection does not exist, it will be created.
|
||||
|
||||
Args:
|
||||
texts (List[str]): The list of texts to add to the vectorstore.
|
||||
metadatas (Optional[List[Dict[str, Any]]]): Optional list of metadata
|
||||
associated with the texts.
|
||||
collection_name (str): The name of the collection in the Zep store.
|
||||
api_key (str): The API key for the Zep API.
|
||||
**kwargs: Additional parameters specific to the vectorstore.
|
||||
|
||||
Returns:
|
||||
ZepVectorStore: An instance of ZepVectorStore.
|
||||
"""
|
||||
if not api_key:
|
||||
raise ValueError("api_key must be specified when using ZepVectorStore.")
|
||||
vecstore = cls(
|
||||
collection_name=collection_name,
|
||||
api_key=api_key,
|
||||
)
|
||||
vecstore.add_texts(texts, metadatas)
|
||||
return vecstore
|
||||
|
||||
def delete(self, ids: Optional[List[str]] = None, **kwargs: Any) -> None:
|
||||
"""Delete by Zep vector UUIDs.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ids : Optional[List[str]]
|
||||
The UUIDs of the vectors to delete.
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If no UUIDs are provided.
|
||||
"""
|
||||
|
||||
if ids is None or len(ids) == 0:
|
||||
raise ValueError("No uuids provided to delete.")
|
||||
|
||||
for u in ids:
|
||||
self._client.document.delete_document(self.collection_name, u)
|
@ -22,6 +22,7 @@ EXPECTED_ALL = [
|
||||
"UpstashRedisChatMessageHistory",
|
||||
"XataChatMessageHistory",
|
||||
"ZepChatMessageHistory",
|
||||
"ZepCloudChatMessageHistory",
|
||||
]
|
||||
|
||||
|
||||
|
@ -43,6 +43,7 @@ EXPECTED_ALL = [
|
||||
"WebResearchRetriever",
|
||||
"YouRetriever",
|
||||
"ZepRetriever",
|
||||
"ZepCloudRetriever",
|
||||
"ZillizRetriever",
|
||||
"DocArrayRetriever",
|
||||
"NeuralDBRetriever",
|
||||
|
@ -100,6 +100,7 @@ EXPECTED_ALL = [
|
||||
"Weaviate",
|
||||
"Yellowbrick",
|
||||
"ZepVectorStore",
|
||||
"ZepCloudVectorStore",
|
||||
"Zilliz",
|
||||
]
|
||||
|
||||
|
@ -98,6 +98,7 @@ def test_compatible_vectorstore_documentation() -> None:
|
||||
"Weaviate",
|
||||
"Yellowbrick",
|
||||
"ZepVectorStore",
|
||||
"ZepCloudVectorStore",
|
||||
"Zilliz",
|
||||
"Lantern",
|
||||
"OpenSearchVectorSearch",
|
||||
|
Loading…
Reference in New Issue
Block a user