nuclia 4.8.8__tar.gz → 4.8.10__tar.gz
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.
- {nuclia-4.8.8 → nuclia-4.8.10}/CHANGELOG.md +12 -0
- nuclia-4.8.10/Makefile +12 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/PKG-INFO +2 -2
- nuclia-4.8.10/VERSION +1 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/docs/11-activity-log.md +13 -15
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/lib/kb.py +43 -127
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/lib/utils.py +57 -14
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/logs.py +25 -59
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_kb/test_logs.py +35 -20
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia.egg-info/PKG-INFO +2 -2
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia.egg-info/SOURCES.txt +0 -3
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia.egg-info/requires.txt +1 -1
- {nuclia-4.8.8 → nuclia-4.8.10}/pyproject.toml +21 -1
- {nuclia-4.8.8 → nuclia-4.8.10}/uv.lock +890 -6
- nuclia-4.8.8/Makefile +0 -19
- nuclia-4.8.8/VERSION +0 -1
- nuclia-4.8.8/code-requirements.txt +0 -2
- nuclia-4.8.8/requirements.txt +0 -16
- nuclia-4.8.8/test-requirements.txt +0 -10
- {nuclia-4.8.8 → nuclia-4.8.10}/.gitignore +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/LICENSE +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/MANIFEST.in +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/README.md +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/docs/01-README.md +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/docs/02-auth.md +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/docs/03-kb.md +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/docs/04-upload.md +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/docs/05-search.md +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/docs/06-read.md +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/docs/07-nua.md +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/docs/08-import-export.md +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/docs/09-kb-backup.md +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/docs/10-manage.md +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/docs/12-da-agents.md +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/docs/13-ai-agents.md +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/__init__.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/cli/__init__.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/cli/run.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/cli/utils.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/config.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/data.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/decorators.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/exceptions.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/lib/__init__.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/lib/conversations.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/lib/models.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/lib/nua.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/lib/nua_chat.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/lib/nua_responses.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/py.typed +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/__init__.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/accounts.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/agent.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/auth.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/backup.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/export_import.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/kb.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/kbs.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/logger.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/nua.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/nucliadb.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/predict.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/process.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/remi.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/resource.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/search.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/task.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/upload.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/sdk/zones.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/__init__.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/assets/conversation.json +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/conftest.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/fixtures.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_kb/test_backup.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_kb/test_conversation.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_kb/test_export_import.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_kb/test_graph.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_kb/test_labels.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_kb/test_remi.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_kb/test_resource.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_kb/test_search.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_kb/test_tasks.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_manage/__init__.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_manage/test_account.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_manage/test_auth.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_manage/test_kb.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_nua/__init__.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_nua/test_agent.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_nua/test_predict.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_nucliadb/__init__.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/test_nucliadb/test_crud.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/unit/__init__.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/unit/test_export_import.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia/tests/unit/test_nua_responses.py +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia.egg-info/dependency_links.txt +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia.egg-info/entry_points.txt +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/nuclia.egg-info/top_level.txt +0 -0
- {nuclia-4.8.8 → nuclia-4.8.10}/setup.cfg +0 -0
nuclia-4.8.10/Makefile
ADDED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: nuclia
|
3
|
-
Version: 4.8.
|
3
|
+
Version: 4.8.10
|
4
4
|
Summary: Nuclia Python SDK
|
5
5
|
Author-email: Nuclia <info@nuclia.com>
|
6
6
|
License-Expression: MIT
|
@@ -26,7 +26,7 @@ Requires-Dist: httpcore>=1.0.0
|
|
26
26
|
Requires-Dist: prompt_toolkit
|
27
27
|
Requires-Dist: nucliadb_sdk<7,>=6.4
|
28
28
|
Requires-Dist: nucliadb_models<7,>=6.4
|
29
|
-
Requires-Dist: nuclia-models>=0.
|
29
|
+
Requires-Dist: nuclia-models>=0.41.1
|
30
30
|
Requires-Dist: tqdm
|
31
31
|
Requires-Dist: aiofiles
|
32
32
|
Requires-Dist: backoff
|
nuclia-4.8.10/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
4.8.10
|
@@ -35,7 +35,7 @@ See the examples for more information
|
|
35
35
|
|
36
36
|
#### Event-Specific Fields
|
37
37
|
- `SEARCH` events: Common fields + `question`, `resources_count`, `filter`, `learning_id`
|
38
|
-
- `
|
38
|
+
- `ASK` events: Common fields + Search fields + `rephrased_question`, `answer`, `retrieved_context`, `chat_history`, `feedback_good`, `feedback_comment`, `model`, `rag_strategies_names`, `rag_strategies`, `status`, `time_to_first_char`
|
39
39
|
|
40
40
|
|
41
41
|
### Query Examples
|
@@ -43,7 +43,7 @@ See the examples for more information
|
|
43
43
|
#### CLI Example
|
44
44
|
|
45
45
|
```bash
|
46
|
-
nuclia kb logs query --type=
|
46
|
+
nuclia kb logs query --type=ASK --query='{
|
47
47
|
"year_month": "2024-10",
|
48
48
|
"show": ["id", "date", "question", "answer", "feedback_good"],
|
49
49
|
"filters": {
|
@@ -58,11 +58,10 @@ nuclia kb logs query --type=CHAT --query='{
|
|
58
58
|
|
59
59
|
```python
|
60
60
|
from nuclia import sdk
|
61
|
-
from
|
62
|
-
from nuclia_models.events.activity_logs import ActivityLogsChatQuery, Pagination
|
61
|
+
from nuclia_models.events.activity_logs import ActivityLogsAskQuery, EventType, Pagination
|
63
62
|
|
64
63
|
kb = sdk.NucliaKB()
|
65
|
-
query =
|
64
|
+
query = ActivityLogsAskQuery(
|
66
65
|
year_month="2024-10",
|
67
66
|
show=["id", "date", "question", "answer"],
|
68
67
|
filters={
|
@@ -71,7 +70,7 @@ query = ActivityLogsChatQuery(
|
|
71
70
|
},
|
72
71
|
pagination=Pagination(limit=10)
|
73
72
|
)
|
74
|
-
kb.logs.query(type=
|
73
|
+
kb.logs.query(type=EventType.ASK, query=query)
|
75
74
|
```
|
76
75
|
### Special Field: `audit_metadata`
|
77
76
|
The `audit_metadata` field is a customizable dictionary. Use the `key` operator to target specific keys within the dictionary.
|
@@ -103,7 +102,7 @@ The `audit_metadata` field is a customizable dictionary. Use the `key` operator
|
|
103
102
|
Request download and wait until the download url is generated
|
104
103
|
|
105
104
|
```bash
|
106
|
-
>>> nuclia kb logs download --wait --type=
|
105
|
+
>>> nuclia kb logs download --wait --type=ASK --format=NDJSON --query='{
|
107
106
|
"year_month": "2024-10",
|
108
107
|
"show": ["id", "date", "question", "answer", "feedback_good"],
|
109
108
|
"filters": {
|
@@ -119,7 +118,7 @@ download_url=https://your-download-url
|
|
119
118
|
|
120
119
|
Request download and ask to be notified
|
121
120
|
```bash
|
122
|
-
>>> nuclia kb logs download --type=
|
121
|
+
>>> nuclia kb logs download --type=ASK --format=NDJSON --query='{
|
123
122
|
"year_month": "2024-10",
|
124
123
|
"show": ["id", "date", "question", "answer", "feedback_good"],
|
125
124
|
"filters": {
|
@@ -136,7 +135,7 @@ download_url=null
|
|
136
135
|
```
|
137
136
|
Request download and poll for the status
|
138
137
|
```bash
|
139
|
-
>>> nuclia kb logs download --type=
|
138
|
+
>>> nuclia kb logs download --type=ASK --format=NDJSON --query='{
|
140
139
|
"year_month": "2024-10",
|
141
140
|
"show": ["id", "date", "question", "answer", "feedback_good"],
|
142
141
|
"filters": {
|
@@ -159,11 +158,10 @@ download_url=https://your-download-url
|
|
159
158
|
|
160
159
|
```python
|
161
160
|
from nuclia import sdk
|
162
|
-
from
|
163
|
-
from nuclia_models.events.activity_logs import DownloadActivityLogsChatQuery
|
161
|
+
from nuclia_models.events.activity_logs import DownloadActivityLogsAskQuery, EventType
|
164
162
|
|
165
163
|
kb = sdk.NucliaKB()
|
166
|
-
query =
|
164
|
+
query = DownloadActivityLogsAskQuery(
|
167
165
|
year_month="2024-10",
|
168
166
|
show=["id", "date", "question", "answer"],
|
169
167
|
filters={
|
@@ -171,7 +169,7 @@ query = DownloadActivityLogsChatQuery(
|
|
171
169
|
"feedback_good": {"eq": True}
|
172
170
|
},
|
173
171
|
)
|
174
|
-
request = kb.logs.download(type=
|
172
|
+
request = kb.logs.download(type=EventType.ASK, query=query, wait=True)
|
175
173
|
return request.download_url
|
176
174
|
```
|
177
175
|
|
@@ -182,7 +180,7 @@ The REMi module provides tools to monitor the quality of your RAG pipeline to ge
|
|
182
180
|
|
183
181
|
## REMi Query
|
184
182
|
|
185
|
-
Use `remi query` to retrieve a list of
|
183
|
+
Use `remi query` to retrieve a list of ask activity logs that match specified criteria for REMi scores.
|
186
184
|
|
187
185
|
### Basic Query
|
188
186
|
|
@@ -284,7 +282,7 @@ kb.remi.query(
|
|
284
282
|
|
285
283
|
### REMi Get
|
286
284
|
|
287
|
-
Use `remi get_event` to fetch detailed information for a specific
|
285
|
+
Use `remi get_event` to fetch detailed information for a specific ask activity log. This command is useful for retrieving full context and score details of an entry obtained from a previous REMi query.
|
288
286
|
|
289
287
|
#### CLI Example
|
290
288
|
```bash
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import base64
|
2
|
-
import csv
|
3
2
|
import os
|
4
3
|
from enum import Enum
|
5
4
|
from typing import Dict, Optional, Union
|
@@ -15,17 +14,17 @@ from tqdm import tqdm
|
|
15
14
|
from nuclia_models.events.activity_logs import ( # type: ignore
|
16
15
|
ActivityLogsQuery,
|
17
16
|
ActivityLogsSearchQuery,
|
18
|
-
|
17
|
+
ActivityLogsAskQuery,
|
19
18
|
DownloadActivityLogsQuery,
|
20
19
|
DownloadActivityLogsSearchQuery,
|
21
|
-
|
20
|
+
DownloadActivityLogsAskQuery,
|
22
21
|
EventType,
|
23
22
|
DownloadFormat,
|
24
23
|
)
|
25
24
|
from nuclia_models.events.remi import RemiQuery
|
26
25
|
from nuclia_models.worker.tasks import TaskStartKB
|
27
26
|
from nuclia.exceptions import RateLimitError
|
28
|
-
from nuclia.lib.utils import
|
27
|
+
from nuclia.lib.utils import handle_http_sync_errors, handle_http_async_errors
|
29
28
|
from datetime import datetime
|
30
29
|
from nuclia.lib.utils import build_httpx_client, build_httpx_async_client, USER_AGENT
|
31
30
|
|
@@ -46,11 +45,9 @@ DOWNLOAD_EXPORT_URL = "/export/{export_id}"
|
|
46
45
|
DOWNLOAD_URL = "/{uri}"
|
47
46
|
TUS_UPLOAD_RESOURCE_URL = "/resource/{rid}/file/{field}/tusupload"
|
48
47
|
TUS_UPLOAD_URL = "/tusupload"
|
49
|
-
LEGACY_ACTIVITY_LOG_URL = "/activity/download?type={type}&month={month}"
|
50
48
|
ACTIVITY_LOG_URL = "/activity/{type}/query/download"
|
51
49
|
ACTIVITY_LOG_DOWNLOAD_REQUEST_URL = "/activity/download_request/{request_id}"
|
52
50
|
ACTIVITY_LOG_QUERY_URL = "/activity/{type}/query"
|
53
|
-
FEEDBACK_LOG_URL = "/feedback/{month}"
|
54
51
|
NOTIFICATIONS = "/notifications"
|
55
52
|
REMI_QUERY_URL = "/remi/query"
|
56
53
|
REMI_EVENT_URL = "/remi/events/{event_id}"
|
@@ -73,23 +70,6 @@ class Environment(str, Enum):
|
|
73
70
|
OSS = "OSS"
|
74
71
|
|
75
72
|
|
76
|
-
class LogType(str, Enum):
|
77
|
-
# Nucliadb
|
78
|
-
VISITED = "visited"
|
79
|
-
MODIFIED = "modified"
|
80
|
-
DELETED = "deleted"
|
81
|
-
NEW = "new"
|
82
|
-
SEARCH = "search"
|
83
|
-
SUGGEST = "suggest"
|
84
|
-
INDEXED = "indexed"
|
85
|
-
CHAT = "chat"
|
86
|
-
# Tasks
|
87
|
-
STARTED = "started"
|
88
|
-
STOPPED = "stopped"
|
89
|
-
# Processor
|
90
|
-
PROCESSED = "processed"
|
91
|
-
|
92
|
-
|
93
73
|
class BaseNucliaDBClient:
|
94
74
|
environment: Environment
|
95
75
|
base_url: str
|
@@ -220,7 +200,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
220
200
|
raise Exception("KB not configured")
|
221
201
|
url = f"{self.url}{NOTIFICATIONS}"
|
222
202
|
response = self.stream_session.get(url, stream=True, timeout=3660)
|
223
|
-
|
203
|
+
handle_http_sync_errors(response)
|
224
204
|
return response
|
225
205
|
|
226
206
|
def ask(self, request: AskRequest, timeout: int = 1000):
|
@@ -233,7 +213,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
233
213
|
stream=True,
|
234
214
|
timeout=timeout,
|
235
215
|
)
|
236
|
-
|
216
|
+
handle_http_sync_errors(response)
|
237
217
|
return response
|
238
218
|
|
239
219
|
def download_export(self, export_id: str, path: str, chunk_size: int):
|
@@ -276,7 +256,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
276
256
|
new_uri = "/".join(uri_parts[3:])
|
277
257
|
url = DOWNLOAD_URL.format(uri=new_uri)
|
278
258
|
response: httpx.Response = self.reader_session.get(url)
|
279
|
-
|
259
|
+
handle_http_sync_errors(response)
|
280
260
|
return response.content
|
281
261
|
|
282
262
|
@backoff.on_exception(
|
@@ -320,7 +300,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
320
300
|
headers["x-extract-strategy"] = extract_strategy
|
321
301
|
|
322
302
|
response: httpx.Response = self.writer_session.post(url, headers=headers)
|
323
|
-
|
303
|
+
handle_http_sync_errors(response)
|
324
304
|
return response.headers.get("Location")
|
325
305
|
|
326
306
|
def patch_tus_upload(self, upload_url: str, data: bytes, offset: int) -> int:
|
@@ -338,7 +318,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
338
318
|
response: httpx.Response = self.writer_session.patch(
|
339
319
|
url, headers=headers, content=data
|
340
320
|
)
|
341
|
-
|
321
|
+
handle_http_sync_errors(response)
|
342
322
|
return int(response.headers.get("Upload-Offset"))
|
343
323
|
|
344
324
|
def summarize(self, request: SummarizeRequest, timeout: int = 1000):
|
@@ -349,44 +329,13 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
349
329
|
response = self.reader_session.post(
|
350
330
|
url, json=request.model_dump(), timeout=timeout
|
351
331
|
)
|
352
|
-
|
332
|
+
handle_http_sync_errors(response)
|
353
333
|
return response
|
354
334
|
|
355
|
-
def logs(self, type: LogType, month: str) -> list[list[str]]:
|
356
|
-
if self.reader_session is None:
|
357
|
-
raise Exception("KB not configured")
|
358
|
-
|
359
|
-
if type != "feedback":
|
360
|
-
url = LEGACY_ACTIVITY_LOG_URL.format(type=type.value, month=month)
|
361
|
-
response: httpx.Response = self.reader_session.get(url)
|
362
|
-
handle_http_errors(response)
|
363
|
-
return [row for row in csv.reader(response.iter_lines())]
|
364
|
-
else:
|
365
|
-
feedback_url = f"{self.url}{FEEDBACK_LOG_URL.format(month=month)}"
|
366
|
-
feedback_response: httpx.Response = self.reader_session.get(feedback_url)
|
367
|
-
handle_http_errors(feedback_response)
|
368
|
-
feedbacks = [row for row in csv.reader(feedback_response.iter_lines())]
|
369
|
-
answers = self.logs(type=LogType.CHAT, month=month)
|
370
|
-
# first row with the columns headers
|
371
|
-
results = [[*feedbacks[0], *answers[0][:-1]]]
|
372
|
-
for feedback in feedbacks[1:]:
|
373
|
-
learning_id = feedback[1]
|
374
|
-
# search for the corresponding question/answer
|
375
|
-
# (the learning id is the same for both question/answer and feedback,
|
376
|
-
# and is the second column in the Q/A csv)
|
377
|
-
matching_answers = [
|
378
|
-
answer for answer in answers if answer[1] == learning_id
|
379
|
-
]
|
380
|
-
if len(matching_answers) > 0:
|
381
|
-
results.append([*feedback, *matching_answers[0][:-1]])
|
382
|
-
else:
|
383
|
-
results.append(feedback)
|
384
|
-
return results
|
385
|
-
|
386
335
|
def logs_query(
|
387
336
|
self,
|
388
337
|
type: EventType,
|
389
|
-
query: Union[ActivityLogsQuery, ActivityLogsSearchQuery,
|
338
|
+
query: Union[ActivityLogsQuery, ActivityLogsSearchQuery, ActivityLogsAskQuery],
|
390
339
|
) -> requests.Response:
|
391
340
|
if self.stream_session is None:
|
392
341
|
raise Exception("KB not configured")
|
@@ -396,7 +345,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
396
345
|
json=query.model_dump(mode="json", exclude_unset=True),
|
397
346
|
stream=True,
|
398
347
|
)
|
399
|
-
|
348
|
+
handle_http_sync_errors(response)
|
400
349
|
return response
|
401
350
|
|
402
351
|
def logs_download(
|
@@ -405,7 +354,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
405
354
|
query: Union[
|
406
355
|
DownloadActivityLogsQuery,
|
407
356
|
DownloadActivityLogsSearchQuery,
|
408
|
-
|
357
|
+
DownloadActivityLogsAskQuery,
|
409
358
|
],
|
410
359
|
download_format: DownloadFormat,
|
411
360
|
):
|
@@ -420,7 +369,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
420
369
|
json=query.model_dump(mode="json", exclude_unset=True),
|
421
370
|
headers={"accept": format_header_value},
|
422
371
|
)
|
423
|
-
|
372
|
+
handle_http_sync_errors(response)
|
424
373
|
return response
|
425
374
|
|
426
375
|
def get_download_request(
|
@@ -431,7 +380,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
431
380
|
raise Exception("KB not configured")
|
432
381
|
download_request_url = f"{self.url}{ACTIVITY_LOG_DOWNLOAD_REQUEST_URL.format(request_id=request_id)}"
|
433
382
|
response: httpx.Response = self.reader_session.get(download_request_url)
|
434
|
-
|
383
|
+
handle_http_sync_errors(response)
|
435
384
|
return response
|
436
385
|
|
437
386
|
def remi_query(
|
@@ -446,7 +395,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
446
395
|
json=query.model_dump(mode="json", exclude_unset=True),
|
447
396
|
timeout=10,
|
448
397
|
)
|
449
|
-
|
398
|
+
handle_http_sync_errors(response)
|
450
399
|
return response
|
451
400
|
|
452
401
|
def get_remi_event(
|
@@ -459,7 +408,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
459
408
|
response: httpx.Response = self.reader_session.get(
|
460
409
|
f"{self.url}{REMI_EVENT_URL.format(event_id=event_id)}"
|
461
410
|
)
|
462
|
-
|
411
|
+
handle_http_sync_errors(response)
|
463
412
|
return response
|
464
413
|
|
465
414
|
def get_remi_scores(
|
@@ -476,7 +425,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
476
425
|
response: httpx.Response = self.reader_session.get(
|
477
426
|
f"{self.url}{REMI_SCORES_URL}", params=params, timeout=10
|
478
427
|
)
|
479
|
-
|
428
|
+
handle_http_sync_errors(response)
|
480
429
|
return response
|
481
430
|
|
482
431
|
def list_tasks(self) -> httpx.Response:
|
@@ -484,7 +433,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
484
433
|
raise Exception("KB not configured")
|
485
434
|
|
486
435
|
response: httpx.Response = self.reader_session.get(f"{self.url}{LIST_TASKS}")
|
487
|
-
|
436
|
+
handle_http_sync_errors(response)
|
488
437
|
return response
|
489
438
|
|
490
439
|
def start_task(self, body: TaskStartKB) -> httpx.Response:
|
@@ -495,7 +444,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
495
444
|
f"{self.url}{START_TASK}",
|
496
445
|
json=body.model_dump(mode="json", exclude_unset=True),
|
497
446
|
)
|
498
|
-
|
447
|
+
handle_http_sync_errors(response)
|
499
448
|
return response
|
500
449
|
|
501
450
|
def delete_task(self, task_id: str) -> httpx.Response:
|
@@ -505,7 +454,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
505
454
|
response: httpx.Response = self.writer_session.delete(
|
506
455
|
f"{self.url}{DELETE_TASK.format(task_id=task_id)}",
|
507
456
|
)
|
508
|
-
|
457
|
+
handle_http_sync_errors(response)
|
509
458
|
return response
|
510
459
|
|
511
460
|
def stop_task(self, task_id: str) -> httpx.Response:
|
@@ -515,7 +464,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
515
464
|
response: httpx.Response = self.writer_session.post(
|
516
465
|
f"{self.url}{STOP_TASK.format(task_id=task_id)}",
|
517
466
|
)
|
518
|
-
|
467
|
+
handle_http_sync_errors(response)
|
519
468
|
return response
|
520
469
|
|
521
470
|
def get_task(self, task_id: str) -> httpx.Response:
|
@@ -525,7 +474,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
525
474
|
response: httpx.Response = self.reader_session.get(
|
526
475
|
f"{self.url}{GET_TASK.format(task_id=task_id)}",
|
527
476
|
)
|
528
|
-
|
477
|
+
handle_http_sync_errors(response)
|
529
478
|
return response
|
530
479
|
|
531
480
|
def restart_task(self, task_id: str) -> httpx.Response:
|
@@ -535,7 +484,7 @@ class NucliaDBClient(BaseNucliaDBClient):
|
|
535
484
|
response: httpx.Response = self.writer_session.post(
|
536
485
|
f"{self.url}{RESTART_TASK.format(task_id=task_id)}",
|
537
486
|
)
|
538
|
-
|
487
|
+
handle_http_sync_errors(response)
|
539
488
|
return response
|
540
489
|
|
541
490
|
|
@@ -583,7 +532,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
583
532
|
url = f"{self.url}{NOTIFICATIONS}"
|
584
533
|
req = self.reader_session.build_request("GET", url, timeout=3660)
|
585
534
|
response = await self.reader_session.send(req, stream=True)
|
586
|
-
|
535
|
+
await handle_http_async_errors(response)
|
587
536
|
return response
|
588
537
|
|
589
538
|
async def ask(self, request: AskRequest, timeout: int = 1000):
|
@@ -594,7 +543,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
594
543
|
"POST", url, json=request.model_dump(), timeout=timeout
|
595
544
|
)
|
596
545
|
response = await self.reader_session.send(req, stream=True)
|
597
|
-
|
546
|
+
await handle_http_async_errors(response)
|
598
547
|
return response
|
599
548
|
|
600
549
|
async def download_export(self, export_id: str, path: str, chunk_size: int):
|
@@ -635,7 +584,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
635
584
|
new_uri = "/".join(uri_parts[3:])
|
636
585
|
url = DOWNLOAD_URL.format(uri=new_uri)
|
637
586
|
response = await self.reader_session.get(url)
|
638
|
-
|
587
|
+
await handle_http_async_errors(response)
|
639
588
|
return response.content
|
640
589
|
|
641
590
|
@backoff.on_exception(
|
@@ -679,7 +628,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
679
628
|
headers["x-extract-strategy"] = extract_strategy
|
680
629
|
|
681
630
|
response = await self.writer_session.post(url, headers=headers)
|
682
|
-
|
631
|
+
await handle_http_async_errors(response)
|
683
632
|
return response.headers.get("Location")
|
684
633
|
|
685
634
|
async def patch_tus_upload(self, upload_url: str, data: bytes, offset: int) -> int:
|
@@ -695,7 +644,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
695
644
|
url = httpx.URL("/".join(url.path.split("/")[3:]))
|
696
645
|
|
697
646
|
response = await self.writer_session.patch(url, headers=headers, content=data)
|
698
|
-
|
647
|
+
await handle_http_async_errors(response)
|
699
648
|
return int(response.headers.get("Upload-Offset"))
|
700
649
|
|
701
650
|
async def summarize(self, request: SummarizeRequest, timeout: int = 1000):
|
@@ -706,46 +655,13 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
706
655
|
response = await self.reader_session.post(
|
707
656
|
url, json=request.model_dump(), timeout=timeout
|
708
657
|
)
|
709
|
-
|
658
|
+
await handle_http_async_errors(response)
|
710
659
|
return response
|
711
660
|
|
712
|
-
async def logs(self, type: LogType, month: str) -> list[list[str]]:
|
713
|
-
if self.reader_session is None:
|
714
|
-
raise Exception("KB not configured")
|
715
|
-
|
716
|
-
if type != "feedback":
|
717
|
-
url = LEGACY_ACTIVITY_LOG_URL.format(type=type.value, month=month)
|
718
|
-
response: httpx.Response = await self.reader_session.get(url)
|
719
|
-
handle_http_errors(response)
|
720
|
-
return [row for row in csv.reader(response.iter_lines())]
|
721
|
-
else:
|
722
|
-
feedback_url = f"{self.url}{FEEDBACK_LOG_URL.format(month=month)}"
|
723
|
-
feedback_response: httpx.Response = await self.reader_session.get(
|
724
|
-
feedback_url
|
725
|
-
)
|
726
|
-
handle_http_errors(feedback_response)
|
727
|
-
feedbacks = [row for row in csv.reader(feedback_response.iter_lines())]
|
728
|
-
answers = await self.logs(type=LogType.CHAT, month=month)
|
729
|
-
# first row with the columns headers
|
730
|
-
results = [[*feedbacks[0], *answers[0][:-1]]]
|
731
|
-
for feedback in feedbacks[1:]:
|
732
|
-
learning_id = feedback[1]
|
733
|
-
# search for the corresponding question/answer
|
734
|
-
# (the learning id is the same for both question/answer and feedback,
|
735
|
-
# and is the second column in the Q/A csv)
|
736
|
-
matching_answers = [
|
737
|
-
answer for answer in answers if answer[1] == learning_id
|
738
|
-
]
|
739
|
-
if len(matching_answers) > 0:
|
740
|
-
results.append([*feedback, *matching_answers[0][:-1]])
|
741
|
-
else:
|
742
|
-
results.append(feedback)
|
743
|
-
return results
|
744
|
-
|
745
661
|
async def logs_query(
|
746
662
|
self,
|
747
663
|
type: EventType,
|
748
|
-
query: Union[ActivityLogsQuery, ActivityLogsSearchQuery,
|
664
|
+
query: Union[ActivityLogsQuery, ActivityLogsSearchQuery, ActivityLogsAskQuery],
|
749
665
|
) -> httpx.Response:
|
750
666
|
if self.reader_session is None:
|
751
667
|
raise Exception("KB not configured")
|
@@ -754,7 +670,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
754
670
|
f"{self.url}{ACTIVITY_LOG_QUERY_URL.format(type=type.value)}",
|
755
671
|
json=query.model_dump(mode="json", exclude_unset=True),
|
756
672
|
)
|
757
|
-
|
673
|
+
await handle_http_async_errors(response)
|
758
674
|
return response
|
759
675
|
|
760
676
|
async def logs_download(
|
@@ -763,7 +679,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
763
679
|
query: Union[
|
764
680
|
DownloadActivityLogsQuery,
|
765
681
|
DownloadActivityLogsSearchQuery,
|
766
|
-
|
682
|
+
DownloadActivityLogsAskQuery,
|
767
683
|
],
|
768
684
|
download_format: DownloadFormat,
|
769
685
|
):
|
@@ -778,7 +694,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
778
694
|
json=query.model_dump(mode="json", exclude_unset=True),
|
779
695
|
headers={"accept": format_header_value},
|
780
696
|
)
|
781
|
-
|
697
|
+
await handle_http_async_errors(response)
|
782
698
|
return response
|
783
699
|
|
784
700
|
async def get_download_request(
|
@@ -789,7 +705,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
789
705
|
raise Exception("KB not configured")
|
790
706
|
download_request_url = f"{self.url}{ACTIVITY_LOG_DOWNLOAD_REQUEST_URL.format(request_id=request_id)}"
|
791
707
|
response: httpx.Response = await self.reader_session.get(download_request_url)
|
792
|
-
|
708
|
+
await handle_http_async_errors(response)
|
793
709
|
return response
|
794
710
|
|
795
711
|
async def remi_query(
|
@@ -804,7 +720,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
804
720
|
json=query.model_dump(mode="json", exclude_unset=True),
|
805
721
|
timeout=10,
|
806
722
|
)
|
807
|
-
|
723
|
+
await handle_http_async_errors(response)
|
808
724
|
return response
|
809
725
|
|
810
726
|
async def get_remi_event(
|
@@ -817,7 +733,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
817
733
|
response: httpx.Response = await self.reader_session.get(
|
818
734
|
f"{self.url}{REMI_EVENT_URL.format(event_id=event_id)}"
|
819
735
|
)
|
820
|
-
|
736
|
+
await handle_http_async_errors(response)
|
821
737
|
return response
|
822
738
|
|
823
739
|
async def get_remi_scores(
|
@@ -834,7 +750,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
834
750
|
response: httpx.Response = await self.reader_session.get(
|
835
751
|
f"{self.url}{REMI_SCORES_URL}", params=params, timeout=10
|
836
752
|
)
|
837
|
-
|
753
|
+
await handle_http_async_errors(response)
|
838
754
|
return response
|
839
755
|
|
840
756
|
async def list_tasks(self) -> httpx.Response:
|
@@ -844,7 +760,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
844
760
|
response: httpx.Response = await self.reader_session.get(
|
845
761
|
f"{self.url}{LIST_TASKS}"
|
846
762
|
)
|
847
|
-
|
763
|
+
await handle_http_async_errors(response)
|
848
764
|
return response
|
849
765
|
|
850
766
|
async def start_task(self, body: TaskStartKB) -> httpx.Response:
|
@@ -855,7 +771,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
855
771
|
f"{self.url}{START_TASK}",
|
856
772
|
json=body.model_dump(mode="json", exclude_unset=True),
|
857
773
|
)
|
858
|
-
|
774
|
+
await handle_http_async_errors(response)
|
859
775
|
return response
|
860
776
|
|
861
777
|
async def delete_task(self, task_id: str) -> httpx.Response:
|
@@ -865,7 +781,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
865
781
|
response: httpx.Response = await self.writer_session.delete(
|
866
782
|
f"{self.url}{DELETE_TASK.format(task_id=task_id)}",
|
867
783
|
)
|
868
|
-
|
784
|
+
await handle_http_async_errors(response)
|
869
785
|
return response
|
870
786
|
|
871
787
|
async def stop_task(self, task_id: str) -> httpx.Response:
|
@@ -875,7 +791,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
875
791
|
response: httpx.Response = await self.writer_session.post(
|
876
792
|
f"{self.url}{STOP_TASK.format(task_id=task_id)}",
|
877
793
|
)
|
878
|
-
|
794
|
+
await handle_http_async_errors(response)
|
879
795
|
return response
|
880
796
|
|
881
797
|
async def get_task(self, task_id: str) -> httpx.Response:
|
@@ -885,7 +801,7 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
885
801
|
response: httpx.Response = await self.reader_session.get(
|
886
802
|
f"{self.url}{GET_TASK.format(task_id=task_id)}",
|
887
803
|
)
|
888
|
-
|
804
|
+
await handle_http_async_errors(response)
|
889
805
|
return response
|
890
806
|
|
891
807
|
async def restart_task(self, task_id: str) -> httpx.Response:
|
@@ -895,5 +811,5 @@ class AsyncNucliaDBClient(BaseNucliaDBClient):
|
|
895
811
|
response: httpx.Response = await self.writer_session.post(
|
896
812
|
f"{self.url}{RESTART_TASK.format(task_id=task_id)}",
|
897
813
|
)
|
898
|
-
|
814
|
+
await handle_http_async_errors(response)
|
899
815
|
return response
|