nucliadb 6.2.1.post2882__py3-none-any.whl → 6.2.1.post2887__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.
@@ -105,6 +105,8 @@ async def get_statuses(
105
105
  pb = writer_pb2.FieldStatus()
106
106
  if serialized_status is not None:
107
107
  pb.ParseFromString(serialized_status)
108
+ else:
109
+ pb = writer_pb2.FieldStatus()
108
110
  statuses.append(pb)
109
111
 
110
112
  return statuses
@@ -69,7 +69,9 @@ from nucliadb_protos.resources_pb2 import Origin as PBOrigin
69
69
  from nucliadb_protos.resources_pb2 import Relations as PBRelations
70
70
  from nucliadb_protos.utils_pb2 import Relation as PBRelation
71
71
  from nucliadb_protos.writer_pb2 import BrokerMessage
72
+ from nucliadb_utils import const
72
73
  from nucliadb_utils.storages.storage import Storage
74
+ from nucliadb_utils.utilities import has_feature
73
75
 
74
76
  if TYPE_CHECKING: # pragma: no cover
75
77
  from nucliadb.ingest.orm.knowledgebox import KnowledgeBox
@@ -535,6 +537,7 @@ class Resource:
535
537
  for (field_type, field), errors in errors_by_field.items():
536
538
  field_obj = await self.get_field(field, field_type, load=False)
537
539
  if from_processor:
540
+ # Create a new field status to clear all errors
538
541
  status = writer_pb2.FieldStatus()
539
542
  else:
540
543
  status = await field_obj.get_status() or writer_pb2.FieldStatus()
@@ -548,7 +551,7 @@ class Resource:
548
551
 
549
552
  # We infer the status for processor messages
550
553
  if message.source == BrokerMessage.MessageSource.PROCESSOR:
551
- if len(errors) > 0:
554
+ if len(status.errors) > 0:
552
555
  status.status = writer_pb2.FieldStatus.Status.ERROR
553
556
  else:
554
557
  status.status = writer_pb2.FieldStatus.Status.PROCESSED
@@ -563,14 +566,19 @@ class Resource:
563
566
  )
564
567
  if field_status:
565
568
  status.status = field_status
569
+ # If the field was not found and the message comes from the writer, this implicitly sets the
570
+ # status to the default value, which is PROCESSING. This covers the case of new field creation.
566
571
 
567
572
  await field_obj.set_status(status)
568
573
 
569
574
  async def update_status(self):
570
575
  field_ids = await self.get_all_field_ids(for_update=False)
576
+ if field_ids is None:
577
+ return
571
578
  field_statuses = await datamanagers.fields.get_statuses(
572
579
  self.txn, kbid=self.kb.kbid, rid=self.uuid, fields=field_ids.fields
573
580
  )
581
+
574
582
  # If any field is processing -> PENDING
575
583
  if any((f.status == writer_pb2.FieldStatus.Status.PENDING for f in field_statuses)):
576
584
  self.basic.metadata.status = PBMetadata.Status.PENDING
@@ -594,12 +602,11 @@ class Resource:
594
602
 
595
603
  @processor_observer.wrap({"type": "apply_extracted"})
596
604
  async def apply_extracted(self, message: BrokerMessage):
597
- errors = False
598
- field_obj: Field
599
- for error in message.errors:
600
- field_obj = await self.get_field(error.field, error.field_type, load=False)
601
- await field_obj.set_error(error)
602
- errors = True
605
+ if not has_feature(const.Features.FIELD_STATUS):
606
+ field_obj: Field
607
+ for error in message.errors:
608
+ field_obj = await self.get_field(error.field, error.field_type, load=False)
609
+ await field_obj.set_error(error)
603
610
 
604
611
  await self.get_basic()
605
612
  if self.basic is None:
@@ -608,11 +615,6 @@ class Resource:
608
615
  previous_basic = Basic()
609
616
  previous_basic.CopyFrom(self.basic)
610
617
 
611
- if errors:
612
- self.basic.metadata.status = PBMetadata.Status.ERROR
613
- elif errors is False and message.source is message.MessageSource.PROCESSOR:
614
- self.basic.metadata.status = PBMetadata.Status.PROCESSED
615
-
616
618
  maybe_update_basic_icon(self.basic, get_text_field_mimetype(message))
617
619
 
618
620
  for question_answers in message.question_answers:
@@ -621,9 +623,17 @@ class Resource:
621
623
  for extracted_text in message.extracted_text:
622
624
  await self._apply_extracted_text(extracted_text)
623
625
 
624
- # TODO: Update field and resource status depending on processing results
626
+ # Update field and resource status depending on processing results
625
627
  await self.apply_fields_status(message, self._modified_extracted_text)
626
- # await self.update_status()
628
+ if has_feature(const.Features.FIELD_STATUS):
629
+ # Compute resource status based on all fields statuses
630
+ await self.update_status()
631
+ else:
632
+ # Old code path, compute resource status based on the presence of errors in this BrokerMessage
633
+ if message.errors:
634
+ self.basic.metadata.status = PBMetadata.Status.ERROR
635
+ elif message.source is message.MessageSource.PROCESSOR:
636
+ self.basic.metadata.status = PBMetadata.Status.PROCESSED
627
637
 
628
638
  extracted_languages = []
629
639
 
@@ -17,7 +17,8 @@
17
17
  # You should have received a copy of the GNU Affero General Public License
18
18
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
19
  #
20
- from typing import Optional
20
+
21
+ from typing import Optional, Union
21
22
 
22
23
  import nucliadb_models as models
23
24
  from nucliadb.common import datamanagers
@@ -50,7 +51,9 @@ from nucliadb_models.resource import (
50
51
  )
