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
@@ -1,14 +1,14 @@
1
1
  from collections import deque
2
2
  from typing import Tuple
3
3
 
4
- from lionagi.libs.sys_util import PATH_TYPE
4
+ from pathlib import Path
5
5
  from lionagi.libs import BaseService, convert, dataframe
6
6
 
7
- from lionagi.core.schema import TOOL_TYPE, Tool, DataLogger
8
- from lionagi.core.tool import ToolManager
9
- from lionagi.core.mail import MailManager
10
- from lionagi.core.messages import System, Instruction
11
- from lionagi.core.branch import Branch
7
+ from lionagi.core.generic import DataLogger
8
+ from lionagi.core.tool import ToolManager, Tool, TOOL_TYPE
9
+ from lionagi.core.mail.mail_manager import MailManager
10
+ from lionagi.core.messages.schema import System, Instruction
11
+ from lionagi.core.branch.branch import Branch
12
12
  from lionagi.core.flow.polyflow import PolyChat
13
13
 
14
14
 
@@ -41,7 +41,7 @@ class Session:
41
41
  tool_manager: ToolManager | None = None,
42
42
  messages: dataframe.ln_DataFrame | None = None,
43
43
  datalogger: None | DataLogger = None,
44
- persist_path: PATH_TYPE | None = None,
44
+ persist_path: Path | str | None = None,
45
45
  ):
46
46
  """Initialize a new session with optional configuration for managing conversations.
47
47
 
@@ -226,7 +226,7 @@ class Session:
226
226
  @classmethod
227
227
  def from_csv(
228
228
  cls,
229
- filepath: PATH_TYPE,
229
+ filepath: Path | str,
230
230
  system: dict | list | System | None = None,
231
231
  sender: str | None = None,
232
232
  llmconfig: dict[str, str | int | dict] | None = None,
@@ -272,7 +272,7 @@ class Session:
272
272
  @classmethod
273
273
  def from_json(
274
274
  cls,
275
- filepath: PATH_TYPE,
275
+ filepath: Path | str,
276
276
  system: dict | list | System | None = None,
277
277
  sender: str | None = None,
278
278
  llmconfig: dict[str, str | int | dict] | None = None,
@@ -852,8 +852,8 @@ class Session:
852
852
 
853
853
  def take_branch(self, branch):
854
854
  self.branches[branch.branch_name] = branch
855
- self.mail_manager.sources[branch.branch_name] = branch
856
- self.mail_manager.mails[branch.branch_name] = {}
855
+ self.mail_manager.sources[branch.id_] = branch
856
+ self.mail_manager.mails[branch.id_] = {}
857
857
 
858
858
  def collect(self, from_: str | Branch | list[str | Branch] | None = None):
859
859
  """
@@ -872,16 +872,17 @@ class Session:
872
872
  >>> session.collect() # Collects from all branches
873
873
  """
874
874
  if from_ is None:
875
- for branch in self.branches.keys():
876
- self.mail_manager.collect(branch)
875
+ for branch in self.branches.values():
876
+ self.mail_manager.collect(branch.id_)
877
877
  else:
878
878
  if not isinstance(from_, list):
879
- from_ = convert.to_list(from_)
879
+ from_ = [from_]
880
880
  for branch in from_:
881
- if isinstance(branch, Branch):
882
- branch = branch.name
883
881
  if isinstance(branch, str):
884
- self.mail_manager.collect(branch)
882
+ branch = self.branches[branch]
883
+ self.mail_manager.collect(branch.id_)
884
+ elif isinstance(branch, Branch):
885
+ self.mail_manager.collect(branch.id_)
885
886
 
886
887
  def send(self, to_: str | Branch | list[str | Branch] | None = None):
887
888
  """
@@ -900,16 +901,17 @@ class Session:
900
901
  >>> session.send() # Sends to all branches
901
902
  """
902
903
  if to_ is None:
903
- for branch in self.branches.keys():
904
- self.mail_manager.send(branch)
904
+ for branch in self.branches.values():
905
+ self.mail_manager.send(branch.id_)
905
906
  else:
906
907
  if not isinstance(to_, list):
907
908
  to_ = [to_]
908
909
  for branch in to_:
909
- if isinstance(branch, Branch):
910
- branch = branch.name
911
910
  if isinstance(branch, str):
912
- self.mail_manager.send(branch)
911
+ branch = self.branches[branch]
912
+ self.mail_manager.send(branch.id_)
913
+ if isinstance(branch, Branch):
914
+ self.mail_manager.send(branch.id_)
913
915
 
914
916
  def collect_send_all(self, receive_all=False):
915
917
  """
