mmar-mapi 1.0.26__py3-none-any.whl → 1.1.0__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.
Potentially problematic release.
This version of mmar-mapi might be problematic. Click here for more details.
- mmar_mapi/__init__.py +0 -5
- mmar_mapi/models/chat.py +16 -176
- {mmar_mapi-1.0.26.dist-info → mmar_mapi-1.1.0.dist-info}/METADATA +1 -1
- {mmar_mapi-1.0.26.dist-info → mmar_mapi-1.1.0.dist-info}/RECORD +6 -7
- mmar_mapi/models/chat_item.py +0 -160
- {mmar_mapi-1.0.26.dist-info → mmar_mapi-1.1.0.dist-info}/WHEEL +0 -0
- {mmar_mapi-1.0.26.dist-info → mmar_mapi-1.1.0.dist-info}/licenses/LICENSE +0 -0
mmar_mapi/__init__.py
CHANGED
|
@@ -11,7 +11,6 @@ from .models.chat import (
|
|
|
11
11
|
Content,
|
|
12
12
|
BaseMessage,
|
|
13
13
|
)
|
|
14
|
-
from .models.chat_item import ChatItem, OuterContextItem, InnerContextItem, ReplicaItem
|
|
15
14
|
from .models.enums import MTRSLabelEnum, DiagnosticsXMLTagEnum, MTRSXMLTagEnum, DoctorChoiceXMLTagEnum
|
|
16
15
|
from .models.tracks import TrackInfo, DomainInfo
|
|
17
16
|
from .models.widget import Widget
|
|
@@ -25,7 +24,6 @@ __all__ = [
|
|
|
25
24
|
"Base",
|
|
26
25
|
"BaseMessage",
|
|
27
26
|
"Chat",
|
|
28
|
-
"ChatItem",
|
|
29
27
|
"ChatMessage",
|
|
30
28
|
"Content",
|
|
31
29
|
"Context",
|
|
@@ -34,12 +32,9 @@ __all__ = [
|
|
|
34
32
|
"DomainInfo",
|
|
35
33
|
"FileStorage",
|
|
36
34
|
"HumanMessage",
|
|
37
|
-
"InnerContextItem",
|
|
38
35
|
"MTRSLabelEnum",
|
|
39
36
|
"MTRSXMLTagEnum",
|
|
40
37
|
"MiscMessage",
|
|
41
|
-
"OuterContextItem",
|
|
42
|
-
"ReplicaItem",
|
|
43
38
|
"ResourceId",
|
|
44
39
|
"TrackInfo",
|
|
45
40
|
"Widget",
|
mmar_mapi/models/chat.py
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import warnings
|
|
2
2
|
from collections.abc import Callable
|
|
3
|
-
from copy import deepcopy
|
|
4
3
|
from datetime import datetime
|
|
5
4
|
from typing import Any, Literal, NotRequired, TypedDict, TypeVar
|
|
6
5
|
|
|
7
|
-
from pydantic import Field
|
|
6
|
+
from pydantic import Field
|
|
8
7
|
|
|
9
|
-
from mmar_mapi.models.chat_item import ChatItem, OuterContextItem, ReplicaItem
|
|
10
8
|
from mmar_mapi.models.widget import Widget
|
|
11
9
|
from mmar_mapi.type_union import TypeUnion
|
|
12
10
|
|
|
@@ -51,10 +49,12 @@ class Context(Base):
|
|
|
51
49
|
|
|
52
50
|
def create_id(self, short: bool = False) -> str:
|
|
53
51
|
uid, sid, cid = self.user_id, self.session_id, self.client_id
|
|
54
|
-
if short:
|
|
55
|
-
return f"{cid}_{uid}_{sid}"
|
|
56
52
|
return f"client_{cid}_user_{uid}_session_{sid}"
|
|
57
53
|
|
|
54
|
+
def create_trace_id(self) -> str:
|
|
55
|
+
uid, sid, cid = self.user_id, self.session_id, self.client_id
|
|
56
|
+
return f"{cid}_{uid}_{sid}"
|
|
57
|
+
|
|
58
58
|
def _get_deprecated_extra(self, field, default):
|
|
59
59
|
# legacy: eliminate after migration
|
|
60
60
|
res = (self.extra or {}).get(field, default)
|
|
@@ -259,11 +259,8 @@ class Chat(Base):
|
|
|
259
259
|
return self.context.create_id(short)
|
|
260
260
|
|
|
261
261
|
@staticmethod
|
|
262
|
-
def parse(chat_obj: str | dict
|
|
263
|
-
return
|
|
264
|
-
|
|
265
|
-
def to_chat_item(self, failsafe: bool = False) -> ChatItem:
|
|
266
|
-
return convert_chat_to_chat_item(self, failsafe)
|
|
262
|
+
def parse(chat_obj: str | dict) -> "Chat":
|
|
263
|
+
return _parse_chat(chat_obj)
|
|
267
264
|
|
|
268
265
|
def add_message(self, message: ChatMessage):
|
|
269
266
|
self.messages.append(message)
|
|
@@ -295,7 +292,10 @@ class Chat(Base):
|
|
|
295
292
|
message = messages[-1]
|
|
296
293
|
return message if isinstance(message, HumanMessage) else None
|
|
297
294
|
|
|
298
|
-
def count_messages(self, func: Callable[[ChatMessage], bool]) -> int:
|
|
295
|
+
def count_messages(self, func: Callable[[ChatMessage], bool] | type) -> int:
|
|
296
|
+
if isinstance(func, type):
|
|
297
|
+
msg_type = func
|
|
298
|
+
func = lambda msg: isinstance(msg, msg_type)
|
|
299
299
|
return sum(map(func, self.messages))
|
|
300
300
|
|
|
301
301
|
|
|
@@ -337,171 +337,11 @@ def make_content(
|
|
|
337
337
|
return content
|
|
338
338
|
|
|
339
339
|
|
|
340
|
-
def
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
text=replica.body,
|
|
344
|
-
resource_id=replica.resource_id,
|
|
345
|
-
command=replica.command,
|
|
346
|
-
widget=replica.widget,
|
|
347
|
-
)
|
|
348
|
-
# legacy: eliminate after migration
|
|
349
|
-
if resource_id := replica.resource_id:
|
|
350
|
-
resource = {"type": "resource_id", "resource_id": resource_id}
|
|
351
|
-
resource_name = replica.resource_name
|
|
352
|
-
if resource_name:
|
|
353
|
-
resource["resource_name"] = resource_name
|
|
354
|
-
else:
|
|
355
|
-
resource = None
|
|
356
|
-
body = replica.body
|
|
357
|
-
command = (replica.command or None) and {"type": "command", "command": replica.command}
|
|
358
|
-
widget = replica.widget
|
|
359
|
-
date_time = replica.date_time
|
|
360
|
-
|
|
361
|
-
content = list(filter(None, [body, resource, command, widget]))
|
|
362
|
-
if len(content) == 0:
|
|
363
|
-
content = ""
|
|
364
|
-
elif len(content) == 1:
|
|
365
|
-
content = content[0]
|
|
366
|
-
|
|
367
|
-
is_bot_message = replica.role
|
|
368
|
-
|
|
369
|
-
if is_bot_message:
|
|
370
|
-
kwargs = dict(
|
|
371
|
-
content=content,
|
|
372
|
-
date_time=date_time,
|
|
373
|
-
state=replica.state,
|
|
374
|
-
extra=dict(
|
|
375
|
-
**(replica.extra or {}),
|
|
376
|
-
action=replica.action,
|
|
377
|
-
moderation=replica.moderation,
|
|
378
|
-
),
|
|
379
|
-
)
|
|
380
|
-
res = AIMessage(**kwargs)
|
|
381
|
-
else:
|
|
382
|
-
kwargs = dict(content=content, date_time=date_time)
|
|
383
|
-
res = HumanMessage(**kwargs)
|
|
384
|
-
return res
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
def convert_outer_context_to_context(octx: OuterContextItem) -> Context:
|
|
388
|
-
# legacy: eliminate after migration
|
|
389
|
-
context = Context(
|
|
390
|
-
client_id=octx.client_id,
|
|
391
|
-
user_id=octx.user_id,
|
|
392
|
-
session_id=octx.session_id,
|
|
393
|
-
track_id=octx.track_id,
|
|
394
|
-
extra=dict(
|
|
395
|
-
sex=octx.sex,
|
|
396
|
-
age=octx.age,
|
|
397
|
-
parent_session_id=octx.parent_session_id,
|
|
398
|
-
entrypoint_key=octx.entrypoint_key,
|
|
399
|
-
language_code=octx.language_code,
|
|
400
|
-
),
|
|
401
|
-
)
|
|
402
|
-
return context
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
def convert_chat_item_to_chat(chat_item: ChatItem) -> Chat:
|
|
406
|
-
# legacy: eliminate after migration
|
|
407
|
-
context = convert_outer_context_to_context(chat_item.outer_context)
|
|
408
|
-
messages = list(map(convert_replica_item_to_message, chat_item.inner_context.replicas))
|
|
409
|
-
res = Chat(context=context, messages=messages)
|
|
410
|
-
return res
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
def convert_context_to_outer_context(context: Context, failsafe: bool = False) -> OuterContextItem:
|
|
414
|
-
# legacy: eliminate after migration
|
|
415
|
-
extra = context.extra or {}
|
|
416
|
-
if failsafe:
|
|
417
|
-
extra["sex"] = extra.get("sex") or True
|
|
418
|
-
extra["age"] = extra.get("age") or 42
|
|
419
|
-
extra["language_code"] = extra.get("language_code") or ""
|
|
420
|
-
extra["entrypoint_key"] = extra.get("entrypoint_key") or ""
|
|
421
|
-
return OuterContextItem(
|
|
422
|
-
client_id=context.client_id,
|
|
423
|
-
user_id=context.user_id,
|
|
424
|
-
session_id=context.session_id,
|
|
425
|
-
track_id=context.track_id,
|
|
426
|
-
sex=extra["sex"],
|
|
427
|
-
age=extra["age"],
|
|
428
|
-
entrypoint_key=extra["entrypoint_key"],
|
|
429
|
-
language_code=extra["language_code"],
|
|
430
|
-
parent_session_id=extra.get("parent_session_id"),
|
|
431
|
-
)
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
def convert_message_to_replica_item(message: ChatMessage) -> ReplicaItem | None:
|
|
435
|
-
# legacy: eliminate after migration
|
|
436
|
-
m_type = message.type
|
|
437
|
-
if m_type in {"ai", "human"}:
|
|
438
|
-
role = m_type == "ai"
|
|
439
|
-
else:
|
|
440
|
-
return None
|
|
441
|
-
|
|
442
|
-
extra = deepcopy(message.extra) if message.extra else {}
|
|
443
|
-
action = extra.pop("action", "")
|
|
444
|
-
moderation = extra.pop("moderation", "OK")
|
|
445
|
-
|
|
446
|
-
kwargs = dict(
|
|
447
|
-
role=role,
|
|
448
|
-
body=message.text,
|
|
449
|
-
resource_id=message.resource_id,
|
|
450
|
-
resource_name=message.resource_name,
|
|
451
|
-
command=message.command,
|
|
452
|
-
widget=message.widget,
|
|
453
|
-
date_time=message.date_time,
|
|
454
|
-
extra=extra or None,
|
|
455
|
-
state=getattr(message, "state", ""),
|
|
456
|
-
action=action,
|
|
457
|
-
moderation=moderation,
|
|
458
|
-
)
|
|
459
|
-
return ReplicaItem(**kwargs)
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
def convert_chat_to_chat_item(chat: Chat, failsafe: bool = False) -> ChatItem:
|
|
463
|
-
# legacy: eliminate after migration
|
|
464
|
-
res = ChatItem(
|
|
465
|
-
outer_context=convert_context_to_outer_context(chat.context, failsafe=failsafe),
|
|
466
|
-
inner_context=dict(replicas=list(map(convert_message_to_replica_item, chat.messages))),
|
|
467
|
-
)
|
|
468
|
-
return res
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
def parse_chat_item_as_chat(chat_obj: str | dict | ChatItem) -> Chat:
|
|
472
|
-
# legacy: eliminate after migration
|
|
473
|
-
if isinstance(chat_obj, ChatItem):
|
|
474
|
-
chat_item = chat_obj
|
|
475
|
-
else:
|
|
476
|
-
chat_item = ChatItem.parse(chat_obj)
|
|
477
|
-
res = convert_chat_item_to_chat(chat_item)
|
|
478
|
-
return res
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
def _parse_chat(chat_obj: str | dict) -> Chat:
|
|
340
|
+
def _parse_chat(chat_obj: str | dict | Chat) -> Chat:
|
|
341
|
+
if isinstance(chat_obj, Chat):
|
|
342
|
+
return chat_obj
|
|
482
343
|
if isinstance(chat_obj, dict):
|
|
483
344
|
return Chat.model_validate(chat_obj)
|
|
484
|
-
|
|
485
|
-
return Chat.model_validate_json(chat_obj)
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
def is_chat_item(chat_obj: str | dict | ChatItem) -> bool:
|
|
489
|
-
if isinstance(chat_obj, ChatItem):
|
|
490
|
-
return True
|
|
491
|
-
if isinstance(chat_obj, dict):
|
|
492
|
-
return "OuterContext" in chat_obj
|
|
493
345
|
if isinstance(chat_obj, str):
|
|
494
|
-
return
|
|
495
|
-
|
|
496
|
-
return False
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
def _parse_chat_compat(chat_obj: str | dict | ChatItem) -> Chat:
|
|
500
|
-
# legacy: eliminate after migration
|
|
501
|
-
if is_chat_item(chat_obj):
|
|
502
|
-
return parse_chat_item_as_chat(chat_obj)
|
|
503
|
-
try:
|
|
504
|
-
return _parse_chat(chat_obj)
|
|
505
|
-
except ValidationError as ex:
|
|
506
|
-
warnings.warn(f"Failed to parse chat: {ex}")
|
|
507
|
-
return parse_chat_item_as_chat(chat_obj)
|
|
346
|
+
return Chat.model_validate_json(chat_obj)
|
|
347
|
+
raise ValueError(f"Bad chat_obj {type(chat_obj)}: {chat_obj}")
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
mmar_mapi/__init__.py,sha256=
|
|
1
|
+
mmar_mapi/__init__.py,sha256=Wq3MAvrtONYfUY63ShtqzbO-05uhxPzKU5I6p27aZc0,1085
|
|
2
2
|
mmar_mapi/api.py,sha256=VGoZ2nYIvm35U4FO4yhFG9nYSaK-gjOUC3pNyfBrq3o,6109
|
|
3
3
|
mmar_mapi/decorators_maybe_lru_cache.py,sha256=eO2I6t1fHLUNRABClK1c8EZzHAmCeSK6O-hbJGb2c9E,444
|
|
4
4
|
mmar_mapi/file_storage.py,sha256=km4xA0h-GU07kBc6v3cG2fd9gDF75OfwBJiy0WOmtn4,5067
|
|
5
5
|
mmar_mapi/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
mmar_mapi/models/base.py,sha256=mKtXV2x51XVj7W-et9tjGcPMDUUUMelW-BywMgFc2p0,411
|
|
7
|
-
mmar_mapi/models/chat.py,sha256=
|
|
8
|
-
mmar_mapi/models/chat_item.py,sha256=TRuV5qn7pi3eOvSG7GUqtTHEaq4b7fPoCCZtW-TyEIU,5702
|
|
7
|
+
mmar_mapi/models/chat.py,sha256=hViSGiRCozpT8Ze_ZBa7kObsTPOttz6TKFKRk47wZQw,10893
|
|
9
8
|
mmar_mapi/models/enums.py,sha256=J-GNpql9MCnKnWiV9aJRQGI-pAybvV86923RZs99grA,1006
|
|
10
9
|
mmar_mapi/models/tracks.py,sha256=HKDp-BX1p7AlDfSEKfOKCu0TRSK9cD4Dmq1vJt8oRjw,307
|
|
11
10
|
mmar_mapi/models/widget.py,sha256=ue5o4AkN8SG09aA8eQLOOxbwah-mkZir0ZGL6OA8S9Q,1355
|
|
@@ -13,7 +12,7 @@ mmar_mapi/type_union.py,sha256=diwmzcnbqkpGFckPHNw9o8zyQ955mOGNvhTlcBJ0RMI,1905
|
|
|
13
12
|
mmar_mapi/utils.py,sha256=FlW9n-84xz2zSHsahHzJ3Y4Wu5mjpFer6t9z6PF6lS0,488
|
|
14
13
|
mmar_mapi/utils_import.py,sha256=pUyMFd8SItTxBKI-GO9JhRmy43jG_OQlUPr8QCBOSwg,1682
|
|
15
14
|
mmar_mapi/xml_parser.py,sha256=VvLIX_XCZao9i0qqpTVx8nx0vbFXSe8pEbdJdXnj97g,568
|
|
16
|
-
mmar_mapi-1.0.
|
|
17
|
-
mmar_mapi-1.0.
|
|
18
|
-
mmar_mapi-1.0.
|
|
19
|
-
mmar_mapi-1.0.
|
|
15
|
+
mmar_mapi-1.1.0.dist-info/licenses/LICENSE,sha256=2A90w8WjhOgQXnFuUijKJYazaqZ4_NTokYb9Po4y-9k,1061
|
|
16
|
+
mmar_mapi-1.1.0.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
|
|
17
|
+
mmar_mapi-1.1.0.dist-info/METADATA,sha256=dJuZVT4KmFH2gUDL7xtFtnq083Xk_tqKVPGXCOJecsI,943
|
|
18
|
+
mmar_mapi-1.1.0.dist-info/RECORD,,
|
mmar_mapi/models/chat_item.py
DELETED
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
from datetime import datetime
|
|
2
|
-
from typing import Annotated, Any
|
|
3
|
-
from collections.abc import Callable
|
|
4
|
-
|
|
5
|
-
from mmar_mapi.models.widget import Widget
|
|
6
|
-
from pydantic import Field, ConfigDict, BeforeValidator, AfterValidator
|
|
7
|
-
|
|
8
|
-
from .base import Base
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
_DT_FORMAT: str = "%Y-%m-%d-%H-%M-%S"
|
|
12
|
-
_EXAMPLE_DT_0 = datetime(1970, 1, 1, 0, 0, 0)
|
|
13
|
-
_EXAMPLE_DT: str = _EXAMPLE_DT_0.strftime(_DT_FORMAT)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def now_pretty() -> str:
|
|
17
|
-
return datetime.now().strftime(ReplicaItem.DATETIME_FORMAT())
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class OuterContextItem(Base):
|
|
21
|
-
# remove annoying warning for protected `model_` namespace
|
|
22
|
-
model_config = ConfigDict(protected_namespaces=())
|
|
23
|
-
|
|
24
|
-
sex: bool = Field(False, alias="Sex", description="True = male, False = female", examples=[True])
|
|
25
|
-
age: int = Field(0, alias="Age", examples=[20])
|
|
26
|
-
user_id: str = Field("", alias="UserId", examples=["123456789"])
|
|
27
|
-
parent_session_id: str | None = Field(None, alias="ParentSessionId", examples=["987654320"])
|
|
28
|
-
session_id: str = Field("", alias="SessionId", examples=["987654321"])
|
|
29
|
-
client_id: str = Field("", alias="ClientId", examples=["543216789"])
|
|
30
|
-
track_id: str = Field(default="Consultation", alias="TrackId")
|
|
31
|
-
entrypoint_key: str = Field("", alias="EntrypointKey", examples=["giga"])
|
|
32
|
-
language_code: str = Field("ru", alias="LanguageCode", examples=["ru"])
|
|
33
|
-
|
|
34
|
-
def create_id(self, short: bool = False) -> str:
|
|
35
|
-
uid, sid, cid = self.user_id, self.session_id, self.client_id
|
|
36
|
-
if short:
|
|
37
|
-
return f"{uid}_{sid}_{cid}"
|
|
38
|
-
return f"user_{uid}_session_{sid}_client_{cid}"
|
|
39
|
-
|
|
40
|
-
def to_dict(self) -> dict[str, Any]:
|
|
41
|
-
return self.model_dump(by_alias=True)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
LABELS = {
|
|
45
|
-
0: "OK",
|
|
46
|
-
1: "NON_MED",
|
|
47
|
-
2: "CHILD",
|
|
48
|
-
3: "ABSURD",
|
|
49
|
-
4: "GREETING",
|
|
50
|
-
5: "RECEIPT",
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def fix_deprecated_moderation(moderation):
|
|
55
|
-
if isinstance(moderation, int):
|
|
56
|
-
return LABELS.get(moderation, "OK")
|
|
57
|
-
elif isinstance(moderation, str):
|
|
58
|
-
return moderation
|
|
59
|
-
else:
|
|
60
|
-
raise ValueError(f"Unsupported moderation: {moderation} :: {type(moderation)}")
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def nullify_empty(text: str) -> str | None:
|
|
64
|
-
return text or None
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
class ReplicaItem(Base):
|
|
68
|
-
body: str = Field("", alias="Body", examples=["Привет"])
|
|
69
|
-
resource_id: Annotated[str | None, AfterValidator(nullify_empty)] = Field(
|
|
70
|
-
None, alias="ResourceId", examples=["<link-id>"]
|
|
71
|
-
)
|
|
72
|
-
resource_name: Annotated[str | None, AfterValidator(nullify_empty)] = Field(
|
|
73
|
-
None, alias="ResourceName", examples=["filename"]
|
|
74
|
-
)
|
|
75
|
-
widget: Widget | None = Field(None, alias="Widget", examples=[None])
|
|
76
|
-
command: dict | None = Field(None, alias="Command", examples=[None])
|
|
77
|
-
role: bool = Field(False, alias="Role", description="True = ai, False = client", examples=[False])
|
|
78
|
-
date_time: str = Field(
|
|
79
|
-
default_factory=now_pretty, alias="DateTime", examples=[_EXAMPLE_DT], description=f"Format: {_DT_FORMAT}"
|
|
80
|
-
)
|
|
81
|
-
state: str = Field("", alias="State", description="chat manager fsm state", examples=["COLLECTION"])
|
|
82
|
-
action: str = Field("", alias="Action", description="chat manager fsm action", examples=["DIAGNOSIS"])
|
|
83
|
-
# todo fix: support loading from `moderation: int`
|
|
84
|
-
moderation: Annotated[str, BeforeValidator(str)] = Field(
|
|
85
|
-
"OK", alias="Moderation", description="moderation outcome", examples=["OK"]
|
|
86
|
-
)
|
|
87
|
-
extra: dict | None = Field(None, alias="Extra", examples=[None])
|
|
88
|
-
|
|
89
|
-
def to_dict(self) -> dict[str, Any]:
|
|
90
|
-
return self.model_dump(by_alias=True)
|
|
91
|
-
|
|
92
|
-
@staticmethod
|
|
93
|
-
def DATETIME_FORMAT() -> str:
|
|
94
|
-
return _DT_FORMAT
|
|
95
|
-
|
|
96
|
-
def with_now_datetime(self):
|
|
97
|
-
return self.model_copy(update=dict(date_time=now_pretty()))
|
|
98
|
-
|
|
99
|
-
@property
|
|
100
|
-
def is_ai(self):
|
|
101
|
-
return self.role
|
|
102
|
-
|
|
103
|
-
@property
|
|
104
|
-
def is_human(self):
|
|
105
|
-
return not self.role
|
|
106
|
-
|
|
107
|
-
def modify_text(self, callback: Callable[[str], str]) -> "ReplicaItem":
|
|
108
|
-
body_upd = callback(self.body)
|
|
109
|
-
return self.model_copy(update=dict(body=body_upd))
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
class InnerContextItem(Base):
|
|
113
|
-
replicas: list[ReplicaItem] = Field(alias="Replicas")
|
|
114
|
-
attrs: dict[str, str | int] | None = Field(default={}, alias="Attrs")
|
|
115
|
-
|
|
116
|
-
def to_dict(self) -> dict[str, list]:
|
|
117
|
-
return self.model_dump(by_alias=True)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
class ChatItem(Base):
|
|
121
|
-
outer_context: OuterContextItem = Field(alias="OuterContext")
|
|
122
|
-
inner_context: InnerContextItem = Field(alias="InnerContext")
|
|
123
|
-
|
|
124
|
-
def create_id(self, short: bool = False) -> str:
|
|
125
|
-
return self.outer_context.create_id(short)
|
|
126
|
-
|
|
127
|
-
def to_dict(self) -> dict[str, Any]:
|
|
128
|
-
return self.model_dump(by_alias=True)
|
|
129
|
-
|
|
130
|
-
def add_replica(self, replica: ReplicaItem):
|
|
131
|
-
self.inner_context.replicas.append(replica)
|
|
132
|
-
|
|
133
|
-
def add_replicas(self, replicas: list[ReplicaItem]):
|
|
134
|
-
for replica in replicas:
|
|
135
|
-
self.inner_context.replicas.append(replica)
|
|
136
|
-
|
|
137
|
-
def replace_replicas(self, replicas: list[ReplicaItem]):
|
|
138
|
-
return self.model_copy(update=dict(inner_context=InnerContextItem(replicas=replicas)))
|
|
139
|
-
|
|
140
|
-
def get_last_state(self, default: str = "empty") -> str:
|
|
141
|
-
replicas = self.inner_context.replicas
|
|
142
|
-
for ii in range(len(replicas) - 1, -1, -1):
|
|
143
|
-
replica = replicas[ii]
|
|
144
|
-
if replica.role:
|
|
145
|
-
return replica.state
|
|
146
|
-
return default
|
|
147
|
-
|
|
148
|
-
def zip_history(self, field: str) -> list[Any]:
|
|
149
|
-
return [replica.to_dict().get(field, None) for replica in self.inner_context.replicas]
|
|
150
|
-
|
|
151
|
-
@classmethod
|
|
152
|
-
def parse(cls, chat_obj: str | dict) -> "ChatItem":
|
|
153
|
-
return _parse_chat_item(chat_obj)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
def _parse_chat_item(chat_obj: str | dict) -> ChatItem:
|
|
157
|
-
if isinstance(chat_obj, dict):
|
|
158
|
-
return ChatItem.model_validate(chat_obj)
|
|
159
|
-
|
|
160
|
-
return ChatItem.model_validate_json(chat_obj)
|
|
File without changes
|
|
File without changes
|