lionagi 0.2.10__py3-none-any.whl → 0.3.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. lionagi/core/action/function_calling.py +13 -6
  2. lionagi/core/action/tool.py +10 -9
  3. lionagi/core/action/tool_manager.py +18 -9
  4. lionagi/core/agent/README.md +1 -1
  5. lionagi/core/agent/base_agent.py +5 -2
  6. lionagi/core/agent/eval/README.md +1 -1
  7. lionagi/core/collections/README.md +1 -1
  8. lionagi/core/collections/_logger.py +16 -6
  9. lionagi/core/collections/abc/README.md +1 -1
  10. lionagi/core/collections/abc/component.py +35 -11
  11. lionagi/core/collections/abc/concepts.py +5 -3
  12. lionagi/core/collections/abc/exceptions.py +3 -1
  13. lionagi/core/collections/flow.py +16 -5
  14. lionagi/core/collections/model.py +34 -8
  15. lionagi/core/collections/pile.py +65 -28
  16. lionagi/core/collections/progression.py +1 -2
  17. lionagi/core/collections/util.py +11 -2
  18. lionagi/core/director/README.md +1 -1
  19. lionagi/core/engine/branch_engine.py +35 -10
  20. lionagi/core/engine/instruction_map_engine.py +14 -5
  21. lionagi/core/engine/sandbox_.py +3 -1
  22. lionagi/core/engine/script_engine.py +6 -2
  23. lionagi/core/executor/base_executor.py +10 -3
  24. lionagi/core/executor/graph_executor.py +12 -4
  25. lionagi/core/executor/neo4j_executor.py +18 -6
  26. lionagi/core/generic/edge.py +7 -2
  27. lionagi/core/generic/graph.py +23 -7
  28. lionagi/core/generic/node.py +14 -5
  29. lionagi/core/generic/tree_node.py +5 -1
  30. lionagi/core/mail/mail_manager.py +3 -1
  31. lionagi/core/mail/package.py +3 -1
  32. lionagi/core/message/action_request.py +9 -2
  33. lionagi/core/message/action_response.py +9 -3
  34. lionagi/core/message/instruction.py +8 -2
  35. lionagi/core/message/util.py +15 -5
  36. lionagi/core/report/base.py +12 -7
  37. lionagi/core/report/form.py +7 -4
  38. lionagi/core/report/report.py +10 -3
  39. lionagi/core/report/util.py +3 -1
  40. lionagi/core/rule/action.py +4 -1
  41. lionagi/core/rule/base.py +17 -6
  42. lionagi/core/rule/rulebook.py +8 -4
  43. lionagi/core/rule/string.py +3 -1
  44. lionagi/core/session/branch.py +15 -4
  45. lionagi/core/session/session.py +6 -2
  46. lionagi/core/unit/parallel_unit.py +9 -3
  47. lionagi/core/unit/template/action.py +1 -1
  48. lionagi/core/unit/template/predict.py +3 -1
  49. lionagi/core/unit/template/select.py +5 -3
  50. lionagi/core/unit/unit.py +50 -2
  51. lionagi/core/unit/unit_form.py +13 -15
  52. lionagi/core/unit/unit_mixin.py +45 -27
  53. lionagi/core/unit/util.py +7 -3
  54. lionagi/core/validator/validator.py +28 -15
  55. lionagi/core/work/work_edge.py +7 -3
  56. lionagi/core/work/work_task.py +11 -5
  57. lionagi/core/work/worker.py +20 -5
  58. lionagi/core/work/worker_engine.py +6 -2
  59. lionagi/core/work/worklog.py +3 -1
  60. lionagi/experimental/compressor/llm_compressor.py +20 -5
  61. lionagi/experimental/directive/README.md +1 -1
  62. lionagi/experimental/directive/parser/base_parser.py +41 -14
  63. lionagi/experimental/directive/parser/base_syntax.txt +23 -23
  64. lionagi/experimental/directive/template/base_template.py +14 -6
  65. lionagi/experimental/directive/tokenizer.py +3 -1
  66. lionagi/experimental/evaluator/README.md +1 -1
  67. lionagi/experimental/evaluator/ast_evaluator.py +6 -2
  68. lionagi/experimental/evaluator/base_evaluator.py +27 -16
  69. lionagi/integrations/bridge/autogen_/autogen_.py +7 -3
  70. lionagi/integrations/bridge/langchain_/documents.py +13 -10
  71. lionagi/integrations/bridge/llamaindex_/llama_pack.py +36 -12
  72. lionagi/integrations/bridge/llamaindex_/node_parser.py +8 -3
  73. lionagi/integrations/bridge/llamaindex_/reader.py +3 -1
  74. lionagi/integrations/bridge/llamaindex_/textnode.py +9 -3
  75. lionagi/integrations/bridge/pydantic_/pydantic_bridge.py +7 -1
  76. lionagi/integrations/bridge/transformers_/install_.py +3 -1
  77. lionagi/integrations/chunker/chunk.py +5 -2
  78. lionagi/integrations/loader/load.py +7 -3
  79. lionagi/integrations/loader/load_util.py +35 -16
  80. lionagi/integrations/provider/oai.py +13 -4
  81. lionagi/integrations/provider/openrouter.py +13 -4
  82. lionagi/integrations/provider/services.py +3 -1
  83. lionagi/integrations/provider/transformers.py +5 -3
  84. lionagi/integrations/storage/neo4j.py +23 -7
  85. lionagi/integrations/storage/storage_util.py +23 -7
  86. lionagi/integrations/storage/structure_excel.py +7 -2
  87. lionagi/integrations/storage/to_csv.py +8 -2
  88. lionagi/integrations/storage/to_excel.py +11 -3
  89. lionagi/libs/ln_api.py +41 -19
  90. lionagi/libs/ln_context.py +4 -4
  91. lionagi/libs/ln_convert.py +35 -14
  92. lionagi/libs/ln_dataframe.py +9 -3
  93. lionagi/libs/ln_func_call.py +53 -18
  94. lionagi/libs/ln_image.py +9 -5
  95. lionagi/libs/ln_knowledge_graph.py +21 -7
  96. lionagi/libs/ln_nested.py +57 -16
  97. lionagi/libs/ln_parse.py +45 -15
  98. lionagi/libs/ln_queue.py +8 -3
  99. lionagi/libs/ln_tokenize.py +19 -6
  100. lionagi/libs/ln_validate.py +14 -3
  101. lionagi/libs/sys_util.py +44 -12
  102. lionagi/lions/coder/coder.py +24 -8
  103. lionagi/lions/coder/util.py +6 -2
  104. lionagi/lions/researcher/data_source/google_.py +12 -4
  105. lionagi/lions/researcher/data_source/wiki_.py +3 -1
  106. lionagi/version.py +1 -1
  107. {lionagi-0.2.10.dist-info → lionagi-0.3.0.dist-info}/METADATA +6 -7
  108. lionagi-0.3.0.dist-info/RECORD +226 -0
  109. lionagi/tests/__init__.py +0 -0
  110. lionagi/tests/api/__init__.py +0 -0
  111. lionagi/tests/api/aws/__init__.py +0 -0
  112. lionagi/tests/api/aws/conftest.py +0 -25
  113. lionagi/tests/api/aws/test_aws_s3.py +0 -6
  114. lionagi/tests/integrations/__init__.py +0 -0
  115. lionagi/tests/libs/__init__.py +0 -0
  116. lionagi/tests/libs/test_api.py +0 -48
  117. lionagi/tests/libs/test_convert.py +0 -89
  118. lionagi/tests/libs/test_field_validators.py +0 -354
  119. lionagi/tests/libs/test_func_call.py +0 -701
  120. lionagi/tests/libs/test_nested.py +0 -382
  121. lionagi/tests/libs/test_parse.py +0 -171
  122. lionagi/tests/libs/test_queue.py +0 -68
  123. lionagi/tests/libs/test_sys_util.py +0 -222
  124. lionagi/tests/test_core/__init__.py +0 -0
  125. lionagi/tests/test_core/collections/__init__.py +0 -0
  126. lionagi/tests/test_core/collections/test_component.py +0 -208
  127. lionagi/tests/test_core/collections/test_exchange.py +0 -139
  128. lionagi/tests/test_core/collections/test_flow.py +0 -146
  129. lionagi/tests/test_core/collections/test_pile.py +0 -172
  130. lionagi/tests/test_core/collections/test_progression.py +0 -130
  131. lionagi/tests/test_core/generic/__init__.py +0 -0
  132. lionagi/tests/test_core/generic/test_edge.py +0 -69
  133. lionagi/tests/test_core/generic/test_graph.py +0 -97
  134. lionagi/tests/test_core/generic/test_node.py +0 -107
  135. lionagi/tests/test_core/generic/test_structure.py +0 -194
  136. lionagi/tests/test_core/generic/test_tree_node.py +0 -74
  137. lionagi/tests/test_core/graph/__init__.py +0 -0
  138. lionagi/tests/test_core/graph/test_graph.py +0 -71
  139. lionagi/tests/test_core/graph/test_tree.py +0 -76
  140. lionagi/tests/test_core/mail/__init__.py +0 -0
  141. lionagi/tests/test_core/mail/test_mail.py +0 -98
  142. lionagi/tests/test_core/test_branch.py +0 -116
  143. lionagi/tests/test_core/test_form.py +0 -47
  144. lionagi/tests/test_core/test_report.py +0 -106
  145. lionagi/tests/test_core/test_structure/__init__.py +0 -0
  146. lionagi/tests/test_core/test_structure/test_base_structure.py +0 -198
  147. lionagi/tests/test_core/test_structure/test_graph.py +0 -55
  148. lionagi/tests/test_core/test_structure/test_tree.py +0 -49
  149. lionagi/tests/test_core/test_validator.py +0 -112
  150. lionagi-0.2.10.dist-info/RECORD +0 -267
  151. {lionagi-0.2.10.dist-info → lionagi-0.3.0.dist-info}/LICENSE +0 -0
  152. {lionagi-0.2.10.dist-info → lionagi-0.3.0.dist-info}/WHEEL +0 -0
