Skip to content

Commit 60b2a84

Browse files
authored
session metadata (#48)
* connection timeout, better url concatentation, improve docs, improve session_id checks * add /get session * add Session to examples
1 parent aa94523 commit 60b2a84

File tree

5 files changed

+386
-21
lines changed

5 files changed

+386
-21
lines changed

examples/async.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
NotFoundError,
1818
ZepClient,
1919
)
20+
from zep_python.models import Session
2021

2122

2223
async def main() -> None:
@@ -25,6 +26,39 @@ async def main() -> None:
2526
async with ZepClient(base_url, api_key) as client:
2627
session_id = uuid.uuid4().hex
2728

29+
#
30+
# Create session
31+
#
32+
print(f"Creating session: {session_id}")
33+
try:
34+
session = Session(session_id=session_id, metadata={"foo": "bar"})
35+
result = await client.aadd_session(session)
36+
print(result)
37+
except APIError as e:
38+
print(f"Unable to create session {session_id} got error: {e}")
39+
40+
#
41+
# Update session metadata
42+
#
43+
print(f"Creating session: {session_id}")
44+
try:
45+
# The new metadata values will be merged with the existing metadata
46+
session = Session(session_id=session_id, metadata={"bar": "foo"})
47+
result = await client.aadd_session(session)
48+
print(result)
49+
except APIError as e:
50+
print(f"Unable to create session {session_id} got error: {e}")
51+
52+
#
53+
# Get session
54+
#
55+
print(f"Getting session: {session_id}")
56+
try:
57+
session = await client.aget_session(session_id)
58+
print(session.dict())
59+
except NotFoundError:
60+
print("Session not found")
61+
2862
print(f"\n1---getMemory for Session: {session_id}")
2963
try:
3064
memory = await client.aget_memory(session_id)

examples/sync.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
NotFoundError,
1717
ZepClient,
1818
)
19+
from zep_python.models import Session
1920

2021

2122
def main() -> None:
@@ -25,6 +26,39 @@ def main() -> None:
2526
# Example usage
2627
session_id = uuid.uuid4().hex
2728

29+
#
30+
# Create session
31+
#
32+
print(f"Creating session: {session_id}")
33+
try:
34+
session = Session(session_id=session_id, metadata={"foo": "bar"})
35+
result = client.add_session(session)
36+
print(result)
37+
except APIError as e:
38+
print(f"Unable to create session {session_id} got error: {e}")
39+
40+
#
41+
# Update session metadata
42+
#
43+
print(f"Creating session: {session_id}")
44+
try:
45+
# The new metadata values will be merged with the existing metadata
46+
session = Session(session_id=session_id, metadata={"bar": "foo"})
47+
result = client.add_session(session)
48+
print(result)
49+
except APIError as e:
50+
print(f"Unable to create session {session_id} got error: {e}")
51+
52+
#
53+
# Get session
54+
#
55+
print(f"Getting session: {session_id}")
56+
try:
57+
session = client.get_session(session_id)
58+
print(session.dict())
59+
except NotFoundError:
60+
print("Session not found")
61+
2862
#
2963
# Get memory
3064
#

tests/client_test.py

Lines changed: 101 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
from pytest_httpx import HTTPXMock
77

88
from zep_python import NotFoundError
9-
from zep_python.models import Memory, MemorySearchPayload, Message
9+
from zep_python.models import Memory, MemorySearchPayload, Message, Session
1010
from zep_python.zep_client import ZepClient
1111

1212
api_base_url = "http://localhost/api/v1"
1313