@@ -1,3 +1,5 @@
1
+ from .tool import Tool, TOOL_TYPE
1
2
  from .tool_manager import ToolManager, func_to_tool
2
3
 
3
- __all__ = ["ToolManager", "func_to_tool"]
4
+
5
+ __all__ = ["Tool", "TOOL_TYPE", "ToolManager", "func_to_tool"]
@@ -0,0 +1,28 @@
1
+ from typing import Any
2
+
3
+ from pydantic import field_serializer
4
+ from lionagi.core.generic import Node
5
+
6
+
7
+ class Tool(Node):
8
+ """
9
+ Represents a tool, extending BaseNode with specific functionalities and configurations.
10
+
11
+ Attributes:
12
+ func: The main function or capability of the tool.
13
+ schema_: An optional schema defining the structure and constraints of data the tool works with.
14
+ manual: Optional documentation or manual for using the tool.
15
+ parser: An optional parser associated with the tool for data processing or interpretation.
16
+ """
17
+
18
+ func: Any
19
+ schema_: dict | None = None
20
+ manual: Any | None = None
21
+ parser: Any | None = None
22
+
23
+ @field_serializer("func")
24
+ def serialize_func(self, func):
25
+ return func.__name__
26
+
27
+
28
+ TOOL_TYPE = bool | Tool | str | list[Tool | str | dict] | dict
@@ -1,9 +1,9 @@
1
- from typing import Tuple, Any, TypeVar, Callable
2
-
3
1
  import asyncio
4
2
 
3
+ from typing import Tuple, Any, TypeVar, Callable
5
4
  from lionagi.libs import func_call, convert, ParseUtil
6
- from lionagi.core.schema import Tool, TOOL_TYPE
5
+
6
+ from lionagi.core.tool.tool import Tool, TOOL_TYPE
7
7
 
8
8
  T = TypeVar("T", bound=Tool)
9
9
 
@@ -17,7 +17,7 @@ class ToolManager:
17
17
  calls.
18
18
 
19
19
  Attributes:
20
- registry (dict[str, Tool]): A dictionary to hold registered tools, keyed by their names.
20
+ registry (dict[str, Tool]): A dictionary to hold registered tools, keyed by their names.
21
21
  """
22
22
 
23
23
  registry: dict = {}
@@ -27,10 +27,10 @@ class ToolManager:
27
27
  Checks if a tool name already exists in the registry.
28
28
 
29
29
  Args:
30
- name (str): The name of the tool to check.
30
+ name (str): The name of the tool to check.
31
31
 
32
32
  Returns:
33
- bool: True if the name exists, False otherwise.
33
+ bool: True if the name exists, False otherwise.
34
34
  """
35
35
  return name in self.registry
36
36
 
@@ -43,10 +43,10 @@ class ToolManager:
43
43
  Registers a tool in the registry. Raises a TypeError if the object is not an instance of Tool.
44
44
 
45
45
  Args:
46
- tool (Tool): The tool instance to register.
46
+ tool (Tool): The tool instance to register.
47
47
 
48
48
  Raises:
49
- TypeError: If the provided object is not an instance of Tool.
49
+ TypeError: If the provided object is not an instance of Tool.
50
50
  """
51
51
  if isinstance(tool, Callable):
52
52
  tool = func_to_tool(tool)[0]
@@ -60,13 +60,13 @@ class ToolManager:
60
60
  Invokes a registered tool's function with the given arguments. Supports both coroutine and regular functions.
61
61
 
62
62
  Args:
63
- func_call (Tuple[str, Dict[str, Any]]): A tuple containing the function name and a dictionary of keyword arguments.
63
+ func_call (Tuple[str, Dict[str, Any]]): A tuple containing the function name and a dictionary of keyword arguments.
64
64
 
65
65
  Returns:
66
- Any: The result of the function call.
66
+ Any: The result of the function call.
67
67
 
68
68
  Raises:
69
- ValueError: If the function name is not registered or if there's an error during function invocation.
69
+ ValueError: If the function name is not registered or if there's an error during function invocation.
70
70
  """
