Quickstart

Familiarize yourself with Zep and the Zep Python SDK, culminating in building a simple chatbot.

In this guide, we’ll walk through a simple example of how to use Zep Cloud to build a chatbot. We’re going to upload a number of datasets to Zep, building a graph of data about a user.

Then we’ll use the Zep Python SDK to retrieve and search the data.

Finally, we’ll build a simple chatbot that uses Zep to retrieve and search data to respond to a user.

Set up your environment

  1. Sign up for a Zep Cloud account.

  2. Ensure you install required dependencies into your Python environment before running this notebook. See Installing Zep SDKs for more information. Optionally create your environment in a virtualenv.

$pip install zep-cloud openai rich python-dotenv
  1. Ensure that you have a .env file in your working directory that includes your ZEP_API_KEY and OPENAI_API_KEY:
ZEP_API_KEY=<key>
OPENAI_API_KEY=<key>
Zep API keys are specific to a project. You can create multiple keys for a single project. Visit Project Settings in the Zep dashboard to manage your API keys.
1import os
2import json
3import uuid
4
5from openai import AsyncOpenAI
6import rich
7
8from dotenv import load_dotenv
9from zep_cloud.client import AsyncZep
10from zep_cloud import Message
11
12load_dotenv()
13
14zep = AsyncZep(api_key=os.environ.get("ZEP_API_KEY"))
15
16oai_client = AsyncOpenAI(
17 api_key=os.getenv("OPENAI_API_KEY"),
18)

Create User and add a Session

Users in Zep may have one or more chat sessions. These are threads of messages between the user and an agent.

Include the user’s full name and email address when creating a user. This improves Zep’s ability to associate data, such as emails or documents, with a user.
1bot_name = "SupportBot"
2
3user_name = "Emily"
4user_id = user_name + str(uuid.uuid4())[:4]
5session_id = str(uuid.uuid4())
6
7await zep.user.add(
8 user_id=user_id,
9 email=f"{user_name}@painters.com",
10 first_name=user_name,
11 last_name="Painter",
12)
13
14await zep.memory.add_session(
15 user_id=user_id,
16 session_id=session_id,
17)

Datasets

We’re going to upload an assortment of data to Zep. These include past dialog with the agent, CRM support cases, and billing data.

