lionagi 0.0.316__py3-none-any.whl → 0.1.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. lionagi/core/__init__.py +19 -8
  2. lionagi/core/agent/__init__.py +0 -3
  3. lionagi/core/agent/base_agent.py +25 -30
  4. lionagi/core/branch/__init__.py +0 -4
  5. lionagi/core/branch/{base_branch.py → base.py} +12 -13
  6. lionagi/core/branch/branch.py +22 -19
  7. lionagi/core/branch/executable_branch.py +0 -347
  8. lionagi/core/branch/{branch_flow_mixin.py → flow_mixin.py} +5 -5
  9. lionagi/core/direct/__init__.py +10 -1
  10. lionagi/core/direct/cot.py +61 -26
  11. lionagi/core/direct/plan.py +10 -8
  12. lionagi/core/direct/predict.py +5 -5
  13. lionagi/core/direct/react.py +8 -8
  14. lionagi/core/direct/score.py +4 -4
  15. lionagi/core/direct/select.py +4 -4
  16. lionagi/core/direct/utils.py +7 -4
  17. lionagi/core/direct/vote.py +2 -2
  18. lionagi/core/execute/base_executor.py +47 -0
  19. lionagi/core/execute/branch_executor.py +296 -0
  20. lionagi/core/execute/instruction_map_executor.py +179 -0
  21. lionagi/core/execute/neo4j_executor.py +381 -0
  22. lionagi/core/execute/structure_executor.py +314 -0
  23. lionagi/core/flow/monoflow/ReAct.py +20 -20
  24. lionagi/core/flow/monoflow/chat.py +6 -6
  25. lionagi/core/flow/monoflow/chat_mixin.py +23 -33
  26. lionagi/core/flow/monoflow/followup.py +14 -15
  27. lionagi/core/flow/polyflow/chat.py +15 -12
  28. lionagi/core/{prompt/action_template.py → form/action_form.py} +2 -2
  29. lionagi/core/{prompt → form}/field_validator.py +40 -31
  30. lionagi/core/form/form.py +302 -0
  31. lionagi/core/form/mixin.py +214 -0
  32. lionagi/core/{prompt/scored_template.py → form/scored_form.py} +2 -2
  33. lionagi/core/generic/__init__.py +37 -0
  34. lionagi/core/generic/action.py +26 -0
  35. lionagi/core/generic/component.py +455 -0
  36. lionagi/core/generic/condition.py +44 -0
  37. lionagi/core/generic/data_logger.py +305 -0
  38. lionagi/core/generic/edge.py +162 -0
  39. lionagi/core/generic/mail.py +90 -0
  40. lionagi/core/generic/mailbox.py +36 -0
  41. lionagi/core/generic/node.py +285 -0
  42. lionagi/core/generic/relation.py +70 -0
  43. lionagi/core/generic/signal.py +22 -0
  44. lionagi/core/generic/structure.py +362 -0
  45. lionagi/core/generic/transfer.py +20 -0
  46. lionagi/core/generic/work.py +40 -0
  47. lionagi/core/graph/graph.py +126 -0
  48. lionagi/core/graph/tree.py +190 -0
  49. lionagi/core/mail/__init__.py +0 -8
  50. lionagi/core/mail/mail_manager.py +15 -12
  51. lionagi/core/mail/schema.py +9 -2
  52. lionagi/core/messages/__init__.py +0 -3
  53. lionagi/core/messages/schema.py +17 -225
  54. lionagi/core/session/__init__.py +0 -3
  55. lionagi/core/session/session.py +24 -22
  56. lionagi/core/tool/__init__.py +3 -1
  57. lionagi/core/tool/tool.py +28 -0
  58. lionagi/core/tool/tool_manager.py +75 -75
  59. lionagi/experimental/directive/evaluator/__init__.py +0 -0
  60. lionagi/experimental/directive/evaluator/ast_evaluator.py +115 -0
  61. lionagi/experimental/directive/evaluator/base_evaluator.py +202 -0
  62. lionagi/experimental/directive/evaluator/sandbox_.py +14 -0
  63. lionagi/experimental/directive/evaluator/script_engine.py +83 -0
  64. lionagi/experimental/directive/parser/__init__.py +0 -0
  65. lionagi/experimental/directive/parser/base_parser.py +215 -0
  66. lionagi/experimental/directive/schema.py +36 -0
  67. lionagi/experimental/directive/template_/__init__.py +0 -0
  68. lionagi/experimental/directive/template_/base_template.py +63 -0
  69. lionagi/experimental/tool/__init__.py +0 -0
  70. lionagi/experimental/tool/function_calling.py +43 -0
  71. lionagi/experimental/tool/manual.py +66 -0
  72. lionagi/experimental/tool/schema.py +59 -0
  73. lionagi/experimental/tool/tool_manager.py +138 -0
  74. lionagi/experimental/tool/util.py +16 -0
  75. lionagi/experimental/work/__init__.py +0 -0
  76. lionagi/experimental/work/_logger.py +25 -0
  77. lionagi/experimental/work/exchange.py +0 -0
  78. lionagi/experimental/work/schema.py +30 -0
  79. lionagi/experimental/work/tests.py +72 -0
  80. lionagi/experimental/work/util.py +0 -0
  81. lionagi/experimental/work/work_function.py +89 -0
  82. lionagi/experimental/work/worker.py +12 -0
  83. lionagi/integrations/bridge/autogen_/__init__.py +0 -0
  84. lionagi/integrations/bridge/autogen_/autogen_.py +124 -0
  85. lionagi/integrations/bridge/llamaindex_/get_index.py +294 -0
  86. lionagi/integrations/bridge/llamaindex_/llama_pack.py +227 -0
  87. lionagi/integrations/bridge/transformers_/__init__.py +0 -0
  88. lionagi/integrations/bridge/transformers_/install_.py +36 -0
  89. lionagi/integrations/chunker/chunk.py +7 -7
  90. lionagi/integrations/config/oai_configs.py +5 -5
  91. lionagi/integrations/config/ollama_configs.py +1 -1
  92. lionagi/integrations/config/openrouter_configs.py +1 -1
  93. lionagi/integrations/loader/load.py +6 -6
  94. lionagi/integrations/loader/load_util.py +8 -8
  95. lionagi/integrations/storage/__init__.py +3 -0
  96. lionagi/integrations/storage/neo4j.py +673 -0
  97. lionagi/integrations/storage/storage_util.py +289 -0
  98. lionagi/integrations/storage/to_csv.py +63 -0
  99. lionagi/integrations/storage/to_excel.py +67 -0
  100. lionagi/libs/ln_api.py +3 -3
  101. lionagi/libs/ln_knowledge_graph.py +405 -0
  102. lionagi/libs/ln_parse.py +43 -6
  103. lionagi/libs/ln_queue.py +101 -0
  104. lionagi/libs/ln_tokenizer.py +57 -0
  105. lionagi/libs/ln_validate.py +288 -0
  106. lionagi/libs/sys_util.py +29 -7
  107. lionagi/lions/__init__.py +0 -0
  108. lionagi/lions/coder/__init__.py +0 -0
  109. lionagi/lions/coder/add_feature.py +20 -0
  110. lionagi/lions/coder/base_prompts.py +22 -0
  111. lionagi/lions/coder/coder.py +121 -0
  112. lionagi/lions/coder/util.py +91 -0
  113. lionagi/lions/researcher/__init__.py +0 -0
  114. lionagi/lions/researcher/data_source/__init__.py +0 -0
  115. lionagi/lions/researcher/data_source/finhub_.py +191 -0
  116. lionagi/lions/researcher/data_source/google_.py +199 -0
  117. lionagi/lions/researcher/data_source/wiki_.py +96 -0
  118. lionagi/lions/researcher/data_source/yfinance_.py +21 -0
  119. lionagi/tests/integrations/__init__.py +0 -0
  120. lionagi/tests/libs/__init__.py +0 -0
  121. lionagi/tests/libs/test_async.py +0 -0
  122. lionagi/tests/libs/test_field_validators.py +353 -0
  123. lionagi/tests/libs/test_queue.py +67 -0
  124. lionagi/tests/test_core/test_base_branch.py +0 -1
  125. lionagi/tests/test_core/test_branch.py +2 -0
  126. lionagi/tests/test_core/test_session_base_util.py +1 -0
  127. lionagi/version.py +1 -1
  128. {lionagi-0.0.316.dist-info → lionagi-0.1.1.dist-info}/METADATA +1 -1
  129. lionagi-0.1.1.dist-info/RECORD +190 -0
  130. lionagi/core/prompt/prompt_template.py +0 -312
  131. lionagi/core/schema/__init__.py +0 -22
  132. lionagi/core/schema/action_node.py +0 -29
  133. lionagi/core/schema/base_mixin.py +0 -296
  134. lionagi/core/schema/base_node.py +0 -199
  135. lionagi/core/schema/condition.py +0 -24
  136. lionagi/core/schema/data_logger.py +0 -354
  137. lionagi/core/schema/data_node.py +0 -93
  138. lionagi/core/schema/prompt_template.py +0 -67
  139. lionagi/core/schema/structure.py +0 -912
  140. lionagi/core/tool/manual.py +0 -1
  141. lionagi-0.0.316.dist-info/RECORD +0 -121
  142. /lionagi/core/{branch/base → execute}/__init__.py +0 -0
  143. /lionagi/core/flow/{base/baseflow.py → baseflow.py} +0 -0
  144. /lionagi/core/flow/{base/__init__.py → mono_chat_mixin.py} +0 -0
  145. /lionagi/core/{prompt → form}/__init__.py +0 -0
  146. /lionagi/{tests/test_integrations → core/graph}/__init__.py +0 -0
  147. /lionagi/{tests/test_libs → experimental}/__init__.py +0 -0
  148. /lionagi/{tests/test_libs/test_async.py → experimental/directive/__init__.py} +0 -0
  149. /lionagi/tests/{test_libs → libs}/test_api.py +0 -0
  150. /lionagi/tests/{test_libs → libs}/test_convert.py +0 -0
  151. /lionagi/tests/{test_libs → libs}/test_func_call.py +0 -0
  152. /lionagi/tests/{test_libs → libs}/test_nested.py +0 -0
  153. /lionagi/tests/{test_libs → libs}/test_parse.py +0 -0
  154. /lionagi/tests/{test_libs → libs}/test_sys_util.py +0 -0
  155. {lionagi-0.0.316.dist-info → lionagi-0.1.1.dist-info}/LICENSE +0 -0
  156. {lionagi-0.0.316.dist-info → lionagi-0.1.1.dist-info}/WHEEL +0 -0
  157. {lionagi-0.0.316.dist-info → lionagi-0.1.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,288 @@
1
+ """
2
+ This module provides functions for validating and fixing field values based on their data types.
3
+
4
+ The module defines several functions for checking and fixing field values of different data types,
5
+ including numeric, boolean, string, and enum. It also provides a dictionary `validation_funcs` that
6
+ maps data types to their corresponding validation functions.
7
+ """
8
+
9
+ from .ln_convert import to_str, is_same_dtype, to_list, to_dict, to_num, strip_lower
10
+ from .ln_parse import StringMatch, ParseUtil
11
+
12
+
13
+ def check_dict_field(x, keys: list[str] | dict, fix_=True, **kwargs):
14
+ if isinstance(x, dict):
15
+ return x
16
+ if fix_:
17
+ try:
18
+ x = to_str(x)
19
+ return StringMatch.force_validate_dict(x, keys=keys, **kwargs)
20
+ except Exception as e:
21
+ raise ValueError("Invalid dict field type.") from e
22
+ raise ValueError(f"Default value for DICT must be a dict, got {type(x).__name__}")
23
+
24
+
25
+ def check_action_field(x, fix_=True, **kwargs):
26
+ if (
27
+ isinstance(x, list)
28
+ and is_same_dtype(x, dict)
29
+ and all(_has_action_keys(y) for y in x)
30
+ ):
31
+ return x
32
+ try:
33
+ x = _fix_action_field(x, fix_)
34
+ return x
35
+ except Exception as e:
36
+ raise ValueError("Invalid action field type.") from e
37
+
38
+
39
+ def check_number_field(x, fix_=True, **kwargs):
40
+ """
41
+ Checks if the given value is a valid numeric field.
42
+
43
+ Args:
44
+ x: The value to check.
45
+ fix_ (bool): Flag indicating whether to attempt fixing the value if it's invalid (default: True).
46
+ **kwargs: Additional keyword arguments for fixing the value.
47
+
48
+ Returns:
49
+ The original value if it's valid, or the fixed value if `fix_` is True.
50
+
51
+ Raises:
52
+ ValueError: If the value is not a valid numeric field and cannot be fixed.
53
+ """
54
+ if not isinstance(x, (int, float)):
55
+ if fix_:
56
+ try:
57
+ return _fix_number_field(x, **kwargs)
58
+ except Exception as e:
59
+ raise e
60
+
61
+ raise ValueError(
62
+ f"Default value for NUMERIC must be an int or float, got {type(x).__name__}"
63
+ )
64
+ return x
65
+
66
+
67
+ def check_bool_field(x, fix_=True):
68
+ """
69
+ Checks if the given value is a valid boolean field.
70
+
71
+ Args:
72
+ x: The value to check.
73
+ fix_ (bool): Flag indicating whether to attempt fixing the value if it's invalid (default: True).
74
+
75
+ Returns:
76
+ The original value if it's valid, or the fixed value if `fix_` is True.
77
+
78
+ Raises:
79
+ ValueError: If the value is not a valid boolean field and cannot be fixed.
80
+ """
81
+ if not isinstance(x, bool):
82
+ if fix_:
83
+ try:
84
+ return _fix_bool_field(x)
85
+ except Exception as e:
86
+ raise e
87
+
88
+ raise ValueError(
89
+ f"Default value for BOOLEAN must be a bool, got {type(x).__name__}"
90
+ )
91
+ return x
92
+
93
+
94
+ def check_str_field(x, *args, fix_=True, **kwargs):
95
+ """
96
+ Checks if the given value is a valid string field.
97
+
98
+ Args:
99
+ x: The value to check.
100
+ *args: Additional positional arguments for fixing the value.
101
+ fix_ (bool): Flag indicating whether to attempt fixing the value if it's invalid (default: True).
102
+ **kwargs: Additional keyword arguments for fixing the value.
103
+
104
+ Returns:
105
+ The original value if it's valid, or the fixed value if `fix_` is True.
106
+
107
+ Raises:
108
+ ValueError: If the value is not a valid string field and cannot be fixed.
109
+ """
110
+ if not isinstance(x, str):
111
+ if fix_:
112
+ try:
113
+ return _fix_str_field(x, *args, **kwargs)
114
+ except Exception as e:
115
+ raise e
116
+
117
+ raise ValueError(
118
+ f"Default value for STRING must be a str, got {type(x).__name__}"
119
+ )
120
+ return x
121
+
122
+
123
+ def check_enum_field(x, choices, fix_=True, **kwargs):
124
+ """
125
+ Checks if the given value is a valid enum field.
126
+
127
+ Args:
128
+ x: The value to check.
129
+ choices: The list of valid choices for the enum field.
130
+ fix_ (bool): Flag indicating whether to attempt fixing the value if it's invalid (default: True).
131
+ **kwargs: Additional keyword arguments for fixing the value.
132
+
133
+ Returns:
134
+ The original value if it's valid, or the fixed value if `fix_` is True.
135
+
136
+ Raises:
137
+ ValueError: If the value is not a valid enum field and cannot be fixed.
138
+ """
139
+ same_dtype, dtype_ = is_same_dtype(choices, return_dtype=True)
140
+ if not same_dtype:
141
+ raise ValueError(
142
+ f"Field type ENUM requires all choices to be of the same type, got {choices}"
143
+ )
144
+
145
+ if not isinstance(x, dtype_):
146
+ raise ValueError(
147
+ f"Default value for ENUM must be an instance of the {dtype_.__name__}, got {type(x).__name__}"
148
+ )
149
+
150
+ if x not in choices:
151
+ if fix_:
152
+ try:
153
+ return _fix_enum_field(x, choices, **kwargs)
154
+ except Exception as e:
155
+ raise e
156
+ raise ValueError(
157
+ f"Default value for ENUM must be one of the {choices}, got {x}"
158
+ )
159
+
160
+ return x
161
+
162
+
163
+ def _has_action_keys(dict_):
164
+ return list(dict_.keys()) >= ["function", "arguments"]
165
+
166
+
167
+ def _fix_action_field(x, discard_=True):
168
+ corrected = []
169
+ if isinstance(x, str):
170
+ x = ParseUtil.fuzzy_parse_json(x)
171
+
172
+ try:
173
+ x = to_list(x)
174
+
175
+ for i in x:
176
+ i = to_dict(i)
177
+ if _has_action_keys(i):
178
+ corrected.append(i)
179
+ elif not discard_:
180
+ raise ValueError(f"Invalid action field: {i}")
181
+ except Exception as e:
182
+ raise ValueError(f"Invalid action field: {e}") from e
183
+
184
+ return corrected
185
+
186
+
187
+ def _fix_number_field(x, *args, **kwargs):
188
+ """
189
+ Attempts to fix an invalid numeric field value.
190
+
191
+ Args:
192
+ x: The value to fix.
193
+ *args: Additional positional arguments for fixing the value.
194
+ **kwargs: Additional keyword arguments for fixing the value.
195
+
196
+ Returns:
197
+ The fixed numeric value.
198
+
199
+ Raises:
200
+ ValueError: If the value cannot be converted into a valid numeric value.
201
+ """
202
+ try:
203
+ x = to_num(x, *args, **kwargs)
204
+ if isinstance(x, (int, float)):
205
+ return x
206
+ raise ValueError(f"Failed to convert {x} into a numeric value")
207
+ except Exception as e:
208
+ raise ValueError(f"Failed to convert {x} into a numeric value") from e
209
+
210
+
211
+ def _fix_bool_field(x):
212
+ """
213
+ Attempts to fix an invalid boolean field value.
214
+
215
+ Args:
216
+ x: The value to fix.
217
+
218
+ Returns:
219
+ The fixed boolean value.
220
+
221
+ Raises:
222
+ ValueError: If the value cannot be converted into a valid boolean value.
223
+ """
224
+ try:
225
+ x = strip_lower(to_str(x))
226
+ if x in ["true", "1", "correct", "yes"]:
227
+ return True
228
+
229
+ elif x in ["false", "0", "incorrect", "no", "none", "n/a"]:
230
+ return False
231
+
232
+ raise ValueError(f"Failed to convert {x} into a boolean value")
233
+ except Exception as e:
234
+ raise ValueError(f"Failed to convert {x} into a boolean value") from e
235
+
236
+
237
+ def _fix_str_field(x):
238
+ """
239
+ Attempts to fix an invalid string field value.
240
+
241
+ Args:
242
+ x: The value to fix.
243
+
244
+ Returns:
245
+ The fixed string value.
246
+
247
+ Raises:
248
+ ValueError: If the value cannot be converted into a valid string value.
249
+ """
250
+ try:
251
+ x = to_str(x)
252
+ if isinstance(x, str):
253
+ return x
254
+ raise ValueError(f"Failed to convert {x} into a string value")
255
+ except Exception as e:
256
+ raise ValueError(f"Failed to convert {x} into a string value") from e
257
+
258
+
259
+ def _fix_enum_field(x, choices, **kwargs):
260
+ """
261
+ Attempts to fix an invalid enum field value.
262
+
263
+ Args:
264
+ x: The value to fix.
265
+ choices: The list of valid choices for the enum field.
266
+ **kwargs: Additional keyword arguments for fixing the value.
267
+
268
+ Returns:
269
+ The fixed enum value.
270
+
271
+ Raises:
272
+ ValueError: If the value cannot be converted into a valid enum value.
273
+ """
274
+ try:
275
+ x = to_str(x)
276
+ return StringMatch.choose_most_similar(x, choices, **kwargs)
277
+ except Exception as e:
278
+ raise ValueError(f"Failed to convert {x} into one of the choices") from e
279
+
280
+
281
+ validation_funcs = {
282
+ "number": check_number_field,
283
+ "bool": check_bool_field,
284
+ "str": check_str_field,
285
+ "enum": check_enum_field,
286
+ "action": check_action_field,
287
+ "dict": check_dict_field,
288
+ }
lionagi/libs/sys_util.py CHANGED
@@ -3,11 +3,26 @@ MIT License
3
3
 
4
4
  Copyright (c) 2023 HaiyangLi quantocean.li@gmail.com
5
5
 
6
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
7
-
8
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9
-
10
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6
+ Permission is hereby granted, free of charge, to any person
7
+ obtaining a copy of this software and associated documentation
8
+ files (the "Software"), to deal in the Software without
9
+ restriction, including without limitation the rights to use,
10
+ copy, modify, merge, publish, distribute, sublicense, and/or
11
+ sell copies of the Software, and to permit persons to whom
12
+ the Software is furnished to do so, subject to the following
13
+ conditions:
14
+
15
+ The above copyright notice and this permission notice shall be
16
+ included in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22
+ BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23
+ ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
11
26
  """
12
27
 
13
28
  import copy
@@ -257,7 +272,7 @@ class SysUtil:
257
272
  """
258
273
  try:
259
274
  if not SysUtil.is_package_installed(package_name):
260
- print("check")
275
+ # print("check")
261
276
  if attempt_install:
262
277
  logging.info(
263
278
  f"Package {package_name} not found. Attempting to install."
@@ -363,6 +378,7 @@ class SysUtil:
363
378
  dir_exist_ok: bool = True,
364
379
  time_prefix: bool = False,
365
380
  custom_timestamp_format: str | None = None,
381
+ random_hash_digits=0,
366
382
  ) -> Path:
367
383
  """
368
384
  Creates a path with an optional timestamp in the specified directory.
@@ -400,7 +416,13 @@ class SysUtil:
400
416
  else:
401
417
  filename = name
402
418
 
403
- full_filename = f"{filename}{ext}"
419
+ random_hash = (
420
+ "-" + SysUtil.create_id(random_hash_digits)
421
+ if random_hash_digits > 0
422
+ else ""
423
+ )
424
+
425
+ full_filename = f"{filename}{random_hash}{ext}"
404
426
  full_path = directory / full_filename
405
427
  full_path.parent.mkdir(parents=True, exist_ok=dir_exist_ok)
406
428
 
File without changes
File without changes
@@ -0,0 +1,20 @@
1
+ # task1 = task1 or """
2
+ # 1. read through the given functions, and try to understand what they do.
3
+ # 2. if any function appear undefined in the environment, define them according to given information
4
+ # 3. add a few test cases and check correctness
5
+ # """
6
+
7
+ # context = "codes to evaluate: "+ context
8
+
9
+ # task2 = task2 or f"""
10
+ # 1. validate correctness, and add 5-10 new functions using pure python
11
+ # 2. improve time/space complexity while preserving usage behavior
12
+ # 3. run to make sure correctness
13
+ # """
14
+
15
+ # task3 = task3 or f"""
16
+ # present the full implementation and save as: {filename}.txt
17
+ # 1. add typing and google format docstrings
18
+ # 2. add a couple examples in the docstrings
19
+ # 3. add unittests
20
+ # """
@@ -0,0 +1,22 @@
1
+ GUIDANCE_RESPONSE = """
2
+ ...
3
+ """
4
+
5
+ PLAN_PROMPT = "..."
6
+ WRITE_PROMPT = "..."
7
+ REVIEW_PROMPT = "..."
8
+ MODIFY_PROMPT = """
9
+ ...
10
+ """
11
+ DEBUG_PROMPT = """
12
+ ...
13
+ """
14
+
15
+ CODER_PROMPTS = {
16
+ "system": GUIDANCE_RESPONSE,
17
+ "plan_code": PLAN_PROMPT,
18
+ "write_code": WRITE_PROMPT,
19
+ "review_code": REVIEW_PROMPT,
20
+ "modify_code": MODIFY_PROMPT,
21
+ "debug_code": DEBUG_PROMPT,
22
+ }
@@ -0,0 +1,121 @@
1
+ import asyncio
2
+ from lionagi.core import Session
3
+
4
+ from .base_prompts import CODER_PROMPTS
5
+ from .util import extract_code_blocks, install_missing_dependencies, set_up_interpreter
6
+
7
+
8
+ class Coder:
9
+ def __init__(
10
+ self, prompts=None, session=None, session_kwargs=None, required_libraries=None
11
+ ):
12
+ print("Initializing Coder...")
13
+ self.prompts = prompts or CODER_PROMPTS
14
+ self.session = session or self._create_session(session_kwargs)
15
+ self.required_libraries = required_libraries or ["lionagi"]
16
+ print("Coder initialized.")
17
+
18
+ def _create_session(self, session_kwargs=None):
19
+ print("Creating session...")
20
+ session_kwargs = session_kwargs or {}
21
+ session = Session(system=self.prompts["system"], **session_kwargs)
22
+ print("Session created.")
23
+ return session
24
+
25
+ async def _plan_code(self, context):
26
+ print("Planning code...")
27
+ plans = await self.session.chat(self.prompts["plan_code"], context=context)
28
+ print("Code planning completed.")
29
+ return plans
30
+
31
+ async def _write_code(self, context=None):
32
+ print("Writing code...")
33
+ code = await self.session.chat(self.prompts["write_code"], context=context)
34
+ print("Code writing completed.")
35
+ return extract_code_blocks(code)
36
+
37
+ async def _review_code(self, context=None):
38
+ print("Reviewing code...")
39
+ code = await self.session.chat(self.prompts["review_code"], context=context)
40
+ print("Code review completed.")
41
+ return code
42
+
43
+ async def _modify_code(self, context=None):
44
+ print("Modifying code...")
45
+ code = await self.session.chat(self.prompts["modify_code"], context=context)
46
+ print("Code modification completed.")
47
+ return code
48
+
49
+ async def _debug_code(self, context=None):
50
+ print("Debugging code...")
51
+ code = await self.session.chat(self.prompts["debug_code"], context=context)
52
+ print("Code debugging completed.")
53
+ return code
54
+
55
+ def _handle_execution_error(self, execution, required_libraries=None):
56
+ print("Handling execution error...")
57
+ if execution.error and execution.error.name == "ModuleNotFoundError":
58
+ print("ModuleNotFoundError detected. Installing missing dependencies...")
59
+ install_missing_dependencies(required_libraries)
60
+ print("Dependencies installed. Retrying execution.")
61
+ return "try again"
62
+ elif execution.error:
63
+ print(f"Execution error: {execution.error}")
64
+ return execution.error
65
+
66
+ def execute_code(self, code, **kwargs):
67
+ print("Executing code...")
68
+ interpreter = set_up_interpreter()
69
+ with interpreter as sandbox:
70
+ print("Running code in sandbox...")
71
+ execution = sandbox.notebook.exec_cell(code, **kwargs)
72
+ error = self._handle_execution_error(
73
+ execution, required_libraries=kwargs.get("required_libraries")
74
+ )
75
+ if error == "try again":
76
+ print("Retrying code execution...")
77
+ execution = sandbox.notebook.exec_cell(code, **kwargs)
78
+ print("Code execution completed.")
79
+ return execution
80
+
81
+
82
+ async def main():
83
+ print("Starting main function...")
84
+ coder = Coder()
85
+
86
+ code_prompt = """
87
+ write a pure python function that takes a list of integers and returns the sum of all the integers in the list. write a couple tests as well
88
+ """
89
+
90
+ print(f"Code prompt: {code_prompt}")
91
+
92
+ print("Planning code...")
93
+ code_plan = await coder._plan_code(context=code_prompt)
94
+ print("Code plan generated.")
95
+
96
+ print("Writing code...")
97
+ code = await coder._write_code()
98
+ print("Code written.")
99
+
100
+ print("Executing code...")
101
+ execution_result = coder.execute_code(code)
102
+ print("Code execution completed.")
103
+
104
+ from IPython.display import Markdown
105
+
106
+ print("Displaying code plan...")
107
+ Markdown(code_plan)
108
+
109
+ print("Displaying generated code...")
110
+ print(code)
111
+
112
+ print("Displaying execution result...")
113
+ print(execution_result)
114
+
115
+ print("Main function completed.")
116
+
117
+
118
+ if __name__ == "__main__":
119
+ print("Running script...")
120
+ asyncio.run(main())
121
+ print("Script execution completed.")
@@ -0,0 +1,91 @@
1
+ E2B_key_scheme = "E2B_API_KEY"
2
+
3
+
4
+ def set_up_interpreter(interpreter_provider="e2b", key_scheme=E2B_key_scheme):
5
+
6
+ if interpreter_provider == "e2b":
7
+ from dotenv import load_dotenv
8
+
9
+ load_dotenv()
10
+
11
+ from lionagi.libs import SysUtil
12
+
13
+ SysUtil.check_import("e2b_code_interpreter")
14
+
15
+ from e2b_code_interpreter import CodeInterpreter # type: ignore
16
+ from os import getenv
17
+
18
+ return CodeInterpreter(api_key=getenv(key_scheme))
19
+
20
+ else:
21
+ raise ValueError("Invalid interpreter provider")
22
+
23
+
24
+ def extract_code_blocks(code):
25
+ print("Extracting code blocks...")
26
+ code_blocks = []
27
+ lines = code.split("\n")
28
+ inside_code_block = False
29
+ current_block = []
30
+
31
+ for line in lines:
32
+ if line.startswith("```"):
33
+ if inside_code_block:
34
+ code_blocks.append("\n".join(current_block))
35
+ current_block = []
36
+ inside_code_block = False
37
+ else:
38
+ inside_code_block = True
39
+ elif inside_code_block:
40
+ current_block.append(line)
41
+
42
+ if current_block:
43
+ code_blocks.append("\n".join(current_block))
44
+
45
+ print(f"Extracted {len(code_blocks)} code block(s).")
46
+ return "\n\n".join(code_blocks)
47
+
48
+
49
+ def install_missing_dependencies(required_libraries):
50
+ print("Checking for missing dependencies...")
51
+ missing_libraries = [
52
+ library for library in required_libraries if not is_library_installed(library)
53
+ ]
54
+
55
+ if missing_libraries:
56
+ print(f"Missing libraries: {', '.join(missing_libraries)}")
57
+ for library in missing_libraries:
58
+ print(f"Installing {library}...")
59
+ install_library(library)
60
+ print("Installation completed.")
61
+ else:
62
+ print("All required dependencies are already installed.")
63
+
64
+
65
+ def is_library_installed(library):
66
+ try:
67
+ import importlib
68
+
69
+ importlib.import_module(library)
70
+ print(f"{library} is already installed.")
71
+ return True
72
+ except ImportError:
73
+ print(f"{library} is not installed.")
74
+ return False
75
+
76
+
77
+ def install_library(library):
78
+ try:
79
+ import subprocess
80
+ import sys
81
+
82
+ subprocess.check_call([sys.executable, "-m", "pip", "install", library])
83
+ print(f"Successfully installed {library}.")
84
+ except subprocess.CalledProcessError as e:
85
+ print(f"Error occurred while installing {library}: {str(e)}")
86
+ print(
87
+ "Please check the error message and ensure you have the necessary permissions to install packages."
88
+ )
89
+ print(
90
+ "You may need to run the script with administrative privileges or use a virtual environment."
91
+ )
File without changes
File without changes