lionagi 0.1.0__py3-none-any.whl → 0.1.1__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.
Files changed (83) hide show
  1. lionagi/core/agent/base_agent.py +2 -3
  2. lionagi/core/branch/base.py +1 -1
  3. lionagi/core/branch/branch.py +2 -1
  4. lionagi/core/branch/flow_mixin.py +1 -1
  5. lionagi/core/branch/util.py +1 -1
  6. lionagi/core/execute/base_executor.py +1 -4
  7. lionagi/core/execute/branch_executor.py +66 -3
  8. lionagi/core/execute/instruction_map_executor.py +48 -0
  9. lionagi/core/execute/neo4j_executor.py +381 -0
  10. lionagi/core/execute/structure_executor.py +99 -3
  11. lionagi/core/flow/monoflow/ReAct.py +18 -18
  12. lionagi/core/flow/monoflow/chat_mixin.py +1 -1
  13. lionagi/core/flow/monoflow/followup.py +11 -12
  14. lionagi/core/flow/polyflow/__init__.py +1 -1
  15. lionagi/core/generic/component.py +0 -2
  16. lionagi/core/generic/condition.py +1 -1
  17. lionagi/core/generic/edge.py +52 -0
  18. lionagi/core/mail/mail_manager.py +3 -2
  19. lionagi/core/session/session.py +1 -1
  20. lionagi/experimental/__init__.py +0 -0
  21. lionagi/experimental/directive/__init__.py +0 -0
  22. lionagi/experimental/directive/evaluator/__init__.py +0 -0
  23. lionagi/experimental/directive/evaluator/ast_evaluator.py +115 -0
  24. lionagi/experimental/directive/evaluator/base_evaluator.py +202 -0
  25. lionagi/experimental/directive/evaluator/sandbox_.py +14 -0
  26. lionagi/experimental/directive/evaluator/script_engine.py +83 -0
  27. lionagi/experimental/directive/parser/__init__.py +0 -0
  28. lionagi/experimental/directive/parser/base_parser.py +215 -0
  29. lionagi/experimental/directive/schema.py +36 -0
  30. lionagi/experimental/directive/template_/__init__.py +0 -0
  31. lionagi/experimental/directive/template_/base_template.py +63 -0
  32. lionagi/experimental/tool/__init__.py +0 -0
  33. lionagi/experimental/tool/function_calling.py +43 -0
  34. lionagi/experimental/tool/manual.py +66 -0
  35. lionagi/experimental/tool/schema.py +59 -0
  36. lionagi/experimental/tool/tool_manager.py +138 -0
  37. lionagi/experimental/tool/util.py +16 -0
  38. lionagi/experimental/work/__init__.py +0 -0
  39. lionagi/experimental/work/_logger.py +25 -0
  40. lionagi/experimental/work/exchange.py +0 -0
  41. lionagi/experimental/work/schema.py +30 -0
  42. lionagi/experimental/work/tests.py +72 -0
  43. lionagi/experimental/work/util.py +0 -0
  44. lionagi/experimental/work/work_function.py +89 -0
  45. lionagi/experimental/work/worker.py +12 -0
  46. lionagi/integrations/bridge/autogen_/__init__.py +0 -0
  47. lionagi/integrations/bridge/autogen_/autogen_.py +124 -0
  48. lionagi/integrations/bridge/llamaindex_/get_index.py +294 -0
  49. lionagi/integrations/bridge/llamaindex_/llama_pack.py +227 -0
  50. lionagi/integrations/bridge/transformers_/__init__.py +0 -0
  51. lionagi/integrations/bridge/transformers_/install_.py +36 -0
  52. lionagi/integrations/config/oai_configs.py +1 -1
  53. lionagi/integrations/config/ollama_configs.py +1 -1
  54. lionagi/integrations/config/openrouter_configs.py +1 -1
  55. lionagi/integrations/storage/__init__.py +3 -0
  56. lionagi/integrations/storage/neo4j.py +673 -0
  57. lionagi/integrations/storage/storage_util.py +289 -0
  58. lionagi/integrations/storage/to_csv.py +63 -0
  59. lionagi/integrations/storage/to_excel.py +67 -0
  60. lionagi/libs/ln_knowledge_graph.py +405 -0
  61. lionagi/libs/ln_queue.py +101 -0
  62. lionagi/libs/ln_tokenizer.py +57 -0
  63. lionagi/libs/sys_util.py +1 -1
  64. lionagi/lions/__init__.py +0 -0
  65. lionagi/lions/coder/__init__.py +0 -0
  66. lionagi/lions/coder/add_feature.py +20 -0
  67. lionagi/lions/coder/base_prompts.py +22 -0
  68. lionagi/lions/coder/coder.py +121 -0
  69. lionagi/lions/coder/util.py +91 -0
  70. lionagi/lions/researcher/__init__.py +0 -0
  71. lionagi/lions/researcher/data_source/__init__.py +0 -0
  72. lionagi/lions/researcher/data_source/finhub_.py +191 -0
  73. lionagi/lions/researcher/data_source/google_.py +199 -0
  74. lionagi/lions/researcher/data_source/wiki_.py +96 -0
  75. lionagi/lions/researcher/data_source/yfinance_.py +21 -0
  76. lionagi/tests/libs/test_queue.py +67 -0
  77. lionagi/tests/test_core/test_branch.py +0 -1
  78. lionagi/version.py +1 -1
  79. {lionagi-0.1.0.dist-info → lionagi-0.1.1.dist-info}/METADATA +1 -1
  80. {lionagi-0.1.0.dist-info → lionagi-0.1.1.dist-info}/RECORD +83 -29
  81. {lionagi-0.1.0.dist-info → lionagi-0.1.1.dist-info}/LICENSE +0 -0
  82. {lionagi-0.1.0.dist-info → lionagi-0.1.1.dist-info}/WHEEL +0 -0
  83. {lionagi-0.1.0.dist-info → lionagi-0.1.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,289 @@
1
+ import json
2
+ import inspect
3
+ import re
4
+
5
+ from lionagi.core import System, Instruction
6
+ from lionagi.core.tool import Tool
7
+ from lionagi.core.generic.action import ActionSelection
8
+ from lionagi.core.agent.base_agent import BaseAgent
9
+ from lionagi.core.generic.condition import Condition
10
+
11
+ from lionagi.core import func_to_tool
12
+
13
+
14
+ def output_node_list(structure):
15
+ """
16
+ Processes a structure object to extract and format all associated nodes into a summary list and detailed output dictionary.
17
+
18
+ This function traverses a structure, extracting key properties of nodes and organizing them by type into a dictionary for easy access and manipulation.
19
+
20
+ Args:
21
+ structure: The structure object containing nodes and potentially other nested structures.
22
+
23
+ Returns:
24
+ tuple: A tuple containing a summary list of all nodes and a dictionary categorizing nodes by type.
25
+ """
26
+ summary_list = []
27
+ output = {}
28
+
29
+ structure_output = {
30
+ "id": structure.id_,
31
+ "timestamp": structure.timestamp,
32
+ "type": structure.class_name(),
33
+ }
34
+ summary_list.append(structure_output.copy())
35
+ structure_output["head_nodes"] = [i.id_ for i in structure.get_heads()]
36
+ # structure_output['nodes'] = json.dumps([i for i in structure.internal_nodes.keys()])
37
+ # structure_output['edges'] = json.dumps([i for i in structure.internal_edges.keys()])
38
+ output[structure_output["type"]] = [structure_output]
39
+ for node in structure.internal_nodes.values():
40
+ node_output = {
41
+ "id": node.id_,
42
+ "timestamp": node.timestamp,
43
+ "type": node.class_name(),
44
+ }
45
+ summary_list.append(node_output.copy())
46
+ if isinstance(node, System) or isinstance(node, Instruction):
47
+ node_output["content"] = json.dumps(node.content)
48
+ node_output["sender"] = node.sender
49
+ node_output["recipient"] = node.recipient
50
+ elif isinstance(node, Tool):
51
+ node_output["function"] = inspect.getsource(node.func)
52
+ # node_output['manual'] = node.manual
53
+ node_output["parser"] = (
54
+ inspect.getsource(node.parser) if node.parser else None
55
+ )
56
+ elif isinstance(node, ActionSelection):
57
+ node_output["action"] = node.action
58
+ node_output["action_kwargs"] = json.dumps(node.action_kwargs)
59
+ elif isinstance(node, BaseAgent):
60
+ node_output["structure_id"] = node.structure.id_
61
+ node_output["output_parser"] = inspect.getsource(node.output_parser)
62
+ else:
63
+ raise ValueError("Not supported node type detected")
64
+ if node_output["type"] not in output:
65
+ output[node_output["type"]] = []
66
+ output[node_output["type"]].append(node_output)
67
+
68
+ return summary_list, output
69
+
70
+
71
+ def output_edge_list(structure):
72
+ """
73
+ Extracts and formats all edges from a given structure into a list and maps any associated condition classes.
74
+
75
+ This function collects edge data from a structure, including identifiers, timestamps, labels, and conditions. It also compiles any unique condition classes associated with these edges.
76
+
77
+ Args:
78
+ structure: The structure object containing edges.
79
+
80
+ Returns:
81
+ tuple: A tuple containing a list of all edges with their details and a list of unique condition classes.
82
+ """
83
+ edge_list = []
84
+ edge_cls_dict = {}
85
+ for edge in structure.internal_edges.values():
86
+ edge_output = {
87
+ "id": edge.id_,
88
+ "timestamp": edge.timestamp,
89
+ "head": edge.head,
90
+ "tail": edge.tail,
91
+ "label": edge.label,
92
+ "bundle": str(edge.bundle),
93
+ }
94
+ if edge.condition:
95
+ cls_name = edge.condition.__class__.__qualname__
96
+ cond = json.dumps({"class": cls_name, "args": edge.condition.model_dump()})
97
+ cls = edge.string_condition()
98
+ if cls is not None and cls_name not in edge_cls_dict:
99
+ edge_cls_dict.update({cls_name: cls})
100
+ else:
101
+ cond = None
102
+ edge_output["condition"] = cond
103
+ edge_list.append(edge_output)
104
+
105
+ edge_cls_list = []
106
+ for key, value in edge_cls_dict.items():
107
+ edge_cls_list.append({"class_name": key, "class": value})
108
+
109
+ return edge_list, edge_cls_list
110
+
111
+
112
+ class ParseNode:
113
+ """
114
+ Provides static methods for converting code strings to functional definitions, classes, and for parsing various types of structured nodes based on dictionary definitions.
115
+
116
+ This utility class facilitates the dynamic execution of code and the instantiation of objects from serialized data.
117
+ """
118
+
119
+ @staticmethod
120
+ def convert_to_def(function_code):
121
+ """
122
+ Converts a string containing a function definition into a callable function object.
123
+
124
+ Args:
125
+ function_code (str): The string code of the function to convert.
126
+
127
+ Returns:
128
+ function: The converted function as a callable.
129
+
130
+ Raises:
131
+ ValueError: If the function code is invalid or the function name cannot be detected.
132
+ """
133
+ import re
134
+
135
+ match = re.search(r"def (\w+)\(", function_code)
136
+ if match:
137
+ class_name = match.group(1)
138
+ try:
139
+ exec(function_code, globals())
140
+ func = globals()[class_name]
141
+ return func
142
+ except Exception as e:
143
+ raise ValueError(f"Failed to convert str to def. Error: {e}")
144
+ else:
145
+ raise ValueError("Failed to detect function name")
146
+
147
+ @staticmethod
148
+ def convert_to_class(cls_code):
149
+ """
150
+ Converts a string containing a class definition into a class object.
151
+
152
+ Args:
153
+ cls_code (str): The string code of the class to convert.
154
+
155
+ Returns:
156
+ class: The converted class.
157
+
158
+ Raises:
159
+ ValueError: If the class code is invalid or the class name cannot be detected.
160
+ """
161
+ import re
162
+
163
+ match = re.search(r"class (\w+)\s*(?:\(([^)]+)\))?:", cls_code)
164
+ if match:
165
+ class_name = match.group(1)
166
+ try:
167
+ exec(cls_code, globals())
168
+ cls = globals()[class_name]
169
+ return cls
170
+ except Exception as e:
171
+ raise ValueError(f"Failed to convert str to class. Error: {e}")
172
+ else:
173
+ raise ValueError("Failed to detect class name")
174
+
175
+ @staticmethod
176
+ def parse_system(info_dict):
177
+ """
178
+ Parses dictionary information into a System node object.
179
+
180
+ Args:
181
+ info_dict (dict): A dictionary containing properties of a system node.
182
+
183
+ Returns:
184
+ System: An instantiated System node filled with properties from info_dict.
185
+ """
186
+ node = System(" ")
187
+ node.id_ = info_dict["id"]
188
+ node.timestamp = info_dict["timestamp"]
189
+ node.content = json.loads(info_dict["content"])
190
+ node.sender = info_dict["sender"]
191
+ node.recipient = info_dict["recipient"]
192
+ return node
193
+
194
+ @staticmethod
195
+ def parse_instruction(info_dict):
196
+ """
197
+ Parses dictionary information into an Instruction node object.
198
+
199
+ Args:
200
+ info_dict (dict): A dictionary containing properties of an instruction node.
201
+
202
+ Returns:
203
+ Instruction: An instantiated Instruction node filled with properties from info_dict.
204
+ """
205
+ node = Instruction(" ")
206
+ node.id_ = info_dict["id"]
207
+ node.timestamp = info_dict["timestamp"]
208
+ node.content = json.loads(info_dict["content"])
209
+ node.sender = info_dict["sender"]
210
+ node.recipient = info_dict["recipient"]
211
+ return node
212
+
213
+ @staticmethod
214
+ def parse_actionSelection(info_dict):
215
+ """
216
+ Parses dictionary information into an ActionSelection node object.
217
+
218
+ Args:
219
+ info_dict (dict): A dictionary containing properties of an action selection node.
220
+
221
+ Returns:
222
+ ActionSelection: An instantiated ActionSelection node filled with properties from info_dict.
223
+ """
224
+ node = ActionSelection()
225
+ node.id_ = info_dict["id"]
226
+ node.action = info_dict["action"]
227
+ if "action_kwargs" in info_dict:
228
+ if info_dict["action_kwargs"]:
229
+ node.action_kwargs = json.loads(info_dict["action_kwargs"])
230
+ elif "actionKwargs" in info_dict:
231
+ if info_dict["actionKwargs"]:
232
+ node.action_kwargs = json.loads(info_dict["actionKwargs"])
233
+ return node
234
+
235
+ @staticmethod
236
+ def parse_tool(info_dict):
237
+ """
238
+ Parses dictionary information into a Tool node object, converting associated function code into a callable.
239
+
240
+ Args:
241
+ info_dict (dict): A dictionary containing properties and function code for a tool node.
242
+
243
+ Returns:
244
+ Tool: An instantiated Tool node with the function converted from code.
245
+
246
+ Raises:
247
+ ValueError: If unsafe code is detected in the function definition.
248
+ """
249
+ func_code = info_dict["function"]
250
+ if "import os" in func_code or "__" in func_code or "import sys" in func_code:
251
+ raise ValueError(
252
+ "Unsafe code detected in Tool function. Please double check or implement explicitly"
253
+ )
254
+
255
+ func = ParseNode.convert_to_def(func_code)
256
+ tool = func_to_tool(func)
257
+ if func.__doc__:
258
+ if re.search(r":param \w+:", func.__doc__):
259
+ tool = func_to_tool(func, docstring_style="reST")
260
+
261
+ tool = tool[0]
262
+ tool.id_ = info_dict["id"]
263
+ tool.timestamp = info_dict["timestamp"]
264
+ return tool
265
+
266
+ @staticmethod
267
+ def parse_condition(condition, cls_code):
268
+ """
269
+ Parses a condition dictionary and corresponding class code into a class instance representing the condition.
270
+
271
+ Args:
272
+ condition (dict): A dictionary containing the serialized form of the condition's arguments.
273
+ cls_code (str): The class code to instantiate the condition class.
274
+
275
+ Returns:
276
+ An instance of the condition class filled with properties from the condition dictionary.
277
+
278
+ Raises:
279
+ ValueError: If the condition or class code is invalid.
280
+ """
281
+ args = condition["args"]
282
+ cls = ParseNode.convert_to_class(cls_code)
283
+
284
+ init_params = {}
285
+ for key in inspect.signature(cls.__init__).parameters.keys():
286
+ if key == "self":
287
+ continue
288
+ init_params[key] = args[key]
289
+ return cls(**init_params)
@@ -0,0 +1,63 @@
1
+ import zipfile
2
+ import pandas as pd
3
+ from pathlib import Path
4
+
5
+ from lionagi.integrations.storage.storage_util import output_node_list, output_edge_list
6
+
7
+
8
+ def _output_csv(
9
+ node_list, node_dict, edge_list, edge_cls_list, zipname="structure_storage"
10
+ ):
11
+ """
12
+ Writes provided node and edge data into multiple CSV files and compresses them into a ZIP archive.
13
+
14
+ This helper function takes lists and dictionaries of nodes and edges, converts them to pandas DataFrames,
15
+ and then writes each DataFrame to a CSV file stored inside a ZIP archive. This includes a separate CSV
16
+ for each type of node and edge, as well as edge conditions if they exist.
17
+
18
+ Args:
19
+ node_list (list): A list of dictionaries where each dictionary contains attributes of a single node.
20
+ node_dict (dict): A dictionary of lists where each key represents a node type and the value is a list of
21
+ node attributes for nodes of that type.
22
+ edge_list (list): A list of dictionaries where each dictionary contains attributes of a single edge.
23
+ edge_cls_list (list): A list of dictionaries where each dictionary contains attributes of edge conditions.
24
+ zipname (str): The base name for the output ZIP file that will store the CSV files.
25
+
26
+ Returns:
27
+ None: This function does not return a value but outputs a ZIP file containing the CSVs.
28
+ """
29
+ tables = {"Nodes": pd.DataFrame(node_list), "Edges": pd.DataFrame(edge_list)}
30
+ if edge_cls_list:
31
+ tables["EdgesCondClass"] = pd.DataFrame(edge_cls_list)
32
+ for i in node_dict:
33
+ tables[i] = pd.DataFrame(node_dict[i])
34
+
35
+ zipname = zipname + ".zip"
36
+
37
+ with zipfile.ZipFile(zipname, "w") as zf:
38
+ for i in tables:
39
+ filename = i + ".csv"
40
+ with zf.open(filename, "w") as file:
41
+ tables[i].to_csv(file, index=False)
42
+
43
+
44
+ def to_csv(structure, filename="structure_storage"):
45
+ """
46
+ Converts a structure into a series of CSV files and stores them in a compressed ZIP archive.
47
+
48
+ This function processes a given structure to extract detailed node and edge information,
49
+ including conditions if applicable. These details are then saved into separate CSV files
50
+ for nodes, edges, and any edge conditions, which are subsequently bundled into a ZIP file.
51
+
52
+ Args:
53
+ structure: An object representing the structure to be serialized. This structure should
54
+ have methods to return lists of nodes and edges.
55
+ filename (str): The base name of the output ZIP file that will store the CSV files.
56
+
57
+ Returns:
58
+ None: This function does not return a value but outputs a ZIP file containing CSVs.
59
+ """
60
+ node_list, node_dict = output_node_list(structure)
61
+ edge_list, edge_cls_list = output_edge_list(structure)
62
+
63
+ _output_csv(node_list, node_dict, edge_list, edge_cls_list, filename)
@@ -0,0 +1,67 @@
1
+ import pandas as pd
2
+ from lionagi.libs import SysUtil
3
+
4
+ from lionagi.integrations.storage.storage_util import output_node_list, output_edge_list
5
+
6
+
7
+ def _output_excel(
8
+ node_list, node_dict, edge_list, edge_cls_list, filename="structure_storage"
9
+ ):
10
+ """
11
+ Writes provided node and edge data into multiple sheets of a single Excel workbook.
12
+
13
+ This helper function takes lists and dictionaries of nodes and edges, converts them into pandas DataFrames,
14
+ and then writes each DataFrame to a distinct sheet in an Excel workbook. This includes a separate sheet
15
+ for each type of node and edge, as well as edge conditions if they exist.
16
+
17
+ Args:
18
+ node_list (list): A list of dictionaries where each dictionary contains attributes of a single node.
19
+ node_dict (dict): A dictionary of lists where each key represents a node type and the value is a list of
20
+ node attributes for nodes of that type.
21
+ edge_list (list): A list of dictionaries where each dictionary contains attributes of a single edge.
22
+ edge_cls_list (list): A list of dictionaries where each dictionary contains attributes of edge conditions.
23
+ filename (str): The base name for the output Excel file. The '.xlsx' extension will be added
24
+ automatically if not included.
25
+
26
+ Returns:
27
+ None: This function does not return a value but writes data directly to an Excel workbook.
28
+
29
+ Raises:
30
+ ImportError: If the required 'openpyxl' library is not installed, which is necessary for pandas to write Excel files.
31
+ """
32
+ SysUtil.check_import("openpyxl")
33
+
34
+ tables = {"Nodes": pd.DataFrame(node_list), "Edges": pd.DataFrame(edge_list)}
35
+ if edge_cls_list:
36
+ tables["EdgesCondClass"] = pd.DataFrame(edge_cls_list)
37
+ for i in node_dict:
38
+ tables[i] = pd.DataFrame(node_dict[i])
39
+
40
+ filename = filename + ".xlsx"
41
+
42
+ with pd.ExcelWriter(filename) as writer:
43
+ for i in tables:
44
+ tables[i].to_excel(writer, sheet_name=i, index=False)
45
+
46
+
47
+ def to_excel(structure, filename="structure_storage"):
48
+ """
49
+ Converts a structure into a series of Excel sheets within a single workbook.
50
+
51
+ This function processes the specified structure to extract detailed node and edge information,
52
+ including conditions if applicable. These details are then saved into separate sheets within an
53
+ Excel workbook for nodes, edges, and any edge conditions.
54
+
55
+ Args:
56
+ structure: An object representing the structure to be serialized. This should have methods
57
+ to return lists of nodes and edges suitable for output.
58
+ filename (str): The base name of the output Excel file. The '.xlsx' extension will be added
59
+ automatically if not included.
60
+
61
+ Returns:
62
+ None: This function does not return a value but outputs an Excel workbook with multiple sheets.
63
+ """
64
+ node_list, node_dict = output_node_list(structure)
65
+ edge_list, edge_cls_list = output_edge_list(structure)
66
+
67
+ _output_excel(node_list, node_dict, edge_list, edge_cls_list, filename)