Skip to content

Commit ead7246

Browse files
vagenasHolyMichael
andauthored
feat: expand Model API Pydantic types
Signed-off-by: Miguel Brandão <[email protected]> Signed-off-by: Panos Vagenas <[email protected]> Co-authored-by: Miguel Brandão <[email protected]>
1 parent b3e7bda commit ead7246

File tree

12 files changed

+213
-114
lines changed

12 files changed

+213
-114
lines changed

deepsearch/model/base/controller.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,42 @@
22
from typing import Optional
33

44
from deepsearch.model.base.model import BaseDSModel
5-
from deepsearch.model.base.types import BaseModelConfig
6-
from deepsearch.model.server.inference_types import ControllerInput, ControllerOutput
5+
from deepsearch.model.base.types import BaseModelConfig, BaseModelMetadata
6+
from deepsearch.model.server.inference_types import (
7+
AppModelInfoOutput,
8+
CtrlPredInput,
9+
CtrlPredOutput,
10+
)
711

812

913
class BaseController(ABC):
1014
_config: Optional[BaseModelConfig] = None
1115

12-
def get_info(self) -> dict:
13-
model = self._get_model()
16+
@abstractmethod
17+
def get_info(self) -> AppModelInfoOutput:
18+
raise NotImplementedError()
19+
20+
def _get_api_version(self) -> str:
21+
return "v1"
22+
23+
def _get_metadata(self) -> BaseModelMetadata:
1424
cfg = self._get_config()
15-
result = { # TODO refactor with pydantic
16-
"definitions": {
17-
"apiVersion": "v1",
18-
"kind": cfg.kind,
19-
"spec": model.get_definition_spec(),
20-
}
21-
}
22-
return result
25+
return BaseModelMetadata(
26+
name=cfg.name,
27+
version=cfg.version,
28+
url=cfg.url,
29+
author=cfg.author,
30+
description=cfg.description,
31+
expected_compute_time=cfg.expected_compute_time,
32+
)
2333

2434
def _get_config(self):
2535
if self._config is None:
2636
self._config = self._get_model().get_config()
2737
return self._config
2838

2939
@abstractmethod
30-
def dispatch_predict(self, spec: ControllerInput) -> ControllerOutput:
40+
def dispatch_predict(self, spec: CtrlPredInput) -> CtrlPredOutput:
3141
raise NotImplementedError()
3242

3343
@abstractmethod

deepsearch/model/base/model.py

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,3 @@ class BaseDSModel(ABC):
77
@abstractmethod
88
def get_config(self) -> BaseModelConfig:
99
raise NotImplementedError()
10-
11-
def get_definition_spec(self) -> dict:
12-
cfg = self.get_config()
13-
spec = { # TODO refactor with pydantic
14-
"metadata": {
15-
"name": cfg.name,
16-
"version": cfg.version,
17-
"url": cfg.url,
18-
"author": cfg.author,
19-
"description": cfg.description,
20-
"expected_compute_time": cfg.expected_compute_time,
21-
},
22-
}
23-
return spec

deepsearch/model/base/types.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from datetime import datetime
22
from enum import Enum
3-
from typing import Any, Optional
3+
from typing import Any, Dict, Optional
44

55
from pydantic import BaseModel, Extra, Field, PositiveFloat
66

@@ -34,18 +34,36 @@ class Metadata(StrictModel):
3434
annotations: Annotations
3535

3636

37-
class BaseInfReq(StrictModel):
37+
class BaseAppPredInput(StrictModel):
3838
apiVersion: str
3939
kind: Kind
4040
metadata: Metadata
4141
spec: Any
4242

4343

