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,9 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import asyncio
4
- from collections.abc import Iterable
4
+ from collections.abc import AsyncIterator, Callable, Iterable
5
5
  from functools import wraps
6
- from typing import Any, AsyncIterator, Callable, Generic, Type, TypeVar
6
+ from typing import Any, Generic, Type, TypeVar
7
7
 
8
8
  from pydantic import Field, field_validator
9
9
 
@@ -55,7 +55,7 @@ class Pile(Element, Record, Generic[T]):
55
55
 
56
56
  use_obj: bool = False
57
57
  pile: dict[str, T] = Field(default_factory=dict)
58
- item_type: set[Type[Element]] | None = Field(default=None)
58
+ item_type: set[type[Element]] | None = Field(default=None)
59
59
  name: str | None = None
60
60
  order: list[str] = Field(default_factory=list)
61
61
  index: Any = None
@@ -91,7 +91,7 @@ class Pile(Element, Record, Generic[T]):
91
91
  )
92
92
  self.order = order
93
93
 
94
- def __getitem__(self, key) -> T | "Pile[T]":
94
+ def __getitem__(self, key) -> T | Pile[T]:
95
95
  """
96
96
  Retrieve items from the pile using a key.
97
97
 
@@ -117,7 +117,11 @@ class Pile(Element, Record, Generic[T]):
117
117
  _key = self.order[key]
118
118
  _key = [_key] if isinstance(key, int) else _key
119
119
  _out = [self.pile.get(i) for i in _key]
120
- return _out[0] if len(_out) == 1 else pile(_out, self.item_type, _key)
120
+ return (
121
+ _out[0]
122
+ if len(_out) == 1
123
+ else pile(_out, self.item_type, _key)
124
+ )
121
125
  except IndexError as e:
122
126
  raise ItemNotFoundError(key) from e
123
127
 
@@ -130,7 +134,9 @@ class Pile(Element, Record, Generic[T]):
130
134
  keys[idx] = item.ln_id
131
135
 
132
136
  if not all(keys):
133
- raise LionTypeError("Invalid item type. Expected LionIDable object(s).")
137
+ raise LionTypeError(
138
+ "Invalid item type. Expected LionIDable object(s)."
139
+ )
134
140
 
135
141
  try:
136
142
  if len(keys) == 1:
@@ -164,7 +170,9 @@ class Pile(Element, Record, Generic[T]):
164
170
  raise e
165
171
 
166
172
  if isinstance(_key, str) and len(item) != 1:
167
- raise ValueError("Cannot assign multiple items to a single item.")
173
+ raise ValueError(
174
+ "Cannot assign multiple items to a single item."
175
+ )
168
176
 
169
177
  if isinstance(_key, list) and len(item) != len(_key):
170
178
  raise ValueError(
@@ -173,7 +181,9 @@ class Pile(Element, Record, Generic[T]):
173
181
 
174
182
  for k, v in item.items():
175
183
  if self.item_type and type(v) not in self.item_type:
176
- raise LionTypeError(f"Invalid item type. Expected {self.item_type}")
184
+ raise LionTypeError(
185
+ f"Invalid item type. Expected {self.item_type}"
186
+ )
177
187
 
178
188
  self.pile[k] = v
179
189
  self.order[key] = k
@@ -181,7 +191,9 @@ class Pile(Element, Record, Generic[T]):
181
191
  return
182
192
 
183
193
  if len(to_list_type(key)) != len(item):
184
- raise ValueError("The length of keys does not match the length of values")
194
+ raise ValueError(
195
+ "The length of keys does not match the length of values"
196
+ )
185
197
 
186
198
  self.pile.update(item)
187
199
  self.order.extend(item.keys())
@@ -210,7 +222,7 @@ class Pile(Element, Record, Generic[T]):
210
222
 
211
223
  return True
212
224
 
213
- def pop(self, key: Any, default=...) -> T | "Pile[T]" | None:
225
+ def pop(self, key: Any, default=...) -> T | Pile[T] | None:
214
226
  """