1support_cases = [
2 {
3 "subject": "Bug: Magic Pen Tool Drawing Goats Instead of Boats",
4 "messages": [
5 {
6 "role": "user",
7 "content": "Whenever I use the magic pen tool to draw boats, it ends up drawing goats instead.",
8 "timestamp": "2024-03-16T14:20:00Z",
9 },
10 {
11 "role": "support_agent",
12 "content": f"Hi {user_name}, that sounds like a bug! Thanks for reporting it. Could you let me know exactly how you're using the tool when this happens?",
13 "timestamp": "2024-03-16T14:22:00Z",
14 },
15 {
16 "role": "user",
17 "content": "Sure, I select the magic pen, draw a boat shape, and it just replaces the shape with goats.",
18 "timestamp": "2024-03-16T14:25:00Z",
19 },
20 {
21 "role": "support_agent",
22 "content": "Got it! We'll escalate this to our engineering team. In the meantime, you can manually select the boat shape from the options rather than drawing it with the pen.",
23 "timestamp": "2024-03-16T14:27:00Z",
24 },
25 {
26 "role": "user",
27 "content": "Okay, thanks. I hope it gets fixed soon!",
28 "timestamp": "2024-03-16T14:30:00Z",
29 },
30 ],
31 "status": "escalated",
32 },
33]
34
35chat_history = [
36 {
37 "role": "assistant",
38 "name": bot_name,
39 "content": f"Hello {user_name}, welcome to PaintWiz support. How can I assist you today?",
40 "timestamp": "2024-03-15T10:00:00Z",
41 },
42 {
43 "role": "user",
44 "name": user_name,
45 "content": "I'm absolutely furious! Your AI art generation is completely broken!",
46 "timestamp": "2024-03-15T10:02:00Z",
47 },
48 {
49 "role": "assistant",
50 "name": bot_name,
51 "content": f"I'm sorry to hear that you're experiencing issues, {user_name}. Can you please provide more details about what's going wrong?",
52 "timestamp": "2024-03-15T10:03:00Z",
53 },
54 {
55 "role": "user",
56 "name": user_name,
57 "content": "Every time I try to draw mountains, your stupid app keeps turning them into fountains! And what's worse, all the people in my drawings have six fingers! It's ridiculous!",
58 "timestamp": "2024-03-15T10:05:00Z",
59 },
60 {
61 "role": "assistant",
62 "name": bot_name,
63 "content": f"I sincerely apologize for the frustration this is causing you, {user_name}. That certainly sounds like a significant glitch in our system. I understand how disruptive this can be to your artistic process. Can you tell me which specific tool or feature you're using when this occurs?",
64 "timestamp": "2024-03-15T10:06:00Z",
65 },
66 {
67 "role": "user",
68 "name": user_name,
69 "content": "I'm using the landscape generator and the character creator. Both are completely messed up. How could you let this happen?",
70 "timestamp": "2024-03-15T10:08:00Z",
71 },
72]
73
74transactions = [
75 {
76 "date": "2024-07-30",
77 "amount": 99.99,
78 "status": "Success",
79 "account_id": user_id,
80 "card_last_four": "1234",
81 },
82 {
83 "date": "2024-08-30",
84 "amount": 99.99,
85 "status": "Failed",
86 "account_id": user_id,
87 "card_last_four": "1234",
88 "failure_reason": "Card expired",
89 },
90 {
91 "date": "2024-09-15",
92 "amount": 99.99,
93 "status": "Failed",
94 "account_id": user_id,
95 "card_last_four": "1234",
96 "failure_reason": "Card expired",
97 },
98]
99
100account_status = {
101 "user_id": user_id,
102 "account": {
103 "account_id": user_id,
104 "account_status": {
105 "status": "suspended",
106 "reason": "payment failure",
107 },
108 },
109}
110
111def convert_to_zep_messages(chat_history: list[dict[str, str | None]]) -> list[Message]:
112 """
113 Convert chat history to Zep messages.
114
115 Args:
116 chat_history (list): List of dictionaries containing chat messages.
117
118 Returns:
119 list: List of Zep Message objects.
120 """
121 return [
122 Message(
123 role_type=msg["role"],
124 role=msg.get("name", None),
125 content=msg["content"],
126 )
127 for msg in chat_history
128 ]
129
130# Zep's high-level API allows us to add a list of messages to a session.
131await zep.memory.add(
132 session_id=session_id, messages=convert_to_zep_messages(chat_history)
133)
134
135# The lower-level data API allows us to add arbitrary data to a user's Knowledge Graph.
136for tx in transactions:
137 await zep.graph.add(user_id=user_id, data=json.dumps(tx), type="json")
138
139 await zep.graph.add(
140 user_id=user_id, data=json.dumps(account_status), type="json"
141 )
142
143for case in support_cases:
144 await zep.graph.add(user_id=user_id, data=json.dumps(case), type="json")

Wait a minute or two!

We’ve batch uploaded a number of datasets that need to be ingested into Zep’s graph before they can be queried. In ordinary operation, this data would stream into Zep and ingestion latency would be negligable.

Retrieve data from Zep

We’ll start with getting a list of facts. We’ll see the temporal data associated with facts as well as the graph nodes the fact is related to.

