nuclia 4.8.10__py3-none-any.whl → 4.9.1__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/models.py +2 -2
- nuclia/lib/nua_responses.py +22 -2
- nuclia/sdk/search.py +56 -0
- nuclia/tests/fixtures.py +2 -2
- nuclia/tests/test_kb/test_conversation.py +0 -5
- nuclia/tests/test_kb/test_graph.py +40 -0
- {nuclia-4.8.10.dist-info → nuclia-4.9.1.dist-info}/METADATA +3 -3
- {nuclia-4.8.10.dist-info → nuclia-4.9.1.dist-info}/RECORD +12 -12
- {nuclia-4.8.10.dist-info → nuclia-4.9.1.dist-info}/WHEEL +0 -0
- {nuclia-4.8.10.dist-info → nuclia-4.9.1.dist-info}/entry_points.txt +0 -0
- {nuclia-4.8.10.dist-info → nuclia-4.9.1.dist-info}/licenses/LICENSE +0 -0
- {nuclia-4.8.10.dist-info → nuclia-4.9.1.dist-info}/top_level.txt +0 -0
nuclia/lib/models.py
CHANGED
@@ -48,7 +48,7 @@ class GraphRelation(BaseModel):
|
|
48
48
|
destination: GraphEntity
|
49
49
|
|
50
50
|
def to_relation(self) -> Relation:
|
51
|
-
return Relation.
|
51
|
+
return Relation.model_validate(
|
52
52
|
{
|
53
53
|
"from": self.source.to_dict(),
|
54
54
|
"to": self.destination.to_dict(),
|
@@ -60,6 +60,6 @@ class GraphRelation(BaseModel):
|
|
60
60
|
|
61
61
|
def get_relation(relation: Union[GraphRelation, dict]) -> GraphRelation:
|
62
62
|
if isinstance(relation, dict):
|
63
|
-
return GraphRelation.
|
63
|
+
return GraphRelation.model_validate(relation)
|
64
64
|
else:
|
65
65
|
return relation
|
nuclia/lib/nua_responses.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
from datetime import datetime
|
2
|
-
from enum import Enum
|
2
|
+
from enum import Enum, IntEnum
|
3
3
|
from typing import Any, Dict, List, Optional, Union, cast
|
4
4
|
|
5
5
|
import pydantic
|
@@ -486,17 +486,37 @@ class ChatResponse(BaseModel):
|
|
486
486
|
return ChatResponse(answer=obj.decode())
|
487
487
|
|
488
488
|
|
489
|
+
class SimilarityFunction(IntEnum):
|
490
|
+
# Keep this in sync with SimilarityFunction in config.proto
|
491
|
+
# It's an IntEnum to match the protobuf definition
|
492
|
+
DOT = 0
|
493
|
+
COSINE = 1
|
494
|
+
|
495
|
+
|
496
|
+
class SemanticConfig(BaseModel):
|
497
|
+
# Keep this in sync with SemanticConfig in config.proto
|
498
|
+
similarity: SimilarityFunction
|
499
|
+
size: int
|
500
|
+
threshold: float
|
501
|
+
max_tokens: Optional[int] = None
|
502
|
+
matryoshka_dims: list[int] = []
|
503
|
+
external: bool = False
|
504
|
+
|
505
|
+
|
489
506
|
class StoredLearningConfiguration(BaseModel):
|
490
507
|
resource_labelers_models: Optional[List[str]] = None
|
491
508
|
paragraph_labelers_models: Optional[List[str]] = None
|
492
509
|
intent_models: Optional[List[str]] = None
|
493
510
|
|
511
|
+
default_semantic_model: Optional[str] = None
|
512
|
+
semantic_models: Optional[list[str]] = Field(default_factory=list[str])
|
513
|
+
semantic_model_configs: dict[str, SemanticConfig] = {}
|
494
514
|
semantic_model: str
|
495
515
|
anonymization_model: str
|
496
516
|
generative_model: str
|
497
517
|
ner_model: str
|
498
518
|
relation_model: str
|
499
|
-
visual_labeling: str
|
519
|
+
visual_labeling: Optional[str] = None
|
500
520
|
|
501
521
|
user_keys: Optional[UserLearningKeys] = None
|
502
522
|
user_prompts: Optional[UserPrompts] = None
|
nuclia/sdk/search.py
CHANGED
@@ -20,6 +20,8 @@ from nucliadb_models.search import (
|
|
20
20
|
SyncAskResponse,
|
21
21
|
ChatModel,
|
22
22
|
)
|
23
|
+
from nucliadb_models.graph.requests import GraphSearchRequest
|
24
|
+
from nucliadb_models.graph.responses import GraphSearchResponse
|
23
25
|
from pydantic import ValidationError
|
24
26
|
|
25
27
|
from nuclia.data import get_async_auth, get_auth
|
@@ -331,6 +333,33 @@ class NucliaSearch:
|
|
331
333
|
result.tokens = ask_response.metadata.tokens.model_dump()
|
332
334
|
return result
|
333
335
|
|
336
|
+
@kb
|
337
|
+
def graph(
|
338
|
+
self,
|
339
|
+
*,
|
340
|
+
query: Union[dict, GraphSearchRequest],
|
341
|
+
**kwargs,
|
342
|
+
) -> GraphSearchResponse:
|
343
|
+
"""
|
344
|
+
Perform a graph path query.
|
345
|
+
|
346
|
+
See https://docs.nuclia.dev/docs/api#tag/Search/operation/graph_search_knowledgebox_kb__kbid__graph_post
|
347
|
+
"""
|
348
|
+
ndb: NucliaDBClient = kwargs["ndb"]
|
349
|
+
|
350
|
+
if isinstance(query, GraphSearchRequest):
|
351
|
+
req = query
|
352
|
+
elif isinstance(query, dict):
|
353
|
+
try:
|
354
|
+
req = GraphSearchRequest.model_validate(query)
|
355
|
+
except ValidationError:
|
356
|
+
logger.exception("Error validating query")
|
357
|
+
raise
|
358
|
+
else:
|
359
|
+
raise Exception(f"Invalid query: '{query}'")
|
360
|
+
|
361
|
+
return ndb.ndb.graph_search(req, kbid=ndb.kbid)
|
362
|
+
|
334
363
|
|
335
364
|
class AsyncNucliaSearch:
|
336
365
|
"""
|
@@ -659,3 +688,30 @@ class AsyncNucliaSearch:
|
|
659
688
|
else: # pragma: no cover
|
660
689
|
warnings.warn(f"Unknown ask stream item type: {ask_response_item.type}")
|
661
690
|
return result
|
691
|
+
|
692
|
+
@kb
|
693
|
+
async def graph(
|
694
|
+
self,
|
695
|
+
*,
|
696
|
+
query: Union[dict, GraphSearchRequest],
|
697
|
+
**kwargs,
|
698
|
+
) -> GraphSearchResponse:
|
699
|
+
"""
|
700
|
+
Perform a graph path query.
|
701
|
+
|
702
|
+
See https://docs.nuclia.dev/docs/api#tag/Search/operation/graph_search_knowledgebox_kb__kbid__graph_post
|
703
|
+
"""
|
704
|
+
ndb: AsyncNucliaDBClient = kwargs["ndb"]
|
705
|
+
|
706
|
+
if isinstance(query, GraphSearchRequest):
|
707
|
+
req = query
|
708
|
+
elif isinstance(query, dict):
|
709
|
+
try:
|
710
|
+
req = GraphSearchRequest.model_validate(query)
|
711
|
+
except ValidationError:
|
712
|
+
logger.exception("Error validating query")
|
713
|
+
raise
|
714
|
+
else:
|
715
|
+
raise Exception(f"Invalid query: '{query}'")
|
716
|
+
|
717
|
+
return await ndb.ndb.graph_search(req, kbid=ndb.kbid)
|
nuclia/tests/fixtures.py
CHANGED
@@ -49,8 +49,8 @@ def testing_config(testing_kb, testing_nua, testing_user):
|
|
49
49
|
nuclia_auth._config.set_default_kb(TESTING_KBID)
|
50
50
|
nuclia_auth._config.set_default_nua(client_id)
|
51
51
|
|
52
|
-
|
53
|
-
|
52
|
+
yield
|
53
|
+
reset_config_file()
|
54
54
|
|
55
55
|
|
56
56
|
@pytest.fixture(autouse=True)
|
@@ -2,7 +2,6 @@ import os
|
|
2
2
|
|
3
3
|
from nucliadb_sdk.v2.exceptions import NotFoundError
|
4
4
|
|
5
|
-
from nuclia.sdk.kb import NucliaKB
|
6
5
|
from nuclia.sdk.resource import NucliaResource
|
7
6
|
from nuclia.sdk.upload import NucliaUpload
|
8
7
|
|
@@ -10,7 +9,6 @@ path = f"{os.path.dirname(__file__)}/../assets/conversation.json"
|
|
10
9
|
|
11
10
|
|
12
11
|
def test_conversation(testing_config):
|
13
|
-
nkb = NucliaKB()
|
14
12
|
nresource = NucliaResource()
|
15
13
|
try:
|
16
14
|
res = nresource.get(slug="conversation1")
|
@@ -18,9 +16,6 @@ def test_conversation(testing_config):
|
|
18
16
|
except NotFoundError:
|
19
17
|
pass
|
20
18
|
|
21
|
-
res = nkb.list()
|
22
|
-
assert len(res.resources) == 2
|
23
|
-
|
24
19
|
nu = NucliaUpload()
|
25
20
|
nu.conversation(path=path, slug="conversation1", field="c1")
|
26
21
|
|
@@ -6,6 +6,13 @@ from time import sleep
|
|
6
6
|
|
7
7
|
def test_graph(testing_config):
|
8
8
|
nkb = NucliaKB()
|
9
|
+
|
10
|
+
# ensure KB is clean
|
11
|
+
try:
|
12
|
+
nkb.delete_graph(slug="graph1")
|
13
|
+
except NotFoundError:
|
14
|
+
pass
|
15
|
+
|
9
16
|
nkb.add_graph(
|
10
17
|
slug="graph1",
|
11
18
|
graph=[
|
@@ -28,6 +35,25 @@ def test_graph(testing_config):
|
|
28
35
|
)
|
29
36
|
relations = nkb.get_graph(slug="graph1")
|
30
37
|
assert len(relations) == 3
|
38
|
+
|
39
|
+
# XXX: sometimes, nucliadb needs some more time to index the graph. We retry
|
40
|
+
# some times and fail if that keeps hapenning
|
41
|
+
RETRIES = 5
|
42
|
+
DELAY = 0.5
|
43
|
+
for _ in range(RETRIES):
|
44
|
+
paths = nkb.search.graph(
|
45
|
+
query={"query": {"prop": "path", "source": {"value": "Alice"}}}
|
46
|
+
)
|
47
|
+
try:
|
48
|
+
assert len(paths.paths) == 2
|
49
|
+
except AssertionError:
|
50
|
+
# wait for a bit before retrying
|
51
|
+
print("Graph was not indexed yet, waiting a bit...")
|
52
|
+
sleep(DELAY)
|
53
|
+
else:
|
54
|
+
break
|
55
|
+
assert len(paths.paths) == 2
|
56
|
+
|
31
57
|
nkb.update_graph(
|
32
58
|
slug="graph1",
|
33
59
|
graph=[
|
@@ -40,6 +66,20 @@ def test_graph(testing_config):
|
|
40
66
|
)
|
41
67
|
relations = nkb.get_graph(slug="graph1")
|
42
68
|
assert len(relations) == 4
|
69
|
+
|
70
|
+
for _ in range(RETRIES):
|
71
|
+
paths = nkb.search.graph(
|
72
|
+
query={"query": {"prop": "path", "source": {"value": "Victor"}}}
|
73
|
+
)
|
74
|
+
try:
|
75
|
+
assert len(paths.paths) == 1
|
76
|
+
except AssertionError:
|
77
|
+
print("Graph was not indexed yet, waiting a bit...")
|
78
|
+
sleep(DELAY)
|
79
|
+
else:
|
80
|
+
break
|
81
|
+
assert len(paths.paths) == 1
|
82
|
+
|
43
83
|
nkb.delete_graph(slug="graph1")
|
44
84
|
try:
|
45
85
|
sleep(0.5)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: nuclia
|
3
|
-
Version: 4.
|
3
|
+
Version: 4.9.1
|
4
4
|
Summary: Nuclia Python SDK
|
5
5
|
Author-email: Nuclia <info@nuclia.com>
|
6
6
|
License-Expression: MIT
|
@@ -24,8 +24,8 @@ Requires-Dist: requests
|
|
24
24
|
Requires-Dist: httpx
|
25
25
|
Requires-Dist: httpcore>=1.0.0
|
26
26
|
Requires-Dist: prompt_toolkit
|
27
|
-
Requires-Dist: nucliadb_sdk<7,>=6.
|
28
|
-
Requires-Dist: nucliadb_models<7,>=6.
|
27
|
+
Requires-Dist: nucliadb_sdk<7,>=6.5
|
28
|
+
Requires-Dist: nucliadb_models<7,>=6.5
|
29
29
|
Requires-Dist: nuclia-models>=0.41.1
|
30
30
|
Requires-Dist: tqdm
|
31
31
|
Requires-Dist: aiofiles
|
@@ -10,10 +10,10 @@ 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
12
|
nuclia/lib/kb.py,sha256=jV-L8-a5oFVHIbFfeGO17hXf2IQk9UuW-9fq5D3LO6Y,28508
|
13
|
-
nuclia/lib/models.py,sha256=
|
13
|
+
nuclia/lib/models.py,sha256=ekEQrVIFU3aFvt60yQh-zpWkGNORBMSc7c5Hd_VzPzI,1564
|
14
14
|
nuclia/lib/nua.py,sha256=sUVFdCjvLigTqUUhILywdHpiC0qKCtKPABn5kUXfuxQ,27064
|
15
15
|
nuclia/lib/nua_chat.py,sha256=ApL1Y1FWvAVUt-Y9a_8TUSJIhg8-UmBSy8TlDPn6tD8,3874
|
16
|
-
nuclia/lib/nua_responses.py,sha256=
|
16
|
+
nuclia/lib/nua_responses.py,sha256=RJB7bbgZEpYr29aOmaT2nb1X0g6wds4MOngq7N-ZcTg,13382
|
17
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
|
@@ -31,18 +31,18 @@ nuclia/sdk/predict.py,sha256=KF7iT2aasaB9DIEAwqktXbOl2H_Y_ne-6-SEErN7YOk,9095
|
|
31
31
|
nuclia/sdk/process.py,sha256=WuNnqaWprp-EABWDC_z7O2woesGIlYWnDUKozh7Ibr4,2241
|
32
32
|
nuclia/sdk/remi.py,sha256=BEb3O9R2jOFlOda4vjFucKKGO1c2eTkqYZdFlIy3Zmo,4357
|
33
33
|
nuclia/sdk/resource.py,sha256=0lSvD4e1FpN5iM9W295dOKLJ8hsXfIe8HKdo0HsVg20,13976
|
34
|
-
nuclia/sdk/search.py,sha256=
|
34
|
+
nuclia/sdk/search.py,sha256=1mLJzDO-W3ObReDL1xK8zgjIxkdpuIhyf87-L4bISKQ,25180
|
35
35
|
nuclia/sdk/task.py,sha256=UawH-7IneRIGVOiLdDQ2vDBwe5eI51UXRbLRRVeu3C4,6095
|
36
36
|
nuclia/sdk/upload.py,sha256=ZBzYROF3yP-77HcaR06OBsFjJAbTOCvF-nlxaqQZsT4,22720
|
37
37
|
nuclia/sdk/zones.py,sha256=1ARWrTsTuzj8zguanpX3OaIw-3Qq_ULS_g4GG2mHxOA,342
|
38
38
|
nuclia/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
39
39
|
nuclia/tests/conftest.py,sha256=-Gv9Q20tBVQNNWqWHGNmzkXJpijmgTdcvNnaRAUluGk,115
|
40
|
-
nuclia/tests/fixtures.py,sha256=
|
40
|
+
nuclia/tests/fixtures.py,sha256=rcGGbtxQbGK9vR9efL7BsE1ugJl15QQDIxUyFZLfv-E,1795
|
41
41
|
nuclia/tests/assets/conversation.json,sha256=jLmVngHEW8QdAzSMa-MYgbJgYxOO8tHq6Ia029-CD0E,348
|
42
42
|
nuclia/tests/test_kb/test_backup.py,sha256=67fAw1C_NB363G-wuI9LnSH6nG_YrYs-uBcFyBx6Peg,2932
|
43
|
-
nuclia/tests/test_kb/test_conversation.py,sha256=
|
43
|
+
nuclia/tests/test_kb/test_conversation.py,sha256=plsWY_gEhK3P4CsIO9jkBmimZk3UDGeMYPu7YVFeuIQ,727
|
44
44
|
nuclia/tests/test_kb/test_export_import.py,sha256=lQEww2jFNHZYcudFJqcHhoWAPrmtvvnPvcFqrijxLbo,1019
|
45
|
-
nuclia/tests/test_kb/test_graph.py,sha256=
|
45
|
+
nuclia/tests/test_kb/test_graph.py,sha256=ecAB-lWqm3_796HUuF-fSpGzlhsXV9NGZnAjvxXANps,2540
|
46
46
|
nuclia/tests/test_kb/test_labels.py,sha256=IUdTq4mzv0OrOkwBWWy4UwKGKyJybtoHrgvXr676vyY,961
|
47
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
|
@@ -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.
|
65
|
-
nuclia-4.
|
66
|
-
nuclia-4.
|
67
|
-
nuclia-4.
|
68
|
-
nuclia-4.
|
69
|
-
nuclia-4.
|
64
|
+
nuclia-4.9.1.dist-info/licenses/LICENSE,sha256=Ops2LTti_HJtpmWcanuUTdTY3vKDR1myJ0gmGBKC0FA,1063
|
65
|
+
nuclia-4.9.1.dist-info/METADATA,sha256=bScM2QXDcmlYLGp0pDG1ij02jclIV8u0Rk_CTFwkjvA,2337
|
66
|
+
nuclia-4.9.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
67
|
+
nuclia-4.9.1.dist-info/entry_points.txt,sha256=iZHOyXPNS54r3eQmdi5So20xO1gudI9K2oP4sQsCJRw,46
|
68
|
+
nuclia-4.9.1.dist-info/top_level.txt,sha256=cqn_EitXOoXOSUvZnd4q6QGrhm04pg8tLAZtem-Zfdo,7
|
69
|
+
nuclia-4.9.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|