215
227
  Remove and return item(s) associated with given key.
216
228
 
@@ -247,7 +259,7 @@ class Pile(Element, Record, Generic[T]):
247
259
 
248
260
  return pile(items) if len(items) > 1 else items[0]
249
261
 
250
- def get(self, key: Any, default=...) -> T | "Pile[T]" | None:
262
+ def get(self, key: Any, default=...) -> T | Pile[T] | None:
251
263
  """
252
264
  Retrieve item(s) associated with given key.
253
265
 
@@ -366,7 +378,7 @@ class Pile(Element, Record, Generic[T]):
366
378
  """
367
379
  return len(self.pile)
368
380
 
369
- def __add__(self, other: T) -> "Pile":
381
+ def __add__(self, other: T) -> Pile:
370
382
  """Create a new pile by including item(s) using `+`.
371
383
 
372
384
  Returns a new `Pile` with all items from the current pile plus
@@ -387,7 +399,7 @@ class Pile(Element, Record, Generic[T]):
387
399
  return _copy
388
400
  raise LionValueError("Item cannot be included in the pile.")
389
401
 
390
- def __sub__(self, other) -> "Pile":
402
+ def __sub__(self, other) -> Pile:
391
403
  """
392
404
  Create a new pile by excluding item(s) using `-`.
393
405
 
@@ -412,7 +424,7 @@ class Pile(Element, Record, Generic[T]):
412
424
  raise LionValueError("Item cannot be excluded from the pile.")
413
425
  return _copy
414
426
 
415
- def __iadd__(self, other: T) -> "Pile":
427
+ def __iadd__(self, other: T) -> Pile:
416
428
  """
417
429
  Include item(s) in the current pile in place using `+=`.
418
430
 
@@ -425,7 +437,7 @@ class Pile(Element, Record, Generic[T]):
425
437
 
426
438
  return self + other
427
439
 
428
- def __isub__(self, other: LionIDable) -> "Pile":
440
+ def __isub__(self, other: LionIDable) -> Pile:
429
441
  """
430
442
  Exclude item(s) from the current pile using `-=`.
431
443
 
@@ -440,7 +452,7 @@ class Pile(Element, Record, Generic[T]):
440
452
  """
441
453
  return self - other
442
454
 
443
- def __radd__(self, other: T) -> "Pile":
455
+ def __radd__(self, other: T) -> Pile:
444
456
  return other + self
445
457
 
446
458
  def __ior__(self, other: Any | Pile) -> Pile:
@@ -630,7 +642,9 @@ class Pile(Element, Record, Generic[T]):
630
642
  )
631
643
 
632
644
  if len(value) != len(set(value)):
633
- raise LionValueError("Detected duplicated item types in item_type.")
645
+ raise LionValueError(
646
+ "Detected duplicated item types in item_type."
647
+ )
634
648
 
635
649
  if len(value) > 0:
636
650
  return set(value)
@@ -716,7 +730,9 @@ class Pile(Element, Record, Generic[T]):
716
730
 
717
731
  raise ValueError("Invalid index type")
718
732
 
719
- def create_query_engine(self, index_type="llama_index", engine_kwargs={}, **kwargs):
733
+ def create_query_engine(
734
+ self, index_type="llama_index", engine_kwargs={}, **kwargs
735
+ ):
720
736
  """
721
737
  Create a query engine for the pile.
722
738
 
@@ -730,7 +746,9 @@ class Pile(Element, Record, Generic[T]):
730
746
  """
731
747
  if index_type == "llama_index":
732
748
  if "node_postprocessor" in kwargs:
733
- engine_kwargs["node_postprocessor"] = kwargs.pop("node_postprocessor")
749
+ engine_kwargs["node_postprocessor"] = kwargs.pop(
750
+ "node_postprocessor"
751
+ )
734
752
  if "llm" in kwargs:
735
753
  engine_kwargs["llm"] = kwargs.pop("llm")
736
754
  if not self.index:
@@ -740,7 +758,9 @@ class Pile(Element, Record, Generic[T]):
740
758
  else:
741
759
  raise ValueError("Invalid index type")
742
760
 
743
- def create_chat_engine(self, index_type="llama_index", engine_kwargs={}, **kwargs):
761
+ def create_chat_engine(
762
+ self, index_type="llama_index", engine_kwargs={}, **kwargs
763
+ ):
744
764
  """