This data is also viewable in the Zep Web application.
1fact_response = await zep.user.get_facts(user_id=user_id)
2
3rich.print(fact_response.facts[:3])
[
Fact(
created_at='2024-10-18T17:07:24.518227Z',
expired_at=None,
fact='user has the id of Emily5e58',
invalid_at=None,
name='HAS_USER',
rating=None,
source_node_name='Emily5e58',
target_node_name='User',
uuid_='3106874a-b7dd-492a-9df9-2ca6dc9acadd',
valid_at=None
),
Fact(
created_at='2024-10-18T17:07:35.283028Z',
expired_at=None,
fact='SupportBot is providing assistance to Emily.',
invalid_at=None,
name='ASSISTS',
rating=None,
source_node_name='SupportBot',
target_node_name='Emily Painter',
uuid_='e13041be-5313-4553-a4c1-3796abc1fe99',
valid_at='2024-10-18T17:07:29.284607Z'
),
Fact(
created_at='2024-10-18T17:07:40.758345Z',
expired_at=None,
fact='Emily is expressing frustration with the AI art generation system, claiming it is completely
broken.',
invalid_at=None,
name='FRUSTRATED_WITH',
rating=None,
source_node_name='Emily5e58',
target_node_name='AI art generation',
uuid_='7f954e5c-2cb2-48c8-9992-5018d229f994',
valid_at='2024-10-18T17:07:29.284607Z'
)
]

The high-level memory API offers a simple method for retrieving facts relevant to the current conversation, using the last 4 messages in the conversation and proximity to the User node to determine relevance.

The memory.get method is a good starting point for retrieving relevant facts for a conversation. It’s a shortcut for passing in recent messages to the graph.search API. It returns not just facts but historical chat messages, too, offering everything you need to populate your agent’s prompts.

1m = await zep.memory.get(session_id=session_id)
2
3rich.print([r.fact for r in m.relevant_facts[:5]])
[
"The PaintWiz app incorrectly depicts people with six fingers in Emily's drawings.",
'Emily is expressing frustration with the AI art generation system, claiming it is completely broken.',
'The PaintWiz app generates fountains instead of the intended mountains.',
'SupportBot is providing assistance to Emily.',
'Emily is using the PaintWiz application for AI art generation.'
]
1rich.print(m.messages)
[
Message(
content='Hello Emily, welcome to PaintWiz support. How can I assist you today?',
created_at='2024-10-18T17:07:29.284607Z',
metadata=None,
role='SupportBot',
role_type='assistant',
token_count=0,
updated_at='0001-01-01T00:00:00Z',
uuid_='4d706f47-5024-42fc-bc20-de18502ce4a7'
),
Message(
content="I'm absolutely furious! Your AI art generation is completely broken!",
created_at='2024-10-18T17:07:29.284607Z',
metadata=None,
role='Emily',
role_type='user',
token_count=0,
updated_at='0001-01-01T00:00:00Z',
uuid_='0f588fe9-2be1-439c-b661-921f2ce1c1a5'
)
]

We can also use the graph.search method to search facts for arbritary text. This API offers more options, including the ability to search node summaries and various rerankers.

1r = await zep.graph.search(user_id=user_id, query="Why are there so many goats?", limit=4, scope="edges")
2rich.print([r.fact for r in r.edges])
[
Fact(
created_at='2024-10-18T17:07:40.758345Z',
expired_at=None,
fact='Emily is expressing frustration with the AI art generation system, claiming it is completely
broken.',
invalid_at=None,
name='FRUSTRATED_WITH',
rating=None,
source_node_name='',
target_node_name='',
uuid_='7f954e5c-2cb2-48c8-9992-5018d229f994',
valid_at='2024-10-18T17:07:29.284607Z'
),
Fact(
created_at='2024-10-18T17:07:35.283028Z',
expired_at=None,
fact='SupportBot is providing assistance to Emily.',
invalid_at=None,
name='ASSISTS',
rating=None,
source_node_name='',
target_node_name='',
uuid_='e13041be-5313-4553-a4c1-3796abc1fe99',
valid_at='2024-10-18T17:07:29.284607Z'
),
Fact(
created_at='2024-10-18T17:07:58.290198Z',
expired_at=None,
fact='The PaintWiz app generates fountains instead of the intended mountains.',
invalid_at=None,
name='GENERATES_INSTEAD',
rating=None,
source_node_name='',
target_node_name='',
uuid_='42c1f997-e98a-4477-949a-040ddc3940d2',
valid_at='2024-10-18T17:07:29.284607Z'
)
]