@@ -1,5 +1,6 @@
1
+ from collections.abc import Callable
1
2
  from functools import singledispatchmethod
2
- from typing import Any, Callable, Dict
3
+ from typing import Any, Dict
3
4
 
4
5
  from lionagi.core.collections.abc import Actionable
5
6
  from lionagi.core.message.action_request import ActionRequest
@@ -14,7 +15,7 @@ class FunctionCalling(Actionable):
14
15
  formats including tuples, dictionaries, ActionRequests, or JSON strings.
15
16
  """
16
17
 
17
- def __init__(self, function: Callable, arguments: Dict[str, Any] = None):
18
+ def __init__(self, function: Callable, arguments: dict[str, Any] = None):
18
19
  """
19
20
  Initializes a new instance of FunctionCalling with the given function
20
21
  and optional arguments.
@@ -59,12 +60,14 @@ class FunctionCalling(Actionable):
59
60
  @create.register(tuple)
60
61
  def _(cls, function_calling: tuple) -> "FunctionCalling":
61
62
  if len(function_calling) == 2:
62
- return cls(function=function_calling[0], arguments=function_calling[1])
63
+ return cls(
64
+ function=function_calling[0], arguments=function_calling[1]
65
+ )
63
66
  else:
64
67
  raise ValueError(f"Invalid function call {function_calling}")