745
765
  Create a chat engine for the pile.
746
766
 
@@ -754,7 +774,9 @@ class Pile(Element, Record, Generic[T]):
754
774
  """
755
775
  if index_type == "llama_index":
756
776
  if "node_postprocessor" in kwargs:
757
- engine_kwargs["node_postprocessor"] = kwargs.pop("node_postprocessor")
777
+ engine_kwargs["node_postprocessor"] = kwargs.pop(
778
+ "node_postprocessor"
779
+ )
758
780
  if "llm" in kwargs:
759
781
  engine_kwargs["llm"] = kwargs.pop("llm")
760
782
  if not self.index:
@@ -764,7 +786,9 @@ class Pile(Element, Record, Generic[T]):
764
786
  else:
765
787
  raise ValueError("Invalid index type")
766
788
 
767
- async def query_pile(self, query, engine_kwargs={}, return_dict=False, **kwargs):
789
+ async def query_pile(
790
+ self, query, engine_kwargs={}, return_dict=False, **kwargs
791
+ ):
768
792
  """
769
793
  Query the pile using the created query engine.
770
794
 
@@ -784,7 +808,9 @@ class Pile(Element, Record, Generic[T]):
784
808
  return to_dict(response)
785
809
  return str(response)
786
810
 
787
- async def chat_pile(self, query, engine_kwargs={}, return_dict=False, **kwargs):
811
+ async def chat_pile(
812
+ self, query, engine_kwargs={}, return_dict=False, **kwargs
813
+ ):
788
814
  """
789
815
  Chat with the pile using the created chat engine.
790
816
 
@@ -805,7 +831,12 @@ class Pile(Element, Record, Generic[T]):
805
831
  return str(response)
806
832
 
807
833
  async def embed_pile(
808
- self, imodel=None, field="content", embed_kwargs={}, verbose=True, **kwargs
834
+ self,
835
+ imodel=None,
836
+ field="content",
837
+ embed_kwargs={},
838
+ verbose=True,
839
+ **kwargs,
809
840
  ):
810
841
  """
811
842
  Embed the items in the pile.
@@ -829,7 +860,9 @@ class Pile(Element, Record, Generic[T]):
829
860
  @cd.max_concurrency(max_concurrency)
830
861
  async def _embed_item(item):
831
862
  try:
832
- return await imodel.embed_node(item, field=field, **embed_kwargs)
863
+ return await imodel.embed_node(
864
+ item, field=field, **embed_kwargs
865
+ )
833
866
  except ModelLimitExceededError:
834
867
  pass
835
868
  return None
@@ -933,10 +966,14 @@ class Pile(Element, Record, Generic[T]):
933
966
 
934
967
  async def query(query: str):
935
968
  if query_type == "query":
936
- return await self.query_pile(query, return_dict=return_dict, **kwargs)
969
+ return await self.query_pile(
970
+ query, return_dict=return_dict, **kwargs
971
+ )
937
972
 
938
973
  elif query_type == "chat":
939
- return await self.chat_pile(query, return_dict=return_dict, **kwargs)
974
+ return await self.chat_pile(
975
+ query, return_dict=return_dict, **kwargs
976
+ )
940
977
 
941
978
  name = name or "query"
942
979
  tool = func_to_tool(query)[0]
@@ -1157,7 +1194,7 @@ class Pile(Element, Record, Generic[T]):
1157
1194
 
