nucliadb-models 6.9.7.post5583__py3-none-any.whl → 6.11.1.post5822__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.
- nucliadb_models/agents/ingestion.py +4 -4
- nucliadb_models/augment.py +100 -84
- nucliadb_models/common.py +56 -56
- nucliadb_models/configuration.py +8 -8
- nucliadb_models/content_types.py +13 -11
- nucliadb_models/conversation.py +25 -26
- nucliadb_models/entities.py +17 -18
- nucliadb_models/external_index_providers.py +1 -2
- nucliadb_models/extracted.py +82 -83
- nucliadb_models/file.py +10 -11
- nucliadb_models/filters.py +78 -74
- nucliadb_models/graph/requests.py +40 -48
- nucliadb_models/graph/responses.py +13 -1
- nucliadb_models/hydration.py +48 -50
- nucliadb_models/internal/predict.py +7 -9
- nucliadb_models/internal/shards.py +2 -3
- nucliadb_models/labels.py +18 -11
- nucliadb_models/link.py +18 -19
- nucliadb_models/metadata.py +66 -54
- nucliadb_models/notifications.py +3 -3
- nucliadb_models/processing.py +1 -2
- nucliadb_models/resource.py +85 -93
- nucliadb_models/retrieval.py +147 -0
- nucliadb_models/search.py +263 -275
- nucliadb_models/security.py +2 -3
- nucliadb_models/text.py +7 -8
- nucliadb_models/trainset.py +1 -2
- nucliadb_models/utils.py +2 -3
- nucliadb_models/vectors.py +2 -5
- nucliadb_models/writer.py +56 -57
- {nucliadb_models-6.9.7.post5583.dist-info → nucliadb_models-6.11.1.post5822.dist-info}/METADATA +1 -1
- nucliadb_models-6.11.1.post5822.dist-info/RECORD +41 -0
- {nucliadb_models-6.9.7.post5583.dist-info → nucliadb_models-6.11.1.post5822.dist-info}/WHEEL +1 -1
- nucliadb_models-6.9.7.post5583.dist-info/RECORD +0 -40
- {nucliadb_models-6.9.7.post5583.dist-info → nucliadb_models-6.11.1.post5822.dist-info}/top_level.txt +0 -0
nucliadb_models/filters.py
CHANGED
|
@@ -15,12 +15,13 @@
|
|
|
15
15
|
|
|
16
16
|
from collections.abc import Sequence
|
|
17
17
|
from enum import Enum
|
|
18
|
-
from typing import Any, Generic, Literal,
|
|
18
|
+
from typing import Annotated, Any, Generic, Literal, TypeVar
|
|
19
19
|
from uuid import UUID
|
|
20
20
|
|
|
21
21
|
import pydantic
|
|
22
22
|
from pydantic import AliasChoices, BaseModel, Discriminator, Tag, field_validator, model_validator
|
|
23
|
-
from
|
|
23
|
+
from pydantic.config import ConfigDict
|
|
24
|
+
from typing_extensions import Self
|
|
24
25
|
|
|
25
26
|
from .common import FieldTypeName, Paragraph
|
|
26
27
|
from .metadata import ResourceProcessingStatus
|
|
@@ -33,7 +34,10 @@ class And(BaseModel, Generic[F], extra="forbid"):
|
|
|
33
34
|
"""AND of other expressions"""
|
|
34
35
|
|
|
35
36
|
operands: Sequence[F] = pydantic.Field(
|
|
36
|
-
|
|
37
|
+
title="And Operands",
|
|
38
|
+
serialization_alias="and",
|
|
39
|
+
validation_alias=AliasChoices("operands", "and"),
|
|
40
|
+
min_length=1,
|
|
37
41
|
)
|
|
38
42
|
|
|
39
43
|
@pydantic.model_serializer
|
|
@@ -45,7 +49,10 @@ class Or(BaseModel, Generic[F], extra="forbid"):
|
|
|
45
49
|
"""OR of other expressions"""
|
|
46
50
|
|
|
47
51
|
operands: Sequence[F] = pydantic.Field(
|
|
48
|
-
|
|
52
|
+
title="Or Operands",
|
|
53
|
+
serialization_alias="or",
|
|
54
|
+
validation_alias=AliasChoices("operands", "or"),
|
|
55
|
+
min_length=1,
|
|
49
56
|
)
|
|
50
57
|
|
|
51
58
|
@pydantic.model_serializer
|
|
@@ -57,7 +64,7 @@ class Not(BaseModel, Generic[F], extra="forbid"):
|
|
|
57
64
|
"""NOT another expression"""
|
|
58
65
|
|
|
59
66
|
operand: F = pydantic.Field(
|
|
60
|
-
serialization_alias="not", validation_alias=AliasChoices("operand", "not")
|
|
67
|
+
title="Not Operand", serialization_alias="not", validation_alias=AliasChoices("operand", "not")
|
|
61
68
|
)
|
|
62
69
|
|
|
63
70
|
@pydantic.model_serializer
|
|
@@ -78,11 +85,11 @@ class FilterProp(BaseModel):
|
|
|
78
85
|
class Resource(FilterProp, extra="forbid"):
|
|
79
86
|
"""Matches all fields of a resource given its id or slug"""
|
|
80
87
|
|
|
88
|
+
model_config = ConfigDict(title="Resource Filter")
|
|
89
|
+
|
|
81
90
|
prop: Literal["resource"] = "resource"
|
|
82
|
-
id:
|
|
83
|
-
slug:
|
|
84
|
-
default=None, description="Slug of the resource to match"
|
|
85
|
-
)
|
|
91
|
+
id: str | None = pydantic.Field(default=None, description="UUID of the resource to match")
|
|
92
|
+
slug: SlugString | None = pydantic.Field(default=None, description="Slug of the resource to match")
|
|
86
93
|
|
|
87
94
|
@field_validator("id", mode="after")
|
|
88
95
|
def validate_id(cls, v: str) -> str:
|
|
@@ -107,8 +114,9 @@ class Field(FilterProp, extra="forbid"):
|
|
|
107
114
|
|
|
108
115
|
prop: Literal["field"] = "field"
|
|
109
116
|
type: FieldTypeName = pydantic.Field(description="Type of the field to match, ")
|
|
110
|
-
name:
|
|
117
|
+
name: str | None = pydantic.Field(
|
|
111
118
|
default=None,
|
|
119
|
+
title="Field Filter",
|
|
112
120
|
description="Name of the field to match. If blank, matches all fields of the given type",
|
|
113
121
|
)
|
|
114
122
|
|
|
@@ -124,10 +132,10 @@ class DateCreated(FilterProp, extra="forbid"):
|
|
|
124
132
|
"""Matches all fields created in a date range"""
|
|
125
133
|
|
|
126
134
|
prop: Literal["created"] = "created"
|
|
127
|
-
since:
|
|
135
|
+
since: DateTime | None = pydantic.Field(
|
|
128
136
|
default=None, description="Start of the date range. Leave blank for unbounded"
|
|
129
137
|
)
|
|
130
|
-
until:
|
|
138
|
+
until: DateTime | None = pydantic.Field(
|
|
131
139
|
default=None, description="End of the date range. Leave blank for unbounded"
|
|
132
140
|
)
|
|
133
141
|
|
|
@@ -142,10 +150,10 @@ class DateModified(FilterProp, extra="forbid"):
|
|
|
142
150
|
"""Matches all fields modified in a date range"""
|
|
143
151
|
|
|
144
152
|
prop: Literal["modified"] = "modified"
|
|
145
|
-
since:
|
|
153
|
+
since: DateTime | None = pydantic.Field(
|
|
146
154
|
default=None, description="Start of the date range. Leave blank for unbounded"
|
|
147
155
|
)
|
|
148
|
-
until:
|
|
156
|
+
until: DateTime | None = pydantic.Field(
|
|
149
157
|
default=None, description="End of the date range. Leave blank for unbounded"
|
|
150
158
|
)
|
|
151
159
|
|
|
@@ -160,8 +168,8 @@ class Label(FilterProp, extra="forbid"):
|
|
|
160
168
|
"""Matches fields/paragraphs with a label (or labelset)"""
|
|
161
169
|
|
|
162
170
|
prop: Literal["label"] = "label"
|
|
163
|
-
labelset: str = pydantic.Field(description="The labelset to match")
|
|
164
|
-
label:
|
|
171
|
+
labelset: str = pydantic.Field(description="The ID of the labelset to match")
|
|
172
|
+
label: str | None = pydantic.Field(
|
|
165
173
|
default=None,
|
|
166
174
|
description="The label to match. If blank, matches all labels in the given labelset",
|
|
167
175
|
)
|
|
@@ -177,7 +185,7 @@ class ResourceMimetype(FilterProp, extra="forbid"):
|
|
|
177
185
|
type: str = pydantic.Field(
|
|
178
186
|
description="Type of the mimetype to match. e.g: In image/jpeg, type is image"
|
|
179
187
|
)
|
|
180
|
-
subtype:
|
|
188
|
+
subtype: str | None = pydantic.Field(
|
|
181
189
|
default=None,
|
|
182
190
|
description=(
|
|
183
191
|
"Type of the mimetype to match. e.g: In image/jpeg, subtype is jpeg."
|
|
@@ -193,7 +201,7 @@ class FieldMimetype(FilterProp, extra="forbid"):
|
|
|
193
201
|
type: str = pydantic.Field(
|
|
194
202
|
description="Type of the mimetype to match. e.g: In image/jpeg, type is image"
|
|
195
203
|
)
|
|
196
|
-
subtype:
|
|
204
|
+
subtype: str | None = pydantic.Field(
|
|
197
205
|
default=None,
|
|
198
206
|
description=(
|
|
199
207
|
"Type of the mimetype to match. e.g: In image/jpeg, subtype is jpeg."
|
|
@@ -207,7 +215,7 @@ class Entity(FilterProp, extra="forbid"):
|
|
|
207
215
|
|
|
208
216
|
prop: Literal["entity"] = "entity"
|
|
209
217
|
subtype: str = pydantic.Field(description="Type of the entity. e.g: PERSON")
|
|
210
|
-
value:
|
|
218
|
+
value: str | None = pydantic.Field(
|
|
211
219
|
default=None,
|
|
212
220
|
description="Value of the entity. e.g: Anna. If blank, matches any entity of the given type",
|
|
213
221
|
)
|
|
@@ -235,8 +243,8 @@ class OriginMetadata(FilterProp, extra="forbid"):
|
|
|
235
243
|
"""Matches metadata from the origin"""
|
|
236
244
|
|
|
237
245
|
prop: Literal["origin_metadata"] = "origin_metadata"
|
|
238
|
-
field: str = pydantic.Field(description="Metadata field")
|
|
239
|
-
value:
|
|
246
|
+
field: str = pydantic.Field(title="Origin Metadata Field", description="Metadata field")
|
|
247
|
+
value: str | None = pydantic.Field(
|
|
240
248
|
default=None,
|
|
241
249
|
description="Value of the metadata field. If blank, matches any document with the given metadata field set (to any value)",
|
|
242
250
|
)
|
|
@@ -246,7 +254,7 @@ class OriginPath(FilterProp, extra="forbid"):
|
|
|
246
254
|
"""Matches the origin path"""
|
|
247
255
|
|
|
248
256
|
prop: Literal["origin_path"] = "origin_path"
|
|
249
|
-
prefix:
|
|
257
|
+
prefix: str | None = pydantic.Field(
|
|
250
258
|
default=None,
|
|
251
259
|
description=(
|
|
252
260
|
"Prefix of the path, matches all paths under this prefix"
|
|
@@ -259,7 +267,7 @@ class OriginSource(FilterProp, extra="forbid"):
|
|
|
259
267
|
"""Matches the origin source id"""
|
|
260
268
|
|
|
261
269
|
prop: Literal["origin_source"] = "origin_source"
|
|
262
|
-
id:
|
|
270
|
+
id: str | None = pydantic.Field(default=None, description=("Source ID"))
|
|
263
271
|
|
|
264
272
|
|
|
265
273
|
class OriginCollaborator(FilterProp, extra="forbid"):
|
|
@@ -276,7 +284,7 @@ class Generated(FilterProp, extra="forbid"):
|
|
|
276
284
|
by: Literal["data-augmentation"] = pydantic.Field(
|
|
277
285
|
description="Generator for this field. Currently, only data-augmentation is supported"
|
|
278
286
|
)
|
|
279
|
-
da_task:
|
|
287
|
+
da_task: str | None = pydantic.Field(
|
|
280
288
|
default=None, description="Matches field generated by an specific DA task, given its prefix"
|
|
281
289
|
)
|
|
282
290
|
|
|
@@ -297,7 +305,7 @@ class Status(FilterProp, extra="forbid"):
|
|
|
297
305
|
|
|
298
306
|
# The discriminator function is optional, everything works without it.
|
|
299
307
|
# We implement it because it makes pydantic produce more user-friendly errors
|
|
300
|
-
def filter_discriminator(v: Any) ->
|
|
308
|
+
def filter_discriminator(v: Any) -> str | None:
|
|
301
309
|
if isinstance(v, dict):
|
|
302
310
|
if "and" in v:
|
|
303
311
|
return "and"
|
|
@@ -319,59 +327,53 @@ def filter_discriminator(v: Any) -> Optional[str]:
|
|
|
319
327
|
|
|
320
328
|
|
|
321
329
|
FieldFilterExpression = Annotated[
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
Annotated[Generated, Tag("generated")],
|
|
342
|
-
],
|
|
330
|
+
Annotated[And["FieldFilterExpression"], Tag("and")]
|
|
331
|
+
| Annotated[Or["FieldFilterExpression"], Tag("or")]
|
|
332
|
+
| Annotated[Not["FieldFilterExpression"], Tag("not")]
|
|
333
|
+
| Annotated[Resource, Tag("resource")]
|
|
334
|
+
| Annotated[Field, Tag("field")]
|
|
335
|
+
| Annotated[Keyword, Tag("keyword")]
|
|
336
|
+
| Annotated[DateCreated, Tag("created")]
|
|
337
|
+
| Annotated[DateModified, Tag("modified")]
|
|
338
|
+
| Annotated[Label, Tag("label")]
|
|
339
|
+
| Annotated[ResourceMimetype, Tag("resource_mimetype")]
|
|
340
|
+
| Annotated[FieldMimetype, Tag("field_mimetype")]
|
|
341
|
+
| Annotated[Entity, Tag("entity")]
|
|
342
|
+
| Annotated[Language, Tag("language")]
|
|
343
|
+
| Annotated[OriginTag, Tag("origin_tag")]
|
|
344
|
+
| Annotated[OriginMetadata, Tag("origin_metadata")]
|
|
345
|
+
| Annotated[OriginPath, Tag("origin_path")]
|
|
346
|
+
| Annotated[OriginSource, Tag("origin_source")]
|
|
347
|
+
| Annotated[OriginCollaborator, Tag("origin_collaborator")]
|
|
348
|
+
| Annotated[Generated, Tag("generated")],
|
|
343
349
|
Discriminator(filter_discriminator),
|
|
344
350
|
]
|
|
345
351
|
|
|
346
352
|
ParagraphFilterExpression = Annotated[
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
Annotated[Kind, Tag("kind")],
|
|
353
|
-
],
|
|
353
|
+
Annotated[And["ParagraphFilterExpression"], Tag("and")]
|
|
354
|
+
| Annotated[Or["ParagraphFilterExpression"], Tag("or")]
|
|
355
|
+
| Annotated[Not["ParagraphFilterExpression"], Tag("not")]
|
|
356
|
+
| Annotated[Label, Tag("label")]
|
|
357
|
+
| Annotated[Kind, Tag("kind")],
|
|
354
358
|
Discriminator(filter_discriminator),
|
|
355
359
|
]
|
|
356
360
|
|
|
357
361
|
ResourceFilterExpression = Annotated[
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
Annotated[Status, Tag("status")],
|
|
374
|
-
],
|
|
362
|
+
Annotated[And["ResourceFilterExpression"], Tag("and")]
|
|
363
|
+
| Annotated[Or["ResourceFilterExpression"], Tag("or")]
|
|
364
|
+
| Annotated[Not["ResourceFilterExpression"], Tag("not")]
|
|
365
|
+
| Annotated[Resource, Tag("resource")]
|
|
366
|
+
| Annotated[DateCreated, Tag("created")]
|
|
367
|
+
| Annotated[DateModified, Tag("modified")]
|
|
368
|
+
| Annotated[Label, Tag("label")]
|
|
369
|
+
| Annotated[ResourceMimetype, Tag("resource_mimetype")]
|
|
370
|
+
| Annotated[Language, Tag("language")]
|
|
371
|
+
| Annotated[OriginTag, Tag("origin_tag")]
|
|
372
|
+
| Annotated[OriginMetadata, Tag("origin_metadata")]
|
|
373
|
+
| Annotated[OriginPath, Tag("origin_path")]
|
|
374
|
+
| Annotated[OriginSource, Tag("origin_source")]
|
|
375
|
+
| Annotated[OriginCollaborator, Tag("origin_collaborator")]
|
|
376
|
+
| Annotated[Status, Tag("status")],
|
|
375
377
|
Discriminator(filter_discriminator),
|
|
376
378
|
]
|
|
377
379
|
|
|
@@ -388,10 +390,10 @@ class FilterExpression(BaseModel, extra="forbid"):
|
|
|
388
390
|
AND = "and"
|
|
389
391
|
OR = "or"
|
|
390
392
|
|
|
391
|
-
field:
|
|
392
|
-
default=None, description="Filter to apply to fields"
|
|
393
|
+
field: FieldFilterExpression | None = pydantic.Field(
|
|
394
|
+
default=None, title="Field Filters", description="Filter to apply to fields"
|
|
393
395
|
)
|
|
394
|
-
paragraph:
|
|
396
|
+
paragraph: ParagraphFilterExpression | None = pydantic.Field(
|
|
395
397
|
default=None, description="Filter to apply to each text block"
|
|
396
398
|
)
|
|
397
399
|
|
|
@@ -413,4 +415,6 @@ class CatalogFilterExpression(BaseModel, extra="forbid"):
|
|
|
413
415
|
`filters`, `range_*`, `with_status`.
|
|
414
416
|
"""
|
|
415
417
|
|
|
416
|
-
resource: ResourceFilterExpression = pydantic.Field(
|
|
418
|
+
resource: ResourceFilterExpression = pydantic.Field(
|
|
419
|
+
title="Resource filters", description="Filter to apply to resources"
|
|
420
|
+
)
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
#
|
|
15
15
|
from enum import Enum
|
|
16
|
-
from typing import Annotated, Any, Literal
|
|
16
|
+
from typing import Annotated, Any, Literal
|
|
17
17
|
|
|
18
18
|
from pydantic import BaseModel, Discriminator, Field, Tag, model_validator
|
|
19
19
|
from typing_extensions import Self
|
|
@@ -38,17 +38,18 @@ class GraphProp(BaseModel):
|
|
|
38
38
|
class NodeMatchKindName(str, Enum):
|
|
39
39
|
EXACT = "exact"
|
|
40
40
|
FUZZY = "fuzzy"
|
|
41
|
+
FUZZY_WORDS = "fuzzy_words"
|
|
41
42
|
|
|
42
43
|
|
|
43
44
|
class GraphNode(BaseModel, extra="forbid"):
|
|
44
|
-
value:
|
|
45
|
+
value: str | None = None
|
|
45
46
|
match: NodeMatchKindName = NodeMatchKindName.EXACT
|
|
46
|
-
type:
|
|
47
|
-
group:
|
|
47
|
+
type: RelationNodeType | None = RelationNodeType.ENTITY
|
|
48
|
+
group: str | None = None
|
|
48
49
|
|
|
49
50
|
@model_validator(mode="after")
|
|
50
51
|
def validate_fuzzy_usage(self) -> Self:
|
|
51
|
-
if self.match
|
|
52
|
+
if self.match in (NodeMatchKindName.FUZZY, NodeMatchKindName.FUZZY_WORDS):
|
|
52
53
|
if self.value is None:
|
|
53
54
|
raise ValueError("Fuzzy match can only be used if a node value is provided")
|
|
54
55
|
else:
|
|
@@ -60,8 +61,8 @@ class GraphNode(BaseModel, extra="forbid"):
|
|
|
60
61
|
|
|
61
62
|
|
|
62
63
|
class GraphRelation(BaseModel, extra="forbid"):
|
|
63
|
-
label:
|
|
64
|
-
type:
|
|
64
|
+
label: str | None = None
|
|
65
|
+
type: RelationType | None = None
|
|
65
66
|
|
|
66
67
|
|
|
67
68
|
## Models for query expressions
|
|
@@ -85,9 +86,9 @@ class Relation(GraphRelation, GraphProp):
|
|
|
85
86
|
|
|
86
87
|
class GraphPath(GraphProp, extra="forbid"):
|
|
87
88
|
prop: Literal["path"] = "path"
|
|
88
|
-
source:
|
|
89
|
-
relation:
|
|
90
|
-
destination:
|
|
89
|
+
source: GraphNode | None = None
|
|
90
|
+
relation: GraphRelation | None = None
|
|
91
|
+
destination: GraphNode | None = None
|
|
91
92
|
undirected: bool = False
|
|
92
93
|
|
|
93
94
|
|
|
@@ -102,7 +103,7 @@ class Generated(GraphProp, extra="forbid"):
|
|
|
102
103
|
|
|
103
104
|
prop: Literal["generated"] = "generated"
|
|
104
105
|
by: Generator = Field(description="Generator for this field.")
|
|
105
|
-
da_task:
|
|
106
|
+
da_task: str | None = Field(
|
|
106
107
|
default=None, description="Matches relations generated by an specific DA task, given its prefix"
|
|
107
108
|
)
|
|
108
109
|
|
|
@@ -122,12 +123,14 @@ class GraphFilterExpression(BaseModel, extra="forbid"):
|
|
|
122
123
|
Filtering examples can be found here: https://docs.nuclia.dev/docs/rag/advanced/search-filters
|
|
123
124
|
"""
|
|
124
125
|
|
|
125
|
-
field: FieldFilterExpression = Field(
|
|
126
|
+
field: FieldFilterExpression = Field(
|
|
127
|
+
title="Graph Field Filters", description="Filter to apply to fields"
|
|
128
|
+
)
|
|
126
129
|
|
|
127
130
|
|
|
128
131
|
class BaseGraphSearchRequest(BaseModel):
|
|
129
132
|
top_k: int = Field(default=50, le=500, title="Number of results to retrieve")
|
|
130
|
-
filter_expression:
|
|
133
|
+
filter_expression: GraphFilterExpression | None = Field(
|
|
131
134
|
default=None,
|
|
132
135
|
title="Filter resource by an expression",
|
|
133
136
|
description=(
|
|
@@ -135,10 +138,10 @@ class BaseGraphSearchRequest(BaseModel):
|
|
|
135
138
|
"Filtering examples can be found here: https://docs.nuclia.dev/docs/rag/advanced/search-filters "
|
|
136
139
|
),
|
|
137
140
|
)
|
|
138
|
-
security:
|
|
141
|
+
security: RequestSecurity | None = Field(
|
|
139
142
|
default=None,
|
|
140
143
|
title="Security",
|
|
141
|
-
description="Security metadata for the request. If not provided, the search request is done without the security lookup phase.",
|
|
144
|
+
description="Security metadata for the request. If not provided, the search request is done without the security lookup phase.",
|
|
142
145
|
)
|
|
143
146
|
show_hidden: bool = Field(
|
|
144
147
|
default=False,
|
|
@@ -153,64 +156,53 @@ graph_query_discriminator = filter_discriminator
|
|
|
153
156
|
# Paths search
|
|
154
157
|
|
|
155
158
|
GraphPathQuery = Annotated[
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
Annotated[DestinationNode, Tag("destination_node")],
|
|
166
|
-
Annotated[AnyNode, Tag("node")],
|
|
167
|
-
# relations
|
|
168
|
-
Annotated[Relation, Tag("relation")],
|
|
169
|
-
# metadata
|
|
170
|
-
Annotated[Generated, Tag("generated")],
|
|
171
|
-
],
|
|
159
|
+
Annotated[And["GraphPathQuery"], Tag("and")]
|
|
160
|
+
| Annotated[Or["GraphPathQuery"], Tag("or")]
|
|
161
|
+
| Annotated[Not["GraphPathQuery"], Tag("not")]
|
|
162
|
+
| Annotated[GraphPath, Tag("path")]
|
|
163
|
+
| Annotated[SourceNode, Tag("source_node")]
|
|
164
|
+
| Annotated[DestinationNode, Tag("destination_node")]
|
|
165
|
+
| Annotated[AnyNode, Tag("node")]
|
|
166
|
+
| Annotated[Relation, Tag("relation")]
|
|
167
|
+
| Annotated[Generated, Tag("generated")],
|
|
172
168
|
Discriminator(graph_query_discriminator),
|
|
173
169
|
]
|
|
174
170
|
|
|
175
171
|
|
|
176
172
|
class GraphSearchRequest(BaseGraphSearchRequest):
|
|
177
|
-
query: GraphPathQuery
|
|
173
|
+
query: GraphPathQuery = Field(title="Graph Path Query")
|
|
178
174
|
|
|
179
175
|
|
|
180
176
|
# Nodes search
|
|
181
177
|
|
|
182
178
|
GraphNodesQuery = Annotated[
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
Annotated[Generated, Tag("generated")],
|
|
189
|
-
],
|
|
179
|
+
Annotated[And["GraphNodesQuery"], Tag("and")]
|
|
180
|
+
| Annotated[Or["GraphNodesQuery"], Tag("or")]
|
|
181
|
+
| Annotated[Not["GraphNodesQuery"], Tag("not")]
|
|
182
|
+
| Annotated[AnyNode, Tag("node")]
|
|
183
|
+
| Annotated[Generated, Tag("generated")],
|
|
190
184
|
Discriminator(graph_query_discriminator),
|
|
191
185
|
]
|
|
192
186
|
|
|
193
187
|
|
|
194
188
|
class GraphNodesSearchRequest(BaseGraphSearchRequest):
|
|
195
|
-
query: GraphNodesQuery
|
|
189
|
+
query: GraphNodesQuery = Field(title="Graph Nodes Query")
|
|
196
190
|
|
|
197
191
|
|
|
198
192
|
# Relations search
|
|
199
193
|
|
|
200
194
|
GraphRelationsQuery = Annotated[
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
Annotated[Generated, Tag("generated")],
|
|
207
|
-
],
|
|
195
|
+
Annotated[And["GraphRelationsQuery"], Tag("and")]
|
|
196
|
+
| Annotated[Or["GraphRelationsQuery"], Tag("or")]
|
|
197
|
+
| Annotated[Not["GraphRelationsQuery"], Tag("not")]
|
|
198
|
+
| Annotated[Relation, Tag("relation")]
|
|
199
|
+
| Annotated[Generated, Tag("generated")],
|
|
208
200
|
Discriminator(graph_query_discriminator),
|
|
209
201
|
]
|
|
210
202
|
|
|
211
203
|
|
|
212
204
|
class GraphRelationsSearchRequest(BaseGraphSearchRequest):
|
|
213
|
-
query: GraphRelationsQuery
|
|
205
|
+
query: GraphRelationsQuery = Field(title="Graph Relations Query")
|
|
214
206
|
|
|
215
207
|
|
|
216
208
|
# We need this to avoid issues with pydantic and generic types defined in another module
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
#
|
|
15
15
|
from enum import Enum
|
|
16
16
|
|
|
17
|
-
from pydantic import BaseModel
|
|
17
|
+
from pydantic import BaseModel, Field
|
|
18
18
|
|
|
19
19
|
from nucliadb_models.metadata import RelationNodeType, RelationType
|
|
20
20
|
|
|
@@ -40,10 +40,22 @@ class GraphRelation(BaseModel):
|
|
|
40
40
|
type: RelationType
|
|
41
41
|
|
|
42
42
|
|
|
43
|
+
class PathMetadata(BaseModel):
|
|
44
|
+
# {rid}/{field_type}/{field_id}
|
|
45
|
+
field_id: str | None = Field(
|
|
46
|
+
default=None, description="Field id where the relation has been extracted from"
|
|
47
|
+
)
|
|
48
|
+
# {rid}/{field_type}/{field_id}/{paragraph_start}-{paragraph_end}
|
|
49
|
+
paragraph_id: str | None = Field(
|
|
50
|
+
default=None, description="Paragraph id where the relation has been extracted from"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
43
54
|
class GraphPath(BaseModel):
|
|
44
55
|
source: GraphNode
|
|
45
56
|
relation: GraphRelation
|
|
46
57
|
destination: GraphNode
|
|
58
|
+
metadata: PathMetadata | None
|
|
47
59
|
|
|
48
60
|
|
|
49
61
|
class GraphSearchResponse(BaseModel):
|