sovant 1.0.0__py3-none-any.whl → 1.0.3__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 CHANGED
@@ -1,63 +1,4 @@
1
- """
2
- Sovant Python SDK
1
+ from .client import Sovant, SovantError
2
+ from .models import MemoryCreate, MemoryResult, SearchQuery
3
3
 
4
- Official Python library for the Sovant Memory API.
5
- """
6
-
7
- __version__ = "1.0.0"
8
-
9
- from .client import SovantClient, AsyncSovantClient
10
- from .exceptions import (
11
- SovantError,
12
- AuthenticationError,
13
- RateLimitError,
14
- ValidationError,
15
- NotFoundError,
16
- NetworkError,
17
- )
18
- from .types import (
19
- Memory,
20
- MemoryType,
21
- EmotionType,
22
- EmotionalContext,
23
- CreateMemoryInput,
24
- UpdateMemoryInput,
25
- SearchOptions,
26
- SearchResult,
27
- Thread,
28
- ThreadStatus,
29
- CreateThreadInput,
30
- UpdateThreadInput,
31
- ThreadStats,
32
- BatchCreateResult,
33
- PaginatedResponse,
34
- )
35
-
36
- __all__ = [
37
- # Client classes
38
- "SovantClient",
39
- "AsyncSovantClient",
40
- # Exceptions
41
- "SovantError",
42
- "AuthenticationError",
43
- "RateLimitError",
44
- "ValidationError",
45
- "NotFoundError",
46
- "NetworkError",
47
- # Types
48
- "Memory",
49
- "MemoryType",
50
- "EmotionType",
51
- "EmotionalContext",
52
- "CreateMemoryInput",
53
- "UpdateMemoryInput",
54
- "SearchOptions",
55
- "SearchResult",
56
- "Thread",
57
- "ThreadStatus",
58
- "CreateThreadInput",
59
- "UpdateThreadInput",
60
- "ThreadStats",
61
- "BatchCreateResult",
62
- "PaginatedResponse",
63
- ]
4
+ __version__ = "0.1.0"
sovant/client.py CHANGED
@@ -1,87 +1,90 @@
1
- """Main client for the Sovant SDK."""
1
+ import os
2
+ import json
3
+ import httpx
4
+ from typing import Any, Dict
5
+ from .models import MemoryCreate, SearchQuery
2
6
 
3
- from typing import Any, Dict, Union
7
+ class SovantError(Exception):
8
+ def __init__(self, message: str, code: str, status: int | None = None, details: Any | None = None):
9
+ super().__init__(message)
10
+ self.code = code
11
+ self.status = status
12
+ self.details = details
4
13
 
5
- from .base_client import AsyncBaseClient, BaseClient
6
- from .resources import AsyncMemories, AsyncThreads, Memories, Threads
7
- from .types import Config
14
+ class Sovant:
15
+ def __init__(self, api_key: str | None = None, base_url: str | None = None, timeout: float = 30.0):
16
+ self.api_key = api_key or os.getenv("SOVANT_API_KEY")
17
+ if not self.api_key:
18
+ raise ValueError("Missing api_key")
19
+ self.base_url = (base_url or os.getenv("SOVANT_BASE_URL") or "https://api.sovant.ai").rstrip("/")
20
+ self.timeout = timeout
21
+ self._client = httpx.Client(
22
+ timeout=self.timeout,
23
+ headers={
24
+ "authorization": f"Bearer {self.api_key}",
25
+ "content-type": "application/json"
26
+ }
27
+ )
8
28
 
29
+ def _handle(self, r: httpx.Response):
30
+ if r.status_code >= 400:
31
+ try:
32
+ body = r.json()
33
+ except Exception:
34
+ body = {"message": r.text}
35
+ msg = body.get("message") or r.reason_phrase
36
+ code = body.get("code") or f"HTTP_{r.status_code}"
37
+ raise SovantError(msg, code, r.status_code, body)
38
+ if not r.text:
39
+ return None
40
+ try:
41
+ return r.json()
42
+ except Exception:
43
+ return r.text
9
44
 