1158
1195
  def pile(
1159
1196
  items: Iterable[T] | None = None,
1160
- item_type: set[Type] | None = None,
1197
+ item_type: set[type] | None = None,
1161
1198
  order=None,
1162
1199
  use_obj=None,
1163
1200
  csv_file=None,
@@ -47,8 +47,7 @@ class Progression(Element, Ordering):
47
47
  yield from self.order
48
48
 
49
49
  def items(self):
50
- for idx, item in enumerate(self.order):
51
- yield idx, item
50
+ yield from enumerate(self.order)
52
51
 
53
52
  def size(self):
54
53
  return len(self)
@@ -1,7 +1,14 @@
1
1
  from collections import deque
2
2
  from collections.abc import Generator, Mapping
3
3
 
4
- from .abc import Component, Element, LionTypeError, Ordering, Record, get_lion_id
4
+ from .abc import (
5
+ Component,
6
+ Element,
7
+ LionTypeError,
8
+ Ordering,
9
+ Record,
10
+ get_lion_id,
11
+ )
5
12
 
6
13
 
7
14
  def to_list_type(value):
@@ -21,7 +28,9 @@ def to_list_type(value):
21
28
  Raises:
22
29
  TypeError: If the value cannot be converted to a list.
23
30
  """
24
- if isinstance(value, Component) and not isinstance(value, (Record, Ordering)):
31
+ if isinstance(value, Component) and not isinstance(
32
+ value, (Record, Ordering)
33
+ ):
25
34
  return [value]
26
35
  if isinstance(value, (Mapping, Record)):
27
36
  return list(value.values())
@@ -1 +1 @@
1
- director is an agent specialized in writing directives
1
+ director is an agent specialized in writing directives
@@ -122,7 +122,9 @@ class BranchExecutor(Branch, BaseExecutor):
122
122
  request_source=self.ln_id,
123
123
  )
124
124
  except Exception as e:
125
- raise ValueError(f"Invalid mail to process. Mail:{mail}, Error: {e}")
125
+ raise ValueError(
126
+ f"Invalid mail to process. Mail:{mail}, Error: {e}"
127
+ )
126
128
 
127
129
  def _process_node_list(self, mail: Mail):
128
130
  """
@@ -134,9 +136,16 @@ class BranchExecutor(Branch, BaseExecutor):
134
136
  Raises:
135
137
  ValueError: When trying to process multiple paths which is currently unsupported.
136
138
  """
137
- self.send(mail.sender, category="end", package="end", request_source=self.ln_id)
139
+ self.send(
140
+ mail.sender,
141
+ category="end",
142
+ package="end",
143
+ request_source=self.ln_id,
144
+ )
138
145
  self.execute_stop = True
139
- raise ValueError("Multiple path selection is not supported in BranchExecutor")
146
+ raise ValueError(
147
+ "Multiple path selection is not supported in BranchExecutor"
148
+ )
140
149
 
141
150
  async def _process_condition(self, mail: Mail):
142
151
  """
@@ -159,7 +168,9 @@ class BranchExecutor(Branch, BaseExecutor):
159
168
  request_source=self.ln_id,
160
169
  )
161
170
 
