lionagi 0.15.9__py3-none-any.whl → 0.15.13__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.
@@ -4,10 +4,10 @@
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
- import json
8
7
  from typing import Any
9
8
 
10
- from pydantic import field_validator
9
+ import orjson
10
+ from pydantic import BaseModel, field_serializer, field_validator
11
11
  from pydapter import Adaptable, AsyncAdaptable
12
12
 
13
13
  from lionagi._class_registry import LION_CLASS_REGISTRY
@@ -44,7 +44,7 @@ class Node(Element, Relational, AsyncAdaptable, Adaptable):
44
44
  return None
45
45
  if isinstance(value, str):
46
46
  try:
47
- loaded = json.loads(value)
47
+ loaded = orjson.loads(value)
48
48
  if not isinstance(loaded, list):
49
49
  raise ValueError
50
50
  return [float(x) for x in loaded]
@@ -63,6 +63,7 @@ class Node(Element, Relational, AsyncAdaptable, Adaptable):
63
63
  self, obj_key: str, many=False, **kwargs: Any
64
64
  ) -> Any:
65
65
  kwargs["adapt_meth"] = "to_dict"
66
+ kwargs["mode"] = "db"
66
67
  return await super().adapt_to_async(
67
68
  obj_key=obj_key, many=many, **kwargs
68
69
  )
@@ -76,6 +77,7 @@ class Node(Element, Relational, AsyncAdaptable, Adaptable):
76
77
  **kwargs: Any,
77
78
  ) -> Node:
78
79
  kwargs["adapt_meth"] = "from_dict"
80
+ kwargs["mode"] = "db"
79
81
  return await super().adapt_from_async(
80
82
  obj, obj_key=obj_key, many=many, **kwargs
81
83
  )
@@ -85,6 +87,7 @@ class Node(Element, Relational, AsyncAdaptable, Adaptable):
85
87
  Convert this Node to another format using a registered adapter.
86
88
  """
87
89
  kwargs["adapt_meth"] = "to_dict"
90
+ kwargs["mode"] = "db"
88
91
  return super().adapt_to(obj_key=obj_key, many=many, **kwargs)
89
92
 
90
93
  @classmethod
@@ -101,8 +104,25 @@ class Node(Element, Relational, AsyncAdaptable, Adaptable):
101
104
  auto-delegate to the correct subclass via from_dict.
102
105
  """
103
106
  kwargs["adapt_meth"] = "from_dict"
107
+ kwargs["mode"] = "db"
104
108
  return super().adapt_from(obj, obj_key=obj_key, many=many, **kwargs)
105
109
 
110
+ @field_serializer("content")
111
+ def _serialize_content(self, value: Any) -> Any:
112
+ if isinstance(value, Element):
113
+ return value.to_dict()
114
+ if isinstance(value, BaseModel):
115
+ return value.model_dump()
116
+ return value
117
+
118
+ @field_validator("content", mode="before")
119
+ def _validate_content(cls, value: Any) -> Any:
120
+ if isinstance(value, dict) and "lion_class" in value.get(
121
+ "metadata", {}
122
+ ):
123
+ return Element.from_dict(value)
124
+ return value
125
+
106
126
 
107
127
  if not _ADAPATER_REGISTERED:
108
128
  from pydapter.adapters import JsonAdapter, TomlAdapter
@@ -392,79 +392,75 @@ class MessageManager(Manager):
392
392
 
393
393
  @property
394
394
  def last_response(self) -> AssistantResponse | None:
395
- """
396
- Retrieve the most recent `AssistantResponse`.
397
- """
398
- for mid in reversed(self.messages.progression):
399
- if isinstance(self.messages[mid], AssistantResponse):
400
- return self.messages[mid]
395
+ """Retrieve the most recent `AssistantResponse`."""
396
+ res = self.messages.filter_by_type(
397
+ item_type=AssistantResponse,
398
+ strict_type=True,
399
+ as_pile=False,
400
+ reverse=True,
401
+ num_items=1,
402
+ )
403
+ if len(res) == 1:
404
+ return res[0]
401
405
  return None
402
406
 
403
407
  @property
404
408
  def last_instruction(self) -> Instruction | None:
405
- """
406
- Retrieve the most recent `Instruction`.
407
- """
408
- for mid in reversed(self.messages.progression):
409
- if isinstance(self.messages[mid], Instruction):
410
- return self.messages[mid]
409
+ """Retrieve the most recent `Instruction`."""
410
+ res = self.messages.filter_by_type(
411
+ item_type=Instruction,
412
+ strict_type=True,
413
+ as_pile=False,
414
+ reverse=True,
415
+ num_items=1,
416
+ )
417
+ if len(res) == 1:
418
+ return res[0]
411
419
  return None
412
420
 
413
421
  @property
414
422
  def assistant_responses(self) -> Pile[AssistantResponse]:
415
423
  """All `AssistantResponse` messages in the manager."""