44-
class BaseModelConfig(StrictModel):
45-
kind: Kind
44+
class BaseModelMetadata(StrictModel):
4645
name: str
4746
version: str
4847
url: Optional[str] = None
4948
author: Optional[str] = None
5049
description: Optional[str] = None
5150
expected_compute_time: Optional[PositiveFloat] = None
51+
52+
53+
class BaseModelConfig(BaseModelMetadata):
54+
kind: Kind
55+
56+
57+
class ModelInfoOutputDefsSpec(BaseModel):
58+
definition: Dict
59+
metadata: BaseModelMetadata
60+
61+
62+
class CtrlInfoOutputDefs(BaseModel):
63+
apiVersion: str
64+
kind: Kind
65+
spec: ModelInfoOutputDefsSpec
66+
67+
68+
class CtrlInfoOutput(BaseModel):
69+
definitions: CtrlInfoOutputDefs

deepsearch/model/examples/dummy_nlp_annotator/model.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from deepsearch.model.base.types import Kind
66
from deepsearch.model.kinds.nlp.model import BaseNLPModel
77
from deepsearch.model.kinds.nlp.types import (
8+
AnnotateEntitiesEntry,
89
AnnotateEntitiesOutput,
910
AnnotatePropertiesOutput,
1011
AnnotateRelationshipsOutput,
@@ -41,18 +42,18 @@ def annotate_batched_entities(
4142
results.append(
4243
{
4344
k: [
44-
{
45-
"type": k,
46-
"match": f"a '{k}' match in '{item}'",
47-
"original": f"a '{k}' original in '{item}'",
48-
"range": [1, 5],
49-
},
50-
{
51-
"type": k,
52-
"match": f"another '{k}' match in '{item}'",
53-
"original": f"another '{k}' original in '{item}'",
54-
"range": [12, 42],
55-
},
45+
AnnotateEntitiesEntry(
46+
type=k,
47+
match=f"a '{k}' match in '{item}'",
48+
original=f"a '{k}' original in '{item}'",
49+
range=[1, 5],
50+
),
51+
AnnotateEntitiesEntry(
52+
type=k,
53+
match=f"another '{k}' match in '{item}'",
54+
original=f"another '{k}' original in '{item}'",
55+
range=[12, 42],
56+
),
5657
]
5758
for k in _entity_names
5859
}

deepsearch/model/examples/simple_geo_nlp_annotator/model.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def annotate_batched_entities(
157157

158158
def _annotate_entities_in_item(
159159
self, object_type: str, item: str, entity_names: Optional[List[str]]
160-
) -> List[dict]:
160+
) -> List:
161161
# In this case entity_names is never None, however since BaseAnnotator defines the signature of this method as
162162
# Optionally having entity names we must ensure that they are defined.
163163
if entity_names is None:
@@ -200,7 +200,7 @@ def annotate_batched_relationships(
200200
if relation in self.relationship_names:
201201
result[relation] = self._rel_annots[
202202
relation
203-
].annotate_relationships_text(text, entity_map)
203+
].annotate_relationships_text(text, entity_map, relation)
204204

205205
if result:
206206
results.append(result)

deepsearch/model/kinds/nlp/controller.py

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,48 @@
88
FindEntitiesText,
99
FindPropertiesText,
1010
FindRelationshipsText,
11-
NLPEntitiesControllerOutput,
1211
NLPEntitiesReqSpec,
13-
NLPPropertiesControllerOutput,
12+
NLPEntsCtrlPredOuput,
13+
NLPInfoOutput,
14+
NLPInfoOutputDefinitions,
15+
NLPInfoOutputDefinitionsSpec,
16+
NLPModelMetadata,
1417
NLPPropertiesReqSpec,
15-
NLPRelationshipsControllerOutput,
18+
NLPPropsCtrlPredOutput,
1619
NLPRelationshipsReqSpec,
20+
NLPRelsCtrlPredOutput,
1721
)
18-
from deepsearch.model.server.inference_types import ControllerInput, ControllerOutput
22+
from deepsearch.model.server.inference_types import CtrlPredInput, CtrlPredOutput
1923

2024

2125
class NLPController(BaseController):
2226
def __init__(self, model: BaseNLPModel):
2327
self._model = model
2428

29+
def get_info(self) -> NLPInfoOutput:
30+
cfg = self._model.get_nlp_config()
31+
metadata = NLPModelMetadata(
32+
supported_object_types=cfg.supported_types,
33+
**self._get_metadata().dict(), # passing parent metadata dict as kwargs
34+
)
35+
spec = NLPInfoOutputDefinitionsSpec(
36+
definition=cfg.labels,
37+
metadata=metadata,
38+
)
39+
definitions = NLPInfoOutputDefinitions(
40+
apiVersion=self._get_api_version(),
41+
kind=self.get_kind(),
42+
spec=spec,
43+
)
44+
return NLPInfoOutput(definitions=definitions)
45+
2546
def get_kind(self) -> str:
2647
return Kind.NLPModel
2748

2849
def _get_model(self) -> BaseDSModel:
2950
return self._model
3051

31-
def dispatch_predict(self, spec: ControllerInput) -> ControllerOutput:
52+
def dispatch_predict(self, spec: CtrlPredInput) -> CtrlPredOutput:
3253
cfg = self._model.get_nlp_config()
3354
type_ok = True
3455

@@ -43,7 +64,7 @@ def dispatch_predict(self, spec: ControllerInput) -> ControllerOutput:
4364
items=spec.findEntities.texts,
4465
entity_names=spec.findEntities.entityNames,
4566
)
46-
return NLPEntitiesControllerOutput(entities=entities)
67+
return NLPEntsCtrlPredOuput(entities=entities)
4768
elif (
4869
isinstance(spec, NLPRelationshipsReqSpec)
4970
and isinstance(spec.findRelationships, FindRelationshipsText)
@@ -55,7 +76,7 @@ def dispatch_predict(self, spec: ControllerInput) -> ControllerOutput:
5576
entities=spec.findRelationships.entities,
5677
relationship_names=spec.findRelationships.relationshipNames,
5778
)
58-
return NLPRelationshipsControllerOutput(relationships=relationships)
79+
return NLPRelsCtrlPredOutput(relationships=relationships)
5980
elif (
6081
isinstance(spec, NLPPropertiesReqSpec)
6182
and isinstance(spec.findProperties, FindPropertiesText)
@@ -71,7 +92,7 @@ def dispatch_predict(self, spec: ControllerInput) -> ControllerOutput:
7192
entities=entities,
7293
property_names=spec.findProperties.propertyNames,
7394
)
74-
return NLPPropertiesControllerOutput(properties=properties)
95+
return NLPPropsCtrlPredOutput(properties=properties)
7596
elif not type_ok:
7697
raise HTTPException(
7798
status_code=status.HTTP_400_BAD_REQUEST,

deepsearch/model/kinds/nlp/model.py

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from abc import abstractmethod
2-
from copy import deepcopy
32
from typing import List, Optional
43

54
from deepsearch.model.base.model import BaseDSModel
@@ -13,8 +12,6 @@
1312

1413

1514
class BaseNLPModel(BaseDSModel):
16-
_cached_def_spec: dict = {}
17-
1815
@abstractmethod
1916
def annotate_batched_entities(
2017
self,
@@ -44,16 +41,6 @@ def annotate_batched_properties(
4441
) -> AnnotatePropertiesOutput:
4542
raise NotImplementedError()
4643

47-
def get_definition_spec(self) -> dict:
48-
cfg = self.get_nlp_config()
49-
if not self._cached_def_spec:
50-
self._cached_def_spec = deepcopy(super().get_definition_spec())
51-
self._cached_def_spec["definition"] = cfg.labels
52-
self._cached_def_spec["metadata"][
53-
"supported_object_types"
54-
] = cfg.supported_types
55-
return self._cached_def_spec
56-
5744
@abstractmethod
5845
def get_nlp_config(self) -> NLPConfig:
5946
raise NotImplementedError()

deepsearch/model/kinds/nlp/types.py

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
from enum import Enum
2-
from typing import List, Literal, Optional, Union
2+
from typing import Dict, List, Literal, Optional, Union
33

4-
from deepsearch.model.base.types import BaseInfReq, BaseModelConfig, Kind, StrictModel
4+
from deepsearch.model.base.types import (
5+
BaseAppPredInput,
6+
BaseModelConfig,
7+
BaseModelMetadata,
8+
CtrlInfoOutput,
9+
CtrlInfoOutputDefs,
10+
Kind,
11+
ModelInfoOutputDefsSpec,
12+
StrictModel,
13+
)
514

615

716
class NLPType(str, Enum):
@@ -48,7 +57,7 @@ class NLPRelationshipsReqSpec(StrictModel):
4857
]
4958

5059

51-
class NLPRequest(BaseInfReq):
60+
class NLPAppPredInput(BaseAppPredInput):
5261
kind: Literal[Kind.NLPModel]
5362
spec: NLPReqSpec
5463

@@ -80,33 +89,60 @@ class AnnotationLabels(StrictModel):
8089
properties: List[PropertyLabel]
8190

8291

83-
# TODO Annotate*Input pydantic models needed?
92+
class AnnotateEntitiesEntry(StrictModel):
93+
type: str
94+
match: str
95+
original: str
96+
range: List[int]
8497

85-
AnnotateEntitiesOutput = List[dict] # TODO provide real implementation
86-
AnnotateRelationshipsOutput = List[dict] # TODO provide real implementation
87-
AnnotatePropertiesOutput = List[dict] # TODO provide real implementation
8898

99+
class AnnotateRelationshipsEntry(StrictModel):
100+
header: list
101+
data: list
89102

90-
class NLPEntitiesControllerOutput(StrictModel):
103+
104+
AnnotateEntitiesOutput = List[Dict[str, List[AnnotateEntitiesEntry]]]
105+
AnnotateRelationshipsOutput = List[Dict[str, AnnotateRelationshipsEntry]]
106+
AnnotatePropertiesOutput = List[Dict] # TODO specify
107+
108+
109+
class NLPEntsCtrlPredOuput(StrictModel):
91110
entities: AnnotateEntitiesOutput
92111

93112

94-
class NLPRelationshipsControllerOutput(StrictModel):
113+
class NLPRelsCtrlPredOutput(StrictModel):
95114
relationships: AnnotateRelationshipsOutput
96115

97116

98-
class NLPPropertiesControllerOutput(StrictModel):
117+
class NLPPropsCtrlPredOutput(StrictModel):
99118
properties: AnnotatePropertiesOutput
100119

101120

102-
NLPControllerOutput = Union[
103-
NLPEntitiesControllerOutput,
104-
NLPRelationshipsControllerOutput,
105-
NLPPropertiesControllerOutput,
121+
NLPCtrlPredOutput = Union[
122+
NLPEntsCtrlPredOuput,
123+
NLPRelsCtrlPredOutput,
124+
NLPPropsCtrlPredOutput,
106125
]
107126

108127

109128
class NLPConfig(BaseModelConfig):
110129
kind: Literal[Kind.NLPModel]
111130
supported_types: List[NLPType]
112131
labels: AnnotationLabels
132+
133+
134+
class NLPModelMetadata(BaseModelMetadata):
135+
supported_object_types: List[Literal["text", "table", "image"]]
136+
137+
138+
class NLPInfoOutputDefinitionsSpec(ModelInfoOutputDefsSpec):
139+
metadata: NLPModelMetadata
140+
141+
142+
class NLPInfoOutputDefinitions(CtrlInfoOutputDefs):
143+
kind: Literal[Kind.NLPModel]
144+
spec: NLPInfoOutputDefinitionsSpec
145+
146+
147+
class NLPInfoOutput(CtrlInfoOutput):
148+
definitions: NLPInfoOutputDefinitions

0 commit comments

Comments
 (0)