65
68
 
66
69
  @create.register(dict)
67
- def _(cls, function_calling: Dict[str, Any]) -> "FunctionCalling":
70
+ def _(cls, function_calling: dict[str, Any]) -> "FunctionCalling":
68
71
  if len(function_calling) == 2 and (
69
72
  {"function", "arguments"} <= function_calling.keys()
70
73
  ):
@@ -75,7 +78,9 @@ class FunctionCalling(Actionable):
75
78
 
76
79
  @create.register(ActionRequest)
77
80
  def _(cls, function_calling: ActionRequest) -> "FunctionCalling":
78
- return cls.create((function_calling.function, function_calling.arguments))
81
+ return cls.create(
82
+ (function_calling.function, function_calling.arguments)
83
+ )
79
84
 
80
85
  @create.register(str)
81
86
  def _(cls, function_calling: str) -> "FunctionCalling":
@@ -83,7 +88,9 @@ class FunctionCalling(Actionable):
83
88
  try:
84
89
  _call = ParseUtil.fuzzy_parse_json(function_calling)
85
90
  except Exception as e:
86
- raise ValueError(f"Invalid function call {function_calling}") from e
91
+ raise ValueError(
92
+ f"Invalid function call {function_calling}"
93
+ ) from e
87
94
 
88
95
  if isinstance(_call, dict):
89
96
  return cls.create(_call)
@@ -1,4 +1,5 @@
1
- from typing import Any, Callable, Dict, List, Union
1
+ from collections.abc import Callable
2
+ from typing import Any, Dict, List, Union
2
3
 
3
4
  from pydantic import Field, field_serializer
4
5
 
@@ -29,18 +30,18 @@ class Tool(Node, Actionable):
29
30
  description="The callable function or capability of the tool.",
30
31
  )
31
32
 