162
- def _system_process(self, system: System, verbose=True, context_verbose=False):
171
+ def _system_process(
172
+ self, system: System, verbose=True, context_verbose=False
173
+ ):
163
174
  """
164
175
  Processes a system node, possibly displaying its content and context if verbose is enabled.
165
176
 
@@ -174,7 +185,9 @@ class BranchExecutor(Branch, BaseExecutor):
174
185
  from IPython.display import Markdown, display
175
186
 
176
187
  if verbose:
177
- print(f"------------------Welcome: {system.sender}--------------------")
188
+ print(
189
+ f"------------------Welcome: {system.sender}--------------------"
190
+ )
178
191
  with contextlib.suppress(Exception):
179
192
  system.content = ParseUtil.fuzzy_parse_json(system.content)
180
193
  display(Markdown(f"system: {convert.to_str(system.system_info)}"))
@@ -201,7 +214,9 @@ class BranchExecutor(Branch, BaseExecutor):
201
214
 
202
215
  if verbose:
203
216
  with contextlib.suppress(Exception):
204
- instruction.content = ParseUtil.fuzzy_parse_json(instruction.content)
217
+ instruction.content = ParseUtil.fuzzy_parse_json(
218
+ instruction.content
219
+ )
205
220
  display(
206
221
  Markdown(
207
222
  f"{instruction.sender}: {convert.to_str(instruction.instruct)}"
@@ -210,11 +225,15 @@ class BranchExecutor(Branch, BaseExecutor):
210
225
 
211
226
  if self.context:
212
227
  result = await self.chat(
213
- instruction=instruction.instruct, context=self.context, **kwargs
228
+ instruction=instruction.instruct,
229
+ context=self.context,
230
+ **kwargs,
214
231
  )
215
232
  self.context = None
216
233
  else:
217
- result = await self.chat(instruction=instruction.instruct, **kwargs)
234
+ result = await self.chat(
235
+ instruction=instruction.instruct, **kwargs
236
+ )
218
237
  # instruction._add_context(context=self.context)
219
238
  # self.context_log.append(self.context)
220
239
  # self.context = None
@@ -224,7 +243,9 @@ class BranchExecutor(Branch, BaseExecutor):
224
243
  if "assistant_response" in result.keys():
225
244
  result = result["assistant_response"]
226
245
  if verbose:
227
- display(Markdown(f"assistant {self.ln_id}: {convert.to_str(result)}"))
246
+ display(
247
+ Markdown(f"assistant {self.ln_id}: {convert.to_str(result)}")
248
+ )
228
249
  print("-----------------------------------------------------")
229
250
 
230
251
  self.execution_responses.append(result)
@@ -276,7 +297,11 @@ class BranchExecutor(Branch, BaseExecutor):
276
297
 
277
298
  if verbose:
278
299
  if action.directive == "chat":
279
- display(Markdown(f"assistant {self.ln_id}: {convert.to_str(result)}"))
300
+ display(
301
+ Markdown(
302
+ f"assistant {self.ln_id}: {convert.to_str(result)}"
303
+ )
304
+ )
280
305
  else:
281
306
  display(Markdown(f"assistant {self.ln_id}:\n"))
282
307
  for k, v in result.work_fields.items():
@@ -23,9 +23,12 @@ class InstructionMapEngine(BaseExecutor):
23
23
  """
24
24
 
25
25
  branches: Pile[BranchExecutor] = Field(
26
- default_factory=dict, description="The branches of the instruction mapping."
26
+ default_factory=dict,
27
+ description="The branches of the instruction mapping.",
28
+ )
29
+ structure_id: str = Field(
30
+ "", description="The ID of the executable structure."
27
31
  )
28
- structure_id: str = Field("", description="The ID of the executable structure.")
29
32
  mail_transfer: Exchange = Field(
30
33
  default_factory=Exchange, description="The mail transfer."
31
34
  )
@@ -106,7 +109,9 @@ class InstructionMapEngine(BaseExecutor):
106
109
  self.mail_manager.add_sources([branch])
107
110
  self.structure_id = start_mail.package.package["structure_id"]
108
111
 