71
71
  name, kwargs = func_calls
72
72
  if not self.name_existed(name):
@@ -93,13 +93,13 @@ class ToolManager:
93
93
  Extracts a function call and arguments from a response dictionary.
94
94
 
95
95
  Args:
96
- response (dict): The response dictionary containing the function call information.
96
+ response (dict): The response dictionary containing the function call information.
97
97
 
98
98
  Returns:
99
- Tuple[str, dict]: A tuple containing the function name and a dictionary of arguments.
99
+ Tuple[str, dict]: A tuple containing the function name and a dictionary of arguments.
100
100
 
101
101
  Raises:
102
- ValueError: If the response does not contain valid function call information.
102
+ ValueError: If the response does not contain valid function call information.
103
103
  """
104
104
  try:
105
105
  func = response["action"][7:]
@@ -118,7 +118,7 @@ class ToolManager:
118
118
  Registers multiple tools in the registry.
119
119
 
120
120
  Args:
121
- tools (list[Tool]): A list of tool instances to register.
121
+ tools (list[Tool]): A list of tool instances to register.
122
122
  """
123
123
  func_call.lcall(tools, self._register_tool)
124
124
 
@@ -127,7 +127,7 @@ class ToolManager:
127
127
  Generates a list of schemas for all registered tools.
128
128
 
129
129
  Returns:
130
- list[dict[str, Any]]: A list of tool schemas.
130
+ list[dict[str, Any]]: A list of tool schemas.
131
131
 
132
132
  """
133
133
  return [tool.schema_ for tool in self.registry.values()]
@@ -137,14 +137,14 @@ class ToolManager:
137
137
  Parses tool information and generates a dictionary for tool invocation.
138
138
 
139
139
  Args:
140
- tools: Tool information which can be a single Tool instance, a list of Tool instances, a tool name, or a list of tool names.
141
- **kwargs: Additional keyword arguments.
140
+ tools: Tool information which can be a single Tool instance, a list of Tool instances, a tool name, or a list of tool names.
141
+ **kwargs: Additional keyword arguments.
142
142
 
143
143
  Returns:
144
- dict: A dictionary containing tool schema information and any additional keyword arguments.
144
+ dict: A dictionary containing tool schema information and any additional keyword arguments.
145
145
 
146
146
  Raises:
147
- ValueError: If a tool name is provided that is not registered.
147
+ ValueError: If a tool name is provided that is not registered.
148
148
  """
149
149
 
150
150
  def tool_check(tool):
@@ -154,7 +154,7 @@ class ToolManager:
154
154
  return tool.schema_
155
155
  elif isinstance(tool, str):
156
156
  if self.name_existed(tool):
157
- tool = self.registry[tool]
157
+ tool: Tool = self.registry[tool]
158
158
  return tool.schema_
159
159
  else:
160
160
  raise ValueError(f"Function {tool} is not registered.")
