nuclia 4.8.8__py3-none-any.whl → 4.8.10__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.
- nuclia/lib/kb.py +43 -127
- nuclia/lib/utils.py +57 -14
- nuclia/sdk/logs.py +25 -59
- nuclia/tests/test_kb/test_logs.py +35 -20
- {nuclia-4.8.8.dist-info → nuclia-4.8.10.dist-info}/METADATA +2 -2
- {nuclia-4.8.8.dist-info → nuclia-4.8.10.dist-info}/RECORD +10 -10
- {nuclia-4.8.8.dist-info → nuclia-4.8.10.dist-info}/WHEEL +1 -1
- {nuclia-4.8.8.dist-info → nuclia-4.8.10.dist-info}/entry_points.txt +0 -0
- {nuclia-4.8.8.dist-info → nuclia-4.8.10.dist-info}/licenses/LICENSE +0 -0
- {nuclia-4.8.8.dist-info → nuclia-4.8.10.dist-info}/top_level.txt +0 -0
nuclia/lib/kb.py
CHANGED
@@ -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
|
nuclia/lib/utils.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
import json
|
2
|
-
from typing import Union
|
3
2
|
|
4
3
|
import httpx
|
5
4
|
import importlib.metadata
|
6
5
|
import requests
|
6
|
+
from httpx import Response as HttpxResponse, HTTPStatusError
|
7
7
|
from tabulate import tabulate
|
8
8
|
from typing import Optional
|
9
9
|
|
@@ -18,24 +18,67 @@ from nucliadb_models.search import SyncAskResponse
|
|
18
18
|
from nuclia.lib.models import ActivityLogsOutput
|
19
19
|
from nuclia_models.worker.tasks import TaskDefinition, TaskList
|
20
20
|
from nucliadb_models.resource import KnowledgeBoxList
|
21
|
+
from requests import Response as RequestsResponse, HTTPError as RequestsHTTPError
|
22
|
+
|
21
23
|
|
22
24
|
USER_AGENT = f"nuclia.py/{importlib.metadata.version('nuclia')}"
|
23
25
|
|
24
26
|
|
25
|
-
def
|
26
|
-
|
27
|
-
response.
|
28
|
-
|
29
|
-
|
27
|
+
def handle_http_sync_errors(response):
|
28
|
+
try:
|
29
|
+
content = response.text
|
30
|
+
except (httpx.ResponseNotRead, requests.exceptions.RequestException):
|
31
|
+
content = "<streaming content not read>"
|
32
|
+
except Exception as e:
|
33
|
+
content = f"<error decoding content: {e}>"
|
34
|
+
|
35
|
+
_raise_for_status(response.status_code, content, response=response)
|
36
|
+
|
37
|
+
|
38
|
+
async def handle_http_async_errors(response: httpx.Response):
|
39
|
+
try:
|
40
|
+
if not response.is_closed and not response.is_stream_consumed:
|
41
|
+
await response.aread()
|
42
|
+
except Exception as e:
|
43
|
+
content = f"<failed to read stream: {e}>"
|
44
|
+
_raise_for_status(
|
45
|
+
response.status_code, content, response=response, request=response.request
|
46
|
+
)
|
47
|
+
return # Defensive
|
48
|
+
try:
|
49
|
+
content = response.text
|
50
|
+
except httpx.ResponseNotRead:
|
51
|
+
content = "<streaming content not read>"
|
52
|
+
except Exception as e:
|
53
|
+
content = f"<error decoding content: {e}>"
|
54
|
+
|
55
|
+
_raise_for_status(
|
56
|
+
response.status_code, content, response=response, request=response.request
|
57
|
+
)
|
58
|
+
|
59
|
+
|
60
|
+
def _raise_for_status(status_code: int, content: str, response=None, request=None):
|
61
|
+
if status_code == 403 and "Hydra token is either unexistent or revoked" in content:
|
30
62
|
raise UserTokenExpired()
|
31
|
-
elif
|
32
|
-
raise RateLimitError(f"Rate limited: {
|
33
|
-
elif
|
34
|
-
raise DuplicateError(f"Duplicate resource: {
|
35
|
-
elif
|
36
|
-
raise InvalidPayload(f"Invalid payload: {
|
37
|
-
elif
|
38
|
-
|
63
|
+
elif status_code == 429:
|
64
|
+
raise RateLimitError(f"Rate limited: {content}")
|
65
|
+
elif status_code == 409:
|
66
|
+
raise DuplicateError(f"Duplicate resource: {content}")
|
67
|
+
elif status_code == 422:
|
68
|
+
raise InvalidPayload(f"Invalid payload: {content}")
|
69
|
+
elif status_code >= 400:
|
70
|
+
if isinstance(response, HttpxResponse):
|
71
|
+
raise HTTPStatusError(
|
72
|
+
f"Status code {status_code}: {content}",
|
73
|
+
request=request,
|
74
|
+
response=response,
|
75
|
+
)
|
76
|
+
elif isinstance(response, RequestsResponse):
|
77
|
+
raise RequestsHTTPError(
|
78
|
+
f"Status code {status_code}: {content}", response=response
|
79
|
+
)
|
80
|
+
else:
|
81
|
+
raise Exception(f"Status code {status_code}: {content}")
|
39
82
|
|
40
83
|
|
41
84
|
def serialize(obj):
|
nuclia/sdk/logs.py
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
from nuclia.decorators import kb
|
2
|
-
from nuclia.lib.kb import
|
2
|
+
from nuclia.lib.kb import NucliaDBClient, AsyncNucliaDBClient
|
3
3
|
from nuclia_models.events.activity_logs import ( # type: ignore
|
4
4
|
ActivityLogsQuery,
|
5
|
-
|
5
|
+
ActivityLogsAskQuery,
|
6
6
|
ActivityLogsSearchQuery,
|
7
7
|
DownloadActivityLogsQuery,
|
8
|
-
|
8
|
+
DownloadActivityLogsAskQuery,
|
9
9
|
DownloadActivityLogsSearchQuery,
|
10
10
|
DownloadFormat,
|
11
11
|
EventType,
|
@@ -25,23 +25,6 @@ WAIT_FOR_DOWNLOAD_TIMEOUT = 120
|
|
25
25
|
|
26
26
|
|
27
27
|
class NucliaLogs:
|
28
|
-
@kb
|
29
|
-
def get(
|
30
|
-
self, *args, type: Union[LogType, str], month: str, **kwargs
|
31
|
-
) -> list[list[str]]:
|
32
|
-
"""
|
33
|
-
Download activity logs.
|
34
|
-
|
35
|
-
:param type: VISITED, MODIFIED, DELETED, NEW, SEARCH, SUGGEST, INDEXED, CHAT, STARTED, STOPPED, PROCESSED
|
36
|
-
:param month: YYYY-MM
|
37
|
-
"""
|
38
|
-
if isinstance(type, str):
|
39
|
-
type = LogType[type.upper()]
|
40
|
-
|
41
|
-
ndb: NucliaDBClient = kwargs["ndb"]
|
42
|
-
resp = ndb.logs(type=type, month=month)
|
43
|
-
return resp
|
44
|
-
|
45
28
|
@kb
|
46
29
|
def query(
|
47
30
|
self,
|
@@ -51,25 +34,25 @@ class NucliaLogs:
|
|
51
34
|
dict,
|
52
35
|
ActivityLogsQuery,
|
53
36
|
ActivityLogsSearchQuery,
|
54
|
-
|
37
|
+
ActivityLogsAskQuery,
|
55
38
|
],
|
56
39
|
**kwargs,
|
57
40
|
) -> ActivityLogsOutput:
|
58
41
|
"""
|
59
42
|
Query activity logs.
|
60
43
|
|
61
|
-
:param type: VISITED, MODIFIED, DELETED, NEW, SEARCH, SUGGEST, INDEXED, CHAT, STARTED, STOPPED, PROCESSED
|
44
|
+
:param type: VISITED, MODIFIED, DELETED, NEW, SEARCH, SUGGEST, INDEXED, CHAT, ASK, STARTED, STOPPED, PROCESSED
|
62
45
|
:param query: ActivityLogsQuery
|
63
46
|
"""
|
64
47
|
_type = EventType[type.upper()] if isinstance(type, str) else type
|
65
48
|
_query: Union[
|
66
49
|
ActivityLogsQuery,
|
67
50
|
ActivityLogsSearchQuery,
|
68
|
-
|
51
|
+
ActivityLogsAskQuery,
|
69
52
|
]
|
70
53
|
if isinstance(query, dict):
|
71
|
-
if _type
|
72
|
-
_query =
|
54
|
+
if _type in (EventType.ASK, EventType.CHAT): # TODO: deprecate chat event
|
55
|
+
_query = ActivityLogsAskQuery.model_validate(query)
|
73
56
|
elif type is EventType.SEARCH:
|
74
57
|
_query = ActivityLogsSearchQuery.model_validate(query)
|
75
58
|
else:
|
@@ -95,7 +78,7 @@ class NucliaLogs:
|
|
95
78
|
dict,
|
96
79
|
DownloadActivityLogsQuery,
|
97
80
|
DownloadActivityLogsSearchQuery,
|
98
|
-
|
81
|
+
DownloadActivityLogsAskQuery,
|
99
82
|
],
|
100
83
|
download_format: Union[DownloadFormat, str],
|
101
84
|
wait: bool = False,
|
@@ -104,8 +87,8 @@ class NucliaLogs:
|
|
104
87
|
"""
|
105
88
|
Download activity logs.
|
106
89
|
|
107
|
-
:param type:
|
108
|
-
:param
|
90
|
+
:param type: VISITED, MODIFIED, DELETED, NEW, SEARCH, SUGGEST, INDEXED, CHAT, ASK, STARTED, STOPPED, PROCESSED
|
91
|
+
:param download_format: NDJSON, CSV
|
109
92
|
:param query: DownloadActivityLogsQuery
|
110
93
|
"""
|
111
94
|
_type = EventType[type.upper()] if isinstance(type, str) else type
|
@@ -119,11 +102,11 @@ class NucliaLogs:
|
|
119
102
|
dict,
|
120
103
|
DownloadActivityLogsQuery,
|
121
104
|
DownloadActivityLogsSearchQuery,
|
122
|
-
|
105
|
+
DownloadActivityLogsAskQuery,
|
123
106
|
]
|
124
107
|
if isinstance(query, dict):
|
125
|
-
if _type
|
126
|
-
_query =
|
108
|
+
if _type in (EventType.ASK, EventType.CHAT): # TODO: deprecate chat event
|
109
|
+
_query = DownloadActivityLogsAskQuery.model_validate(query)
|
127
110
|
elif type is EventType.SEARCH:
|
128
111
|
_query = DownloadActivityLogsSearchQuery.model_validate(query)
|
129
112
|
else:
|
@@ -168,23 +151,6 @@ class NucliaLogs:
|
|
168
151
|
|
169
152
|
|
170
153
|
class AsyncNucliaLogs:
|
171
|
-
@kb
|
172
|
-
async def get(
|
173
|
-
self, *args, type: Union[LogType, str], month: str, **kwargs
|
174
|
-
) -> list[list[str]]:
|
175
|
-
"""
|
176
|
-
Download activity logs.
|
177
|
-
|
178
|
-
:param type: VISITED, MODIFIED, DELETED, NEW, SEARCH, SUGGEST, INDEXED, CHAT, STARTED, STOPPED, PROCESSED
|
179
|
-
:param month: YYYY-MM
|
180
|
-
"""
|
181
|
-
if isinstance(type, str):
|
182
|
-
type = LogType[type.upper()]
|
183
|
-
|
184
|
-
ndb: AsyncNucliaDBClient = kwargs["ndb"]
|
185
|
-
resp = await ndb.logs(type=type, month=month)
|
186
|
-
return resp
|
187
|
-
|
188
154
|
@kb
|
189
155
|
async def query(
|
190
156
|
self,
|
@@ -194,25 +160,25 @@ class AsyncNucliaLogs:
|
|
194
160
|
dict,
|
195
161
|
ActivityLogsQuery,
|
196
162
|
ActivityLogsSearchQuery,
|
197
|
-
|
163
|
+
ActivityLogsAskQuery,
|
198
164
|
],
|
199
165
|
**kwargs,
|
200
166
|
) -> ActivityLogsOutput:
|
201
167
|
"""
|
202
168
|
Query activity logs.
|
203
169
|
|
204
|
-
:param type: VISITED, MODIFIED, DELETED, NEW, SEARCH, SUGGEST, INDEXED, CHAT, STARTED, STOPPED, PROCESSED
|
170
|
+
:param type: VISITED, MODIFIED, DELETED, NEW, SEARCH, SUGGEST, INDEXED, CHAT, ASK, STARTED, STOPPED, PROCESSED
|
205
171
|
:param query: ActivityLogsQuery
|
206
172
|
"""
|
207
173
|
_type = EventType[type.upper()] if isinstance(type, str) else type
|
208
174
|
_query: Union[
|
209
175
|
ActivityLogsQuery,
|
210
176
|
ActivityLogsSearchQuery,
|
211
|
-
|
177
|
+
ActivityLogsAskQuery,
|
212
178
|
]
|
213
179
|
if isinstance(query, dict):
|
214
|
-
if _type
|
215
|
-
_query =
|
180
|
+
if _type in (EventType.ASK, EventType.CHAT): # TODO: deprecate chat event
|
181
|
+
_query = ActivityLogsAskQuery.model_validate(query)
|
216
182
|
elif type is EventType.SEARCH:
|
217
183
|
_query = ActivityLogsSearchQuery.model_validate(query)
|
218
184
|
else:
|
@@ -238,7 +204,7 @@ class AsyncNucliaLogs:
|
|
238
204
|
dict,
|
239
205
|
DownloadActivityLogsQuery,
|
240
206
|
DownloadActivityLogsSearchQuery,
|
241
|
-
|
207
|
+
DownloadActivityLogsAskQuery,
|
242
208
|
],
|
243
209
|
download_format: Union[DownloadFormat, str],
|
244
210
|
wait: bool = False,
|
@@ -247,8 +213,8 @@ class AsyncNucliaLogs:
|
|
247
213
|
"""
|
248
214
|
Download activity logs.
|
249
215
|
|
250
|
-
:param type:
|
251
|
-
:param
|
216
|
+
:param type: VISITED, MODIFIED, DELETED, NEW, SEARCH, SUGGEST, INDEXED, CHAT, ASK, STARTED, STOPPED, PROCESSED
|
217
|
+
:param download_format: NDJSON, CSV
|
252
218
|
:param query: DownloadActivityLogsQuery
|
253
219
|
"""
|
254
220
|
_type = EventType[type.upper()] if isinstance(type, str) else type
|
@@ -262,11 +228,11 @@ class AsyncNucliaLogs:
|
|
262
228
|
dict,
|
263
229
|
DownloadActivityLogsQuery,
|
264
230
|
DownloadActivityLogsSearchQuery,
|
265
|
-
|
231
|
+
DownloadActivityLogsAskQuery,
|
266
232
|
]
|
267
233
|
if isinstance(query, dict):
|
268
|
-
if _type
|
269
|
-
_query =
|
234
|
+
if _type in (EventType.ASK, EventType.CHAT): # TODO: deprecate chat event
|
235
|
+
_query = DownloadActivityLogsAskQuery.model_validate(query)
|
270
236
|
elif type is EventType.SEARCH:
|
271
237
|
_query = DownloadActivityLogsSearchQuery.model_validate(query)
|
272
238
|
else:
|
@@ -1,24 +1,15 @@
|
|
1
1
|
from nuclia.sdk.kb import NucliaKB, AsyncNucliaKB
|
2
2
|
from nuclia.tests.fixtures import IS_PROD
|
3
|
-
from nuclia.lib.kb import LogType
|
4
3
|
from nuclia_models.events.activity_logs import (
|
5
4
|
ActivityLogsQuery,
|
6
5
|
Pagination,
|
7
6
|
DownloadActivityLogsQuery,
|
8
7
|
DownloadFormat,
|
8
|
+
EventType,
|
9
9
|
)
|
10
10
|
import pytest
|
11
11
|
|
12
12
|
|
13
|
-
def test_logs(testing_config):
|
14
|
-
if not IS_PROD:
|
15
|
-
assert True
|
16
|
-
return
|
17
|
-
nkb = NucliaKB()
|
18
|
-
logs = nkb.logs.get(type=LogType.NEW, month="2024-06")
|
19
|
-
assert len(logs) == 23
|
20
|
-
|
21
|
-
|
22
13
|
def test_activity_logs_query(testing_config):
|
23
14
|
if not IS_PROD:
|
24
15
|
assert True
|
@@ -30,7 +21,7 @@ def test_activity_logs_query(testing_config):
|
|
30
21
|
pagination=Pagination(limit=10),
|
31
22
|
)
|
32
23
|
nkb = NucliaKB()
|
33
|
-
output = nkb.logs.query(type=
|
24
|
+
output = nkb.logs.query(type=EventType.CHAT, query=query)
|
34
25
|
assert len(output.data) == 10
|
35
26
|
assert output.has_more
|
36
27
|
|
@@ -46,24 +37,48 @@ def test_activity_logs_download(testing_config):
|
|
46
37
|
)
|
47
38
|
nkb = NucliaKB()
|
48
39
|
output = nkb.logs.download(
|
49
|
-
type=
|
40
|
+
type=EventType.CHAT, query=query, download_format=DownloadFormat.NDJSON
|
50
41
|
)
|
51
42
|
assert output.request_id
|
52
43
|
assert output.download_url is None
|
53
44
|
|
54
45
|
|
55
46
|
@pytest.mark.asyncio
|
56
|
-
async def
|
47
|
+
async def test_activity_logs_query_async(testing_config):
|
57
48
|
if not IS_PROD:
|
58
49
|
assert True
|
59
50
|
return
|
51
|
+
query = ActivityLogsQuery(
|
52
|
+
year_month="2024-10",
|
53
|
+
show=["id", "date", "client_type", "total_duration"],
|
54
|
+
filters={},
|
55
|
+
pagination=Pagination(limit=10),
|
56
|
+
)
|
60
57
|
nkb = AsyncNucliaKB()
|
61
|
-
|
62
|
-
assert len(
|
58
|
+
output = await nkb.logs.query(type=EventType.CHAT, query=query)
|
59
|
+
assert len(output.data) == 10
|
60
|
+
assert output.has_more
|
63
61
|
|
64
62
|
|
65
63
|
@pytest.mark.asyncio
|
66
|
-
async def
|
64
|
+
async def test_activity_logs_download_async(testing_config):
|
65
|
+
if not IS_PROD:
|
66
|
+
assert True
|
67
|
+
return
|
68
|
+
query = DownloadActivityLogsQuery(
|
69
|
+
year_month="2024-10",
|
70
|
+
show=["id", "date", "client_type", "total_duration"],
|
71
|
+
filters={},
|
72
|
+
)
|
73
|
+
nkb = AsyncNucliaKB()
|
74
|
+
output = await nkb.logs.download(
|
75
|
+
type=EventType.CHAT, query=query, download_format=DownloadFormat.NDJSON
|
76
|
+
)
|
77
|
+
assert output.request_id
|
78
|
+
assert output.download_url is None
|
79
|
+
|
80
|
+
|
81
|
+
def test_activity_logs_ask_query(testing_config):
|
67
82
|
if not IS_PROD:
|
68
83
|
assert True
|
69
84
|
return
|
@@ -73,14 +88,14 @@ async def test_activity_logs_query_async(testing_config):
|
|
73
88
|
filters={},
|
74
89
|
pagination=Pagination(limit=10),
|
75
90
|
)
|
76
|
-
nkb =
|
77
|
-
output =
|
91
|
+
nkb = NucliaKB()
|
92
|
+
output = nkb.logs.query(type=EventType.ASK, query=query)
|
78
93
|
assert len(output.data) == 10
|
79
94
|
assert output.has_more
|
80
95
|
|
81
96
|
|
82
97
|
@pytest.mark.asyncio
|
83
|
-
async def
|
98
|
+
async def test_activity_logs_ask_download_async(testing_config):
|
84
99
|
if not IS_PROD:
|
85
100
|
assert True
|
86
101
|
return
|
@@ -91,7 +106,7 @@ async def test_activity_logs_download_async(testing_config):
|
|
91
106
|
)
|
92
107
|
nkb = AsyncNucliaKB()
|
93
108
|
output = await nkb.logs.download(
|
94
|
-
type=
|
109
|
+
type=EventType.ASK, query=query, download_format=DownloadFormat.NDJSON
|
95
110
|
)
|
96
111
|
assert output.request_id
|
97
112
|
assert output.download_url is None
|
@@ -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
|
@@ -9,12 +9,12 @@ nuclia/cli/run.py,sha256=B1hP0upSbSCqqT89WAwsd93ZxkAoF6ajVyLOdYmo8fU,1560
|
|
9
9
|
nuclia/cli/utils.py,sha256=iZ3P8juBdAGvaRUd2BGz7bpUXNDHdPrC5p876yyZ2Cs,1223
|
10
10
|
nuclia/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
11
|
nuclia/lib/conversations.py,sha256=M6qhL9NPEKroYF767S-Q2XWokRrjX02kpYTzRvZKwUE,149
|
12
|
-
nuclia/lib/kb.py,sha256=
|
12
|
+
nuclia/lib/kb.py,sha256=jV-L8-a5oFVHIbFfeGO17hXf2IQk9UuW-9fq5D3LO6Y,28508
|
13
13
|
nuclia/lib/models.py,sha256=lO3TZa4jTQ6C8ptGO1oX-5pxDgv8ocO13z7j5jXOC0Y,1554
|
14
14
|
nuclia/lib/nua.py,sha256=sUVFdCjvLigTqUUhILywdHpiC0qKCtKPABn5kUXfuxQ,27064
|
15
15
|
nuclia/lib/nua_chat.py,sha256=ApL1Y1FWvAVUt-Y9a_8TUSJIhg8-UmBSy8TlDPn6tD8,3874
|
16
16
|
nuclia/lib/nua_responses.py,sha256=9WRGpvvhA2ZOyOv9kzX1zI7C3ypM8ySqciVYCSibUjo,12724
|
17
|
-
nuclia/lib/utils.py,sha256=
|
17
|
+
nuclia/lib/utils.py,sha256=9l6DxBk-11WqUhXRn99cqeuVTUOJXj-1S6zckal7wOk,6312
|
18
18
|
nuclia/sdk/__init__.py,sha256=-nAw8i53XBdmbfTa1FJZ0FNRMNakimDVpD6W4OdES-c,1374
|
19
19
|
nuclia/sdk/accounts.py,sha256=7XQ3K9_jlSuk2Cez868FtazZ05xSGab6h3Mt1qMMwIE,647
|
20
20
|
nuclia/sdk/agent.py,sha256=ot_oA4yi7TkXahPnhcRIxztq9Dtskc85-A57WN1BNGg,1961
|
@@ -24,7 +24,7 @@ nuclia/sdk/export_import.py,sha256=y5cTOxhILwRPIvR2Ya12bk-ReGbeDzA3C9TPxgnOHD4,9
|
|
24
24
|
nuclia/sdk/kb.py,sha256=iDJimbzw_R9VeUu7a4F5wXoLdLxCim7W3UeEaAQ5dGI,26820
|
25
25
|
nuclia/sdk/kbs.py,sha256=nXEvg5ddZYdDS8Kie7TrN-s1meU9ecYLf9FlT5xr-ro,9131
|
26
26
|
nuclia/sdk/logger.py,sha256=UHB81eS6IGmLrsofKxLh8cmF2AsaTj_HXP0tGqMr_HM,57
|
27
|
-
nuclia/sdk/logs.py,sha256=
|
27
|
+
nuclia/sdk/logs.py,sha256=3jfORpo8fzZiXFFSbGY0o3Bre1ZgJaKQCXgxP1keNHw,9614
|
28
28
|
nuclia/sdk/nua.py,sha256=6t0m0Sx-UhqNU2Hx9v6vTwy0m3a30K4T0KmP9G43MzY,293
|
29
29
|
nuclia/sdk/nucliadb.py,sha256=bOESIppPgY7IrNqrYY7T3ESoxwttbOSTm5zj1xUS1jI,1288
|
30
30
|
nuclia/sdk/predict.py,sha256=KF7iT2aasaB9DIEAwqktXbOl2H_Y_ne-6-SEErN7YOk,9095
|
@@ -44,7 +44,7 @@ nuclia/tests/test_kb/test_conversation.py,sha256=L__KMBucqChPGeYR_XwXl7Elt4LDlp1
|
|
44
44
|
nuclia/tests/test_kb/test_export_import.py,sha256=lQEww2jFNHZYcudFJqcHhoWAPrmtvvnPvcFqrijxLbo,1019
|
45
45
|
nuclia/tests/test_kb/test_graph.py,sha256=PQSdqvPvOHr71pfdbUpsAK-_DxBQh7spxtJaaleF87A,1434
|
46
46
|
nuclia/tests/test_kb/test_labels.py,sha256=IUdTq4mzv0OrOkwBWWy4UwKGKyJybtoHrgvXr676vyY,961
|
47
|
-
nuclia/tests/test_kb/test_logs.py,sha256=
|
47
|
+
nuclia/tests/test_kb/test_logs.py,sha256=Z9ELtiiU9NniITJzeWt92GCcERKYy9Nwc_fUVPboRU0,3121
|
48
48
|
nuclia/tests/test_kb/test_remi.py,sha256=OX5N-MHbgcwpLg6fBjrAK_KhqkMspJo_VKQHCBCayZ8,2080
|
49
49
|
nuclia/tests/test_kb/test_resource.py,sha256=05Xgmg5fwcPW2PZKnUSSjr6MPXp5w8XDgx8plfNcR68,1102
|
50
50
|
nuclia/tests/test_kb/test_search.py,sha256=bsQhfB6-NYFwY3gqkrVJJnru153UgZqEhV22ho4VeWM,4660
|
@@ -61,9 +61,9 @@ nuclia/tests/test_nucliadb/test_crud.py,sha256=GuY76HRvt2DFaNgioKm5n0Aco1HnG7zzV
|
|
61
61
|
nuclia/tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
62
62
|
nuclia/tests/unit/test_export_import.py,sha256=xo_wVbjUnNlVV65ZGH7LtZ38qy39EkJp2hjOuTHC1nU,980
|
63
63
|
nuclia/tests/unit/test_nua_responses.py,sha256=t_hIdVztTi27RWvpfTJUYcCL0lpKdZFegZIwLdaPNh8,319
|
64
|
-
nuclia-4.8.
|
65
|
-
nuclia-4.8.
|
66
|
-
nuclia-4.8.
|
67
|
-
nuclia-4.8.
|
68
|
-
nuclia-4.8.
|
69
|
-
nuclia-4.8.
|
64
|
+
nuclia-4.8.10.dist-info/licenses/LICENSE,sha256=Ops2LTti_HJtpmWcanuUTdTY3vKDR1myJ0gmGBKC0FA,1063
|
65
|
+
nuclia-4.8.10.dist-info/METADATA,sha256=Vcg3SQFhjDTSZ9akWQevdKqRVZyt8ModTnX5BcwgmsI,2338
|
66
|
+
nuclia-4.8.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
67
|
+
nuclia-4.8.10.dist-info/entry_points.txt,sha256=iZHOyXPNS54r3eQmdi5So20xO1gudI9K2oP4sQsCJRw,46
|
68
|
+
nuclia-4.8.10.dist-info/top_level.txt,sha256=cqn_EitXOoXOSUvZnd4q6QGrhm04pg8tLAZtem-Zfdo,7
|
69
|
+
nuclia-4.8.10.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|