109
- pack = Package(category="start", package="start", request_source=branch.ln_id)
112
+ pack = Package(
113
+ category="start", package="start", request_source=branch.ln_id
114
+ )
110
115
  mail = Mail(
111
116
  sender=self.ln_id,
112
117
  recipient=self.structure_id,
@@ -129,7 +134,9 @@ class InstructionMapEngine(BaseExecutor):
129
134
  base_branch = self.branches[source_branch_id]
130
135
 
131
136
  pack = Package(
132
- category="node", package=node_list[0], request_source=source_branch_id
137
+ category="node",
138
+ package=node_list[0],
139
+ request_source=source_branch_id,
133
140
  )
134
141
  mail = Mail(
135
142
  sender=self.mail_transfer.ln_id,
@@ -167,7 +174,9 @@ class InstructionMapEngine(BaseExecutor):
167
174
  self.branches[branch.ln_id] = branch
168
175
  self.mail_manager.add_sources([branch])
169
176
  node_pacakge = Package(
170
- category="node", package=node_list[i], request_source=source_branch_id
177
+ category="node",
178
+ package=node_list[i],
179
+ request_source=source_branch_id,
171
180
  )
172
181
  node_mail = Mail(
173
182
  sender=self.mail_transfer.ln_id,
@@ -6,7 +6,9 @@ class SandboxTransformer(ast.NodeTransformer):
6
6
  """AST transformer to enforce restrictions in sandbox mode."""
7
7
 
8
8
  def visit_Import(self, node):
9
- raise RuntimeError("Import statements are not allowed in sandbox mode.")
9
+ raise RuntimeError(
10
+ "Import statements are not allowed in sandbox mode."
11
+ )
10
12
 
11
13
  def visit_Exec(self, node):
12
14
  raise RuntimeError("Exec statements are not allowed in sandbox mode.")
@@ -37,9 +37,13 @@ class ScriptEngine:
37
37
  var_name = stmt.targets[0].id
38
38
  value = self._evaluate_expression(ast.unparse(stmt.value))
39
39
  self._assign_variable(var_name, value)
40
- elif isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Call):
40
+ elif isinstance(stmt, ast.Expr) and isinstance(
41
+ stmt.value, ast.Call
42
+ ):
41
43
  func_name = stmt.value.func.id
42
- arg = self._evaluate_expression(ast.unparse(stmt.value.args[0]))
44
+ arg = self._evaluate_expression(
45
+ ast.unparse(stmt.value.args[0])
46
+ )
43
47
  result = self._execute_function(func_name, arg)
44
48
  # For demonstration, manually update 'x' to simulate expected behavior
45
49
  if func_name == "processData":
@@ -30,14 +30,21 @@ class BaseExecutor(Element, Progressable, Executable, ABC):
30
30
  default_factory=list, description="The list of responses."
31
31
  )
32
32
 
33
- context_log: list = Field(default_factory=list, description="The context log.")
33
+ context_log: list = Field(
34
+ default_factory=list, description="The context log."
35
+ )
34
36
 
35
37
  verbose: bool = Field(
36
- True, description="A flag indicating whether to provide verbose output."
38
+ True,
39
+ description="A flag indicating whether to provide verbose output.",
37
40
  )
38
41
 
39
42
  def send(
40
- self, recipient: str, category: str, package: Any, request_source: str = None
43
+ self,
44
+ recipient: str,
45
+ category: str,
46
+ package: Any,
47
+ request_source: str = None,
41
48
  ) -> None:
42
49
  """
43
50
  Sends a mail to a recipient.
@@ -21,7 +21,9 @@ class GraphExecutor(BaseExecutor, Graph):
21
21
 
22
22
  condition_check_result: bool | None = None
23
23
 
24
- async def check_edge_condition(self, edge: Edge, executable_id, request_source):
24
+ async def check_edge_condition(
25
+ self, edge: Edge, executable_id, request_source
26
+ ):
25
27
  """
26
28
  Evaluates the condition associated with an edge, determining if execution should proceed along that edge based
27
29
  on the condition's source type.
@@ -67,7 +69,9 @@ class GraphExecutor(BaseExecutor, Graph):
67
69
  and mail.package.package["edge_id"] == edge_id
68
70
  ):
69
71
  self.mailbox.pile.pop(mail_id)
70
- self.condition_check_result = mail.package.package["check_result"]
72
+ self.condition_check_result = mail.package.package[
73
+ "check_result"
74
+ ]
71
75
  else:
72
76
  skipped_requests.append(mail)
73
77
  self.mailbox.pending_ins[key] = skipped_requests
@@ -162,7 +166,9 @@ class GraphExecutor(BaseExecutor, Graph):
162
166
  except Exception as e:
163
167
  raise ValueError(f"Error handling node_id: {e}") from e
164
168
 
165
- elif mail.category == "node" and isinstance(mail.package.package, Node):
169
+ elif mail.category == "node" and isinstance(
170
+ mail.package.package, Node
171
+ ):
166
172
  try:
167
173
  return await self._handle_node(mail)