32
- schema_: Union[Dict, None] = Field(
33
+ schema_: dict | None = Field(
33
34
  None,
34
35
  description="Schema in OpenAI format.",
35
36
  )
36
37
 
37
- pre_processor: Union[Callable, None] = None
38
- pre_processor_kwargs: Union[Dict, None] = None
38
+ pre_processor: Callable | None = None
39
+ pre_processor_kwargs: dict | None = None
39
40
 
40
- post_processor: Union[Callable, None] = None
41
- post_processor_kwargs: Union[Dict, None] = None
41
+ post_processor: Callable | None = None
42
+ post_processor_kwargs: dict | None = None
42
43
 
43
- parser: Union[Callable, None] = None # Parse result to JSON serializable format
44
+ parser: Callable | None = None # Parse result to JSON serializable format
44
45
 
45
46
  @field_serializer("function", check_fields=False)
46
47
  def serialize_func(self, func: Callable) -> str:
@@ -65,7 +66,7 @@ class Tool(Node, Actionable):
65
66
  """
66
67
  return self.schema_["function"]["name"]
67
68
 
68
- async def invoke(self, kwargs: Dict = {}) -> Any:
69
+ async def invoke(self, kwargs: dict = {}) -> Any:
69
70
  """
70
71
  Invoke the tool's function with optional pre-processing and post-processing.
71
72
 
@@ -98,4 +99,4 @@ class Tool(Node, Actionable):
98
99
  return result if not self.parser else self.parser(result)
99
100
 
100
101
 
101
- TOOL_TYPE = Union[bool, Tool, str, List[Union[Tool, str, Dict]], Dict]
102
+ TOOL_TYPE = Union[bool, Tool, str, list[Union[Tool, str, dict]], dict]
@@ -1,6 +1,7 @@
1
1
  import inspect
2
+ from collections.abc import Callable
2
3
  from functools import singledispatchmethod
3
- from typing import Any, Callable, List, Tuple, Union
4
+ from typing import Any, List, Tuple, Union
4
5
 
5
6
  from lionfuncs import function_to_schema, lcall, to_dict, to_list
6
7
 
@@ -37,7 +38,9 @@ class ToolManager(Actionable):
37
38
 
38
39
  return False
39
40
 
40
- def _register_tool(self, tool: Tool | Callable, update: bool = False) -> bool:
41
+ def _register_tool(
42
+ self, tool: Tool | Callable, update: bool = False
43
+ ) -> bool:
41
44
  """
42
45
  Registers a single tool or multiple tools based on the input type.
43
46
 
@@ -51,7 +54,9 @@ class ToolManager(Actionable):
51
54
  raise ValueError(f"Function {tool.name} is already registered.")
52
55
  if isinstance(tool, Callable):
53
56
  tool = func_to_tool(tool)
54
- tool = tool[0] if isinstance(tool, list) and len(tool) == 1 else tool
57
+ tool = (
58
+ tool[0] if isinstance(tool, list) and len(tool) == 1 else tool
59
+ )
55
60
  if not isinstance(tool, Tool):
56
61
  raise TypeError("Please register a Tool object.")
57
62
  self.registry[tool.name] = tool
@@ -107,7 +112,9 @@ class ToolManager(Actionable):
107
112
  func_calling=func_calling
108
113
  )
109
114
 
110
- raise ValueError(f"Function {func_calling.func_name} is not registered.")
115
+ raise ValueError(
116
+ f"Function {func_calling.func_name} is not registered."
117
+ )
111
118
 
112
119
  @property
113
120
  def _schema_list(self) -> list[dict[str, Any]]:
@@ -233,14 +240,16 @@ class ToolManager(Actionable):
233
240
  tool_kwarg = {"tools": self._schema_list}
234
241
  kwargs = tool_kwarg | kwargs
235
242
  else:
236
- tools = to_list(tools) if not isinstance(tools, list) else [tools]
243
+ tools = (
244
+ to_list(tools) if not isinstance(tools, list) else [tools]
245
+ )
237
246
  tool_kwarg = {"tools": lcall(tools, self._get_tool_schema)}
238
247
  kwargs = tool_kwarg | kwargs
239
248
 
240
249
  return kwargs
241
250
 
242
251
  @staticmethod
243
- def parse_tool_request(response: dict) -> Tuple[str, dict]:
252
+ def parse_tool_request(response: dict) -> tuple[str, dict]:
244
253
  """
245
254
  Parses a tool request from a given response dictionary.
246
255
 
@@ -267,11 +276,11 @@ class ToolManager(Actionable):
267
276
 
268
277
 
269
278
  def func_to_tool(
270
- func_: Union[Callable, List[Callable]],
271
- parser: Union[Callable, List[Callable]] = None,
279
+ func_: Callable | list[Callable],
280
+ parser: Callable | list[Callable] = None,
272
281
  docstring_style: str = "google",
273
282
  **kwargs,
274
- ) -> List[Tool]:
283
+ ) -> list[Tool]:
275
284
  """
276
285
  Converts functions to Tool objects, optionally associating parsers with each function
277
286
  and applying a specified docstring parsing style to generate tool schemas.
@@ -1 +1 @@
1
- agent as worker with structured executor
1
+ agent as worker with structured executor
@@ -1,4 +1,5 @@
1
- from typing import Any, Callable
1
+ from collections.abc import Callable
2
+ from typing import Any
2
3
 
3
4
  from lionagi.core.executor.base_executor import BaseExecutor
4
5
  from lionagi.core.generic.node import Node
@@ -41,7 +42,9 @@ class BaseAgent(Node):
41
42
  Args:
42
43
  refresh_time: The time interval (in seconds) for checking the execution states (default: 1).
43
44
  """