@@ -190,66 +190,66 @@ def func_to_tool(
190
190
  objects with structured metadata.
191
191
 
192
192
  Args:
193
- func_ (Callable): The function to be transformed into a Tool object. This
194
- function should have a docstring that follows the
195
- specified docstring style for accurate schema generation.
196
- parser (Optional[Any]): An optional parser object associated with the Tool.
197
- This parameter is currently not utilized in the
198
- transformation process but is included for future
199
- compatibility and extension purposes.
200
- docstring_style (str): The format of the docstring to be parsed, indicating
201
- the convention used in the function's docstring.
202
- Supports 'google' for Google-style docstrings and
203
- 'reST' for reStructuredText-style docstrings. The
204
- chosen style affects how the docstring is parsed and
205
- how the schema is generated.
193
+ func_ (Callable): The function to be transformed into a Tool object. This
194
+ function should have a docstring that follows the
195
+ specified docstring style for accurate schema generation.
196
+ parser (Optional[Any]): An optional parser object associated with the Tool.
197
+ This parameter is currently not utilized in the
198
+ transformation process but is included for future
199
+ compatibility and extension purposes.
200
+ docstring_style (str): The format of the docstring to be parsed, indicating
201
+ the convention used in the function's docstring.
202
+ Supports 'google' for Google-style docstrings and
203
+ 'reST' for reStructuredText-style docstrings. The
204
+ chosen style affects how the docstring is parsed and
205
+ how the schema is generated.
206
206
 
207
207
  Returns:
208
- Tool: An object representing the original function wrapped as a Tool, along
209
- with its generated schema. This Tool object can be used in systems that
210
- require detailed metadata about functions, facilitating tasks such as
211
- automatic documentation generation, user interface creation, or
212
- integration with other software tools.
208
+ Tool: An object representing the original function wrapped as a Tool, along
209
+ with its generated schema. This Tool object can be used in systems that
210
+ require detailed metadata about functions, facilitating tasks such as
211
+ automatic documentation generation, user interface creation, or
212
+ integration with other software tools.
213
213
 
214
214
  Examples:
215
- >>> def example_function_google(param1: int, param2: str) -> bool:
216
- ... '''
217
- ... An example function using Google style docstrings.
218
- ...
219
- ... Args:
220
- ... param1 (int): The first parameter, demonstrating an integer input_.
221
- ... param2 (str): The second parameter, demonstrating a string input_.
222
- ...
223
- ... Returns:
224
- ... bool: A boolean value, illustrating the return type.
225
- ... '''
226
- ... return True
227
- ...
228
- >>> tool_google = func_to_tool(example_function_google, docstring_style='google')
229
- >>> print(isinstance(tool_google, Tool))
230
- True
231
-
232
- >>> def example_function_reST(param1: int, param2: str) -> bool:
233
- ... '''
234
- ... An example function using reStructuredText (reST) style docstrings.
235
- ...
236
- ... :param param1: The first parameter, demonstrating an integer input_.
237
- ... :type param1: int
238
- ... :param param2: The second parameter, demonstrating a string input_.
239
- ... :type param2: str
240
- ... :returns: A boolean value, illustrating the return type.
241
- ... :rtype: bool
242
- ... '''
243
- ... return True
244
- ...
245
- >>> tool_reST = func_to_tool(example_function_reST, docstring_style='reST')
246
- >>> print(isinstance(tool_reST, Tool))
247
- True
215
+ >>> def example_function_google(param1: int, param2: str) -> bool:
216
+ ... '''
217
+ ... An example function using Google style docstrings.
218
+ ...
219
+ ... Args:
220
+ ... param1 (int): The first parameter, demonstrating an integer input_.
221
+ ... param2 (str): The second parameter, demonstrating a string input_.
222
+ ...
223
+ ... Returns:
224
+ ... bool: A boolean value, illustrating the return type.
225
+ ... '''
226
+ ... return True
227
+ ...
228
+ >>> tool_google = func_to_tool(example_function_google, docstring_style='google')
229
+ >>> print(isinstance(tool_google, Tool))
230
+ True
231
+
232
+ >>> def example_function_reST(param1: int, param2: str) -> bool:
233
+ ... '''
234
+ ... An example function using reStructuredText (reST) style docstrings.
235
+ ...
236
+ ... :param param1: The first parameter, demonstrating an integer input_.
237
+ ... :type param1: int
238
+ ... :param param2: The second parameter, demonstrating a string input_.
239
+ ... :type param2: str
240
+ ... :returns: A boolean value, illustrating the return type.
241
+ ... :rtype: bool
242
+ ... '''
243
+ ... return True
244
+ ...
245
+ >>> tool_reST = func_to_tool(example_function_reST, docstring_style='reST')
246
+ >>> print(isinstance(tool_reST, Tool))
247
+ True
248
248
 
249
249
  Note:
250
- The transformation process relies heavily on the accuracy and completeness of
251
- the function's docstring. Functions with incomplete or incorrectly formatted
252
- docstrings may result in incomplete or inaccurate Tool schemas.
250
+ The transformation process relies heavily on the accuracy and completeness of
251
+ the function's docstring. Functions with incomplete or incorrectly formatted
252
+ docstrings may result in incomplete or inaccurate Tool schemas.
253
253
  """
254
254
 
255
255
  fs = []
File without changes
@@ -0,0 +1,115 @@
1
+ import ast
2
+ import operator
3
+
4
+
5
+ class ASTEvaluator:
6
+ """
7
+ Safely evaluates expressions using AST parsing to prevent unsafe operations.
8
+ """
9
+
10
+ def __init__(self):
11
+ self.allowed_operators = {
12
+ ast.Eq: operator.eq,
13
+ ast.NotEq: operator.ne,
14
+ ast.Lt: operator.lt,
15
+ ast.LtE: operator.le,
16
+ ast.Gt: operator.gt,
17
+ ast.GtE: operator.ge,
18
+ # Additional operators can be added here as needed
19
+ }
20
+
21
+ def evaluate(self, expression, context):
22
+ """
23
+ Evaluate a condition expression within a given context using AST parsing.
24
+ """
25
+ try:
26
+ tree = ast.parse(expression, mode="eval")
27
+ return self._evaluate_node(tree.body, context)
28
+ except Exception as e:
29
+ raise ValueError(f"Failed to evaluate expression: {expression}. Error: {e}")
30
+
31
+ def _evaluate_node(self, node, context):
32
+ if isinstance(node, ast.Compare):
33
+ left = self._evaluate_node(node.left, context)
34
+ for operation, comparator in zip(node.ops, node.comparators):
35
+ op_func = self.allowed_operators.get(type(operation))
36
+ if not op_func:
37
+ raise ValueError(
38
+ f"Operation {type(operation).__name__} is not allowed."
39
+ )
40
+ right = self._evaluate_node(comparator, context)
41
+ if not op_func(left, right):
42
+ return False
43
+ return True
44
+ elif isinstance(node, ast.Name):
45
+ return context.get(node.id)
46
+ elif isinstance(node, ast.Constant):
47
+ return node.n
48
+ else:
49
+ raise ValueError(
50
+ "Unsupported AST node type encountered in condition evaluation."
51
+ )
52
+
53
+
54
+ class ASTEvaluationEngine:
55
+ """
56
+ Executes scripts safely using the SafeEvaluator for expression evaluation.
57
+ """
58
+
59
+ def __init__(self):
60
+ self.variables = {}
61
+ self.safe_evaluator = ASTEvaluator()
62
+ self.functions = {
63
+ "processData": self.process_data,
64
+ }
65
+
66
+ def process_data(self, data):
67
+ # Example placeholder function for data processing
68
+ return data * 2
69
+
70
+ def _evaluate_expression(self, expression):
71
+ """
72
+ Evaluates expressions within scripts using SafeEvaluator.
73
+ """
74
+ # Here, 'self.variables' serves as the context for the evaluation
75
+ return self.safe_evaluator.evaluate(expression, self.variables)
76
+
77
+ def _assign_variable(self, var_name, value):
78
+ """
79
+ Assigns a value to a variable within the script's context.
80
+ """
81
+ self.variables[var_name] = value
82
+
83
+ def _execute_function(self, func_name, arg):
84
+ """
85
+ Executes a predefined function with the given argument.
86
+ """
87
+ if func_name in self.functions:
88
+ function = self.functions[func_name]
89
+ return function(arg)
90
+ else:
91
+ raise ValueError(f"Function '{func_name}' is not defined.")
92
+
93
+ def execute(self, script):
94
+ """
95
+ Parses and executes a script, handling variable assignments and function calls.
96
+ """
97
+ tree = ast.parse(script, mode="exec")
98
+ for stmt in tree.body:
99
+ if isinstance(stmt, ast.Assign):
100
+ var_name = stmt.targets[
101
+ 0
102
+ ].id # Assumes single target assignment for simplicity
103
+ # Convert the AST node back to a string for evaluation
104
+ value_expr = ast.unparse(stmt.value)
105
+ value = self._evaluate_expression(value_expr)
106
+ self._assign_variable(var_name, value)
107
+ elif isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Call):
108
+ func_name = stmt.value.func.id
109
+ arg_expr = ast.unparse(stmt.value.args[0])
110
+ arg = self._evaluate_expression(arg_expr)
111
+ self._execute_function(func_name, arg)
112
+ else:
113
+ raise ValueError(
114
+ "Unsupported statement type encountered in script execution."
115
+ )