agi-med-common 5.0.24__py3-none-any.whl → 5.0.26__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.
@@ -1,4 +1,4 @@
1
- __version__ = "5.0.24"
1
+ __version__ = "5.0.26"
2
2
 
3
3
  from .models import (
4
4
  MTRSLabelEnum,
@@ -1,7 +1,7 @@
1
1
  import warnings
2
2
  from copy import deepcopy
3
3
  from datetime import datetime
4
- from typing import Any, List, Dict, Literal, TypeVar
4
+ from typing import Any, List, Dict, Literal, TypeVar, Callable
5
5
 
6
6
  from agi_med_common.models.chat_item import ChatItem, ReplicaItem, OuterContextItem
7
7
  from agi_med_common.models.widget import Widget
@@ -17,7 +17,7 @@ _EXAMPLE_DT: str = datetime(year=1970, month=1, day=1).strftime(_DT_FORMAT)
17
17
  StrDict = Dict[str, Any]
18
18
  ContentBase = str | Widget | StrDict
19
19
  Content = ContentBase | List[ContentBase]
20
- T = TypeVar('T')
20
+ T = TypeVar("T")
21
21
 
22
22
 
23
23
  def now_pretty() -> str:
@@ -76,6 +76,18 @@ def _get_text(obj: Content) -> str:
76
76
  return ""
77
77
 
78
78
 
79
+ def _modify_text(obj: Content, callback: Callable[[str], str | None]) -> str:
80
+ if isinstance(obj, str):
81
+ return callback(obj)
82
+ if isinstance(obj, list):
83
+ return [_modify_text(el, callback) for el in obj]
84
+ if isinstance(obj, dict) and obj.get("type") == "text":
85
+ text = _get_field(obj, "text", str) or ""
86
+ text_upd = callback(text)
87
+ return {"type": "text", "text": text_upd}
88
+ return obj
89
+
90
+
79
91
  def _get_resource_id(obj: Content) -> str | None:
80
92
  if isinstance(obj, list):
81
93
  return first_nonnull(map(_get_resource_id, obj))
@@ -113,6 +125,10 @@ class BaseMessage(_Base):
113
125
  def text(self) -> str:
114
126
  return _get_text(self.content)
115
127
 
128
+ def modify_text(self, callback: Callable[[str], str]) -> "BaseMessage":
129
+ content_upd = _modify_text(self.content, callback)
130
+ return self.model_copy(update=dict(content=content_upd))
131
+
116
132
  @property
117
133
  def body(self) -> str:
118
134
  # legacy: eliminate after migration
@@ -137,6 +153,14 @@ class BaseMessage(_Base):
137
153
  def with_now_datetime(self):
138
154
  return self.model_copy(update=dict(date_time=now_pretty()))
139
155
 
156
+ @property
157
+ def is_ai(self):
158
+ return self.type == "ai"
159
+
160
+ @property
161
+ def is_human(self):
162
+ return self.type == "human"
163
+
140
164
 
141
165
  class HumanMessage(BaseMessage):
142
166
  type: Literal["human"] = "human"
@@ -146,6 +170,10 @@ class AIMessage(BaseMessage):
146
170
  type: Literal["ai"] = "ai"
147
171
  state: str = Field("", examples=["COLLECTION"])
148
172
 
173
+ @property
174
+ def action(self) -> str:
175
+ return self.extra.get("action", "")
176
+
149
177
 
150
178
  class MiscMessage(BaseMessage):
151
179
  type: Literal["misc"] = "misc"
@@ -168,6 +196,22 @@ class Chat(_Base):
168
196
  def to_chat_item(self) -> ChatItem:
169
197
  return convert_chat_to_chat_item(self)
170
198
 
199
+ def add_message(self, message: ChatMessage):
200
+ self.messages.append(message)
201
+
202
+ def add_messages(self, messages: List[ChatMessage]):
203
+ for message in messages:
204
+ self.messages.append(message)
205
+
206
+ def replace_messages(self, messages: List[ChatMessage]):
207
+ return self.model_copy(update=dict(messages=messages))
208
+
209
+ def get_last_state(self, default: str = "empty") -> str:
210
+ for msg in range(self.messages - 1, -1, -1):
211
+ if isinstance(msg, AIMessage):
212
+ return msg.state
213
+ return default
214
+
171
215
 
172
216
  def convert_replica_item_to_message(replica: ReplicaItem) -> ChatMessage:
173
217
  # legacy: eliminate after migration
@@ -1,5 +1,5 @@
1
1
  from datetime import datetime
2
- from typing import Annotated, Any, List
2
+ from typing import Annotated, Any, List, Callable
3
3
 
4
4
  from agi_med_common.models.widget import Widget
5
5
  from pydantic import Field, ConfigDict, BeforeValidator, AfterValidator
@@ -92,6 +92,18 @@ class ReplicaItem(_Base):
92
92
  def with_now_datetime(self):
93
93
  return self.model_copy(update=dict(date_time=now_pretty()))
94
94
 
95
+ @property
96
+ def is_ai(self):
97
+ return self.role
98
+
99
+ @property
100
+ def is_human(self):
101
+ return not self.role
102
+
103
+ def modify_text(self, callback: Callable[[str], str]) -> "ReplicaItem":
104
+ body_upd = callback(self.body)
105
+ return self.model_copy(update=dict(body=body_upd))
106
+
95
107
 
96
108
  class InnerContextItem(_Base):
97
109
  replicas: list[ReplicaItem] = Field(alias="Replicas")
@@ -118,6 +130,9 @@ class ChatItem(_Base):
118
130
  for replica in replicas:
119
131
  self.inner_context.replicas.append(replica)
120
132
 
133
+ def replace_replicas(self, replicas: List[ReplicaItem]):
134
+ return self.model_copy(update=dict(inner_context=InnerContextItem(replicas=replicas)))
135
+
121
136
  def zip_history(self, field: str) -> list[Any]:
122
137
  return [replica.to_dict().get(field, None) for replica in self.inner_context.replicas]
123
138
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agi_med_common
3
- Version: 5.0.24
3
+ Version: 5.0.26
4
4
  Summary: Сommon for agi-med team
5
5
  Author: AGI-MED-TEAM
6
6
  Requires-Python: >=3.11
@@ -1,4 +1,4 @@
1
- agi_med_common/__init__.py,sha256=MKI-hB8aFY-Yktyicq9m-8w-pX37IyFztVaKV5Q3Ipk,740
1
+ agi_med_common/__init__.py,sha256=3iqTNDjcukCgm6cnLY8vQaom03mBn2KH-MPxaVOM4y0,740
2
2
  agi_med_common/api.py,sha256=kGLKiebbF91s_7V2S55ETS7R6tQgZNkoFMoawdjeMYw,1860
3
3
  agi_med_common/api_v2.py,sha256=gj6BPEAOvpT6GHWeE7bzmKIR-pvq0yORZ3L0ADvI8ps,1828
4
4
  agi_med_common/file_storage.py,sha256=T0Hbs4W-pWO6HdWcmlVqABrQHYdq7lLZH4_Vu-YNVbw,1802
@@ -9,14 +9,14 @@ agi_med_common/validators.py,sha256=vMoPN42XzC8re-zdjekk5_lNQYHuTiAWD56YLvj2Z2w,
9
9
  agi_med_common/xml_parser.py,sha256=VvLIX_XCZao9i0qqpTVx8nx0vbFXSe8pEbdJdXnj97g,568
10
10
  agi_med_common/models/__init__.py,sha256=dqr2kP-RuxFfAZhCr103PQzTVZFKIcdxyzTYiHhdTsE,375
11
11
  agi_med_common/models/_base.py,sha256=qNdH8x3x3mYbo5XgWtR9VpEarxsEvXvzynadUlDvHmU,149
12
- agi_med_common/models/chat.py,sha256=0VXu-SUPlOeGRO8SMCFPfGoAiVoPIm_v3hKMG-nGhNI,9230
13
- agi_med_common/models/chat_item.py,sha256=bg_l6B4RAqiSO84vF50nQN7kYCkLB6JHAzItwm1-RzM,4791
12
+ agi_med_common/models/chat.py,sha256=1GVcwOM97UMrsiPg3fAd9xJe2p9cHouidWgIPMWUxc0,10668
13
+ agi_med_common/models/chat_item.py,sha256=eTUBCLlTVPqIS64qnaPB92vCJyiBixIPi8ochrgOPHo,5262
14
14
  agi_med_common/models/enums.py,sha256=J-GNpql9MCnKnWiV9aJRQGI-pAybvV86923RZs99grA,1006
15
15
  agi_med_common/models/tracks.py,sha256=UP-jeWqDiCK6dyoMDfs7hemgl_xsJKee_DApjBf-XYc,311
16
16
  agi_med_common/models/widget.py,sha256=aJZ2vWx_PTFN02Wz16eokz9IIVrxqNuZYVDqLG36toE,710
17
17
  agi_med_common/models/base_config_models/__init__.py,sha256=KjS_bSCka8BOMsigwcIML-e6eNB2ouMU6gxlhRmzeuY,44
18
18
  agi_med_common/models/base_config_models/gigachat_config.py,sha256=WNSCTO8Fjpxc1v2LRUHfKqo9aeMDpXltTHYBFgTD2N0,422
19
- agi_med_common-5.0.24.dist-info/METADATA,sha256=2stOgKcSCPgY9VKJ4XJLKmAFnsyCXchTasY9WTaGgks,518
20
- agi_med_common-5.0.24.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
21
- agi_med_common-5.0.24.dist-info/top_level.txt,sha256=26o565jF_7wYQj7-YJfTedtT9yDxDcf8RNikOYuPq78,15
22
- agi_med_common-5.0.24.dist-info/RECORD,,
19
+ agi_med_common-5.0.26.dist-info/METADATA,sha256=wlJpGlj3NNyi2UvSjBx9z8474Nysj20mMfbOmVyhNO0,518
20
+ agi_med_common-5.0.26.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
21
+ agi_med_common-5.0.26.dist-info/top_level.txt,sha256=26o565jF_7wYQj7-YJfTedtT9yDxDcf8RNikOYuPq78,15
22
+ agi_med_common-5.0.26.dist-info/RECORD,,