44
- while not self.structure.execute_stop or not self.executable.execute_stop:
45
+ while (
46
+ not self.structure.execute_stop or not self.executable.execute_stop
47
+ ):
45
48
  await AsyncUtil.sleep(refresh_time)
46
49
  self.mail_manager.execute_stop = True
47
50
 
@@ -1 +1 @@
1
- TODO
1
+ TODO
@@ -20,4 +20,4 @@ The `lionagi.core.collections` module provides essential data structures and abs
20
20
 
21
21
  These core collections work together to provide a robust and flexible framework for managing data within the LionAGI system. They offer powerful capabilities for storing, accessing, and manipulating collections, sequences, and flows of items, enabling developers to build efficient and organized AI-driven applications.
22
22
 
23
- For detailed usage examples and advanced features, please refer to the individual component documentation and upcoming tutorials.
23
+ For detailed usage examples and advanced features, please refer to the individual component documentation and upcoming tutorials.
@@ -28,7 +28,9 @@ class DLog:
28
28
  input_data: Any
29
29
  output_data: Any
30
30
 
31
- def serialize(self, *, flatten_: bool = True, sep: str = "[^_^]") -> dict[str, Any]:
31
+ def serialize(
32
+ self, *, flatten_: bool = True, sep: str = "[^_^]"
33
+ ) -> dict[str, Any]:
32
34
  """Serialize the DLog instance into a dictionary with an added timestamp.
33
35
 
34
36
  Args:
@@ -51,7 +53,9 @@ class DLog:
51
53
  data = convert.to_dict(data)
52
54
 
53
55
  if isinstance(self.input_data, dict) and flatten_:
54
- log_dict[field] = convert.to_str(nested.flatten(data, sep=sep))
56
+ log_dict[field] = convert.to_str(
57
+ nested.flatten(data, sep=sep)
58
+ )
55
59
  else:
56
60
  log_dict[field] = convert.to_str(data)
57
61
 
@@ -134,7 +138,7 @@ class DataLogger:
134
138
  def __init__(
135
139
  self,
136
140
  persist_path: str | Path | None = None,
137
- log: List[Dict] | None = None,
141
+ log: list[dict] | None = None,
138
142
  filename: str | None = None,
139
143
  ) -> None:
140
144
  """Initialize the DataLogger with optional custom settings for log storage.
@@ -145,7 +149,9 @@ class DataLogger:
145
149
  log: Initial log entries.
146
150
  filename: Base name for exported log files.