10
- class SovantClient:
11
- """Synchronous client for the Sovant API."""
12
-
13
- def __init__(self, api_key: Union[str, Config, None] = None):
14
- """
15
- Initialize the Sovant client.
45
+ def memory_create(self, create: MemoryCreate):
46
+ # Convert data field to content field for API
47
+ body = create.model_dump()
48
+ if 'data' in body:
49
+ body['content'] = json.dumps(body.pop('data')) if not isinstance(body.get('data'), str) else body.pop('data')
16
50
 
17
- Args:
18
- api_key: API key string, Config object, or None (uses env var)
19
- """
20
- if api_key is None:
21
- import os
22
- api_key = os.environ.get("SOVANT_API_KEY", "")
23
-
24
- if isinstance(api_key, str):
25
- config = Config(api_key=api_key)
26
- else:
27
- config = api_key
28
-
29
- self.memories = Memories(config)
30
- self.threads = Threads(config)
31
- self._config = config
32
-
33
- def ping(self) -> Dict[str, str]:
34
- """Test API connection."""
35
- client = BaseClient(self._config)
36
- return client.request("GET", "/health")
37
-
38
- def get_usage(self) -> Dict[str, Any]:
39
- """Get current API usage and quota."""
40
- client = BaseClient(self._config)
41
- return client.request("GET", "/usage")
51
+ # Ensure type has a default
52
+ if 'type' not in body or body['type'] is None:
53
+ body['type'] = 'journal'
54
+
55
+ r = self._client.post(f"{self.base_url}/v1/memory", content=json.dumps(body))
56
+ return self._handle(r)
42
57
 
58
+ def memory_get(self, id: str):
59
+ r = self._client.get(f"{self.base_url}/v1/memories/{id}")
60
+ return self._handle(r)
43
61
 