14-
mock_response = {
14+
mock_messages = {
1515
"messages": [
1616
{
1717
"uuid": "msg-uuid",
@@ -60,15 +60,15 @@ def filter_unset_fields(d: Dict) -> Dict:
6060

6161

6262
def validate_memory(memory: Memory):
63-
assert len(memory.messages) == len(mock_response["messages"])
63+
assert len(memory.messages) == len(mock_messages["messages"])
6464

6565
for i in range(len(memory.messages)):
66-
assert memory.messages[i].uuid == mock_response["messages"][i]["uuid"]
67-
assert memory.messages[i].role == mock_response["messages"][i]["role"]
68-
assert memory.messages[i].content == mock_response["messages"][i]["content"]
69-
assert memory.messages[i].metadata == mock_response["messages"][i]["metadata"]
66+
assert memory.messages[i].uuid == mock_messages["messages"][i]["uuid"]
67+
assert memory.messages[i].role == mock_messages["messages"][i]["role"]
68+
assert memory.messages[i].content == mock_messages["messages"][i]["content"]
69+
assert memory.messages[i].metadata == mock_messages["messages"][i]["metadata"]
7070

71-
assert filter_unset_fields(memory.dict()) == mock_response
71+
assert filter_unset_fields(memory.dict()) == mock_messages
7272

7373

7474
@pytest.mark.asyncio
@@ -87,7 +87,7 @@ async def test_set_authorization_header(httpx_mock):
8787
async def test_aget_memory(httpx_mock: HTTPXMock):
8888
session_id = str(uuid4())
8989

90-
httpx_mock.add_response(status_code=200, json=mock_response)
90+
httpx_mock.add_response(status_code=200, json=mock_messages)
9191

9292
async with ZepClient(base_url=api_base_url) as client:
9393
memory = await client.aget_memory(session_id)
@@ -132,7 +132,7 @@ async def test_aget_memory_missing_values(httpx_mock: HTTPXMock):
132132
def test_get_memory(httpx_mock: HTTPXMock):
133133
session_id = str(uuid4())
134134

135-
httpx_mock.add_response(status_code=200, json=mock_response)
135+
httpx_mock.add_response(status_code=200, json=mock_messages)
136136

137137
with ZepClient(base_url=api_base_url) as client:
138138
memory = client.get_memory(session_id)
@@ -267,3 +267,94 @@ def test_search_memory(httpx_mock: HTTPXMock):
267267
assert search_results[0].message["role"] == "user"
268268
assert search_results[0].message["content"] == "Test message"
269269
assert search_results[0].dist == 0.9
270+
271+
272+
# Predefined session response
273+
mock_session = {
274+
"uuid": str(uuid4()),
275+
"created_at": "2020-12-31T23:59:59",
276+
"updated_at": "2021-01-01T00:00:00",
277+
"deleted_at": None,
278+
"session_id": "abc123",
279+
"metadata": {},
280+
}
281+
282+
283+
def validate_session(session):
284+
# Validate the session object here
285+
assert Session.parse_obj(mock_session) == session
286+
287+
288+
@pytest.mark.asyncio
289+
async def test_get_session(httpx_mock: HTTPXMock):
290+
session_id = "abc123"
291+
292+
httpx_mock.add_response(status_code=200, json=mock_session)
293+
294+
client = ZepClient(base_url=api_base_url)
295+
session = client.get_session(session_id)
296+
297+
validate_session(session)
298+
299+
300+
def test_get_session_missing_id():
301+
client = ZepClient(base_url=api_base_url)
302+
303+
with pytest.raises(ValueError):
304+
client.get_session(session_id=None) # type: ignore
305+
306+
307+
@pytest.mark.asyncio
308+
async def test_aget_session(httpx_mock: HTTPXMock):
309+
session_id = "abc123"
310+
311+
httpx_mock.add_response(status_code=200, json=mock_session)
312+
313+
async with ZepClient(base_url=api_base_url) as client:
314+
session = await client.aget_session(session_id)
315+
316+
validate_session(session)
317+
318+
319+
@pytest.mark.asyncio
320+
async def test_aget_session_missing_id(httpx_mock: HTTPXMock):
321+
async with ZepClient(base_url=api_base_url) as client:
322+
with pytest.raises(ValueError):
323+
_ = await client.aget_session(session_id=None) # type: ignore
324+
325+
326+
def test_add_session(httpx_mock: HTTPXMock):
327+
session = Session(**mock_session)
328+
329+
httpx_mock.add_response(status_code=200, text="OK")
330+
331+
client = ZepClient(base_url=api_base_url)
332+
result = client.add_session(session)
333+
334+
assert result == "OK"
335+
336+
337+
def test_add_session_missing_session():
338+
client = ZepClient(base_url=api_base_url)
339+
340+
with pytest.raises(ValueError):
341+
client.add_session(session=None) # type: ignore
342+
343+
344+
@pytest.mark.asyncio
345+
async def test_aadd_session(httpx_mock: HTTPXMock):
346+
session = Session(**mock_session)
347+
348+
httpx_mock.add_response(status_code=200, text="OK")
349+
350+
async with ZepClient(base_url=api_base_url) as client:
351+
result = await client.aadd_session(session)
352+
353+
assert result == "OK"
354+
355+
356+
@pytest.mark.asyncio
357+
async def test_aadd_session_missing_session(httpx_mock: HTTPXMock):
358+
async with ZepClient(base_url=api_base_url) as client:
359+
with pytest.raises(ValueError):
360+
_ = await client.aadd_session(session=None) # type: ignore

zep_python/models.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,39 @@
55
from pydantic import BaseModel, Field
66

77

8+
class Session(BaseModel):
9+
"""
10+
Represents a session object with a unique identifier, metadata,
11+
and other attributes.
12+
13+
Attributes
14+
----------
15+
uuid : Optional[str]
16+
A unique identifier for the session.
17+
This is generated server-side and is not expected to be present on creation.
18+
created_at : str
19+
The timestamp when the session was created.
20+
Generated by the server.
21+
updated_at : str
22+
The timestamp when the session was last updated.
23+
Generated by the server.
24+
deleted_at : Optional[datetime]
25+
The timestamp when the session was deleted.
26+
Generated by the server.
27+
session_id : str
28+
The unique identifier of the session.
29+
metadata : Dict[str, Any]
30+
The metadata associated with the session.
31+
"""
32+
33+
uuid: Optional[str]
34+
created_at: Optional[str]
35+
updated_at: Optional[str]
36+
deleted_at: Optional[str]
37+
session_id: str
38+
metadata: Dict[str, Any]
39+
40+
841
class Summary(BaseModel):
942
"""
1043
Represents a summary of a conversation.

0 commit comments

Comments
 (0)