sovant 1.1.0__py3-none-any.whl → 1.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sovant/__init__.py +1 -1
- sovant/client.py +127 -5
- {sovant-1.1.0.dist-info → sovant-1.3.0.dist-info}/METADATA +91 -2
- {sovant-1.1.0.dist-info → sovant-1.3.0.dist-info}/RECORD +7 -7
- {sovant-1.1.0.dist-info → sovant-1.3.0.dist-info}/WHEEL +0 -0
- {sovant-1.1.0.dist-info → sovant-1.3.0.dist-info}/licenses/LICENSE +0 -0
- {sovant-1.1.0.dist-info → sovant-1.3.0.dist-info}/top_level.txt +0 -0
sovant/__init__.py
CHANGED
sovant/client.py
CHANGED
|
@@ -131,7 +131,7 @@ class Sovant:
|
|
|
131
131
|
|
|
132
132
|
def memory_create(self, create: MemoryCreate):
|
|
133
133
|
# Convert data field to content field for API
|
|
134
|
-
body = create.model_dump()
|
|
134
|
+
body = create.model_dump(exclude_none=True)
|
|
135
135
|
if 'data' in body:
|
|
136
136
|
body['content'] = json.dumps(body.pop('data')) if not isinstance(body.get('data'), str) else body.pop('data')
|
|
137
137
|
|
|
@@ -162,9 +162,27 @@ class Sovant:
|
|
|
162
162
|
params['to_date'] = q.to_date
|
|
163
163
|
return self._request("GET", f"{self.base_url}/api/v1/memory/search", params=params)
|
|
164
164
|
|
|
165
|
-
def memory_recall(self,
|
|
166
|
-
"""
|
|
167
|
-
|
|
165
|
+
def memory_recall(self, query: str, thread_id: str | None = None, limit: int | None = None):
|
|
166
|
+
"""
|
|
167
|
+
Hybrid recall with profile awareness
|
|
168
|
+
|
|
169
|
+
Uses multi-stage pipeline (profile fast-path + lexical + semantic)
|
|
170
|
+
Guarantees profile facts (name/age/location) when available
|
|
171
|
+
|
|
172
|
+
Use recall() for conversational queries ("who am I?", "what do you know about me?")
|
|
173
|
+
Use memory_search() for pure semantic topic lookup
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
query: The search query (required)
|
|
177
|
+
thread_id: Optional thread context for thread-scoped recall
|
|
178
|
+
limit: Maximum results to return (default 8, max 50)
|
|
179
|
+
"""
|
|
180
|
+
params = {'query': query}
|
|
181
|
+
if thread_id:
|
|
182
|
+
params['thread_id'] = thread_id
|
|
183
|
+
if limit:
|
|
184
|
+
params['limit'] = str(limit)
|
|
185
|
+
return self._request("GET", f"{self.base_url}/api/v1/memory/recall", params=params)
|
|
168
186
|
|
|
169
187
|
def memory_update(self, id: str, patch: Dict[str, Any]):
|
|
170
188
|
# Convert data field to content field if present
|
|
@@ -199,4 +217,108 @@ class Sovant:
|
|
|
199
217
|
"data": data
|
|
200
218
|
})
|
|
201
219
|
|
|
202
|
-
return self._request("POST", f"{self.base_url}/api/v1/memory/batch", json=operations)
|
|
220
|
+
return self._request("POST", f"{self.base_url}/api/v1/memory/batch", json=operations)
|
|
221
|
+
|
|
222
|
+
# ==================== Thread Methods ====================
|
|
223
|
+
|
|
224
|
+
def threads_create(self, title: str, description: str | None = None, metadata: Dict[str, Any] | None = None):
|
|
225
|
+
"""
|
|
226
|
+
Create a new thread
|
|
227
|
+
|
|
228
|
+
Args:
|
|
229
|
+
title: Thread title (required)
|
|
230
|
+
description: Optional thread description
|
|
231
|
+
metadata: Optional metadata dictionary
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
Created thread object with id
|
|
235
|
+
"""
|
|
236
|
+
body = {"title": title}
|
|
237
|
+
if description:
|
|
238
|
+
body["description"] = description
|
|
239
|
+
if metadata:
|
|
240
|
+
body["metadata"] = metadata
|
|
241
|
+
return self._request("POST", f"{self.base_url}/api/v1/threads", json=body)
|
|
242
|
+
|
|
243
|
+
def threads_list(self, limit: int = 20, offset: int = 0, status: str | None = None):
|
|
244
|
+
"""
|
|
245
|
+
List threads with pagination
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
limit: Maximum number of threads to return (default: 20)
|
|
249
|
+
offset: Number of threads to skip (default: 0)
|
|
250
|
+
status: Filter by status: 'active', 'archived', or 'completed'
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
Paginated list of threads
|
|
254
|
+
"""
|
|
255
|
+
params = {"limit": str(limit), "offset": str(offset)}
|
|
256
|
+
if status:
|
|
257
|
+
params["status"] = status
|
|
258
|
+
return self._request("GET", f"{self.base_url}/api/v1/threads", params=params)
|
|
259
|
+
|
|
260
|
+
def threads_get(self, thread_id: str, include_memories: bool = False, limit: int = 50):
|
|
261
|
+
"""
|
|
262
|
+
Get a thread by ID
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
thread_id: Thread UUID
|
|
266
|
+
include_memories: If True, include full memory objects (default: False)
|
|
267
|
+
limit: Maximum number of memories to include (default: 50)
|
|
268
|
+
|
|
269
|
+
Returns:
|
|
270
|
+
Thread object with optional memories
|
|
271
|
+
"""
|
|
272
|
+
params = {}
|
|
273
|
+
if include_memories:
|
|
274
|
+
params["include_memories"] = "true"
|
|
275
|
+
params["limit"] = str(limit)
|
|
276
|
+
return self._request("GET", f"{self.base_url}/api/v1/threads/{thread_id}", params=params)
|
|
277
|
+
|
|
278
|
+
def threads_update(
|
|
279
|
+
self,
|
|
280
|
+
thread_id: str,
|
|
281
|
+
title: str | None = None,
|
|
282
|
+
description: str | None = None,
|
|
283
|
+
status: str | None = None,
|
|
284
|
+
metadata: Dict[str, Any] | None = None
|
|
285
|
+
):
|
|
286
|
+
"""
|
|
287
|
+
Update a thread
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
thread_id: Thread UUID
|
|
291
|
+
title: New title
|
|
292
|
+
description: New description
|
|
293
|
+
status: New status ('active', 'archived', or 'completed')
|
|
294
|
+
metadata: New metadata dictionary
|
|
295
|
+
|
|
296
|
+
Returns:
|
|
297
|
+
Updated thread object
|
|
298
|
+
"""
|
|
299
|
+
body = {}
|
|
300
|
+
if title is not None:
|
|
301
|
+
body["title"] = title
|
|
302
|
+
if description is not None:
|
|
303
|
+
body["description"] = description
|
|
304
|
+
if status is not None:
|
|
305
|
+
body["status"] = status
|
|
306
|
+
if metadata is not None:
|
|
307
|
+
body["metadata"] = metadata
|
|
308
|
+
return self._request("PUT", f"{self.base_url}/api/v1/threads/{thread_id}", json=body)
|
|
309
|
+
|
|
310
|
+
def threads_delete(self, thread_id: str, delete_memories: bool = False):
|
|
311
|
+
"""
|
|
312
|
+
Delete a thread
|
|
313
|
+
|
|
314
|
+
Args:
|
|
315
|
+
thread_id: Thread UUID
|
|
316
|
+
delete_memories: If True, also delete all associated memories (default: False)
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
Deletion confirmation
|
|
320
|
+
"""
|
|
321
|
+
params = {}
|
|
322
|
+
if delete_memories:
|
|
323
|
+
params["delete_memories"] = "true"
|
|
324
|
+
return self._request("DELETE", f"{self.base_url}/api/v1/threads/{thread_id}", params=params)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: sovant
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Sovant Memory-as-a-Service Python SDK
|
|
5
5
|
Author: Sovant
|
|
6
6
|
License: MIT
|
|
@@ -16,7 +16,8 @@ Dynamic: license-file
|
|
|
16
16
|
|
|
17
17
|
# Sovant Python SDK
|
|
18
18
|
|
|
19
|
-
Sovant is
|
|
19
|
+
**Sovant is a governed AI memory layer for AI agents and applications.**
|
|
20
|
+
Use it to store, search, and recall memories with profile awareness and enterprise-grade control over how memory is captured and used.
|
|
20
21
|
|
|
21
22
|
[](https://pypi.org/project/sovant/)
|
|
22
23
|
[](https://opensource.org/licenses/MIT)
|
|
@@ -57,6 +58,94 @@ updated = client.memory.update(mem["id"], {
|
|
|
57
58
|
client.memory.delete(mem["id"])
|
|
58
59
|
```
|
|
59
60
|
|
|
61
|
+
## Recall vs Search
|
|
62
|
+
|
|
63
|
+
Sovant provides two ways to query memories:
|
|
64
|
+
|
|
65
|
+
- **`memory_recall()`** – Hybrid recall, profile-aware
|
|
66
|
+
Use for conversational queries: "What do you know about me?", "What happened on Project X?".
|
|
67
|
+
Uses Sovant's hybrid pipeline (profile fast-path + thread-scoped lexical + vector semantic search) and prioritizes profile facts (name/age/location) when available.
|
|
68
|
+
|
|
69
|
+
- **`memory_search()`** – Semantic search
|
|
70
|
+
Use for topic lookup and discovery. Pure vector similarity search without profile logic.
|
|
71
|
+
Behavior unchanged from previous versions.
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
# Recall for conversational queries
|
|
75
|
+
context = client.memory_recall(
|
|
76
|
+
query="what do you know about me?",
|
|
77
|
+
limit=10
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# Search for topic discovery
|
|
81
|
+
topics = client.memory_search({
|
|
82
|
+
"query": "project updates",
|
|
83
|
+
"limit": 5
|
|
84
|
+
})
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Working with Threads
|
|
88
|
+
|
|
89
|
+
Threads let you organize related memories into conversations or sessions. Each thread has a `title` and can contain multiple memories.
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from sovant import Sovant
|
|
93
|
+
|
|
94
|
+
client = Sovant(api_key="sk_live_your_api_key_here")
|
|
95
|
+
|
|
96
|
+
# Create a new thread
|
|
97
|
+
thread = client.threads_create(
|
|
98
|
+
title="Project Alpha Discussion",
|
|
99
|
+
description="Q1 planning meeting notes",
|
|
100
|
+
metadata={"project": "alpha", "quarter": "Q1"}
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
# Store memories in the thread
|
|
104
|
+
from sovant.models import MemoryCreate
|
|
105
|
+
|
|
106
|
+
mem1 = client.memory_create(MemoryCreate(
|
|
107
|
+
data="Decided to launch in March",
|
|
108
|
+
type="journal",
|
|
109
|
+
thread_id=thread["id"]
|
|
110
|
+
))
|
|
111
|
+
|
|
112
|
+
mem2 = client.memory_create(MemoryCreate(
|
|
113
|
+
data="Budget approved: $50k",
|
|
114
|
+
type="insight",
|
|
115
|
+
thread_id=thread["id"]
|
|
116
|
+
))
|
|
117
|
+
|
|
118
|
+
# Recall memories from this specific thread
|
|
119
|
+
thread_memories = client.memory_recall(
|
|
120
|
+
query="launch date",
|
|
121
|
+
thread_id=thread["id"],
|
|
122
|
+
limit=10
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# Get thread with all its memories
|
|
126
|
+
thread_with_memories = client.threads_get(
|
|
127
|
+
thread["id"],
|
|
128
|
+
include_memories=True,
|
|
129
|
+
limit=50
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# List all threads
|
|
133
|
+
threads = client.threads_list(limit=20, offset=0)
|
|
134
|
+
|
|
135
|
+
# Update thread
|
|
136
|
+
updated = client.threads_update(
|
|
137
|
+
thread["id"],
|
|
138
|
+
title="Project Alpha - Q1 Launch",
|
|
139
|
+
status="completed"
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# Delete thread (keeps memories by default)
|
|
143
|
+
client.threads_delete(thread["id"])
|
|
144
|
+
|
|
145
|
+
# Delete thread AND all its memories
|
|
146
|
+
client.threads_delete(thread["id"], delete_memories=True)
|
|
147
|
+
```
|
|
148
|
+
|
|
60
149
|
## Chat in 60 Seconds
|
|
61
150
|
|
|
62
151
|
Stream real-time chat responses with memory context:
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
sovant/__init__.py,sha256=
|
|
1
|
+
sovant/__init__.py,sha256=u5rAQYbVb4cDn8QvmJB-VusRtSXzQsFH6bAJrBMvvNI,122
|
|
2
2
|
sovant/base_client.py,sha256=Vmn6OGywGwLbH5cEeflSjVOFwn5iX_YdfTdUq9pWWxA,8778
|
|
3
|
-
sovant/client.py,sha256=
|
|
3
|
+
sovant/client.py,sha256=8VnTPSli1QgRky9PqUb9OAKdbMPTfXlGoUkmAYsFfCw,11804
|
|
4
4
|
sovant/exceptions.py,sha256=MQMSgk7ckXnAbe7hPPpbKOnRBHSPxuCY7WSjqfJAvd0,1557
|
|
5
5
|
sovant/models.py,sha256=avDAITMptDDdDfNH_ed854Q7kF6z_1OzjwJ9Xeft_-8,979
|
|
6
6
|
sovant/types.py,sha256=gnvdXksJt8LObti7nc6eHSBCB7Pz7SNpS5o_HRTq_kA,6098
|
|
7
7
|
sovant/resources/__init__.py,sha256=cPFIM7h8duviDdeHudnVEAmv3F89RHQxdH5BCRWFteQ,193
|
|
8
8
|
sovant/resources/memories.py,sha256=bKKE0uWqFkPa1OEvbK1LrdSD7v6N04RhJ_2VDoPPQBA,11379
|
|
9
9
|
sovant/resources/threads.py,sha256=mN29xP0JODmZBKyfhpeqJyViUWNVMAx3TlYAW-1ruTs,12558
|
|
10
|
-
sovant-1.
|
|
11
|
-
sovant-1.
|
|
12
|
-
sovant-1.
|
|
13
|
-
sovant-1.
|
|
14
|
-
sovant-1.
|
|
10
|
+
sovant-1.3.0.dist-info/licenses/LICENSE,sha256=rnNP6-elrMIlQ9jf2aqnHZMyyQ_wvF3y1hTpVUusCWU,1062
|
|
11
|
+
sovant-1.3.0.dist-info/METADATA,sha256=6-_NLCFzejStKM-YRnzYNXBLh9WWoNyO4K6cYvr02W4,14201
|
|
12
|
+
sovant-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
13
|
+
sovant-1.3.0.dist-info/top_level.txt,sha256=za6eVEsYd_ZQQs8vrmEWNcAR58r1wCDge_jA60e4CvQ,7
|
|
14
|
+
sovant-1.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|