168
174
  except Exception as e:
@@ -171,7 +177,9 @@ class GraphExecutor(BaseExecutor, Graph):
171
177
  else:
172
178
  raise ValueError(f"Invalid mail type for structure")
173
179
 
174
- async def _next_node(self, current_node: Node, executable_id, request_source):
180
+ async def _next_node(
181
+ self, current_node: Node, executable_id, request_source
182
+ ):
175
183
  """
176
184
  Get the next step nodes based on the current node.
177
185
 
@@ -1,6 +1,6 @@
1
1
  import json
2
2
  from collections import deque
3
- from typing import Callable
3
+ from collections.abc import Callable
4
4
 
5
5
  from lionagi.core.action import ActionNode, DirectiveSelection, Tool
6
6
  from lionagi.core.agent.base_agent import BaseAgent
@@ -77,7 +77,9 @@ class Neo4jExecutor(BaseExecutor):
77
77
  and mail.package.package["edge_id"] == edge_id
78
78
  ):
79
79
  self.mailbox.pile.pop(mail_id)
80
- self.condition_check_result = mail.package.package["check_result"]
80
+ self.condition_check_result = mail.package.package[
81
+ "check_result"
82
+ ]
81
83
  else:
82
84
  skipped_requests.append(mail)
83
85
  self.mailbox.pending_ins[key] = skipped_requests
@@ -205,12 +207,18 @@ class Neo4jExecutor(BaseExecutor):
205
207
  condition_cls = await self.driver.get_condition_cls_code(
206
208
  condition["class"]
207
209
  )
208
- condition_obj = ParseNode.parse_condition(condition, condition_cls)
210
+ condition_obj = ParseNode.parse_condition(
211
+ condition, condition_cls
212
+ )
209
213
 
210
214
  head = node_id
211
215
  tail = node_properties["ln_id"]
212
216
  check = await self.check_edge_condition(
213
- condition_obj, executable_id, request_source, head, tail
217
+ condition_obj,
218
+ executable_id,
219
+ request_source,
220
+ head,
221
+ tail,
214
222
  )
215
223
  if not check:
216
224
  continue
@@ -259,7 +267,9 @@ class Neo4jExecutor(BaseExecutor):
259
267
  self.structure_id = id_
260
268
  return await self._next_node(head_list)
261
269
  except Exception as e:
262
- raise ValueError(f"Error in searching for structure in Neo4j. Error: {e}")
270
+ raise ValueError(
271
+ f"Error in searching for structure in Neo4j. Error: {e}"
272
+ )
263
273
 
264
274
  async def _handle_node_id(self, node_id, executable_id, request_source):
265
275
  """
@@ -277,7 +287,9 @@ class Neo4jExecutor(BaseExecutor):
277
287
  if not check:
278
288
  raise ValueError(f"Node {node_id} if not found in the database")
279
289
  node_list = await self.driver.get_forwards(node_id)
280
- return await self._next_node(node_list, node_id, executable_id, request_source)
290
+ return await self._next_node(
291
+ node_list, node_id, executable_id, request_source
292
+ )
281
293
 
282
294
  async def _handle_mail(self, mail: Mail):
283
295
  """
@@ -2,7 +2,12 @@ from typing import Any
2
2
 
3
3
  from pydantic import Field, field_validator
4
4
 
5
- from lionagi.core.collections.abc import Component, Condition, LionIDable, get_lion_id
5
+ from lionagi.core.collections.abc import (
6
+ Component,
7
+ Condition,
8
+ LionIDable,
9
+ get_lion_id,
10
+ )
6
11
  from lionagi.core.generic.edge_condition import EdgeCondition
7
12
 
8
13
 
@@ -94,7 +99,7 @@ class Edge(Component):
94
99
  ):
95
100
  return inspect.getfile(member)
96
101
  else:
97
- raise TypeError("Source for {!r} not found".format(object))
102
+ raise TypeError(f"Source for {object!r} not found")
98
103
 
99
104
  inspect.getfile = new_getfile
100
105