147
151
  """
148
- self.persist_path = Path(persist_path) if persist_path else Path("data/logs/")
152
+ self.persist_path = (
153
+ Path(persist_path) if persist_path else Path("data/logs/")
154
+ )
149
155
  self.log = deque(log) if log else deque()
150
156
  self.filename = filename or "log"
151
157
  atexit.register(self.save_at_exit)
@@ -218,7 +224,9 @@ class DataLogger:
218
224
  random_hash_digits=random_hash_digits,
219
225
  )
220
226
  try:
221
- logs = [log.serialize(flatten_=flatten_, sep=sep) for log in self.log]
227
+ logs = [
228
+ log.serialize(flatten_=flatten_, sep=sep) for log in self.log
229
+ ]
222
230
  df = convert.to_df(convert.to_list(logs, flatten=True))
223
231
  df.to_csv(filepath, index=index, **kwargs)
224
232
  if verbose:
@@ -271,7 +279,9 @@ class DataLogger:
271
279
  )
272
280
 
273
281
  try:
274
- logs = [log.serialize(flatten_=flatten_, sep=sep) for log in self.log]
282
+ logs = [
283
+ log.serialize(flatten_=flatten_, sep=sep) for log in self.log
284
+ ]
275
285
  df = convert.to_df(convert.to_list(logs, flatten=True))
276
286
  df.to_json(filepath, index=index, **kwargs)
277
287
  if verbose:
@@ -60,4 +60,4 @@ These exceptions contribute to a robust error handling mechanism within the Lion
60
60
 
61
61
  ^1: [Design Patterns: Elements of Reusable Object-Oriented Software](https://en.wikipedia.org/wiki/Design_Patterns)
62
62
 
63
- ^2: [Python Exceptions: An Introduction](https://realpython.com/python-exceptions/)
63
+ ^2: [Python Exceptions: An Introduction](https://realpython.com/python-exceptions/)
@@ -90,7 +90,9 @@ class Component(Element, ABC):
90
90
  content: Any = Field(
91
91
  default=None,
92
92
  description="The optional content of the node.",
93
- validation_alias=AliasChoices("text", "page_content", "chunk_content", "data"),
93
+ validation_alias=AliasChoices(
94
+ "text", "page_content", "chunk_content", "data"
95
+ ),
94
96
  )
95
97
 
96
98
  embedding: list[float] = Field(
@@ -201,7 +203,9 @@ class Component(Element, ABC):
201
203
 
202
204
  SysUtil.change_dict_key(metadata, "class_name", "llama_index_class")
203
205
  SysUtil.change_dict_key(metadata, "id_", "llama_index_id")
204
- SysUtil.change_dict_key(metadata, "relationships", "llama_index_relationships")
206
+ SysUtil.change_dict_key(
207
+ metadata, "relationships", "llama_index_relationships"
208
+ )
205
209
 
206
210
  dict_["metadata"] = metadata
207
211
  return cls.from_obj(dict_)
@@ -218,7 +222,9 @@ class Component(Element, ABC):
218
222
  try:
219
223
  dict_ = {**obj, **kwargs}
220
224
  if "embedding" in dict_:
221
- dict_["embedding"] = cls._validate_embedding(dict_["embedding"])
225
+ dict_["embedding"] = cls._validate_embedding(
226
+ dict_["embedding"]
227
+ )
222
228
 
223
229
  if "lion_class" in dict_:
224
230
  cls = _init_class.get(dict_.pop("lion_class"), cls)
@@ -231,7 +237,9 @@ class Component(Element, ABC):
231
237
  return cls.model_validate(dict_, *args, **kwargs)
232
238
 
233
239
  except ValidationError as e:
234
- raise LionValueError("Invalid dictionary for deserialization.") from e
240
+ raise LionValueError(
241
+ "Invalid dictionary for deserialization."
242
+ ) from e
235
243
 
236
244
  @classmethod
237
245
  def _process_langchain_dict(cls, dict_: dict) -> dict:
@@ -260,7 +268,9 @@ class Component(Element, ABC):
260
268
  SysUtil.change_dict_key(metadata, "type", "lc_type")
261
269
  SysUtil.change_dict_key(metadata, "id", "lc_id")
262
270
 
263
- extra_fields = {k: v for k, v in metadata.items() if k not in lc_meta_fields}
271
+ extra_fields = {
272
+ k: v for k, v in metadata.items() if k not in lc_meta_fields
273
+ }
264
274
  metadata = {k: v for k, v in metadata.items() if k in lc_meta_fields}
265
275
  dict_["metadata"] = metadata
266
276
  dict_.update(extra_fields)
@@ -299,7 +309,9 @@ class Component(Element, ABC):
299
309
  return dict_
300
310
 
301
311
  @classmethod
302
- def _from_str(cls, obj: str, /, *args, fuzzy_parse: bool = False, **kwargs) -> T:
312
+ def _from_str(
313
+ cls, obj: str, /, *args, fuzzy_parse: bool = False, **kwargs
314
+ ) -> T:
303
315
  """Create a Component instance from a JSON string."""
304
316
  obj = ParseUtil.fuzzy_parse_json(obj) if fuzzy_parse else to_dict(obj)
305
317
  try:
@@ -412,17 +424,23 @@ class Component(Element, ABC):
412
424
  convert(self.to_dict(*args, dropna=dropna, **kwargs), root)
413
425
  return ET.tostring(root, encoding="unicode")
414
426
 
415
- def to_pd_series(self, *args, pd_kwargs=None, dropna=False, **kwargs) -> Series:
427
+ def to_pd_series(
428
+ self, *args, pd_kwargs=None, dropna=False, **kwargs
429
+ ) -> Series:
416
430
  """Convert the node to a Pandas Series."""
417
431
  pd_kwargs = pd_kwargs or {}
418
432
  dict_ = self.to_dict(*args, dropna=dropna, **kwargs)
419
433
  return Series(dict_, **pd_kwargs)
420
434
 
421
- def to_llama_index_node(self, node_type: Type | str | Any = None, **kwargs) -> Any:
435
+ def to_llama_index_node(
436
+ self, node_type: type | str | Any = None, **kwargs
437
+ ) -> Any:
422
438
  """Serializes this node for LlamaIndex."""
423
439
  from lionagi.integrations.bridge import LlamaIndexBridge
424
440
 
425
- return LlamaIndexBridge.to_llama_index_node(self, node_type=node_type, **kwargs)
441
+ return LlamaIndexBridge.to_llama_index_node(
442
+ self, node_type=node_type, **kwargs
443
+ )
426
444
 
427
445
  def to_langchain_doc(self, **kwargs) -> Any:
428
446
  """Serializes this node for Langchain."""
@@ -454,7 +472,11 @@ class Component(Element, ABC):
454
472
  dict_ = flatten(dict_)
455
473
 
456
474
  try:
457
- out_ = dict_.pop(indices, default) if default != ... else dict_.pop(indices)
475
+ out_ = (
476
+ dict_.pop(indices, default)
477
+ if default != ...
478
+ else dict_.pop(indices)
479
+ )
458
480
  except KeyError as e:
459
481
  if default == ...:
460
482
  raise KeyError(f"Key {indices} not found in metadata.") from e
@@ -494,7 +516,9 @@ class Component(Element, ABC):
494
516
  **kwargs,
495
517
  ) -> None:
496
518
  """Add a field to the model after initialization."""
497
- self.extra_fields[field] = field_obj or Field(default=default, **kwargs)
519
+ self.extra_fields[field] = field_obj or Field(
520
+ default=default, **kwargs
521
+ )
498
522
  if annotation:
499
523
  self.extra_fields[field].annotation = annotation
500
524
 
@@ -1,8 +1,8 @@
1
1
  """This module defines abstract base classes for LionAGI."""
2
2
 
3
3
  from abc import ABC, abstractmethod
4
- from collections.abc import Generator
5
- from typing import Any, Iterator, TypeVar
4
+ from collections.abc import Generator, Iterator
5
+ from typing import Any, TypeVar
6
6
 
7
7
  from pydantic import BaseModel, Field, field_validator
8
8
 
@@ -194,7 +194,9 @@ class Sendable(BaseModel, ABC):
194
194
  sender: str = Field(
195
195
  "N/A",
196
196
  title="Sender",
197
- description=("The id of the sender node, or 'system', 'user', or 'assistant'."),
197
+ description=(
198
+ "The id of the sender node, or 'system', 'user', or 'assistant'."
199
+ ),
198
200
  )
199
201
 
200
202
  recipient: str = Field(
@@ -115,7 +115,9 @@ class TimeoutError(LionOperationError):
115
115
  """Exception raised when an operation times out."""
116
116
 
117
117
  def __init__(self, operation, timeout):
118
- super().__init__(operation, f"Operation timed out after {timeout} seconds.")
118
+ super().__init__(
119
+ operation, f"Operation timed out after {timeout} seconds."
120
+ )
119
121
 
120
122
 
121
123
  class ServiceError(LionAGIError):
@@ -70,7 +70,7 @@ class Flow(Element):
70
70
  """