51
52
  from nucliadb_models.search import ResourceProperties
52
53
  from nucliadb_models.security import ResourceSecurity
53
- from nucliadb_utils.utilities import get_storage
54
+ from nucliadb_protos.writer_pb2 import FieldStatus
55
+ from nucliadb_utils import const
56
+ from nucliadb_utils.utilities import get_storage, has_feature
54
57
 
55
58
 
56
59
  async def set_resource_field_extracted_data(
@@ -145,6 +148,40 @@ async def serialize(
145
148
  )
146
149
 
147
150
 
151
+ async def serialize_field_errors(
152
+ field: Field,
153
+ serialized: Union[
154
+ TextFieldData, FileFieldData, LinkFieldData, ConversationFieldData, GenericFieldData
155
+ ],
156
+ ):
157
+ if has_feature(const.Features.FIELD_STATUS):
158
+ status = await field.get_status()
159
+ if status is None:
160
+ status = FieldStatus()
161
+ serialized.status = status.Status.Name(status.status)
162
+ if status.errors:
163
+ serialized.errors = []
164
+ for error in status.errors:
165
+ serialized.errors.append(
166
+ Error(
167
+ body=error.source_error.error,
168
+ code=error.source_error.code,
169
+ code_str=error.source_error.ErrorCode.Name(error.source_error.code),
170
+ created=error.created.ToDatetime(),
171
+ )
172
+ )
173
+ serialized.error = serialized.errors[-1]
174
+ else:
175
+ field_error = await field.get_error()
176
+ if field_error is not None:
177
+ serialized.error = Error(
178
+ body=field_error.error,
179
+ code=field_error.code,
180
+ code_str=field_error.ErrorCode.Name(field_error.code),
181
+ created=None,
182
+ )
183
+
184
+
148
185
  async def managed_serialize(
149
186
  txn: Transaction,
150
187
  kbid: str,
@@ -249,9 +286,7 @@ async def managed_serialize(
249
286
  serialized_value = from_proto.field_text(value) if value is not None else None
250
287
  resource.data.texts[field.id].value = serialized_value
251
288
  if include_errors:
252
- error = await field.get_error()
253
- if error is not None:
254
- resource.data.texts[field.id].error = Error(body=error.error, code=error.code)
289
+ await serialize_field_errors(field, resource.data.texts[field.id])
255
290
  if include_extracted_data:
256
291
  resource.data.texts[field.id].extracted = TextFieldExtractedData()
257
292
  await set_resource_field_extracted_data(
@@ -272,9 +307,7 @@ async def managed_serialize(
272
307
  resource.data.files[field.id].value = None
273
308
 
274
309
  if include_errors:
275
- error = await field.get_error()
276
- if error is not None:
277
- resource.data.files[field.id].error = Error(body=error.error, code=error.code)
310
+ await serialize_field_errors(field, resource.data.files[field.id])
278
311
 
279
312
  if include_extracted_data:
280
313
  resource.data.files[field.id].extracted = FileFieldExtractedData()
@@ -293,9 +326,7 @@ async def managed_serialize(
293
326
  resource.data.links[field.id].value = from_proto.field_link(value)
294
327
 
295
328
  if include_errors:
296
- error = await field.get_error()
297
- if error is not None:
298
- resource.data.links[field.id].error = Error(body=error.error, code=error.code)
329
+ await serialize_field_errors(field, resource.data.links[field.id])
299
330
 
300
331
  if include_extracted_data:
301
332
  resource.data.links[field.id].extracted = LinkFieldExtractedData()
@@ -311,11 +342,7 @@ async def managed_serialize(
311
342
  if field.id not in resource.data.conversations:
312
343
  resource.data.conversations[field.id] = ConversationFieldData()
313
344
  if include_errors:
314
- error = await field.get_error()
315
- if error is not None:
316
- resource.data.conversations[field.id].error = Error(
317
- body=error.error, code=error.code
318
- )
345
+ await serialize_field_errors(field, resource.data.conversations[field.id])
319
346
  if include_value and isinstance(field, Conversation):
320
347
  value = await field.get_metadata()
321
348
  resource.data.conversations[field.id].value = from_proto.field_conversation(value)
@@ -335,9 +362,7 @@ async def managed_serialize(
335
362
  if include_value:
336
363
  resource.data.generics[field.id].value = value
337
364
  if include_errors:
338
- error = await field.get_error()
339
- if error is not None:
340
- resource.data.generics[field.id].error = Error(body=error.error, code=error.code)
365
+ await serialize_field_errors(field, resource.data.generics[field.id])
341
366
  if include_extracted_data:
342
367
  resource.data.generics[field.id].extracted = TextFieldExtractedData(
343
368
  text=models.ExtractedText(text=resource.data.generics[field.id].value)
@@ -31,12 +31,12 @@ from nucliadb.common.maindb.utils import setup_driver
31
31
  from nucliadb.ingest import SERVICE_NAME, logger
32
32
  from nucliadb.ingest.orm.broker_message import generate_broker_message
33
33
  from nucliadb.ingest.orm.entities import EntitiesManager
34
- from nucliadb.ingest.orm.exceptions import KnowledgeBoxConflict, VectorSetConflict
34
+ from nucliadb.ingest.orm.exceptions import KnowledgeBoxConflict
35
35
  from nucliadb.ingest.orm.knowledgebox import KnowledgeBox as KnowledgeBoxORM
36
36
  from nucliadb.ingest.orm.processor import Processor, sequence_manager
37
37
  from nucliadb.ingest.orm.resource import Resource as ResourceORM
38
38
  from nucliadb.ingest.settings import settings
39
- from nucliadb_protos import nodewriter_pb2, writer_pb2, writer_pb2_grpc
39
+ from nucliadb_protos import writer_pb2, writer_pb2_grpc
40
40
  from nucliadb_protos.knowledgebox_pb2 import (
41
41
  DeleteKnowledgeBoxResponse,
42
42
  KnowledgeBoxID,
@@ -44,13 +44,10 @@ from nucliadb_protos.knowledgebox_pb2 import (
44
44
  KnowledgeBoxUpdate,
45
45
  SemanticModelMetadata,
46
46
  UpdateKnowledgeBoxResponse,
47
- VectorSetConfig,
48
47
  )
49
48
  from nucliadb_protos.writer_pb2 import (
50
49
  BrokerMessage,
51
50
  DelEntitiesRequest,
52
- DelVectorSetRequest,
53
- DelVectorSetResponse,
54
51
  GetEntitiesGroupRequest,
55
52
  GetEntitiesGroupResponse,
56
53
  GetEntitiesRequest,
@@ -63,8 +60,6 @@ from nucliadb_protos.writer_pb2 import (
63
60
  ListMembersResponse,
64
61
  NewEntitiesGroupRequest,
65
62
  NewEntitiesGroupResponse,
66
- NewVectorSetRequest,
67
- NewVectorSetResponse,
68
63
  OpStatusWriter,
69
64
  SetEntitiesRequest,
70
65
  UpdateEntitiesGroupRequest,
@@ -472,56 +467,3 @@ class WriterServicer(writer_pb2_grpc.WriterServicer):
472
467
  errors.capture_exception(e)
473
468
  logger.error("Error in ingest gRPC servicer", exc_info=True)
474
469
  raise
475
-
476
- async def NewVectorSet( # type: ignore
477
- self, request: NewVectorSetRequest, context=None
478
- ) -> NewVectorSetResponse:
479
- config = VectorSetConfig(
480
- vectorset_id=request.vectorset_id,
481
- vectorset_index_config=nodewriter_pb2.VectorIndexConfig(
482
- similarity=request.similarity,
483
- normalize_vectors=request.normalize_vectors,
484
- vector_type=request.vector_type,
485
- vector_dimension=request.vector_dimension,
486
- ),
487
- matryoshka_dimensions=request.matryoshka_dimensions,
488
- storage_key_kind=VectorSetConfig.StorageKeyKind.VECTORSET_PREFIX,
489
- )
490
- response = NewVectorSetResponse()
491
- try:
492
- async with self.driver.transaction() as txn:
493
- kbobj = KnowledgeBoxORM(txn, self.storage, request.kbid)
494
- await kbobj.create_vectorset(config)
495
- await txn.commit()
496
- except VectorSetConflict as exc:
497
- response.status = NewVectorSetResponse.Status.ERROR
498
- response.details = str(exc)
499
- except Exception as exc:
500
- errors.capture_exception(exc)
501
- logger.error("Error in ingest gRPC while creating a vectorset", exc_info=True)
502
- response.status = NewVectorSetResponse.Status.ERROR
503
- response.details = str(exc)
504
- else:
505
- response.status = NewVectorSetResponse.Status.OK
506
- return response
507
-
508
- async def DelVectorSet( # type: ignore
509
- self, request: DelVectorSetRequest, context=None
510
- ) -> DelVectorSetResponse:
511
- response = DelVectorSetResponse()
512
- try:
513
- async with self.driver.transaction() as txn:
514
- kbobj = KnowledgeBoxORM(txn, self.storage, request.kbid)
515
- await kbobj.delete_vectorset(request.vectorset_id)
516
- await txn.commit()
517
- except VectorSetConflict as exc:
518
- response.status = DelVectorSetResponse.Status.ERROR
519
- response.details = str(exc)
520
- except Exception as exc:
521
- errors.capture_exception(exc)
522
- logger.error("Error in ingest gRPC while deleting a vectorset", exc_info=True)
523
- response.status = DelVectorSetResponse.Status.ERROR
524
- response.details = str(exc)
525
- else:
526
- response.status = DelVectorSetResponse.Status.OK
527
- return response
@@ -52,6 +52,8 @@ class ResourceField(BaseModel):
52
52
  value: ValueType = None
53
53
  extracted: Optional[ExtractedDataType] = None
54
54
  error: Optional[Error] = None
55
+ status: Optional[str] = None
56
+ errors: Optional[list[Error]] = None
55
57
 
56
58
 
57
59
  FIELD_NAME_TO_EXTRACTED_DATA_FIELD_MAP: dict[FieldTypeName, Any] = {
@@ -52,6 +52,7 @@ from nucliadb_models.resource import (
52
52
  )
53
53
  from nucliadb_models.search import ResourceProperties
54
54
  from nucliadb_protos import resources_pb2
55
+ from nucliadb_protos.writer_pb2 import FieldStatus
55
56
  from nucliadb_telemetry import errors
56
57
  from nucliadb_utils.authentication import requires, requires_one
57
58
  from nucliadb_utils.utilities import get_audit, get_storage
@@ -388,9 +389,22 @@ async def _get_resource_field(
388
389
  )
389
390
 
390
391
  if ResourceFieldProperties.ERROR in show:
391
- error = await field.get_error()
392
- if error is not None:
393
- resource_field.error = Error(body=error.error, code=error.code)
392
+ status = await field.get_status()
393
+ if status is None:
394
+ status = FieldStatus()
395
+ resource_field.status = status.Status.Name(status.status)
396
+ if status.errors:
397
+ resource_field.errors = []
398
+ for error in status.errors:
399
+ resource_field.errors.append(
400
+ Error(
401
+ body=error.source_error.error,
402
+ code=error.source_error.code,
403
+ code_str=error.source_error.ErrorCode.Name(error.source_error.code),
404
+ created=error.created.ToDatetime(),
405
+ )
406
+ )
407
+ resource_field.error = resource_field.errors[-1]
394
408
 
395
409
  return Response(
396
410
  content=resource_field.model_dump_json(exclude_unset=True, by_alias=True),
@@ -24,4 +24,5 @@ from . import learning_config # noqa
24
24
  from . import resource # noqa
25
25
  from . import services # noqa
26
26
  from . import upload # noqa
27
+ from . import vectorsets # noqa
27
28
  from .router import api # noqa
@@ -20,7 +20,7 @@
20
20
  import asyncio
21
21
  from functools import partial
22
22
 
23
- from fastapi import HTTPException, Response
23
+ from fastapi import HTTPException
24
24
  from fastapi_versioning import version
25
25
  from starlette.requests import Request
26
26
 
@@ -32,7 +32,7 @@ from nucliadb.common.external_index_providers.exceptions import (
32
32
  from nucliadb.common.maindb.utils import get_driver
33
33
  from nucliadb.ingest.orm.exceptions import KnowledgeBoxConflict
34
34
  from nucliadb.ingest.orm.knowledgebox import KnowledgeBox
35
- from nucliadb.writer import logger, vectorsets
35
+ from nucliadb.writer import logger
36
36
  from nucliadb.writer.api.utils import only_for_onprem
37
37
  from nucliadb.writer.api.v1.router import KB_PREFIX, KBS_PREFIX, api
38
38
  from nucliadb.writer.utilities import get_processing
@@ -248,47 +248,3 @@ def to_pinecone_serverless_cloud_pb(
248
248
  PineconeServerlessCloud.AZURE_EASTUS2: knowledgebox_pb2.PineconeServerlessCloud.AZURE_EASTUS2,
249
249
  PineconeServerlessCloud.GCP_US_CENTRAL1: knowledgebox_pb2.PineconeServerlessCloud.GCP_US_CENTRAL1,
250
250
  }[serverless]
251
-
252
-
253
- @api.post(
254
- f"/{KB_PREFIX}/{{kbid}}/vectorsets/{{vectorset_id}}",
255
- status_code=200,
256
- summary="Add a vectorset to Knowledge Box",
257
- tags=["Knowledge Boxes"],
258
- # TODO: remove when the feature is mature
259
- include_in_schema=False,
260
- )
261
- @requires(NucliaDBRoles.MANAGER)
262
- @version(1)
263
- async def add_vectorset(request: Request, kbid: str, vectorset_id: str) -> Response:
264
- try:
265
- await vectorsets.add(kbid, vectorset_id)
266
- except learning_proxy.ProxiedLearningConfigError as err:
267
- return Response(
268
- status_code=err.status_code,
269
- content=err.content,
270
- media_type=err.content_type,
271
- )
272
- return Response(status_code=200)
273
-
274
-
275
- @api.delete(
276
- f"/{KB_PREFIX}/{{kbid}}/vectorsets/{{vectorset_id}}",
277
- status_code=200,
278
- summary="Delete vectorset from Knowledge Box",
279
- tags=["Knowledge Boxes"],
280
- # TODO: remove when the feature is mature
281
- include_in_schema=False,
282
- )
283
- @requires(NucliaDBRoles.MANAGER)
284
- @version(1)
285
- async def delete_vectorset(request: Request, kbid: str, vectorset_id: str) -> Response:
286
- try:
287
- await vectorsets.delete(kbid, vectorset_id)
288
- except learning_proxy.ProxiedLearningConfigError as err:
289
- return Response(
290
- status_code=err.status_code,
291
- content=err.content,
292
- media_type=err.content_type,
293
- )
294
- return Response(status_code=200)
@@ -64,8 +64,8 @@ from nucliadb_models import content_types
64
64
  from nucliadb_models.resource import NucliaDBRoles
65
65
  from nucliadb_models.utils import FieldIdString
66
66
  from nucliadb_models.writer import CreateResourcePayload, ResourceFileUploaded
67
- from nucliadb_protos.resources_pb2 import CloudFile, FieldFile, Metadata
68
- from nucliadb_protos.writer_pb2 import BrokerMessage
67
+ from nucliadb_protos.resources_pb2 import CloudFile, FieldFile, FieldID, FieldType, Metadata
68
+ from nucliadb_protos.writer_pb2 import BrokerMessage, FieldIDStatus, FieldStatus
69
69
  from nucliadb_utils.authentication import requires_one
70
70
  from nucliadb_utils.exceptions import LimitsExceededError, SendToProcessError
71
71
  from nucliadb_utils.storages.storage import KB_RESOURCE_FIELD
@@ -511,7 +511,7 @@ async def _tus_patch(
511
511
 
512
512
  if offset != dm.offset:
513
513
  raise HTTPConflict(
514
- detail=f"Current upload offset({offset}) does not match " f"object offset {dm.offset}"
514
+ detail=f"Current upload offset({offset}) does not match object offset {dm.offset}"
515
515
  )
516
516
 
517
517
  storage_manager = get_storage_manager()
@@ -946,6 +946,12 @@ async def store_file_on_nuclia_db(
946
946
  writer.files[field].CopyFrom(file_field)
947
947
  # Do not store passwords on maindb
948
948
  writer.files[field].ClearField("password")
949
+ writer.field_statuses.append(
950
+ FieldIDStatus(
951
+ id=FieldID(field_type=FieldType.FILE, field=field),
952
+ status=FieldStatus.Status.PENDING,
953
+ )
954
+ )
949
955
 
950
956
  toprocess.filefield[field] = await processing.convert_internal_filefield_to_str(
951
957
  file_field, storage=storage
@@ -0,0 +1,79 @@
1
+ # Copyright (C) 2021 Bosutech XXI S.L.
2
+ #
3
+ # nucliadb is offered under the AGPL v3.0 and as commercial software.
4
+ # For commercial licensing, contact us at info@nuclia.com.
5
+ #
6
+ # AGPL:
7
+ # This program is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Affero General Public License as
9
+ # published by the Free Software Foundation, either version 3 of the
10
+ # License, or (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Affero General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Affero General Public License
18
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
+ #
20
+
21
+ from fastapi import Response
22
+ from fastapi_versioning import version
23
+ from starlette.requests import Request
24
+
25
+ from nucliadb import learning_proxy
26
+ from nucliadb.ingest.orm.exceptions import VectorSetConflict
27
+ from nucliadb.models.responses import HTTPConflict
28
+ from nucliadb.writer import vectorsets
29
+ from nucliadb.writer.api.v1.router import KB_PREFIX, api
30
+ from nucliadb_models.resource import (
31
+ NucliaDBRoles,
32
+ )
33
+ from nucliadb_utils.authentication import requires
34
+
35
+
36
+ @api.post(
37
+ f"/{KB_PREFIX}/{{kbid}}/vectorsets/{{vectorset_id}}",
38
+ status_code=200,
39
+ summary="Add a vectorset to Knowledge Box",
40
+ tags=["Knowledge Boxes"],
41
+ # TODO: remove when the feature is mature
42
+ include_in_schema=False,
43
+ )
44
+ @requires(NucliaDBRoles.MANAGER)
45
+ @version(1)
46
+ async def add_vectorset(request: Request, kbid: str, vectorset_id: str) -> Response:
47
+ try:
48
+ await vectorsets.add(kbid, vectorset_id)
49
+ except learning_proxy.ProxiedLearningConfigError as err:
50
+ return Response(
51
+ status_code=err.status_code,
52
+ content=err.content,
53
+ media_type=err.content_type,
54
+ )
55
+ return Response(status_code=200)
56
+
57
+
58
+ @api.delete(
59
+ f"/{KB_PREFIX}/{{kbid}}/vectorsets/{{vectorset_id}}",
60
+ status_code=200,
61
+ summary="Delete vectorset from Knowledge Box",
62
+ tags=["Knowledge Boxes"],
63
+ # TODO: remove when the feature is mature
64
+ include_in_schema=False,
65
+ )
66
+ @requires(NucliaDBRoles.MANAGER)
67
+ @version(1)
68
+ async def delete_vectorset(request: Request, kbid: str, vectorset_id: str) -> Response:
69
+ try:
70
+ await vectorsets.delete(kbid, vectorset_id)
71
+ except VectorSetConflict as exc:
72
+ return HTTPConflict(detail=str(exc))
73
+ except learning_proxy.ProxiedLearningConfigError as err:
74
+ return Response(
75
+ status_code=err.status_code,
76
+ content=err.content,
77
+ media_type=err.content_type,
78
+ )
79
+ return Response(status_code=200)
@@ -59,9 +59,10 @@ async def add(kbid: str, vectorset_id: str) -> None:
59
59
  assert lconfig is not None
60
60
 
61
61
  # Then, add the vectorset to the index if it's not already there
62
+ storage = await get_storage()
63
+ vectorset_config = get_vectorset_config(lconfig, vectorset_id)
62
64
  async with datamanagers.with_rw_transaction() as txn:
63
- kbobj = KnowledgeBox(txn, await get_storage(), kbid)
64
- vectorset_config = get_vectorset_config(lconfig, vectorset_id)
65
+ kbobj = KnowledgeBox(txn, storage, kbid)
65
66
  try:
66
67
  await kbobj.create_vectorset(vectorset_config)
67
68
  await txn.commit()
@@ -77,11 +78,17 @@ async def delete(kbid: str, vectorset_id: str) -> None:
77
78
  if vectorset_id in semantic_models:
78
79
  semantic_models.remove(vectorset_id)
79
80
  await learning_proxy.update_configuration(kbid, {"semantic_models": semantic_models})
81
+
82
+ storage = await get_storage()
80
83
  try:
81
84
  async with datamanagers.with_rw_transaction() as txn:
82
- kbobj = KnowledgeBox(txn, await get_storage(), kbid)
85
+ kbobj = KnowledgeBox(txn, storage, kbid)
83
86
  await kbobj.delete_vectorset(vectorset_id=vectorset_id)
84
87
  await txn.commit()
88
+
89
+ except VectorSetConflict:
90
+ # caller should handle this error
91
+ raise
85
92
  except Exception as ex:
86
93
  errors.capture_exception(ex)
87
94
  logger.exception(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: nucliadb
3
- Version: 6.2.1.post2882
3
+ Version: 6.2.1.post2887
4
4
  Home-page: https://docs.nuclia.dev/docs/management/nucliadb/intro
5
5
  Author: NucliaDB Community
6
6
  Author-email: nucliadb@nuclia.com
@@ -22,10 +22,10 @@ Classifier: Programming Language :: Python :: 3.12
22
22
  Classifier: Programming Language :: Python :: 3 :: Only
23
23
  Requires-Python: >=3.9, <4
24
24
  Description-Content-Type: text/markdown
25
- Requires-Dist: nucliadb-telemetry[all]>=6.2.1.post2882
26
- Requires-Dist: nucliadb-utils[cache,fastapi,storages]>=6.2.1.post2882
27
- Requires-Dist: nucliadb-protos>=6.2.1.post2882
28
- Requires-Dist: nucliadb-models>=6.2.1.post2882
25
+ Requires-Dist: nucliadb-telemetry[all]>=6.2.1.post2887
26
+ Requires-Dist: nucliadb-utils[cache,fastapi,storages]>=6.2.1.post2887
27
+ Requires-Dist: nucliadb-protos>=6.2.1.post2887
28
+ Requires-Dist: nucliadb-models>=6.2.1.post2887
29
29
  Requires-Dist: nucliadb-admin-assets>=1.0.0.post1224
30
30
  Requires-Dist: nucliadb-node-binding>=2.26.0
31
31
  Requires-Dist: nuclia-models>=0.24.2
@@ -71,7 +71,7 @@ nucliadb/common/datamanagers/atomic.py,sha256=DU7RihO8WaGNuh_GTEpQ-8hkoinY5GSpNS
71
71
  nucliadb/common/datamanagers/cluster.py,sha256=psTwAWSLj83vhFnC1iJJ6holrolAI4nKos9PuEWspYY,1500
72
72
  nucliadb/common/datamanagers/entities.py,sha256=hqw4YcEOumGK_1vgNNfxP-WafHvWN5jf61n4U01WJtc,5311
73
73
  nucliadb/common/datamanagers/exceptions.py,sha256=Atz_PP_GGq4jgJaWcAkcRbHBoBaGcC9yJvFteylKtTE,883
74
- nucliadb/common/datamanagers/fields.py,sha256=QqWVFqLp58Ib9fadXkSBuaYU-Mo6VJHZWg-taUqreNM,3915
74
+ nucliadb/common/datamanagers/fields.py,sha256=9KqBzTssAT68FR5hd17Xu_CSwAYdKFuYic1ITnrfFNc,3971
75
75
  nucliadb/common/datamanagers/kb.py,sha256=P7EhF4tApIUG2jw_HH1oMufTKG9__kuOLKnrCNGbDM4,6156
76
76
  nucliadb/common/datamanagers/labels.py,sha256=Zm0GQpSPoGXEEysUY7VsDIcyKSIIQsMVphj23IyM9_c,4502
77
77
  nucliadb/common/datamanagers/processing.py,sha256=ByxdZzdbAfJGqC6__mY-zryjk040TyQfcUq3rxujeoY,1587
@@ -115,7 +115,7 @@ nucliadb/ingest/cache.py,sha256=w7jMMzamOmQ7gwXna6Dqm6isRNBVv6l5BTBlTxaYWjE,1005
115
115
  nucliadb/ingest/partitions.py,sha256=2NIhMYbNT0TNBL6bX1UMSi7vxFGICstCKEqsB0TXHOE,2410
116
116
  nucliadb/ingest/processing.py,sha256=gg1DqbMFwqdOsmCSGsZc2abRdYz86xOZJun9vrHOCzs,20618
117
117
  nucliadb/ingest/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
118
- nucliadb/ingest/serialize.py,sha256=03q9TBC9kbqbVq59SSL4ok1e3ThU0zeuYGdqY-B1V2M,15889
118
+ nucliadb/ingest/serialize.py,sha256=13NcAP0Tw0zxMsjdudnSnedsg1YpiqFrA-TTIxQA6Ww,16634
119
119
  nucliadb/ingest/settings.py,sha256=0B-wQNa8FLqtNcQgRzh-fuIuGptM816XHcbH1NQKfmE,3050
120
120
  nucliadb/ingest/utils.py,sha256=l1myURu3r8oA11dx3GpHw-gNTUc1AFX8xdPm9Lgl2rA,2275
121
121
  nucliadb/ingest/consumer/__init__.py,sha256=cp15ZcFnHvpcu_5-aK2A4uUyvuZVV_MJn4bIXMa20ks,835
@@ -142,7 +142,7 @@ nucliadb/ingest/orm/entities.py,sha256=2PslT1FZ6yCvJtjR0UpKTSzxJrtS-C_gZx4ZTWHun
142
142
  nucliadb/ingest/orm/exceptions.py,sha256=k4Esv4NtL4TrGTcsQpwrSfDhPQpiYcRbB1SpYmBX5MY,1432
143
143
  nucliadb/ingest/orm/knowledgebox.py,sha256=XefDz6YsA0DLMS6T5W8P3VMFTkwr13bIae2ot7wAFpE,25259
144
144
  nucliadb/ingest/orm/metrics.py,sha256=OkwMSPKLZcKba0ZTwtTiIxwBgaLMX5ydhGieKvi2y7E,1096
145
- nucliadb/ingest/orm/resource.py,sha256=KhucZzQzUbTBUm8_9gaCqxH68Fy1Q2u804IfTcjAIIk,43970
145
+ nucliadb/ingest/orm/resource.py,sha256=CAASCYIPwyhMgwc3_qKjZ-AOVM2IZuaTN-95PlKealg,44658
146
146
  nucliadb/ingest/orm/utils.py,sha256=vCe_9UxHu26JDFGLwQ0wH-XyzJIpQCTK-Ow9dtZR5Vg,2716
147
147
  nucliadb/ingest/orm/processor/__init__.py,sha256=Aqd9wCNTvggkMkCY3WvoI8spdr94Jnqk-0iq9XpLs18,922
148
148
  nucliadb/ingest/orm/processor/auditing.py,sha256=TeYhXGJRyQ7ROytbb2u8R0fIh_FYi3HgTu3S1ribY3U,4623
@@ -152,7 +152,7 @@ nucliadb/ingest/orm/processor/processor.py,sha256=2FxAetUvtHvg6l-24xYrmBdsyqc0RU
152
152
  nucliadb/ingest/orm/processor/sequence_manager.py,sha256=uqEphtI1Ir_yk9jRl2gPf7BlzzXWovbARY5MNZSBI_8,1704
153
153
  nucliadb/ingest/service/__init__.py,sha256=MME_G_ERxzJR6JW_hfE2qcfXpmpH1kdG-S0a-M0qRm8,2043
154
154
  nucliadb/ingest/service/exceptions.py,sha256=cp15ZcFnHvpcu_5-aK2A4uUyvuZVV_MJn4bIXMa20ks,835
155
- nucliadb/ingest/service/writer.py,sha256=aBLLpPUJLlIf-VjAczBCUrcb-zMxRZOFHXkA0QE1pgw,22952
155
+ nucliadb/ingest/service/writer.py,sha256=IJOuSmetWq0oajtJiq5KmFvZMaYX5LGJa6pa9eGBtHY,20406
156
156
  nucliadb/middleware/__init__.py,sha256=A8NBlBuEkunCFMKpR9gnfNELsVn0Plc55BIQMbWDM8Q,2202
157
157
  nucliadb/migrator/__init__.py,sha256=cp15ZcFnHvpcu_5-aK2A4uUyvuZVV_MJn4bIXMa20ks,835
158
158
  nucliadb/migrator/command.py,sha256=dKbJ1tAmP6X4lMVRSSlz351euaqs2wBPpOczLjATUes,2089
@@ -174,13 +174,13 @@ nucliadb/reader/openapi.py,sha256=ZwXYXZPYpxQL68HyWI310YnmMKJMzBUtYe-r9OSbN8I,10
174
174
  nucliadb/reader/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
175
175
  nucliadb/reader/run.py,sha256=AR-iCnON3YVXgI5-KEgg99G4KAPN1BKXDg7nr4dgoDA,1447
176
176
  nucliadb/reader/api/__init__.py,sha256=c-UD29C0FVzQDGEvslebDCKtvnyEcAbiDd-3Q_QgGN4,872
177
- nucliadb/reader/api/models.py,sha256=AeovJ2c4fFIt0FLNkYwzyTuqznFvh6atnkK92jHQAyk,2002
177
+ nucliadb/reader/api/models.py,sha256=UHhOPmh8xcHhDjFm8_-8t66yEggXdxRBoY0xV-hI9to,2076
178
178
  nucliadb/reader/api/v1/__init__.py,sha256=G1s6_1SEvv8CrC_V_tB4fvjQ8tLHivAIbK47dOT_lb4,1069
179
179
  nucliadb/reader/api/v1/download.py,sha256=rGv1c5CjrJheDgGwAnNWy76A_4V2shqqHYvwmKGFlpk,10758
180
180
  nucliadb/reader/api/v1/export_import.py,sha256=x4VBNDFjnlY1nIt5kdq0eZTB_DeRzGzT8T7uB7wUhNU,6448
181
181
  nucliadb/reader/api/v1/knowledgebox.py,sha256=Uu-yPB8KKZt1VaFrFNMMaXOvLsclBJDK9dzZ9lF2ctI,3645
182
182
  nucliadb/reader/api/v1/learning_config.py,sha256=w5a_miobPGakKmyLXkmuz1e6tXyIMSas-qLngqzVQTw,4436
183
- nucliadb/reader/api/v1/resource.py,sha256=GHptgNPGgrLbwjlz5Dlig0lD_nQ50uMWZYAXVArHGek,13396
183
+ nucliadb/reader/api/v1/resource.py,sha256=SFIv_vpgkdJQv7L_UgYZS5FvubipJ0ligpExGDjKHV0,14064
184
184
  nucliadb/reader/api/v1/router.py,sha256=eyNmEGSP9zHkCIG5XlAXl6sukq950B7gFT3X2peMtIE,1011
185
185
  nucliadb/reader/api/v1/services.py,sha256=B8fD4zcUydZ5Fl1DDxfXGNuW6C8rhGYc920O5Zy5Yv8,11716
186
186
  nucliadb/reader/reader/__init__.py,sha256=cp15ZcFnHvpcu_5-aK2A4uUyvuZVV_MJn4bIXMa20ks,835
@@ -310,21 +310,22 @@ nucliadb/writer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
310
310
  nucliadb/writer/run.py,sha256=euVZ_rtHDXs-O1kB-Pt1Id8eft9CYVpWH3zJzEoEqls,1448
311
311
  nucliadb/writer/settings.py,sha256=32Umt2SqeIL8PW4_C6hkuq01QT1YmcROiWpmoy1D5Wk,3286
312
312
  nucliadb/writer/utilities.py,sha256=AZ5qEny1Xm0IDsFtH13oJa2usvJZK8f0FdgF1LrnLCw,1036
313
- nucliadb/writer/vectorsets.py,sha256=ocUTieBzStbNRgKX32wzrNJIuSaS9NjntMYbpzbBbQ4,5520
313
+ nucliadb/writer/vectorsets.py,sha256=18XJvsyi0-tePQWig8dl5qaNPaufEZb0-uD22IAOTa0,5648
314
314
  nucliadb/writer/api/__init__.py,sha256=cp15ZcFnHvpcu_5-aK2A4uUyvuZVV_MJn4bIXMa20ks,835
315
315
  nucliadb/writer/api/constants.py,sha256=qWEDjFUycrEZnSJyLnNK4PQNodU2oVmkO4NycaEZtio,1738
316
316
  nucliadb/writer/api/utils.py,sha256=wIQHlU8RQiIGVLI72suvyVIKlCU44Unh0Ae0IiN6Qwo,1313
317
- nucliadb/writer/api/v1/__init__.py,sha256=FVn7N9VJ6bsEoy4TRnkclr4Umd5hECiwPXVqRnJ8BME,1095
317
+ nucliadb/writer/api/v1/__init__.py,sha256=akI9A_jloNLb0dU4T5zjfdyvmSAiDeIdjAlzNx74FlU,1128
318
318
  nucliadb/writer/api/v1/export_import.py,sha256=6_gn0-emCjmK6bCUX5kgMvG0qkZr4HlfGmBXhhngsxo,8243
319
319
  nucliadb/writer/api/v1/field.py,sha256=OsWOYA0WQ6onE5Rkl20QIEdtrSi7Jgnu62fUt90Ziy8,17503
320
- nucliadb/writer/api/v1/knowledgebox.py,sha256=Mr1vJSWOtiraDdtoTqQ1V2rSirMdojL4wN0Q3cOiX4k,10929
320
+ nucliadb/writer/api/v1/knowledgebox.py,sha256=MLeIuym4jPrJgfy1NTcN9CpUGwuBiqDHMcx0hY9DR7g,9530
321
321
  nucliadb/writer/api/v1/learning_config.py,sha256=GaYaagjBrVG9ZxrWQyVQfqGMQV3tAJjqJ5CStaKhktU,2058
322
322
  nucliadb/writer/api/v1/resource.py,sha256=A8fAHlN5XFsg6XFYKhfWJS8czgNH6yXr-PsnUqz2WUE,18757
323
323
  nucliadb/writer/api/v1/router.py,sha256=RjuoWLpZer6Kl2BW_wznpNo6XL3BOpdTGqXZCn3QrrQ,1034
324
324
  nucliadb/writer/api/v1/services.py,sha256=U8OGxhA1tdt-wxw2uDAjFpwFXFEXSDTfBe1iV5nfmx8,9897
325
325
  nucliadb/writer/api/v1/slug.py,sha256=xlVBDBpRi9bNulpBHZwhyftVvulfE0zFm1XZIWl-AKY,2389
326
326
  nucliadb/writer/api/v1/transaction.py,sha256=d2Vbgnkk_-FLGSTt3vfldwiJIUf0XoyD0wP1jQNz_DY,2430
327
- nucliadb/writer/api/v1/upload.py,sha256=wSSQ8cBgjkxuo9EU-buxXVunI6HIBWhTBLlDmyZJ3Ck,32909
327
+ nucliadb/writer/api/v1/upload.py,sha256=VOeqNTrZx1_z8iaKjM7p8fVlVcIYMtnQNK1dm72ct6k,33161
328
+ nucliadb/writer/api/v1/vectorsets.py,sha256=zj-GBnG_H-aIRVq-9WNT9OVryeYeqdFL1YUUfebC-Ag,2758
328
329
  nucliadb/writer/resource/__init__.py,sha256=cp15ZcFnHvpcu_5-aK2A4uUyvuZVV_MJn4bIXMa20ks,835
329
330
  nucliadb/writer/resource/audit.py,sha256=FvxMZPzrNHtd31HgpZEvxzwAkbxJTZRhPLqRYYJi3tA,1426
330
331
  nucliadb/writer/resource/basic.py,sha256=l9zD-Qiq4eUkHezMf0w1Ksx2izKYLYuNoMIlXcNxxpM,11163
@@ -339,9 +340,9 @@ nucliadb/writer/tus/local.py,sha256=7jYa_w9b-N90jWgN2sQKkNcomqn6JMVBOVeDOVYJHto,
339
340
  nucliadb/writer/tus/s3.py,sha256=vF0NkFTXiXhXq3bCVXXVV-ED38ECVoUeeYViP8uMqcU,8357
340
341
  nucliadb/writer/tus/storage.py,sha256=ToqwjoYnjI4oIcwzkhha_MPxi-k4Jk3Lt55zRwaC1SM,2903
341
342
  nucliadb/writer/tus/utils.py,sha256=MSdVbRsRSZVdkaum69_0wku7X3p5wlZf4nr6E0GMKbw,2556
342
- nucliadb-6.2.1.post2882.dist-info/METADATA,sha256=BB5F9fAJJ9T68B2AhfC9Zkzda13dFCHw_87tl0GL6d0,4689
343
- nucliadb-6.2.1.post2882.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
344
- nucliadb-6.2.1.post2882.dist-info/entry_points.txt,sha256=XqGfgFDuY3zXQc8ewXM2TRVjTModIq851zOsgrmaXx4,1268
345
- nucliadb-6.2.1.post2882.dist-info/top_level.txt,sha256=hwYhTVnX7jkQ9gJCkVrbqEG1M4lT2F_iPQND1fCzF80,20
346
- nucliadb-6.2.1.post2882.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
347
- nucliadb-6.2.1.post2882.dist-info/RECORD,,
343
+ nucliadb-6.2.1.post2887.dist-info/METADATA,sha256=BJ9ngeXJ9o7YbMIoaEcblmpX0bRR0A_xOhtsFnBW8ts,4689
344
+ nucliadb-6.2.1.post2887.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
345
+ nucliadb-6.2.1.post2887.dist-info/entry_points.txt,sha256=XqGfgFDuY3zXQc8ewXM2TRVjTModIq851zOsgrmaXx4,1268
346
+ nucliadb-6.2.1.post2887.dist-info/top_level.txt,sha256=hwYhTVnX7jkQ9gJCkVrbqEG1M4lT2F_iPQND1fCzF80,20
347
+ nucliadb-6.2.1.post2887.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
348
+ nucliadb-6.2.1.post2887.dist-info/RECORD,,