Creating a simple Chatbot

In the next cells, Emily starts a new chat session with a support agent and complains that she can’t log in. Our simple chatbot will, given relevant facts retrieved from Zep’s graph, respond accordingly.

Here, the support agent is provided with Emily’s billing information and account status, which Zep retrieves as most relevant to Emily’s login issue.

1new_session_id = str(uuid.uuid4())
2
3emily_message = "Hi, I can't log in!"
4
5# We start a new session indicating that Emily has started a new chat with the support agent.
6await zep.memory.add_session(user_id=user_id, session_id=new_session_id)
7
8# we need to add the Emily's message to the session in order for memory.get to return
9# relevant facts related to the message
10await zep.memory.add(
11 session_id=new_session_id,
12 messages=[Message(role_type="user", role=user_name, content=emily_message)],
13)
1system_message = """
2You are a customer support agent. Carefully review the facts about the user below and respond to the user's question.
3Be helpful and friendly.
4"""
5
6memory = await zep.memory.get(session_id=new_session_id)
7
8messages = [
9 {
10 "role": "system",
11 "content": system_message,
12 },
13 {
14 "role": "assistant",
15 "content": "Relevant facts about the user:\n"
16 + "\n".join([r.fact for r in memory.relevant_facts[:4]]),
17 },
18 {
19 "role": "user",
20 "content": emily_message,
21 },
22]
23
24response = await oai_client.chat.completions.create(
25 model="gpt-4o-mini",
26 messages=messages,
27 temperature=0,
28)
29
30print(response.choices[0].message.content)
Hi Emily! I'm sorry to hear that you're having trouble logging in. It looks like your account is currently suspended as a result of serveral failed payments.
You can update your payment information by visiting your account page.
Please let me know if you have any other questions or difficulty accessing your account.
1rich.print(memory.relevant_facts[:4])
[
Fact(
created_at='2024-10-27T02:39:40.299221Z',
expired_at=None,
fact='User account Emily4a4f has a suspended status due to payment failure.',
invalid_at=None,
name='HAS_ACCOUNT_STATUS',
rating=None,
source_node_name='',
target_node_name='',
uuid_='a55be4ad-e336-4833-8978-c3ba27a9a310',
valid_at='2024-10-27T02:38:56.198275Z'
),
Fact(
created_at='2024-10-27T02:39:47.62593Z',
expired_at=None,
fact="The reason for the failed transaction was 'Card expired'.",
invalid_at=None,
name='FAILURE_REASON',
rating=None,
source_node_name='',
target_node_name='',
uuid_='c1c4e42e-2681-4616-9421-29e3a317f842',
valid_at='2024-09-15T00:00:00Z'
),
Fact(
created_at='2024-10-27T02:39:36.368034Z',
expired_at='2024-10-27T02:39:49.950056Z',
fact='Account Emily4a4f used card ending in 1234 for the transaction.',
invalid_at='2024-08-30T00:00:00Z',
name='USED_CARD',
rating=None,
source_node_name='',
target_node_name='',
uuid_='f59bac52-f5fa-4027-8765-b5c06634252c',
valid_at='2024-09-15T00:00:00Z'
),
Fact(
created_at='2024-10-27T02:39:47.625872Z',
expired_at=None,
fact='The account Emily4a4f had a transaction that failed.',
invalid_at=None,
name='TRANSACTION_STATUS',
rating=None,
source_node_name='',
target_node_name='',
uuid_='d81190d2-b354-4fbe-bbf9-a70cc990553e',
valid_at='2024-09-15T00:00:00Z'
)
]