agi-med-common 5.0.16__py3-none-any.whl → 5.0.18__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.
- agi_med_common/__init__.py +2 -1
- agi_med_common/api/critic_api.py +6 -0
- agi_med_common/models/chat.py +161 -1
- agi_med_common/models/chat_item.py +28 -40
- {agi_med_common-5.0.16.dist-info → agi_med_common-5.0.18.dist-info}/METADATA +1 -1
- {agi_med_common-5.0.16.dist-info → agi_med_common-5.0.18.dist-info}/RECORD +8 -7
- {agi_med_common-5.0.16.dist-info → agi_med_common-5.0.18.dist-info}/WHEEL +0 -0
- {agi_med_common-5.0.16.dist-info → agi_med_common-5.0.18.dist-info}/top_level.txt +0 -0
agi_med_common/__init__.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
__version__ = "5.0.
|
1
|
+
__version__ = "5.0.18"
|
2
2
|
|
3
3
|
from .models import (
|
4
4
|
MTRSLabelEnum,
|
@@ -26,3 +26,4 @@ from .api.content_interpreter_api import ContentInterpreterAPI, Interpretation
|
|
26
26
|
from .api.content_interpreter_remote_api import ContentInterpreterRemoteAPI
|
27
27
|
from .api.text_generator_api import TextGeneratorAPI
|
28
28
|
from .api.classifier_api import ClassifierAPI
|
29
|
+
from .api.critic_api import CriticAPI
|
agi_med_common/models/chat.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from datetime import datetime
|
2
2
|
from typing import Any, List, Dict, Literal
|
3
3
|
|
4
|
+
from agi_med_common.models.chat_item import ChatItem, ReplicaItem, OuterContextItem
|
4
5
|
from agi_med_common.models.widget import Widget
|
5
6
|
from agi_med_common.type_union import TypeUnion
|
6
7
|
from agi_med_common.utils import first_nonnull
|
@@ -55,12 +56,31 @@ def _get_text(obj: Content) -> str:
|
|
55
56
|
|
56
57
|
def _get_resource_id(obj: Content) -> str | None:
|
57
58
|
if isinstance(obj, list):
|
58
|
-
return first_nonnull(
|
59
|
+
return first_nonnull(map(_get_resource_id, obj))
|
59
60
|
if isinstance(obj, dict) and obj.get("type") == "resource_id":
|
60
61
|
return _get_str_field(obj, "resource_id")
|
61
62
|
return None
|
62
63
|
|
63
64
|
|
65
|
+
def _get_command(obj: Content) -> dict | None:
|
66
|
+
if isinstance(obj, list):
|
67
|
+
return first_nonnull(map(_get_command, obj))
|
68
|
+
if isinstance(obj, dict) and obj.get("type") == "command":
|
69
|
+
return _get_str_field(obj, "command")
|
70
|
+
return None
|
71
|
+
|
72
|
+
|
73
|
+
def _get_widget(obj: Content) -> Widget | None:
|
74
|
+
if isinstance(obj, list):
|
75
|
+
return first_nonnull(map(_get_widget, obj))
|
76
|
+
if isinstance(obj, Widget):
|
77
|
+
return obj
|
78
|
+
return None
|
79
|
+
|
80
|
+
|
81
|
+
# todo fix: generalize functions above
|
82
|
+
|
83
|
+
|
64
84
|
class BaseMessage(_Base):
|
65
85
|
type: str
|
66
86
|
content: Content = Field("", examples=["Привет"])
|
@@ -75,6 +95,14 @@ class BaseMessage(_Base):
|
|
75
95
|
def resource_id(self) -> str | None:
|
76
96
|
return _get_resource_id(self.content)
|
77
97
|
|
98
|
+
@property
|
99
|
+
def command(self) -> dict | None:
|
100
|
+
return _get_command(self.content)
|
101
|
+
|
102
|
+
@property
|
103
|
+
def widget(self) -> Widget | None:
|
104
|
+
return _get_widget(self.content)
|
105
|
+
|
78
106
|
@staticmethod
|
79
107
|
def DATETIME_FORMAT() -> str:
|
80
108
|
return _DT_FORMAT
|
@@ -105,3 +133,135 @@ class Chat(_Base):
|
|
105
133
|
|
106
134
|
def create_id(self, short: bool = False) -> str:
|
107
135
|
return self.context.create_id(short)
|
136
|
+
|
137
|
+
@classmethod
|
138
|
+
def parse(self, chat_obj: str | dict) -> "Chat":
|
139
|
+
return _parse_chat_compat(chat_obj)
|
140
|
+
|
141
|
+
|
142
|
+
def convert_replica_item_to_message(replica: ReplicaItem) -> ChatMessage:
|
143
|
+
resource_id = (replica.resource_id or None) and {"type": "resource_id", "resource_id": replica.resource_id}
|
144
|
+
body = replica.body
|
145
|
+
command = replica.command
|
146
|
+
widget = replica.widget
|
147
|
+
|
148
|
+
content = list(filter(None, [body, resource_id, command, widget]))
|
149
|
+
if len(content) == 0:
|
150
|
+
content = ""
|
151
|
+
elif len(content) == 1:
|
152
|
+
content = content[0]
|
153
|
+
|
154
|
+
kwargs = dict(
|
155
|
+
content=content,
|
156
|
+
date_time=replica.date_time,
|
157
|
+
extra=replica.extra,
|
158
|
+
)
|
159
|
+
if not replica.role:
|
160
|
+
return HumanMessage(**kwargs)
|
161
|
+
return AIMessage(
|
162
|
+
**kwargs,
|
163
|
+
state=replica.state,
|
164
|
+
extra=dict(
|
165
|
+
action=replica.action,
|
166
|
+
moderation=replica.moderation,
|
167
|
+
),
|
168
|
+
)
|
169
|
+
|
170
|
+
|
171
|
+
def convert_outer_context_to_context(octx: OuterContextItem) -> Context:
|
172
|
+
# legacy: eliminate
|
173
|
+
context = Context(
|
174
|
+
client_id=octx.client_id,
|
175
|
+
user_id=octx.user_id,
|
176
|
+
session_id=octx.session_id,
|
177
|
+
track_id=octx.track_id,
|
178
|
+
extra=dict(
|
179
|
+
sex=octx.sex,
|
180
|
+
age=octx.age,
|
181
|
+
parent_session_id=octx.parent_session_id,
|
182
|
+
entrypoint_key=octx.entrypoint_key,
|
183
|
+
language_code=octx.language_code,
|
184
|
+
),
|
185
|
+
)
|
186
|
+
return context
|
187
|
+
|
188
|
+
|
189
|
+
def convert_chat_item_to_chat(chat_item: ChatItem) -> Chat:
|
190
|
+
# legacy: eliminate
|
191
|
+
context = convert_outer_context_to_context(chat_item.outer_context)
|
192
|
+
messages = [convert_replica_item_to_message(replica) for replica in chat_item.inner_context.replicas]
|
193
|
+
res = Chat(context=context, messages=messages)
|
194
|
+
return res
|
195
|
+
|
196
|
+
|
197
|
+
def convert_context_to_outer_context(context: Context) -> OuterContextItem:
|
198
|
+
# legacy: eliminate
|
199
|
+
extra = context.extra or {}
|
200
|
+
return OuterContextItem(
|
201
|
+
client_id=context.client_id,
|
202
|
+
user_id=context.user_id,
|
203
|
+
session_id=context.session_id,
|
204
|
+
track_id=context.track_id,
|
205
|
+
sex=extra.get("sex"),
|
206
|
+
age=extra.get("age"),
|
207
|
+
parent_session_id=extra.get("parent_session_id"),
|
208
|
+
entrypoint_key=extra.get("entrypoint_key"),
|
209
|
+
language_code=extra.get("language_code"),
|
210
|
+
)
|
211
|
+
|
212
|
+
|
213
|
+
def convert_message_to_replica_item(message: ChatMessage) -> ReplicaItem | None:
|
214
|
+
# legacy: eliminate
|
215
|
+
m_type = message.type
|
216
|
+
if m_type in {"ai", "human"}:
|
217
|
+
role = m_type == "ai"
|
218
|
+
else:
|
219
|
+
return None
|
220
|
+
|
221
|
+
extra = message.extra or {}
|
222
|
+
action = extra.pop("action")
|
223
|
+
moderation = extra.pop("moderation")
|
224
|
+
|
225
|
+
kwargs = dict(
|
226
|
+
role=role,
|
227
|
+
body=message.body,
|
228
|
+
resource_id=message.resource_id,
|
229
|
+
command=message.command,
|
230
|
+
widget=message.widget,
|
231
|
+
date_time=message.date_time,
|
232
|
+
extra=extra or None,
|
233
|
+
state=getattr(message, "state", ""),
|
234
|
+
action=action,
|
235
|
+
moderation=moderation,
|
236
|
+
)
|
237
|
+
return ReplicaItem(**kwargs)
|
238
|
+
|
239
|
+
|
240
|
+
def convert_chat_to_chat_item(chat: Chat) -> ChatItem:
|
241
|
+
# legacy: eliminate
|
242
|
+
return ChatItem(
|
243
|
+
outer_context=convert_context_to_outer_context(chat.context),
|
244
|
+
inner_context=dict(replicas=list(map(convert_message_to_replica_item, chat.messages))),
|
245
|
+
)
|
246
|
+
|
247
|
+
|
248
|
+
def parse_chat_item_as_chat(chat_obj: str | dict) -> Chat:
|
249
|
+
# legacy: eliminate
|
250
|
+
chat_item = ChatItem.parse(chat_obj)
|
251
|
+
res = convert_chat_item_to_chat(chat_item)
|
252
|
+
return res
|
253
|
+
|
254
|
+
|
255
|
+
def _parse_chat(chat_obj: str | dict) -> Chat:
|
256
|
+
if isinstance(chat_obj, dict):
|
257
|
+
return Chat.model_validate(chat_obj)
|
258
|
+
|
259
|
+
return Chat.model_validate_json(chat_obj)
|
260
|
+
|
261
|
+
|
262
|
+
def _parse_chat_compat(chat_obj: str | dict) -> Chat:
|
263
|
+
# legacy: eliminate
|
264
|
+
try:
|
265
|
+
return _parse_chat(chat_obj)
|
266
|
+
except Exception:
|
267
|
+
return parse_chat_item_as_chat(chat_obj)
|
@@ -1,11 +1,8 @@
|
|
1
|
-
import json
|
2
|
-
import warnings
|
3
1
|
from datetime import datetime
|
4
|
-
from typing import Any, List
|
2
|
+
from typing import Annotated, Any, List
|
5
3
|
|
6
4
|
from agi_med_common.models.widget import Widget
|
7
|
-
from
|
8
|
-
from pydantic import Field, ConfigDict, ValidationError
|
5
|
+
from pydantic import Field, ConfigDict, BeforeValidator
|
9
6
|
|
10
7
|
from ._base import _Base
|
11
8
|
|
@@ -42,6 +39,24 @@ class OuterContextItem(_Base):
|
|
42
39
|
def to_dict(self) -> dict[str, Any]:
|
43
40
|
return self.model_dump(by_alias=True)
|
44
41
|
|
42
|
+
LABELS = {
|
43
|
+
0: "OK",
|
44
|
+
1: "NON_MED",
|
45
|
+
2: "CHILD",
|
46
|
+
3: "ABSURD",
|
47
|
+
4: "GREETING",
|
48
|
+
5: "RECEIPT",
|
49
|
+
}
|
50
|
+
|
51
|
+
|
52
|
+
def fix_deprecated_moderation(moderation):
|
53
|
+
if isinstance(moderation, int):
|
54
|
+
return LABELS.get(moderation, "OK")
|
55
|
+
elif isinstance(moderation, str):
|
56
|
+
return moderation
|
57
|
+
else:
|
58
|
+
raise ValueError(f"Unsupported moderation: {moderation} :: {type(moderation)}")
|
59
|
+
|
45
60
|
|
46
61
|
class ReplicaItem(_Base):
|
47
62
|
body: str = Field("", alias="Body", examples=["Привет"])
|
@@ -55,7 +70,9 @@ class ReplicaItem(_Base):
|
|
55
70
|
state: str = Field("", alias="State", description="chat manager fsm state", examples=["COLLECTION"])
|
56
71
|
action: str = Field("", alias="Action", description="chat manager fsm action", examples=["DIAGNOSIS"])
|
57
72
|
# todo fix: support loading from `moderation: int`
|
58
|
-
moderation: str = Field(
|
73
|
+
moderation: Annotated[str, BeforeValidator(str)] = Field(
|
74
|
+
"OK", alias="Moderation", description="moderation outcome", examples=["OK"]
|
75
|
+
)
|
59
76
|
extra: dict | None = Field(None, alias="Extra", examples=[None])
|
60
77
|
|
61
78
|
def to_dict(self) -> dict[str, Any]:
|
@@ -99,40 +116,11 @@ class ChatItem(_Base):
|
|
99
116
|
|
100
117
|
@classmethod
|
101
118
|
def parse(cls, chat_obj: str | dict) -> "ChatItem":
|
102
|
-
return
|
103
|
-
|
119
|
+
return _parse_chat_item(chat_obj)
|
104
120
|
|
105
|
-
def _is_moderation_int_error(err):
|
106
|
-
# fmt: off
|
107
|
-
if err['type'] != 'string_type': return False
|
108
|
-
if err['loc'][0] != 'InnerContext': return False
|
109
|
-
if err['loc'][1] != 'Replicas': return False
|
110
|
-
if err['loc'][3] != 'Moderation': return False
|
111
|
-
if err['msg'] != 'Input should be a valid string': return False
|
112
|
-
# fmt: on
|
113
|
-
return True
|
114
121
|
|
115
|
-
|
116
|
-
def _is_moderation_int_errors(ex):
|
117
|
-
errs = ex.errors()
|
118
|
-
return all(map(_is_moderation_int_error, errs))
|
119
|
-
|
120
|
-
|
121
|
-
def _parse_chat(chat_obj: str | dict) -> ChatItem:
|
122
|
+
def _parse_chat_item(chat_obj: str | dict) -> ChatItem:
|
122
123
|
if isinstance(chat_obj, dict):
|
123
|
-
return ChatItem(
|
124
|
-
|
125
|
-
|
126
|
-
except ValidationError as ex:
|
127
|
-
if _is_moderation_int_errors(ex):
|
128
|
-
msg = "Failed to parse ChatItem, fallback to old version with `Moderation:int`"
|
129
|
-
else:
|
130
|
-
msg = f"Failed to parse: {ex}"
|
131
|
-
warnings.warn(msg)
|
132
|
-
|
133
|
-
# old version
|
134
|
-
chat_dict = json.loads(chat_obj)
|
135
|
-
for rep in chat_dict["InnerContext"]["Replicas"]:
|
136
|
-
rep["Moderation"] = "OK"
|
137
|
-
|
138
|
-
return ChatItem.model_validate(chat_dict)
|
124
|
+
return ChatItem.model_validate(chat_obj)
|
125
|
+
|
126
|
+
return ChatItem.model_validate_json(chat_obj)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
agi_med_common/__init__.py,sha256=
|
1
|
+
agi_med_common/__init__.py,sha256=cuekTezA2-btHu0RL4MBMrmhiBvYJFPqQCobGaH_4hY,1081
|
2
2
|
agi_med_common/file_storage.py,sha256=T0Hbs4W-pWO6HdWcmlVqABrQHYdq7lLZH4_Vu-YNVbw,1802
|
3
3
|
agi_med_common/parallel_map.py,sha256=Qx6xe7DqlEUDpSucp5Hm8r9y9Iquwh9JvX7lOqHhnOw,921
|
4
4
|
agi_med_common/type_union.py,sha256=diwmzcnbqkpGFckPHNw9o8zyQ955mOGNvhTlcBJ0RMI,1905
|
@@ -9,17 +9,18 @@ agi_med_common/api/chat_manager_api.py,sha256=e-LJSmnWCFW1Wj5R3uavlKaq9p5VBoErqP
|
|
9
9
|
agi_med_common/api/classifier_api.py,sha256=PnB9PXNxgKwgcLSg4RtoLr2nXn378_Q5IdP81aAf-_w,286
|
10
10
|
agi_med_common/api/content_interpreter_api.py,sha256=g5CSJC1wpFRnl2UzunNYrJ9I4qRQFrPuENfbvIb7K1M,430
|
11
11
|
agi_med_common/api/content_interpreter_remote_api.py,sha256=cGaIKZGuosneLXs0jCM8QdqoX9W0kj0EvWLfDGZqjWQ,474
|
12
|
+
agi_med_common/api/critic_api.py,sha256=9s58hzIOLPZb1ea2sKNX8g5n5PwZvx4Xri5V7sOmUvE,192
|
12
13
|
agi_med_common/api/text_generator_api.py,sha256=c-Yy7KcldyyJtJo6cK6K_qDD1cm8yTMWMiUpzn4l1Kc,171
|
13
14
|
agi_med_common/models/__init__.py,sha256=dqr2kP-RuxFfAZhCr103PQzTVZFKIcdxyzTYiHhdTsE,375
|
14
15
|
agi_med_common/models/_base.py,sha256=qNdH8x3x3mYbo5XgWtR9VpEarxsEvXvzynadUlDvHmU,149
|
15
|
-
agi_med_common/models/chat.py,sha256=
|
16
|
-
agi_med_common/models/chat_item.py,sha256=
|
16
|
+
agi_med_common/models/chat.py,sha256=LihfERvN_owk4zsW8eQPKOoXyYCz9lmsD5zw7db6vYk,7583
|
17
|
+
agi_med_common/models/chat_item.py,sha256=aF_sUtucV5hXeQ42Z-Jtsz9G1sWtjSFtElRs6hr0AQQ,4648
|
17
18
|
agi_med_common/models/enums.py,sha256=J-GNpql9MCnKnWiV9aJRQGI-pAybvV86923RZs99grA,1006
|
18
19
|
agi_med_common/models/tracks.py,sha256=UP-jeWqDiCK6dyoMDfs7hemgl_xsJKee_DApjBf-XYc,311
|
19
20
|
agi_med_common/models/widget.py,sha256=aJZ2vWx_PTFN02Wz16eokz9IIVrxqNuZYVDqLG36toE,710
|
20
21
|
agi_med_common/models/base_config_models/__init__.py,sha256=KjS_bSCka8BOMsigwcIML-e6eNB2ouMU6gxlhRmzeuY,44
|
21
22
|
agi_med_common/models/base_config_models/gigachat_config.py,sha256=WNSCTO8Fjpxc1v2LRUHfKqo9aeMDpXltTHYBFgTD2N0,422
|
22
|
-
agi_med_common-5.0.
|
23
|
-
agi_med_common-5.0.
|
24
|
-
agi_med_common-5.0.
|
25
|
-
agi_med_common-5.0.
|
23
|
+
agi_med_common-5.0.18.dist-info/METADATA,sha256=rk_a5rZWAslucJtPdNmM65RwNnH9DBMde0gHTIxsDPI,518
|
24
|
+
agi_med_common-5.0.18.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
25
|
+
agi_med_common-5.0.18.dist-info/top_level.txt,sha256=26o565jF_7wYQj7-YJfTedtT9yDxDcf8RNikOYuPq78,15
|
26
|
+
agi_med_common-5.0.18.dist-info/RECORD,,
|
File without changes
|
File without changes
|