71
71
  return [list(seq) for seq in self.sequences]
72
72
 
73
- def all_unique_items(self) -> Tuple[str]:
73
+ def all_unique_items(self) -> tuple[str]:
74
74
  """
75
75
  Retrieves all unique items across sequences.
76
76
 
@@ -115,7 +115,9 @@ class Flow(Element):
115
115
  seq = self.registry[seq]
116
116
 
117
117
  return (
118
- self.sequences[seq] if default == ... else self.sequences.get(seq, default)
118
+ self.sequences[seq]
119
+ if default == ...
120
+ else self.sequences.get(seq, default)
119
121
  )
120
122
 
121
123
  def __getitem__(self, seq=None, /):
@@ -149,7 +151,9 @@ class Flow(Element):
149
151
  self.registry.clear()
150
152
 
151
153
  def include(self, seq=None, item=None, name=None):
152
- _sequence = self._find_sequence(seq, None) or self._find_sequence(name, None)
154
+ _sequence = self._find_sequence(seq, None) or self._find_sequence(
155
+ name, None
156
+ )
153
157
  if not _sequence:
154
158
  if not item and not name:
155
159
  """None is not in the registry or sequencees."""
@@ -285,7 +289,10 @@ class Flow(Element):
285
289
  return self.sequences[sequence].popleft()
286
290
 
287
291
  def shape(self):
288
- return {key: len(self.sequences[value]) for key, value in self.registry.items()}
292
+ return {
293
+ key: len(self.sequences[value])
294
+ for key, value in self.registry.items()
295
+ }
289
296
 
290
297
  def get(self, sequence: str, /, default=...) -> deque[str] | None:
291
298
  sequence = getattr(sequence, "ln_id", None) or sequence
@@ -348,7 +355,11 @@ class Flow(Element):
348
355
  raise ItemNotFoundError("No sequence found.")
349
356
 
350
357
  if sequence in self.sequences:
351
- return sequence.ln_id if isinstance(sequence, Progression) else sequence
358
+ return (
359
+ sequence.ln_id
360
+ if isinstance(sequence, Progression)
361
+ else sequence
362
+ )
352
363
 
353
364
  if sequence in self.registry:
354
365
  return self.registry[sequence]
@@ -4,7 +4,14 @@ import os
4
4
  import numpy as np
5
5
  from dotenv import load_dotenv
6
6
 
7
- from lionagi.libs import APIUtil, BaseService, StatusTracker, SysUtil, ninsert, to_list
7
+ from lionagi.libs import (
8
+ APIUtil,
9
+ BaseService,
10
+ StatusTracker,
11
+ SysUtil,
12
+ ninsert,
13
+ to_list,
14
+ )
8
15
 
9
16
  from .abc import Component, ModelLimitExceededError
10
17
 
@@ -94,7 +101,9 @@ class iModel:
94
101
  else:
95
102
  provider = str(provider).lower() if provider else "openai"
96
103
 
97
- from lionagi.integrations.provider._mapping import SERVICE_PROVIDERS_MAPPING
104
+ from lionagi.integrations.provider._mapping import (
105
+ SERVICE_PROVIDERS_MAPPING,
106
+ )
98
107
 
99
108
  self.provider_schema = (
100
109
  provider_schema or SERVICE_PROVIDERS_MAPPING[provider]["schema"]
@@ -233,7 +242,9 @@ class iModel:
233
242
  if allowed_params != []:
234
243
  if (
235
244
  len(
236
- not_allowed := [k for k in params.keys() if k not in allowed_params]
245
+ not_allowed := [
246
+ k for k in params.keys() if k not in allowed_params
247
+ ]
237
248
  )
238
249
  > 0
239
250
  ):
@@ -294,7 +305,13 @@ class iModel:
294
305
  embed_str.pop("image_detail", None)
295
306
 
296
307
  num_tokens = APIUtil.calculate_num_token(
297
- {"input": str(embed_str) if isinstance(embed_str, dict) else embed_str},
308
+ {
309
+ "input": (
310
+ str(embed_str)
311
+ if isinstance(embed_str, dict)
312
+ else embed_str
313
+ )
314
+ },
298
315
  "embeddings",
299
316
  self.endpoint_schema["token_encoding_name"],
300
317
  )
@@ -323,7 +340,9 @@ class iModel:
323
340
  }
324
341
  kwargs["model"] = kwargs.pop("model", "gpt-4o-mini")
325
342
  if not request_fields and not json_schema:
326
- raise ValueError("Either request_fields or json_schema must be provided")
343
+ raise ValueError(
344
+ "Either request_fields or json_schema must be provided"
345
+ )
327
346
  request_fields = request_fields or json_schema["properties"]
328
347
 
329
348
  messages = [
@@ -360,7 +379,8 @@ class iModel:
360
379
  **{
361
380
  k: v
362
381
  for k, v in self.config.items()
363
- if k in getattr(self.service, "allowed_kwargs", []) and v is not None
382
+ if k in getattr(self.service, "allowed_kwargs", [])
383
+ and v is not None
364
384
  },
365
385
  "model_costs": None if self.costs == (0, 0) else self.costs,
366
386
  }
@@ -384,7 +404,9 @@ class iModel:
384
404
  if n_samples == 1:
385
405
  samples = [tokens]
386
406
  else:
387
- samples = [tokens[: (i + 1) * sample_token_len] for i in range(n_samples)]
407
+ samples = [
408
+ tokens[: (i + 1) * sample_token_len] for i in range(n_samples)
409
+ ]
388
410
 
389
411
  if use_residue and residue != 0:
390
412
  samples.append(tokens[-residue:])
@@ -392,7 +414,11 @@ class iModel:
392
414
  sampless = [context + " ".join(sample) for sample in samples]
393
415
 
394
416
  for sample in sampless:
395
- messages = [{"role": "system", "content": system_msg}] if system_msg else []
417
+ messages = (
418
+ [{"role": "system", "content": system_msg}]
419
+ if system_msg
420
+ else []
421
+ )
396
422
  messages.append(
397
423
  {"role": "user", "content": sample},
398
424
  )