querymemory 0.1.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.
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: querymemory
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official Query Memory SDK for Knowledge, Agent, and Web Parsing APIs
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: requests>=2.31.0
|
|
8
|
+
|
|
9
|
+
# Query Memory Python SDK
|
|
10
|
+
|
|
11
|
+
Official SDK for Query Memory Knowledge, Agent, and Web Parsing APIs.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install querymemory-sdk
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
from querymemory_sdk import QueryMemoryClient
|
|
23
|
+
|
|
24
|
+
client = QueryMemoryClient(
|
|
25
|
+
base_url="https://api.querymemory.com",
|
|
26
|
+
api_key="<USER_API_KEY>",
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
result = client.knowledge.query(
|
|
30
|
+
knowledge_id="<KNOWLEDGE_ID>",
|
|
31
|
+
query="Summarize key points",
|
|
32
|
+
top_k=5,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
print(result)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Use root domain for `base_url` (no `/api/v1`):
|
|
39
|
+
|
|
40
|
+
- Correct: `https://api.querymemory.com`
|
|
41
|
+
- Incorrect: `https://api.querymemory.com/api/v1`
|
|
42
|
+
|
|
43
|
+
## Auth
|
|
44
|
+
|
|
45
|
+
- Public query APIs use `api_key`.
|
|
46
|
+
- Management APIs can use `api_key` (user API key) or `auth_token` depending on deployment policy.
|
|
47
|
+
|
|
48
|
+
You can pass one or both to one client.
|
|
49
|
+
|
|
50
|
+
## Modules
|
|
51
|
+
|
|
52
|
+
- `client.knowledge`
|
|
53
|
+
- `client.agents`
|
|
54
|
+
- `client.web`
|
|
55
|
+
|
|
56
|
+
Each module includes both management and public query helpers.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
querymemory_sdk/__init__.py,sha256=-Rg--eN4tCkd3W2PTtzvmjWbIEqQO5FN9gV5vhJdj4M,109
|
|
2
|
+
querymemory_sdk/client.py,sha256=nj4KIt-9fTHZ1yZvD60t9P4dq6GqHXYfB4Kvq4RJfnM,11386
|
|
3
|
+
querymemory-0.1.0.dist-info/METADATA,sha256=iCElgL1mYt6lVjFSp9G2OwMI9LvS8xWTHHemyiKM00w,1150
|
|
4
|
+
querymemory-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
5
|
+
querymemory-0.1.0.dist-info/top_level.txt,sha256=ffEr1Qj_8eoIGmcNisIAqWoMdGwlA6Vek1yTyu9mNWg,16
|
|
6
|
+
querymemory-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
querymemory_sdk
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Any, Dict, Optional
|
|
6
|
+
|
|
7
|
+
import requests
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class QueryMemoryError(Exception):
|
|
11
|
+
def __init__(self, message: str, status: int = 0, details: Any = None):
|
|
12
|
+
super().__init__(message)
|
|
13
|
+
self.status = status
|
|
14
|
+
self.details = details
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass
|
|
18
|
+
class QueryMemoryClientOptions:
|
|
19
|
+
base_url: str = "http://localhost:8000"
|
|
20
|
+
api_key: Optional[str] = None
|
|
21
|
+
auth_token: Optional[str] = None
|
|
22
|
+
timeout: int = 60
|
|
23
|
+
default_headers: Optional[Dict[str, str]] = None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class _HttpClient:
|
|
27
|
+
def __init__(self, options: QueryMemoryClientOptions):
|
|
28
|
+
self.base_url = options.base_url.rstrip("/")
|
|
29
|
+
self.api_key = options.api_key
|
|
30
|
+
self.auth_token = options.auth_token
|
|
31
|
+
self.timeout = options.timeout
|
|
32
|
+
self.default_headers = options.default_headers or {}
|
|
33
|
+
self.session = requests.Session()
|
|
34
|
+
|
|
35
|
+
def _headers(self, auth_mode: str = "auto") -> Dict[str, str]:
|
|
36
|
+
headers = dict(self.default_headers)
|
|
37
|
+
if auth_mode in ("api_key", "auto") and self.api_key:
|
|
38
|
+
headers["X-API-Key"] = self.api_key
|
|
39
|
+
elif auth_mode in ("auth_token", "auto") and self.auth_token:
|
|
40
|
+
headers["Authorization"] = f"Bearer {self.auth_token}"
|
|
41
|
+
return headers
|
|
42
|
+
|
|
43
|
+
def request(
|
|
44
|
+
self,
|
|
45
|
+
method: str,
|
|
46
|
+
path: str,
|
|
47
|
+
*,
|
|
48
|
+
params: Optional[Dict[str, Any]] = None,
|
|
49
|
+
json_body: Optional[Dict[str, Any]] = None,
|
|
50
|
+
auth_mode: str = "auto",
|
|
51
|
+
) -> Dict[str, Any]:
|
|
52
|
+
url = f"{self.base_url}{path}"
|
|
53
|
+
try:
|
|
54
|
+
response = self.session.request(
|
|
55
|
+
method=method,
|
|
56
|
+
url=url,
|
|
57
|
+
params={k: v for k, v in (params or {}).items() if v is not None},
|
|
58
|
+
json=json_body,
|
|
59
|
+
headers=self._headers(auth_mode),
|
|
60
|
+
timeout=self.timeout,
|
|
61
|
+
)
|
|
62
|
+
except requests.RequestException as exc:
|
|
63
|
+
raise QueryMemoryError(str(exc), 0) from exc
|
|
64
|
+
|
|
65
|
+
payload: Any
|
|
66
|
+
try:
|
|
67
|
+
payload = response.json()
|
|
68
|
+
except Exception:
|
|
69
|
+
payload = {"detail": response.text}
|
|
70
|
+
|
|
71
|
+
if not response.ok:
|
|
72
|
+
detail = payload.get("detail") if isinstance(payload, dict) else str(payload)
|
|
73
|
+
raise QueryMemoryError(detail or response.reason, response.status_code, payload)
|
|
74
|
+
|
|
75
|
+
if isinstance(payload, dict):
|
|
76
|
+
return payload
|
|
77
|
+
return {"data": payload}
|
|
78
|
+
|
|
79
|
+
def wait_for_task(
|
|
80
|
+
self,
|
|
81
|
+
path: str,
|
|
82
|
+
*,
|
|
83
|
+
timeout_sec: int = 120,
|
|
84
|
+
interval_sec: float = 1.0,
|
|
85
|
+
auth_mode: str = "auto",
|
|
86
|
+
) -> Dict[str, Any]:
|
|
87
|
+
started = time.time()
|
|
88
|
+
while time.time() - started < timeout_sec:
|
|
89
|
+
status = self.request("GET", path, auth_mode=auth_mode)
|
|
90
|
+
state = str(status.get("status", "")).lower()
|
|
91
|
+
if state in ("completed", "success"):
|
|
92
|
+
result = status.get("result")
|
|
93
|
+
if isinstance(result, dict):
|
|
94
|
+
return result
|
|
95
|
+
return status
|
|
96
|
+
if state == "failed":
|
|
97
|
+
raise QueryMemoryError(status.get("error", "Task failed"), 500, status)
|
|
98
|
+
time.sleep(interval_sec)
|
|
99
|
+
raise QueryMemoryError(f"Task polling timed out after {timeout_sec}s", 408)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class KnowledgeApi:
|
|
103
|
+
def __init__(self, http: _HttpClient):
|
|
104
|
+
self._http = http
|
|
105
|
+
|
|
106
|
+
def list(self) -> Dict[str, Any]:
|
|
107
|
+
return self._http.request("GET", "/api/v1/knowledges", auth_mode="auto")
|
|
108
|
+
|
|
109
|
+
def get(self, knowledge_id: str) -> Dict[str, Any]:
|
|
110
|
+
return self._http.request("GET", f"/api/v1/knowledges/{knowledge_id}", auth_mode="auto")
|
|
111
|
+
|
|
112
|
+
def create(self, *, name: str, description: Optional[str] = None, connected_documents: Optional[list[str]] = None) -> Dict[str, Any]:
|
|
113
|
+
return self._http.request(
|
|
114
|
+
"POST",
|
|
115
|
+
"/api/v1/knowledges",
|
|
116
|
+
auth_mode="auto",
|
|
117
|
+
json_body={
|
|
118
|
+
"name": name,
|
|
119
|
+
"description": description,
|
|
120
|
+
"connected_documents": connected_documents or [],
|
|
121
|
+
},
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
def update(self, knowledge_id: str, **payload: Any) -> Dict[str, Any]:
|
|
125
|
+
return self._http.request("PUT", f"/api/v1/knowledges/{knowledge_id}", auth_mode="auto", json_body=payload)
|
|
126
|
+
|
|
127
|
+
def delete(self, knowledge_id: str) -> Dict[str, Any]:
|
|
128
|
+
return self._http.request("DELETE", f"/api/v1/knowledges/{knowledge_id}", auth_mode="auto")
|
|
129
|
+
|
|
130
|
+
def query(
|
|
131
|
+
self,
|
|
132
|
+
*,
|
|
133
|
+
knowledge_id: str,
|
|
134
|
+
query: str,
|
|
135
|
+
top_k: int = 5,
|
|
136
|
+
retrieve_k: Optional[int] = None,
|
|
137
|
+
include_context: bool = True,
|
|
138
|
+
wait_for_result: bool = True,
|
|
139
|
+
wait_timeout_sec: int = 45,
|
|
140
|
+
) -> Dict[str, Any]:
|
|
141
|
+
return self._http.request(
|
|
142
|
+
"POST",
|
|
143
|
+
f"/api/v1/knowledge/{knowledge_id}/query",
|
|
144
|
+
auth_mode="api_key",
|
|
145
|
+
params={
|
|
146
|
+
"top_k": top_k,
|
|
147
|
+
"retrieve_k": retrieve_k,
|
|
148
|
+
"wait_for_result": wait_for_result,
|
|
149
|
+
"wait_timeout_sec": wait_timeout_sec,
|
|
150
|
+
},
|
|
151
|
+
json_body={
|
|
152
|
+
"query": query,
|
|
153
|
+
"top_k": top_k,
|
|
154
|
+
"retrieve_k": retrieve_k,
|
|
155
|
+
"include_context": include_context,
|
|
156
|
+
},
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
def get_query_job(self, task_id: str) -> Dict[str, Any]:
|
|
160
|
+
return self._http.request("GET", f"/api/v1/knowledge/query-jobs/{task_id}", auth_mode="api_key")
|
|
161
|
+
|
|
162
|
+
def wait_for_query_job(self, task_id: str, *, timeout_sec: int = 120, interval_sec: float = 1.0) -> Dict[str, Any]:
|
|
163
|
+
return self._http.wait_for_task(
|
|
164
|
+
f"/api/v1/knowledge/query-jobs/{task_id}",
|
|
165
|
+
timeout_sec=timeout_sec,
|
|
166
|
+
interval_sec=interval_sec,
|
|
167
|
+
auth_mode="api_key",
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class AgentsApi:
|
|
172
|
+
def __init__(self, http: _HttpClient):
|
|
173
|
+
self._http = http
|
|
174
|
+
|
|
175
|
+
def list(self) -> Dict[str, Any]:
|
|
176
|
+
return self._http.request("GET", "/api/v1/agents", auth_mode="auto")
|
|
177
|
+
|
|
178
|
+
def get(self, agent_id: str) -> Dict[str, Any]:
|
|
179
|
+
return self._http.request("GET", f"/api/v1/agents/{agent_id}", auth_mode="auto")
|
|
180
|
+
|
|
181
|
+
def create(self, **payload: Any) -> Dict[str, Any]:
|
|
182
|
+
return self._http.request("POST", "/api/v1/agents", auth_mode="auto", json_body=payload)
|
|
183
|
+
|
|
184
|
+
def update(self, agent_id: str, **payload: Any) -> Dict[str, Any]:
|
|
185
|
+
return self._http.request("PUT", f"/api/v1/agents/{agent_id}", auth_mode="auto", json_body=payload)
|
|
186
|
+
|
|
187
|
+
def create_session(self, agent_id: str, title: Optional[str] = None) -> Dict[str, Any]:
|
|
188
|
+
return self._http.request("POST", f"/api/v1/agents/{agent_id}/sessions", auth_mode="auto", json_body={"title": title})
|
|
189
|
+
|
|
190
|
+
def list_sessions(self, agent_id: str) -> Dict[str, Any]:
|
|
191
|
+
return self._http.request("GET", f"/api/v1/agents/{agent_id}/sessions", auth_mode="auto")
|
|
192
|
+
|
|
193
|
+
def get_session(self, agent_id: str, session_id: str) -> Dict[str, Any]:
|
|
194
|
+
return self._http.request("GET", f"/api/v1/agents/{agent_id}/sessions/{session_id}", auth_mode="auto")
|
|
195
|
+
|
|
196
|
+
def send_session_message(
|
|
197
|
+
self,
|
|
198
|
+
*,
|
|
199
|
+
agent_id: str,
|
|
200
|
+
session_id: str,
|
|
201
|
+
message: str,
|
|
202
|
+
wait_for_result: bool = True,
|
|
203
|
+
wait_timeout_sec: int = 90,
|
|
204
|
+
) -> Dict[str, Any]:
|
|
205
|
+
return self._http.request(
|
|
206
|
+
"POST",
|
|
207
|
+
f"/api/v1/agents/{agent_id}/sessions/{session_id}/messages",
|
|
208
|
+
auth_mode="auto",
|
|
209
|
+
json_body={
|
|
210
|
+
"message": message,
|
|
211
|
+
"wait_for_result": wait_for_result,
|
|
212
|
+
"wait_timeout_sec": wait_timeout_sec,
|
|
213
|
+
},
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
def query(
|
|
217
|
+
self,
|
|
218
|
+
*,
|
|
219
|
+
agent_id: str,
|
|
220
|
+
query: str,
|
|
221
|
+
wait_for_result: bool = True,
|
|
222
|
+
wait_timeout_sec: int = 90,
|
|
223
|
+
external_user_id: Optional[str] = None,
|
|
224
|
+
external_session_id: Optional[str] = None,
|
|
225
|
+
) -> Dict[str, Any]:
|
|
226
|
+
return self._http.request(
|
|
227
|
+
"POST",
|
|
228
|
+
f"/api/v1/agents/{agent_id}/query",
|
|
229
|
+
auth_mode="api_key",
|
|
230
|
+
json_body={
|
|
231
|
+
"query": query,
|
|
232
|
+
"wait_for_result": wait_for_result,
|
|
233
|
+
"wait_timeout_sec": wait_timeout_sec,
|
|
234
|
+
"external_user_id": external_user_id,
|
|
235
|
+
"external_session_id": external_session_id,
|
|
236
|
+
},
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
def get_users(self, agent_id: str) -> Dict[str, Any]:
|
|
240
|
+
return self._http.request("GET", f"/api/v1/agents/{agent_id}/users", auth_mode="api_key")
|
|
241
|
+
|
|
242
|
+
def get_job(self, task_id: str) -> Dict[str, Any]:
|
|
243
|
+
return self._http.request("GET", f"/api/v1/agents/jobs/{task_id}", auth_mode="api_key")
|
|
244
|
+
|
|
245
|
+
def wait_for_job(self, task_id: str, *, timeout_sec: int = 120, interval_sec: float = 1.0) -> Dict[str, Any]:
|
|
246
|
+
return self._http.wait_for_task(
|
|
247
|
+
f"/api/v1/agents/jobs/{task_id}",
|
|
248
|
+
timeout_sec=timeout_sec,
|
|
249
|
+
interval_sec=interval_sec,
|
|
250
|
+
auth_mode="api_key",
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class WebApi:
|
|
255
|
+
def __init__(self, http: _HttpClient):
|
|
256
|
+
self._http = http
|
|
257
|
+
|
|
258
|
+
def list_endpoints(self) -> Dict[str, Any]:
|
|
259
|
+
return self._http.request("GET", "/api/v1/web-parsing-endpoints", auth_mode="auto")
|
|
260
|
+
|
|
261
|
+
def get_endpoint(self, endpoint_id: str) -> Dict[str, Any]:
|
|
262
|
+
return self._http.request("GET", f"/api/v1/web-parsing-endpoints/{endpoint_id}", auth_mode="auto")
|
|
263
|
+
|
|
264
|
+
def create_endpoint(self, **payload: Any) -> Dict[str, Any]:
|
|
265
|
+
return self._http.request("POST", "/api/v1/web-parsing-endpoints", auth_mode="auto", json_body=payload)
|
|
266
|
+
|
|
267
|
+
def update_endpoint(self, endpoint_id: str, **payload: Any) -> Dict[str, Any]:
|
|
268
|
+
return self._http.request("PUT", f"/api/v1/web-parsing-endpoints/{endpoint_id}", auth_mode="auto", json_body=payload)
|
|
269
|
+
|
|
270
|
+
def delete_endpoint(self, endpoint_id: str) -> Dict[str, Any]:
|
|
271
|
+
return self._http.request("DELETE", f"/api/v1/web-parsing-endpoints/{endpoint_id}", auth_mode="auto")
|
|
272
|
+
|
|
273
|
+
def query(
|
|
274
|
+
self,
|
|
275
|
+
*,
|
|
276
|
+
endpoint_id: str,
|
|
277
|
+
query: str,
|
|
278
|
+
max_pages: Optional[int] = None,
|
|
279
|
+
domains: Optional[list[str]] = None,
|
|
280
|
+
output_format: Optional[str] = None,
|
|
281
|
+
options: Optional[Dict[str, Any]] = None,
|
|
282
|
+
) -> Dict[str, Any]:
|
|
283
|
+
return self._http.request(
|
|
284
|
+
"POST",
|
|
285
|
+
f"/api/v1/web-parsing-endpoints/{endpoint_id}/query",
|
|
286
|
+
auth_mode="api_key",
|
|
287
|
+
json_body={
|
|
288
|
+
"query": query,
|
|
289
|
+
"max_pages": max_pages,
|
|
290
|
+
"domains": domains,
|
|
291
|
+
"output_format": output_format,
|
|
292
|
+
"options": options or {},
|
|
293
|
+
},
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class QueryMemoryClient:
|
|
298
|
+
def __init__(
|
|
299
|
+
self,
|
|
300
|
+
*,
|
|
301
|
+
base_url: str = "http://localhost:8000",
|
|
302
|
+
api_key: Optional[str] = None,
|
|
303
|
+
auth_token: Optional[str] = None,
|
|
304
|
+
timeout: int = 60,
|
|
305
|
+
default_headers: Optional[Dict[str, str]] = None,
|
|
306
|
+
):
|
|
307
|
+
http = _HttpClient(
|
|
308
|
+
QueryMemoryClientOptions(
|
|
309
|
+
base_url=base_url,
|
|
310
|
+
api_key=api_key,
|
|
311
|
+
auth_token=auth_token,
|
|
312
|
+
timeout=timeout,
|
|
313
|
+
default_headers=default_headers,
|
|
314
|
+
)
|
|
315
|
+
)
|
|
316
|
+
self.knowledge = KnowledgeApi(http)
|
|
317
|
+
self.agents = AgentsApi(http)
|
|
318
|
+
self.web = WebApi(http)
|