nucliadb 6.3.1.post3457__py3-none-any.whl → 6.3.1.post3470__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.
@@ -101,15 +101,15 @@ async def move_set_of_kb_resources(
101
101
  to_shard = [s for s in kb_shards.shards if s.shard == to_shard_id][0]
102
102
 
103
103
  from_node, from_shard_replica_id = choose_node(from_shard)
104
- search_response: nodereader_pb2.SearchResponse = await from_node.reader.Search( # type: ignore
105
- nodereader_pb2.SearchRequest(
106
- shard=from_shard_replica_id,
107
- paragraph=False,
108
- document=True,
109
- result_per_page=count,
110
- fields=["a/title"],
111
- )
104
+ request = nodereader_pb2.SearchRequest(
105
+ shard=from_shard_replica_id,
106
+ paragraph=False,
107
+ document=True,
108
+ result_per_page=count,
112
109
  )
110
+ request.field_filter.field.field_type = "a"
111
+ request.field_filter.field.field_id = "title"
112
+ search_response: nodereader_pb2.SearchResponse = await from_node.reader.Search(request) # type: ignore
113
113
 
114
114
  for result in search_response.document.results:
115
115
  resource_id = result.uuid
@@ -18,7 +18,6 @@
18
18
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
19
  #
20
20
  import asyncio
21
- import json
22
21
  import logging
23
22
  from copy import deepcopy
24
23
  from typing import Any, Iterator, Optional
@@ -41,7 +40,7 @@ from nucliadb.common.ids import FieldId, ParagraphId, VectorId
41
40
  from nucliadb_models.search import SCORE_TYPE, TextPosition
42
41
  from nucliadb_protos import knowledgebox_pb2 as kb_pb2
43
42
  from nucliadb_protos import utils_pb2
44
- from nucliadb_protos.nodereader_pb2 import SearchRequest, Timestamps
43
+ from nucliadb_protos.nodereader_pb2 import FilterExpression, SearchRequest
45
44
  from nucliadb_protos.noderesources_pb2 import IndexParagraph, Resource, VectorSentence
46
45
  from nucliadb_telemetry.metrics import Observer
47
46
  from nucliadb_utils.aiopynecone.client import DataPlane, FilterOperator, LogicalOperator
@@ -762,24 +761,10 @@ def convert_to_pinecone_filter(request: SearchRequest) -> Optional[dict[str, Any
762
761
  can be used on Pinecone indexes.
763
762
  """
764
763
  and_terms = []
765
- if request.HasField("filter"):
766
- # Label filtering
767
- if len(request.filter.paragraph_labels) > 0 and len(request.filter.field_labels) > 0:
768
- raise ValueError("Cannot filter by paragraph and field labels at the same request")
769
-
770
- decoded_expression: dict[str, Any] = json.loads(request.filter.labels_expression)
771
- if len(request.filter.paragraph_labels) > 0:
772
- and_terms.append(convert_label_filter_expression("paragraph_labels", decoded_expression))
773
- else:
774
- and_terms.append(convert_label_filter_expression("field_labels", decoded_expression))
775
-
776
- if request.HasField("timestamps"):
777
- # Date range filtering
778
- and_terms.extend(convert_timestamp_filter(request.timestamps))
779
-
780
- if len(request.key_filters) > 0:
781
- # Filter by resource_id
782
- and_terms.append({"rid": {FilterOperator.IN: list(set(request.key_filters))}})
764
+ if request.HasField("field_filter"):
765
+ and_terms.append(convert_filter_expression("field_labels", request.field_filter))
766
+ if request.HasField("paragraph_filter"):
767
+ and_terms.append(convert_filter_expression("paragraph_labels", request.field_filter))
783
768
 
784
769
  if len(request.security.access_groups):
785
770
  # Security filtering
@@ -795,12 +780,6 @@ def convert_to_pinecone_filter(request: SearchRequest) -> Optional[dict[str, Any
795
780
  }
796
781
  and_terms.append(security_term)
797
782
 
798
- if len(request.fields) > 0:
799
- # Filter by field_id
800
- fields_term = {
801
- "field_id": {FilterOperator.IN: list({field_id.strip("/") for field_id in request.fields})}
802
- }
803
- and_terms.append(fields_term)
804
783
  if len(and_terms) == 0:
805
784
  return None
806
785
  if len(and_terms) == 1:
@@ -808,8 +787,8 @@ def convert_to_pinecone_filter(request: SearchRequest) -> Optional[dict[str, Any
808
787
  return {LogicalOperator.AND: and_terms}
809
788
 
810
789
 
811
- def convert_label_filter_expression(
812
- field: str, expression: dict[str, Any], negative: bool = False
790
+ def convert_filter_expression(
791
+ field: str, expression: FilterExpression, negative: bool = False
813
792
  ) -> dict[str, Any]:
814
793
  """
815
794
  Converts internal label filter expressions to Pinecone's metadata query language.
@@ -817,77 +796,99 @@ def convert_label_filter_expression(
817
796
  Note: Since Pinecone does not support negation of expressions, we need to use De Morgan's laws to
818
797
  convert the expression to a positive one.
819
798
  """
820
- if "literal" in expression:
821
- if negative:
822
- return {field: {FilterOperator.NOT_IN: [expression["literal"]]}}
823
- else:
824
- return {field: {FilterOperator.IN: [expression["literal"]]}}
825
799
 
826
- if "and" in expression:
800
+ kind = expression.WhichOneof("expr")
801
+ if kind == "bool_and":
827
802
  if negative:
828
803
  return {
829
804
  LogicalOperator.OR: [
830
- convert_label_filter_expression(field, sub_expression, negative=True)
831
- for sub_expression in expression["and"]
805
+ convert_filter_expression(field, sub_expression, negative=True)
806
+ for sub_expression in expression.bool_and.operands
832
807
  ]
833
808
  }
834
809
  else:
835
810
  return {
836
811
  LogicalOperator.AND: [
837
- convert_label_filter_expression(field, sub_expression)
838
- for sub_expression in expression["and"]
812
+ convert_filter_expression(field, sub_expression)
813
+ for sub_expression in expression.bool_and.operands
839
814
  ]
840
815
  }
841
-
842
- if "or" in expression:
816
+ elif kind == "bool_or":
843
817
  if negative:
844
818
  return {
845
819
  LogicalOperator.AND: [
846
- convert_label_filter_expression(field, sub_expression, negative=True)
847
- for sub_expression in expression["or"]
820
+ convert_filter_expression(field, sub_expression, negative=True)
821
+ for sub_expression in expression.bool_or.operands
848
822
  ]
849
823
  }
850
824
  else:
851
825
  return {
852
826
  LogicalOperator.OR: [
853
- convert_label_filter_expression(field, sub_expression)
854
- for sub_expression in expression["or"]
827
+ convert_filter_expression(field, sub_expression)
828
+ for sub_expression in expression.bool_or.operands
855
829
  ]
856
830
  }
857
831
 
858
- if "not" in expression:
859
- return convert_label_filter_expression(field, expression["not"], negative=True)
832
+ elif kind == "bool_not":
833
+ return convert_filter_expression(field, expression.bool_not, negative=not negative)
860
834
 
861
- raise ValueError(f"Invalid label filter expression: {expression}")
835
+ elif kind == "resource":
836
+ operator = FilterOperator.NOT_EQUALS if negative else FilterOperator.EQUALS
837
+ return {"rid": {operator: expression.resource.resource_id}}
862
838
 
839
+ elif kind == "field":
840
+ field_id = expression.field.field_type
841
+ if expression.field.HasField("field_id"):
842
+ field_id += f"/{expression.field.field_id}"
843
+ operator = FilterOperator.NOT_EQUALS if negative else FilterOperator.EQUALS
844
+ return {"field_id": {operator: field_id}}
863
845
 
864
- def convert_timestamp_filter(timestamps: Timestamps) -> list[dict[str, Any]]:
865
- """
866
- Allows to filter by date_created and date_modified fields in Pinecone.
867
- Powers date range filtering at NucliaDB.
868
- """
869
- and_terms = []
870
- if timestamps.HasField("from_modified"):
871
- and_terms.append(
872
- {
873
- "date_modified": {
874
- FilterOperator.GREATER_THAN_OR_EQUAL: timestamps.from_modified.ToSeconds()
875
- }
876
- }
877
- )
878
- if timestamps.HasField("to_modified"):
879
- and_terms.append(
880
- {"date_modified": {FilterOperator.LESS_THAN_OR_EQUAL: timestamps.to_modified.ToSeconds()}}
881
- )
882
- if timestamps.HasField("from_created"):
883
- and_terms.append(
884
- {"date_created": {FilterOperator.GREATER_THAN_OR_EQUAL: timestamps.from_created.ToSeconds()}}
885
- )
886
- if timestamps.HasField("to_created"):
887
- and_terms.append(
888
- {"date_created": {FilterOperator.LESS_THAN_OR_EQUAL: timestamps.to_created.ToSeconds()}}
846
+ elif kind == "keyword":
847
+ raise ValueError("Cannot filter by keywords")
848
+
849
+ elif kind == "date":
850
+ date_field = (
851
+ "date_created"
852
+ if expression.date.field == FilterExpression.DateRangeFilter.DateField.CREATED
853
+ else "date_modified"
889
854
  )
890
- return and_terms
855
+ if negative:
856
+ terms = []
857
+ if expression.date.HasField("since"):
858
+ operator = FilterOperator.LESS_THAN
859
+ terms.append({date_field: {operator: expression.date.since.ToSeconds()}})
860
+ if expression.date.HasField("until"):
861
+ operator = FilterOperator.GREATER_THAN
862
+ terms.append({date_field: {operator: expression.date.until.ToSeconds()}})
863
+
864
+ if len(terms) == 2:
865
+ return {LogicalOperator.OR: terms}
866
+ elif len(terms) == 1:
867
+ return terms[0]
868
+ else:
869
+ raise ValueError(f"Invalid filter expression: {expression}")
870
+ else:
871
+ terms = []
872
+ if expression.date.HasField("since"):
873
+ operator = FilterOperator.GREATER_THAN_OR_EQUAL
874
+ terms.append({date_field: {operator: expression.date.since.ToSeconds()}})
875
+ if expression.date.HasField("until"):
876
+ operator = FilterOperator.LESS_THAN_OR_EQUAL
877
+ terms.append({date_field: {operator: expression.date.until.ToSeconds()}})
878
+
879
+ if len(terms) == 2:
880
+ return {LogicalOperator.AND: terms}
881
+ elif len(terms) == 1:
882
+ return terms[0]
883
+ else:
884
+ raise ValueError(f"Invalid filter expression: {expression}")
885
+
886
+ elif kind == "facet":
887
+ operator = FilterOperator.NOT_IN if negative else FilterOperator.IN
888
+ return {field: {operator: [expression.facet.facet]}}
889
+
890
+ else:
891
+ raise ValueError(f"Invalid filter expression: {expression}")
891
892
 
892
893
 
893
894
  def iter_paragraphs(resource: Resource) -> Iterator[tuple[str, IndexParagraph]]:
@@ -437,14 +437,32 @@ class NotEnoughContextAskResult(AskResult):
437
437
  context in the corpus to answer.
438
438
  """
439
439
  yield self._ndjson_encode(RetrievalAskResponseItem(results=self.main_results))
440
+ if self.prequeries_results:
441
+ yield self._ndjson_encode(
442
+ PrequeriesAskResponseItem(
443
+ results={
444
+ prequery.id or f"prequery_{index}": prequery_result
445
+ for index, (prequery, prequery_result) in enumerate(self.prequeries_results)
446
+ }
447
+ )
448
+ )
440
449
  yield self._ndjson_encode(AnswerAskResponseItem(text=NOT_ENOUGH_CONTEXT_ANSWER))
441
450
  status = AnswerStatusCode.NO_RETRIEVAL_DATA
442
451
  yield self._ndjson_encode(StatusAskResponseItem(code=status.value, status=status.prettify()))
443
452
 
444
453
  async def json(self) -> str:
454
+ prequeries = (
455
+ {
456
+ prequery.id or f"prequery_{index}": prequery_result
457
+ for index, (prequery, prequery_result) in enumerate(self.prequeries_results)
458
+ }
459
+ if self.prequeries_results
460
+ else None
461
+ )
445
462
  return SyncAskResponse(
446
463
  answer=NOT_ENOUGH_CONTEXT_ANSWER,
447
464
  retrieval_results=self.main_results,
465
+ prequeries=prequeries,
448
466
  status=AnswerStatusCode.NO_RETRIEVAL_DATA.prettify(),
449
467
  ).model_dump_json()
450
468
 
@@ -225,9 +225,6 @@ class QueryParser:
225
225
  security_pb.access_groups.append(group_id)
226
226
  request.security.CopyFrom(security_pb)
227
227
 
228
- if self.with_status is not None:
229
- request.with_status = PROCESSING_STATUS_TO_PB_MAP[self.with_status]
230
-
231
228
  has_old_filters = False
232
229
  if self.old_filters:
233
230
  field_expr, paragraph_expr = await parse_old_filters(self.old_filters, self.fetcher)
@@ -60,7 +60,6 @@ async def generate_image_classification_payloads(
60
60
  ) -> AsyncGenerator[ImageClassification, None]:
61
61
  request = StreamRequest()
62
62
  request.shard_id.id = shard_replica_id
63
- request.reload = True
64
63
  async for item in node.stream_get_fields(request):
65
64
  rid = item.uuid
66
65
  resource = await get_resource_from_cache_or_db(kbid, rid)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: nucliadb
3
- Version: 6.3.1.post3457
3
+ Version: 6.3.1.post3470
4
4
  Summary: NucliaDB
5
5
  Author-email: Nuclia <nucliadb@nuclia.com>
6
6
  License: AGPL
@@ -20,11 +20,11 @@ Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Programming Language :: Python :: 3 :: Only
21
21
  Requires-Python: <4,>=3.9
22
22
  Description-Content-Type: text/markdown
23
- Requires-Dist: nucliadb-telemetry[all]>=6.3.1.post3457
24
- Requires-Dist: nucliadb-utils[cache,fastapi,storages]>=6.3.1.post3457
25
- Requires-Dist: nucliadb-protos>=6.3.1.post3457
26
- Requires-Dist: nucliadb-models>=6.3.1.post3457
27
- Requires-Dist: nidx-protos>=6.3.1.post3457
23
+ Requires-Dist: nucliadb-telemetry[all]>=6.3.1.post3470
24
+ Requires-Dist: nucliadb-utils[cache,fastapi,storages]>=6.3.1.post3470
25
+ Requires-Dist: nucliadb-protos>=6.3.1.post3470
26
+ Requires-Dist: nucliadb-models>=6.3.1.post3470
27
+ Requires-Dist: nidx-protos>=6.3.1.post3470
28
28
  Requires-Dist: nucliadb-admin-assets>=1.0.0.post1224
29
29
  Requires-Dist: nuclia-models>=0.24.2
30
30
  Requires-Dist: uvicorn
@@ -51,7 +51,7 @@ nucliadb/common/cluster/exceptions.py,sha256=V3c_fgH00GyJ-a5CaGLhwTuhwhUNR9YAGvS
51
51
  nucliadb/common/cluster/grpc_node_dummy.py,sha256=L85wBnfab7Rev0CfsfUjPxQC6DiHPsETKrZAOLx9XHg,3510
52
52
  nucliadb/common/cluster/index_node.py,sha256=g38H1kiAliF3Y6et_CWYInpn_xPxf7THAFJ7RtgLNZo,3246
53
53
  nucliadb/common/cluster/manager.py,sha256=-y5PCUzxrvvUCBopmi8JztPiSBYYbUBeLer0XtO4Ukk,15383
54
- nucliadb/common/cluster/rebalance.py,sha256=cGrqc6GQ6Y2X1moW7NzIdLLsij0cbKySiu-qUa3fA-o,8700
54
+ nucliadb/common/cluster/rebalance.py,sha256=cLUlR08SsqmnoA_9GDflV6k2tXmkAPpyFxZErzp45vo,8754
55
55
  nucliadb/common/cluster/rollover.py,sha256=iTJ9EQmHbzXL34foNFto-hqdC0Kq1pF1mNxqv0jqhBs,25362
56
56
  nucliadb/common/cluster/settings.py,sha256=TMoym-cZsQ2soWfLAce0moSa2XncttQyhahL43LrWTo,3384
57
57
  nucliadb/common/cluster/utils.py,sha256=7nQvnVFxM4XV7J560R8hUA-GPzrgD19UlQxHrl4mZUc,4687
@@ -77,7 +77,7 @@ nucliadb/common/external_index_providers/__init__.py,sha256=cp15ZcFnHvpcu_5-aK2A
77
77
  nucliadb/common/external_index_providers/base.py,sha256=yfPkCigT4unXFvAyzy1tXSy2UgWC481GcZAS9bdE4NI,8871
78
78
  nucliadb/common/external_index_providers/exceptions.py,sha256=nDhhOIkb66hjCrBk4Spvl2vN1SuW5gbwrMCDmrdjHHE,1209
79
79
  nucliadb/common/external_index_providers/manager.py,sha256=aFSrrKKYG1ydpTSyq4zYD0LOxFS7P-CO6rcKC0hiF4I,4267
80
- nucliadb/common/external_index_providers/pinecone.py,sha256=SZKOkc-F6vdSmkQsEBK3VrV3omfEfMuhkkxhEsvd6_A,39799
80
+ nucliadb/common/external_index_providers/pinecone.py,sha256=19DIpgaItaWOwrcXsm3HnkbQrAjq-kG9Wehh38CcVbQ,40027
81
81
  nucliadb/common/external_index_providers/settings.py,sha256=EGHnIkwxqe6aypwKegXTlKO3AgUxNa-6GeAZG25Njis,2002
82
82
  nucliadb/common/http_clients/__init__.py,sha256=cp15ZcFnHvpcu_5-aK2A4uUyvuZVV_MJn4bIXMa20ks,835
83
83
  nucliadb/common/http_clients/auth.py,sha256=srfpgAbs2wmqA9u_l-HxsV4YoO77Tse4y3gm3q2YvYM,2112
@@ -225,14 +225,14 @@ nucliadb/search/search/metrics.py,sha256=81X-tahGW4n2CLvUzCPdNxNClmZqUWZjcVOGCUH
225
225
  nucliadb/search/search/paragraphs.py,sha256=pNAEiYqJGGUVcEf7xf-PFMVqz0PX4Qb-WNG-_zPGN2o,7799
226
226
  nucliadb/search/search/pgcatalog.py,sha256=V1NYLEUSXHpWmgcPIo1HS2riK_HDXSi-uykJjSoOOrE,9033
227
227
  nucliadb/search/search/predict_proxy.py,sha256=IFI3v_ODz2_UU1XZnyaD391fE7-2C0npSmj_HmDvzS4,3123
228
- nucliadb/search/search/query.py,sha256=S6kvvTNIgOaqsPEisasgbcfsI7ax5E1G5RJwp7-a9jA,29981
228
+ nucliadb/search/search/query.py,sha256=CCz58Cs_VKxbwGO6VdhOzl9HXwKny2hfH2llJVR9emM,29859
229
229
  nucliadb/search/search/rank_fusion.py,sha256=tRGo_KlsFsVx1CQEy1iqQ6f0T1Dq1kf0axDXHuuzvvM,6946
230
230
  nucliadb/search/search/rerankers.py,sha256=3vep4EOVNeDJGsMdx-1g6Ar4ZGJG3IHym3HkxnbwtAQ,7321
231
231
  nucliadb/search/search/shards.py,sha256=JSRSrHgHcF4sXyuZZoJdMfK0v_LHpoSRf1lCr5-K5ko,2742
232
232
  nucliadb/search/search/summarize.py,sha256=ksmYPubEQvAQgfPdZHfzB_rR19B2ci4IYZ6jLdHxZo8,4996
233
233
  nucliadb/search/search/utils.py,sha256=iF2tbBA56gRMJH1TlE2hMrqeXqjoeOPt4KgRdp2m9Ek,3313
234
234
  nucliadb/search/search/chat/__init__.py,sha256=cp15ZcFnHvpcu_5-aK2A4uUyvuZVV_MJn4bIXMa20ks,835
235
- nucliadb/search/search/chat/ask.py,sha256=HPHM97s1dxbHvugoWZj6aP8vL4gzHjjtwoDvzUMaLfw,36547
235
+ nucliadb/search/search/chat/ask.py,sha256=olZT08JVo3ZGDsDXkjvI2JTlqQln_o91HJzv0TKFQ7I,37244
236
236
  nucliadb/search/search/chat/exceptions.py,sha256=Siy4GXW2L7oPhIR86H3WHBhE9lkV4A4YaAszuGGUf54,1356
237
237
  nucliadb/search/search/chat/images.py,sha256=PA8VWxT5_HUGfW1ULhKTK46UBsVyINtWWqEM1ulzX1E,3095
238
238
  nucliadb/search/search/chat/prompt.py,sha256=Jnja-Ss7skgnnDY8BymVfdeYsFPnIQFL8tEvcRXTKUE,47356
@@ -294,7 +294,7 @@ nucliadb/train/api/v1/trainset.py,sha256=kpnpDgiMWr1FKHZJgwH7hue5kzilA8-i9X0YHlN
294
294
  nucliadb/train/generators/__init__.py,sha256=cp15ZcFnHvpcu_5-aK2A4uUyvuZVV_MJn4bIXMa20ks,835
295
295
  nucliadb/train/generators/field_classifier.py,sha256=yatj7U-LHRN5xTR6XsYz_3acIAUKTcpkNZcZaSY8MtE,3482
296
296
  nucliadb/train/generators/field_streaming.py,sha256=kjwg4VNiROVqVDN--mRd4ylLw55Sg2VYxKRDdbmpYSM,5398
297
- nucliadb/train/generators/image_classifier.py,sha256=NZ993L1Fxjc7kB_yEMhCpdlMaNQbPrFz2LOUiF9eSYs,6730
297
+ nucliadb/train/generators/image_classifier.py,sha256=yqdBKIHiumeDSTggbxLFiUPanjMtbWGEaWo4mg2OcqA,6704
298
298
  nucliadb/train/generators/paragraph_classifier.py,sha256=0pOZYcT1cAmG7gjSD1HIUaMM5T3Ag-96iUTXRhiV8MI,2761
299
299
  nucliadb/train/generators/paragraph_streaming.py,sha256=dsM7a5hBd2iokvFuxnZhQeko4Jad6djyP2p3tevku8A,3586
300
300
  nucliadb/train/generators/question_answer_streaming.py,sha256=P7-de4W4yW2mgEQ82fF2OZVyx6QJHXezY52qDciDcmw,5680
@@ -340,8 +340,8 @@ nucliadb/writer/tus/local.py,sha256=7jYa_w9b-N90jWgN2sQKkNcomqn6JMVBOVeDOVYJHto,
340
340
  nucliadb/writer/tus/s3.py,sha256=vF0NkFTXiXhXq3bCVXXVV-ED38ECVoUeeYViP8uMqcU,8357
341
341
  nucliadb/writer/tus/storage.py,sha256=ToqwjoYnjI4oIcwzkhha_MPxi-k4Jk3Lt55zRwaC1SM,2903
342
342
  nucliadb/writer/tus/utils.py,sha256=MSdVbRsRSZVdkaum69_0wku7X3p5wlZf4nr6E0GMKbw,2556
343
- nucliadb-6.3.1.post3457.dist-info/METADATA,sha256=Q7ES2awV8PZOanfl6y5nQZebnPb0AzQhXJvQipxzQAA,4291
344
- nucliadb-6.3.1.post3457.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
345
- nucliadb-6.3.1.post3457.dist-info/entry_points.txt,sha256=XqGfgFDuY3zXQc8ewXM2TRVjTModIq851zOsgrmaXx4,1268
346
- nucliadb-6.3.1.post3457.dist-info/top_level.txt,sha256=hwYhTVnX7jkQ9gJCkVrbqEG1M4lT2F_iPQND1fCzF80,20
347
- nucliadb-6.3.1.post3457.dist-info/RECORD,,
343
+ nucliadb-6.3.1.post3470.dist-info/METADATA,sha256=D70V8N1xQhfe8pD1j1CJs2JaOAn8Yf10reTomEznVFs,4291
344
+ nucliadb-6.3.1.post3470.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
345
+ nucliadb-6.3.1.post3470.dist-info/entry_points.txt,sha256=XqGfgFDuY3zXQc8ewXM2TRVjTModIq851zOsgrmaXx4,1268
346
+ nucliadb-6.3.1.post3470.dist-info/top_level.txt,sha256=hwYhTVnX7jkQ9gJCkVrbqEG1M4lT2F_iPQND1fCzF80,20
347
+ nucliadb-6.3.1.post3470.dist-info/RECORD,,