44
- class AsyncSovantClient:
45
- """Asynchronous client for the Sovant API."""
46
-
47
- def __init__(self, api_key: Union[str, Config, None] = None):
48
- """
49
- Initialize the async Sovant client.
50
-
51
- Args:
52
- api_key: API key string, Config object, or None (uses env var)
53
- """
54
- if api_key is None:
55
- import os
56
- api_key = os.environ.get("SOVANT_API_KEY", "")
57
-
58
- if isinstance(api_key, str):
59
- config = Config(api_key=api_key)
60
- else:
61
- config = api_key
62
-
63
- self.memories = AsyncMemories(config)
64
- self.threads = AsyncThreads(config)
65
- self._config = config
66
-
67
- async def ping(self) -> Dict[str, str]:
68
- """Test API connection."""
69
- async with AsyncBaseClient(self._config) as client:
70
- return await client.request("GET", "/health")
71
-
72
- async def get_usage(self) -> Dict[str, Any]:
73
- """Get current API usage and quota."""
74
- async with AsyncBaseClient(self._config) as client:
75
- return await client.request("GET", "/usage")
76
-
77
- async def __aenter__(self):
78
- """Context manager entry."""
79
- return self
80
-
81
- async def __aexit__(self, exc_type, exc_val, exc_tb):
82
- """Context manager exit."""
83
- # Clean up any open connections
84
- if hasattr(self.memories, "client"):
85
- await self.memories.client.aclose()
86
- if hasattr(self.threads, "client"):
87
- await self.threads.client.aclose()
62
+ def memory_search(self, q: SearchQuery):
63
+ params = {}
64
+ if q.query:
65
+ params['query'] = q.query
66
+ if q.type:
67
+ params['type'] = q.type
68
+ if q.tags:
69
+ params['tags'] = ','.join(q.tags)
70
+ if q.thread_id:
71
+ params['thread_id'] = q.thread_id
72
+ if q.limit:
73
+ params['limit'] = str(q.limit)
74
+ if q.from_date:
75
+ params['from_date'] = q.from_date
76
+ if q.to_date:
77
+ params['to_date'] = q.to_date
78
+ r = self._client.get(f"{self.base_url}/v1/memory/search", params=params)
79
+ return self._handle(r)
80
+
81
+ def memory_update(self, id: str, patch: Dict[str, Any]):
82
+ # Convert data field to content field if present
83
+ if 'data' in patch:
84
+ patch['content'] = json.dumps(patch.pop('data')) if not isinstance(patch.get('data'), str) else patch.pop('data')
85
+ r = self._client.patch(f"{self.base_url}/v1/memories/{id}", content=json.dumps(patch))
86
+ return self._handle(r)
87
+
88
+ def memory_delete(self, id: str):
89
+ r = self._client.delete(f"{self.base_url}/v1/memories/{id}")
90
+ return self._handle(r)
sovant/models.py ADDED
@@ -0,0 +1,30 @@
1
+ from pydantic import BaseModel, Field
2
+ from typing import Any, Dict, List, Optional, Literal
3
+
4
+ class MemoryCreate(BaseModel):
5
+ data: Any
6
+ type: Optional[Literal['journal', 'insight', 'observation', 'task', 'preference']] = 'journal'
7
+ ttl: Optional[str] = None
8
+ tags: Optional[List[str]] = None
9
+ metadata: Optional[Dict[str, Any]] = None
10
+ thread_id: Optional[str] = None
11
+
12
+ class MemoryResult(BaseModel):
13
+ id: str
14
+ content: str
15
+ type: str
16
+ ttl: Optional[str] = None
17
+ tags: Optional[List[str]] = None
18
+ metadata: Optional[Dict[str, Any]] = None
19
+ thread_id: Optional[str] = None
20
+ created_at: Optional[str] = None
21
+ updated_at: Optional[str] = None
22
+
23
+ class SearchQuery(BaseModel):
24
+ query: Optional[str] = None
25
+ type: Optional[str] = None
26
+ tags: Optional[List[str]] = None
27
+ thread_id: Optional[str] = None
28
+ limit: Optional[int] = Field(default=10, ge=1, le=100)
29
+ from_date: Optional[str] = None
30
+ to_date: Optional[str] = None
@@ -0,0 +1,118 @@
1
+ Metadata-Version: 2.4
2
+ Name: sovant
3
+ Version: 1.0.3
4
+ Summary: Sovant Memory-as-a-Service Python SDK
5
+ Author: Sovant
6
+ License: MIT
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: httpx>=0.27.0
11
+ Requires-Dist: pydantic>=2.8.2
12
+ Dynamic: license-file
13
+
14
+ # Sovant Python SDK
15
+
16
+ **AI Infrastructure: Memory-as-a-Service for AI systems.**
17
+ The official Python client for the Sovant Memory API.
18
+
19
+ [![PyPI version](https://img.shields.io/pypi/v/sovant)](https://pypi.org/project/sovant/)
20
+ [![Documentation](https://img.shields.io/badge/docs-sovant.ai-blue)](https://sovant.ai/docs)
21
+ [![GitHub](https://img.shields.io/badge/github-sovant-lightgrey)](https://github.com/sovant-ai/sovant)
22
+
23
+ ---
24
+
25
+ ## What is Sovant?
26
+
27
+ Sovant is an **AI infrastructure company** providing the **memory layer for AI systems**.
28
+ Our platform makes it simple to persist, search, and manage conversational/context data securely across sessions, channels, and applications.
29
+
30
+ - **Problem:** Most AI systems forget once a session ends → compliance risk, knowledge loss, poor UX.
31
+ - **Solution:** Sovant provides a **Memory-as-a-Service API** — store, retrieve, and search memories with audit-ready controls.
32
+ - **Built for:** Developers & enterprises building AI agents, copilots, or compliance-driven apps that need persistent context.
33
+
34
+ ---
35
+
36
+ ## Installation
37
+
38
+ ```bash
39
+ pip install sovant
40
+ ```
41
+
42
+ ## 60-Second Quickstart
43
+
44
+ ```python
45
+ from sovant import Sovant, MemoryCreate, SearchQuery
46
+
47
+ client = Sovant(api_key="YOUR_API_KEY")
48
+
49
+ # Create a memory
50
+ created = client.memory_create(MemoryCreate(
51
+ content="User prefers morning meetings",
52
+ type="preference",
53
+ tags=["customer:123"],
54
+ # metadata={"source": "crm"},
55
+ # thread_id="00000000-0000-0000-0000-000000000000",
56
+ ))
57
+ print(created)
58
+
59
+ # Search memories
60
+ results = client.memory_search(SearchQuery(
61
+ query="meeting preferences",
62
+ topK=3,
63
+ # tags=["customer:123"],
64
+ # thread_id="...",
65
+ ))
66
+ print(results)
67
+ ```
68
+
69
+ ## Features
70
+
71
+ - **Memory CRUD** — create, retrieve, update (PATCH/PUT), delete
72
+ - **Semantic Search** — full-text/semantic with topK and filters
73
+ - **Threads** — group related memories via thread_id (REST API)
74
+ - **Batch Operations (Beta)** — atomic multi-operation requests
75
+ - **Compliance-ready** — audit trails, PDPA/GDPR-friendly design
76
+ - **SDKs** — official Python & TypeScript clients + REST reference
77
+
78
+ ## SDKs & Documentation
79
+
80
+ - **Python** (this package) on PyPI: https://pypi.org/project/sovant/
81
+ - **TypeScript** on npm: https://www.npmjs.com/package/@sovant/sdk
82
+ - **REST API Reference**: https://sovant.ai/docs/api
83
+ - **Full Documentation**: https://sovant.ai/docs
84
+
85
+ ## API Overview
86
+
87
+ ### Endpoints Summary
88
+
89
+ - `POST /api/v1/memory` — Create memory
90
+ - `GET /api/v1/memory` — List memories
91
+ - `GET /api/v1/memories/{id}` — Get by ID
92
+ - `PATCH | PUT /api/v1/memories/{id}` — Update
93
+ - `DELETE /api/v1/memories/{id}` — Delete
94
+ - `GET /api/v1/memory/search` — Search
95
+ - `POST /api/v1/memory/batch` — Batch (Beta)
96
+
97
+ **Auth:** Bearer token in the `Authorization` header.
98
+
99
+ ## Field Mapping Note
100
+
101
+ - **API expects:** `content` (required), optional `type`, `tags`, `metadata`, `thread_id`.
102
+ - **SDK convenience:** Some client methods may accept `data` and map it to `content` internally.
103
+ - **Deprecated:** `subject` is ignored by the API. Use `thread_id`, `tags`, or `metadata` for grouping.
104
+
105
+ ## Status of Advanced Features
106
+
107
+ - **Batch API:** Available, marked Beta (contract may evolve).
108
+ - **Threads:** Fully supported via REST API.
109
+ - **Webhooks / Personalization / Multi-Channel Sync:** Coming soon.
110
+
111
+ ## Versioning & Changelog
112
+
113
+ - **Stable baseline:** 1.0.3
114
+ - See [CHANGELOG.md](https://github.com/sovant-ai/sovant) in the repo for details.
115
+
116
+ ## License
117
+
118
+ MIT © Sovant AI
@@ -0,0 +1,14 @@
1
+ sovant/__init__.py,sha256=1GYQzmb1Ni5-y874HOs1J-rYrpx-iBzR4_cCEBFIjpk,122
2
+ sovant/base_client.py,sha256=Vmn6OGywGwLbH5cEeflSjVOFwn5iX_YdfTdUq9pWWxA,8778
3
+ sovant/client.py,sha256=QmcUnK_IFXIE9VbvNy3VeI8rsGeeJpLkUvB-721VNBY,3356
4
+ sovant/exceptions.py,sha256=MQMSgk7ckXnAbe7hPPpbKOnRBHSPxuCY7WSjqfJAvd0,1557
5
+ sovant/models.py,sha256=avDAITMptDDdDfNH_ed854Q7kF6z_1OzjwJ9Xeft_-8,979
6
+ sovant/types.py,sha256=gnvdXksJt8LObti7nc6eHSBCB7Pz7SNpS5o_HRTq_kA,6098
7
+ sovant/resources/__init__.py,sha256=cPFIM7h8duviDdeHudnVEAmv3F89RHQxdH5BCRWFteQ,193
8
+ sovant/resources/memories.py,sha256=bKKE0uWqFkPa1OEvbK1LrdSD7v6N04RhJ_2VDoPPQBA,11379
9
+ sovant/resources/threads.py,sha256=mN29xP0JODmZBKyfhpeqJyViUWNVMAx3TlYAW-1ruTs,12558
10
+ sovant-1.0.3.dist-info/licenses/LICENSE,sha256=rnNP6-elrMIlQ9jf2aqnHZMyyQ_wvF3y1hTpVUusCWU,1062
11
+ sovant-1.0.3.dist-info/METADATA,sha256=ul2TZUpPijkKMc0ySZn7goqy_5VDzFuj-y7KzZI5zew,3757
12
+ sovant-1.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
13
+ sovant-1.0.3.dist-info/top_level.txt,sha256=za6eVEsYd_ZQQs8vrmEWNcAR58r1wCDge_jA60e4CvQ,7
14
+ sovant-1.0.3.dist-info/RECORD,,
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Sovant AI
3
+ Copyright (c) 2025 Sovant
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,492 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: sovant
3
- Version: 1.0.0
4
- Summary: Official Python SDK for Sovant Memory API
5
- Author-email: Sovant AI <support@sovant.ai>
6
- License: MIT License
7
-
8
- Copyright (c) 2024 Sovant AI
9
-
10
- Permission is hereby granted, free of charge, to any person obtaining a copy
11
- of this software and associated documentation files (the "Software"), to deal
12
- in the Software without restriction, including without limitation the rights
13
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
- copies of the Software, and to permit persons to whom the Software is
15
- furnished to do so, subject to the following conditions:
16
-
17
- The above copyright notice and this permission notice shall be included in all
18
- copies or substantial portions of the Software.
19
-
20
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
- SOFTWARE.
27
- Project-URL: Homepage, https://sovant.ai
28
- Project-URL: Documentation, https://docs.sovant.ai
29
- Project-URL: Repository, https://github.com/sovant-ai/python-sdk
30
- Project-URL: Issues, https://github.com/sovant-ai/python-sdk/issues
31
- Keywords: sovant,memory,api,ai,sdk
32
- Classifier: Development Status :: 4 - Beta
33
- Classifier: Intended Audience :: Developers
34
- Classifier: License :: OSI Approved :: MIT License
35
- Classifier: Programming Language :: Python :: 3
36
- Classifier: Programming Language :: Python :: 3.8
37
- Classifier: Programming Language :: Python :: 3.9
38
- Classifier: Programming Language :: Python :: 3.10
39
- Classifier: Programming Language :: Python :: 3.11
40
- Classifier: Programming Language :: Python :: 3.12
41
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
42
- Requires-Python: >=3.8
43
- Description-Content-Type: text/markdown
44
- License-File: LICENSE
45
- Requires-Dist: httpx>=0.25.0
46
- Requires-Dist: pydantic>=2.0.0
47
- Requires-Dist: python-dateutil>=2.8.0
48
- Provides-Extra: async
49
- Requires-Dist: httpx[http2]; extra == "async"
50
- Provides-Extra: dev
51
- Requires-Dist: pytest>=7.0.0; extra == "dev"
52
- Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
53
- Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
54
- Requires-Dist: black>=23.0.0; extra == "dev"
55
- Requires-Dist: mypy>=1.0.0; extra == "dev"
56
- Requires-Dist: ruff>=0.1.0; extra == "dev"
57
- Dynamic: license-file
58
-
59
- # Sovant Python SDK
60
-
61
- Official Python SDK for the Sovant Memory API. Build AI applications with persistent memory, semantic search, and intelligent context management.
62
-
63
- > **Note: Coming Soon!** This SDK is currently in development and will be available on PyPI soon. In the meantime, you can use our REST API directly.
64
-
65
- ## Installation
66
-
67
- ```bash
68
- # Coming soon
69
- pip install sovant
70
- ```
71
-
72
- For async support:
73
-
74
- ```bash
75
- # Coming soon
76
- pip install sovant[async]
77
- ```
78
-
79
- ## Quick Start
80
-
81
- ```python
82
- from sovant import SovantClient
83
-
84
- # Initialize the client
85
- client = SovantClient(api_key="YOUR_API_KEY")
86
-
87
- # Create a memory
88
- memory = client.memories.create({
89
- "content": "User prefers Python for data science projects",
90
- "type": "preference",
91
- "metadata": {
92
- "confidence": 0.95,
93
- "context": "programming_languages"
94
- }
95
- })
96
-
97
- print(f"Created memory: {memory.id}")
98
-
99
- # Search memories
100
- results = client.memories.search({
101
- "query": "What programming languages does the user prefer?",
102
- "limit": 5
103
- })
104
-
105
- for result in results:
106
- print(f"- {result.content} (relevance: {result.relevance_score:.2f})")
107
- ```
108
-
109
- ## Features
110
-
111
- - 🐍 **Full Type Hints** - Complete type annotations for better IDE support
112
- - 🔄 **Async/Await Support** - Built for modern Python applications
113
- - 🔁 **Automatic Retries** - Configurable retry logic with exponential backoff
114
- - 📦 **Batch Operations** - Efficient bulk create/delete operations
115
- - 🎯 **Smart Search** - Semantic, keyword, and hybrid search modes
116
- - 🧵 **Thread Management** - Organize memories into contextual threads
117
- - 📊 **Analytics** - Built-in insights and statistics
118
- - 🛡️ **Comprehensive Error Handling** - Typed exceptions for all error cases
119
-
120
- ## Configuration
121
-
122
- ```python
123
- from sovant import SovantClient, Config
124
-
125
- # Using configuration object
126
- config = Config(
127
- api_key="YOUR_API_KEY",
128
- base_url="https://api.sovant.ai/v1", # Optional
129
- timeout=30, # Request timeout in seconds
130
- max_retries=3, # Number of retries for failed requests
131
- retry_delay=1.0 # Initial delay between retries
132
- )
133
-
134
- client = SovantClient(config)
135
- ```
136
-
137
- You can also use environment variables:
138
-
139
- ```bash
140
- export SOVANT_API_KEY="YOUR_API_KEY"
141
- ```
142
-
143
- ```python
144
- from sovant import SovantClient
145
-
146
- # Automatically reads from SOVANT_API_KEY env var
147
- client = SovantClient()
148
- ```
149
-
150
- ## Memory Operations
151
-
152
- ### Create a Memory
153
-
154
- ```python
155
- from sovant import MemoryType, EmotionType
156
-
157
- memory = client.memories.create({
158
- "content": "User completed the onboarding tutorial",
159
- "type": MemoryType.EVENT,
160
- "importance": 0.8,
161
- "metadata": {
162
- "step_completed": "tutorial",
163
- "duration_seconds": 180
164
- },
165
- "tags": ["onboarding", "milestone"],
166
- "emotion": {
167
- "type": EmotionType.POSITIVE,
168
- "intensity": 0.7
169
- },
170
- "action_items": ["Send welcome email", "Unlock advanced features"]
171
- })
172
- ```
173
-
174
- ### Update a Memory
175
-
176
- ```python
177
- updated = client.memories.update(memory.id, {
178
- "importance": 0.9,
179
- "follow_up_required": True,
180
- "follow_up_due": "2024-12-31T23:59:59Z"
181
- })
182
- ```
183
-
184
- ### Search Memories
185
-
186
- ```python
187
- # Semantic search
188
- semantic_results = client.memories.search({
189
- "query": "user achievements and milestones",
190
- "search_type": "semantic",
191
- "limit": 10
192
- })
193
-
194
- # Filtered search
195
- from sovant import MemoryType
196
-
197
- filtered_results = client.memories.search({
198
- "query": "preferences",
199
- "type": [MemoryType.PREFERENCE, MemoryType.DECISION],
200
- "tags": ["important"],
201
- "created_after": "2024-01-01",
202
- "sort_by": "importance",
203
- "sort_order": "desc"
204
- })
205
- ```
206
-
207
- ### Batch Operations
208
-
209
- ```python
210
- # Batch create
211
- memories_data = [
212
- {"content": "User is a data scientist", "type": "observation"},
213
- {"content": "User works with ML models", "type": "learning"},
214
- {"content": "User prefers Jupyter notebooks", "type": "preference"}
215
- ]
216
-
217
- batch_result = client.memories.create_batch(memories_data)
218
- print(f"Created {batch_result.success_count} memories")
219
- print(f"Failed {batch_result.failed_count} memories")
220
-
221
- # Batch delete
222
- result = client.memories.delete_batch(["mem_123", "mem_456", "mem_789"])
223
- print(f"Deleted {result['deleted']} memories")
224
- ```
225
-
226
- ## Thread Management
227
-
228
- ### Create a Thread
229
-
230
- ```python
231
- thread = client.threads.create({
232
- "name": "Customer Support Chat",
233
- "description": "Tracking customer issues and resolutions",
234
- "tags": ["support", "customer", "priority"]
235
- })
236
- ```
237
-
238
- ### Add Memories to Thread
239
-
240
- ```python
241
- # Add existing memories
242
- client.threads.add_memories(thread.id, [memory1.id, memory2.id])
243
-
244
- # Create and add in one operation
245
- new_memory = client.memories.create({
246
- "content": "Customer reported login issue",
247
- "type": "conversation",
248
- "thread_ids": [thread.id]
249
- })
250
- ```
251
-
252
- ### Get Thread with Memories
253
-
254
- ```python
255
- # Get thread with all memories included
256
- thread_with_memories = client.threads.get(thread.id, include_memories=True)
257
-
258
- print(f"Thread: {thread_with_memories.name}")
259
- print(f"Total memories: {len(thread_with_memories.memories)}")
260
-
261
- for memory in thread_with_memories.memories:
262
- print(f"- {memory.content}")
263
- ```
264
-
265
- ### Thread Analytics
266
-
267
- ```python
268
- stats = client.threads.get_stats(thread.id)
269
-
270
- print(f"Total memories: {stats.memory_count}")
271
- print(f"Average importance: {stats.avg_importance:.2f}")
272
- print(f"Decisions made: {stats.total_decisions}")
273
- print(f"Open questions: {stats.total_questions}")
274
- print(f"Action items: {stats.total_action_items}")
275
- ```
276
-
277
- ## Async Support
278
-
279
- ```python
280
- import asyncio
281
- from sovant import AsyncSovantClient
282
-
283
- async def main():
284
- # Use async client for better performance
285
- async with AsyncSovantClient(api_key="YOUR_API_KEY") as client:
286
- # Create multiple memories concurrently
287
- memories = await asyncio.gather(
288
- client.memories.create({"content": "Memory 1"}),
289
- client.memories.create({"content": "Memory 2"}),
290
- client.memories.create({"content": "Memory 3"})
291
- )
292
-
293
- print(f"Created {len(memories)} memories")
294
-
295
- # Async search
296
- results = await client.memories.search({
297
- "query": "user preferences",
298
- "search_type": "semantic"
299
- })
300
-
301
- for result in results:
302
- print(f"- {result.content}")
303
-
304
- asyncio.run(main())
305
- ```
306
-
307
- ## Error Handling
308
-
309
- The SDK provides typed exceptions for different error scenarios:
310
-
311
- ```python
312
- from sovant import (
313
- AuthenticationError,
314
- RateLimitError,
315
- ValidationError,
316
- NotFoundError,
317
- NetworkError
318
- )
319
-
320
- try:
321
- memory = client.memories.get("invalid_id")
322
- except NotFoundError:
323
- print("Memory not found")
324
- except RateLimitError as e:
325
- print(f"Rate limited. Retry after {e.retry_after} seconds")
326
- except ValidationError as e:
327
- print(f"Validation errors: {e.errors}")
328
- except AuthenticationError:
329
- print("Invalid API key")
330
- except NetworkError:
331
- print("Network error occurred")
332
- ```
333
-
334
- ## Advanced Usage
335
-
336
- ### Memory Insights
337
-
338
- ```python
339
- insights = client.memories.get_insights(
340
- time_range="last_30_days",
341
- group_by="type"
342
- )
343
-
344
- print(f"Total memories: {insights['total_count']}")
345
- print(f"Type distribution: {insights['type_distribution']}")
346
- print(f"Emotion distribution: {insights['emotion_distribution']}")
347
- print(f"Average importance: {insights['importance_stats']['avg']}")
348
- print(f"Growth rate: {insights['growth_rate']}%")
349
- ```
350
-
351
- ### Related Memories
352
-
353
- ```python
354
- # Find memories related to a specific memory
355
- related = client.memories.get_related(
356
- memory_id=memory.id,
357
- limit=5,
358
- threshold=0.7 # Minimum similarity score
359
- )
360
-
361
- for r in related:
362
- print(f"- {r.content} (similarity: {r.relevance_score:.2f})")
363
- ```
364
-
365
- ### Thread Operations
366
-
367
- ```python
368
- # Archive a thread
369
- archived = client.threads.archive(thread.id)
370
-
371
- # Search threads
372
- threads = client.threads.search(
373
- query="customer support",
374
- status="active",
375
- tags=["priority"]
376
- )
377
-
378
- # Merge threads
379
- merged = client.threads.merge(
380
- target_id=main_thread.id,
381
- source_ids=[thread2.id, thread3.id]
382
- )
383
-
384
- # Clone a thread
385
- cloned = client.threads.clone(
386
- thread_id=thread.id,
387
- name="Cloned Thread",
388
- include_memories=True
389
- )
390
- ```
391
-
392
- ### Pagination
393
-
394
- ```python
395
- # List memories with pagination
396
- page1 = client.memories.list(limit=20, offset=0)
397
- print(f"Total memories: {page1.total}")
398
- print(f"Has more: {page1.has_more}")
399
-
400
- # Get next page
401
- if page1.has_more:
402
- page2 = client.memories.list(limit=20, offset=20)
403
- ```
404
-
405
- ## Type Safety
406
-
407
- The SDK uses Pydantic for data validation and provides enums for better type safety:
408
-
409
- ```python
410
- from sovant import MemoryType, EmotionType, ThreadStatus
411
-
412
- # Using enums ensures valid values
413
- memory = client.memories.create({
414
- "content": "Important decision made",
415
- "type": MemoryType.DECISION, # Type-safe enum
416
- "emotion": {
417
- "type": EmotionType.NEUTRAL, # Type-safe enum
418
- "intensity": 0.5
419
- }
420
- })
421
-
422
- # IDE will provide autocompletion for all fields
423
- thread = client.threads.create({
424
- "name": "Project Planning",
425
- "status": ThreadStatus.ACTIVE # Type-safe enum
426
- })
427
- ```
428
-
429
- ## Best Practices
430
-
431
- 1. **Use batch operations for bulk actions**
432
-
433
- ```python
434
- # Good - single API call
435
- batch_result = client.memories.create_batch(memories_list)
436
-
437
- # Avoid - multiple API calls
438
- for memory_data in memories_list:
439
- client.memories.create(memory_data)
440
- ```
441
-
442
- 2. **Use async client for concurrent operations**
443
-
444
- ```python
445
- async with AsyncSovantClient() as client:
446
- results = await asyncio.gather(*tasks)
447
- ```
448
-
449
- 3. **Handle errors gracefully**
450
-
451
- ```python
452
- try:
453
- result = client.memories.search({"query": "test"})
454
- except RateLimitError as e:
455
- await asyncio.sleep(e.retry_after)
456
- # Retry the request
457
- ```
458
-
459
- 4. **Use type hints for better IDE support**
460
-
461
- ```python
462
- from sovant import Memory, SearchResult
463
-
464
- def process_memory(memory: Memory) -> None:
465
- print(f"Processing {memory.id}")
466
-
467
- def handle_results(results: list[SearchResult]) -> None:
468
- for result in results:
469
- print(f"Score: {result.relevance_score}")
470
- ```
471
-
472
- ## Examples
473
-
474
- Check out the [examples directory](https://github.com/sovant-ai/python-sdk/tree/main/examples) for complete working examples:
475
-
476
- - Basic CRUD operations
477
- - Advanced search techniques
478
- - Thread management workflows
479
- - Async patterns
480
- - Error handling
481
- - Data analysis with pandas integration
482
-
483
- ## Support
484
-
485
- - 📚 [Documentation](https://docs.sovant.ai)
486
- - 💬 [Discord Community](https://discord.gg/sovant)
487
- - 🐛 [Issue Tracker](https://github.com/sovant-ai/python-sdk/issues)
488
- - 📧 [Email Support](mailto:support@sovant.ai)
489
-
490
- ## License
491
-
492
- MIT © Sovant AI
@@ -1,13 +0,0 @@
1
- sovant/__init__.py,sha256=1MoHw4tAMuMjBUakVz6qXqFgKf37ijZVveSOB6wcXwE,1174
2
- sovant/base_client.py,sha256=Vmn6OGywGwLbH5cEeflSjVOFwn5iX_YdfTdUq9pWWxA,8778
3
- sovant/client.py,sha256=C71f9tFfbpQAkw5yjOfalNeCPwOqu9M5FyNzuittOAU,2763
4
- sovant/exceptions.py,sha256=MQMSgk7ckXnAbe7hPPpbKOnRBHSPxuCY7WSjqfJAvd0,1557
5
- sovant/types.py,sha256=gnvdXksJt8LObti7nc6eHSBCB7Pz7SNpS5o_HRTq_kA,6098
6
- sovant/resources/__init__.py,sha256=cPFIM7h8duviDdeHudnVEAmv3F89RHQxdH5BCRWFteQ,193
7
- sovant/resources/memories.py,sha256=bKKE0uWqFkPa1OEvbK1LrdSD7v6N04RhJ_2VDoPPQBA,11379
8
- sovant/resources/threads.py,sha256=mN29xP0JODmZBKyfhpeqJyViUWNVMAx3TlYAW-1ruTs,12558
9
- sovant-1.0.0.dist-info/licenses/LICENSE,sha256=Z_4cIqcf0pj97wNZqUXZgynU_gwhNzriM5u3HzlzFzM,1065
10
- sovant-1.0.0.dist-info/METADATA,sha256=jOe4BqtU1QYbscc59vLCl1d-76wo9wCfCltyyS__GjE,13179
11
- sovant-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
12
- sovant-1.0.0.dist-info/top_level.txt,sha256=za6eVEsYd_ZQQs8vrmEWNcAR58r1wCDge_jA60e4CvQ,7
13
- sovant-1.0.0.dist-info/RECORD,,
File without changes