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 CHANGED
@@ -48,7 +48,7 @@ class GraphRelation(BaseModel):
48
48
  destination: GraphEntity
49
49
 
50
50
  def to_relation(self) -> Relation:
51
- return Relation.parse_obj(
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.parse_obj(relation)
63
+ return GraphRelation.model_validate(relation)
64
64
  else:
65
65
  return relation
@@ -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
- yield
53
- reset_config_file()
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.8.10
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.4
28
- Requires-Dist: nucliadb_models<7,>=6.4
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=lO3TZa4jTQ6C8ptGO1oX-5pxDgv8ocO13z7j5jXOC0Y,1554
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=9WRGpvvhA2ZOyOv9kzX1zI7C3ypM8ySqciVYCSibUjo,12724
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=OpW2Tl0RQwG6e2Ytw6Iz7L0SMzaX06qTpb-f4mzw6_g,23435
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=ppjT1VgEdkrqvRPoqt1LU7T6rUf9qZ1UkplQz4hT0IQ,1787
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=L__KMBucqChPGeYR_XwXl7Elt4LDlp1mcmFdD71U8cQ,840
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=PQSdqvPvOHr71pfdbUpsAK-_DxBQh7spxtJaaleF87A,1434
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.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,,
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,,