416
- return Pile(
417
- collections=[
418
- self.messages[mid]
419
- for mid in self.messages.progression
420
- if isinstance(self.messages[mid], AssistantResponse)
421
- ]
424
+ return self.messages.filter_by_type(
425
+ item_type=AssistantResponse,
426
+ strict_type=True,
427
+ as_pile=True,
422
428
  )
423
429
 
424
430
  @property
425
431
  def actions(self) -> Pile[ActionRequest | ActionResponse]:
426
432
  """All action messages in the manager."""
427
- return Pile(
428
- collections=[
429
- self.messages[mid]
430
- for mid in self.messages.progression
431
- if isinstance(
432
- self.messages[mid], (ActionRequest, ActionResponse)
433
- )
434
- ]
433
+ return self.messages.filter_by_type(
434
+ item_type={ActionRequest, ActionResponse},
435
+ strict_type=True,
436
+ as_pile=True,
435
437
  )
436
438
 
437
439
  @property
438
440
  def action_requests(self) -> Pile[ActionRequest]:
439
441
  """All `ActionRequest` messages in the manager."""
440
- return Pile(
441
- collections=[
442
- self.messages[mid]
443
- for mid in self.messages.progression
444
- if isinstance(self.messages[mid], ActionRequest)
445
- ]
442
+ return self.messages.filter_by_type(
443
+ item_type=ActionRequest,
444
+ strict_type=True,
445
+ as_pile=True,
446
446
  )
447
447
 
448
448
  @property
449
449
  def action_responses(self) -> Pile[ActionResponse]:
450
450
  """All `ActionResponse` messages in the manager."""
451
- return Pile(
452
- collections=[
453
- self.messages[mid]
454
- for mid in self.messages.progression
455
- if isinstance(self.messages[mid], ActionResponse)
456
- ]
451
+ return self.messages.filter_by_type(
452
+ item_type=ActionResponse,
453
+ strict_type=True,
454
+ as_pile=True,
457
455
  )
458
456
 
459
457
  @property
460
458
  def instructions(self) -> Pile[Instruction]:
461
459
  """All `Instruction` messages in the manager."""
462
- return Pile(
463
- collections=[
464
- self.messages[mid]
465
- for mid in self.messages.progression
466
- if isinstance(self.messages[mid], Instruction)
467
- ]
460
+ return self.messages.filter_by_type(
461
+ item_type=Instruction,
462
+ strict_type=True,
463
+ as_pile=True,
468
464
  )
469
465
 
470
466
  def remove_last_instruction_tool_schemas(self) -> None:
@@ -481,7 +477,7 @@ class MessageManager(Manager):
481
477
  Example method to merge the content of recent ActionResponses
482
478
  into an instruction's context.
483
479
  """
484
- for i in reversed(self.messages.progression):
480
+ for i in reversed(list(self.messages.progression)):
485
481
  if isinstance(self.messages[i], ActionResponse):
486
482
  instruction.context.append(self.messages[i].content)
487
483
  else:
@@ -2,36 +2,19 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
- from pydantic import BaseModel, Field
5
+ from pydantic import BaseModel
6
6
  from pydantic.fields import FieldInfo
7
7
 
8
8
  from lionagi.fields.action import (
9
9
  ACTION_REQUESTS_FIELD,
10
10
  ACTION_REQUIRED_FIELD,
11
11
  ACTION_RESPONSES_FIELD,
12
- ActionRequestModel,
13
- ActionResponseModel,
14
12
  )
15
- from lionagi.fields.reason import REASON_FIELD, Reason
13
+ from lionagi.fields.reason import REASON_FIELD
16
14
  from lionagi.models import FieldModel, ModelParams
17
15
  from lionagi.protocols.operatives.operative import Operative
18
16
 
19
17
 
20
- class StepModel(BaseModel):
21
- """Model representing a single operational step with optional reasoning and actions."""
22
-
23
- title: str
24
- description: str
25
- reason: Reason | None = Field(**REASON_FIELD.to_dict())
26
- action_requests: list[ActionRequestModel] = Field(
27
- **ACTION_REQUESTS_FIELD.to_dict()
28
- )
29
- action_required: bool = Field(**ACTION_REQUIRED_FIELD.to_dict())
30
- action_responses: list[ActionResponseModel] = Field(
31
- **ACTION_RESPONSES_FIELD.to_dict()
32
- )
33
-
34
-
35
18
  class Step:
36
19
  """Utility class providing methods to create and manage Operative instances for steps."""
37
20
 
@@ -49,7 +49,7 @@ from .messages.manager import (
49
49
  SenderRecipient,
50
50
  System,
51
51
  )
52
- from .operatives.step import Operative, Step, StepModel
52
+ from .operatives.step import Operative, Step
53
53
 
54
54
  __all__ = (
55
55
  "Collective",
@@ -107,7 +107,6 @@ __all__ = (
107
107
  "Report",
108
108
  "Operative",
109
109
  "Step",
110
- "StepModel",
111
110
  "ActionManager",
112
111
  "Tool",
113
112
  "FunctionCalling",
@@ -173,13 +173,12 @@ class ReaderTool(LionTool):
173
173
  system_tool_name = "reader_tool"
174
174
 
175
175
  def __init__(self):
176
- from lionagi.libs.package.imports import check_import
176
+ from lionagi.libs.file.process import _HAS_DOCLING
177
177
 
178
- DocumentConverter = check_import(
179
- "docling",
180
- module_name="document_converter",
181
- import_name="DocumentConverter",
182
- )
178
+ if _HAS_DOCLING is not True:
179
+ raise _HAS_DOCLING
180
+
181
+ from docling.document_converter import DocumentConverter
183
182
 
184
183
  super().__init__()
185
184
  self.converter = DocumentConverter()