forked from kyegomez/swarms
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtool_builder.py
170 lines (145 loc) · 6.91 KB
/
tool_builder.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
import os
from pydantic import BaseModel, Field
from swarm_models import OpenAIFunctionCaller
from dotenv import load_dotenv
from typing import Any
from swarms.utils.loguru_logger import logger
from swarms.tools.prebuilt.code_executor import CodeExecutor
load_dotenv()
class Tool(BaseModel):
id: str = Field(
description="A unique identifier for the task. This should be a short, descriptive name that captures the main purpose of the task. Use - to separate words and make it lowercase."
)
plan: str = Field(
description="The comprehensive plan detailing how the task will accomplish the given task. This should include the high-level strategy, key milestones, and expected outcomes. The plan should clearly articulate what the overall goal is, what success looks like, and how progress will be measured throughout execution."
)
failures_prediction: str = Field(
description="A thorough analysis of potential failure modes and mitigation strategies. This should identify technical risks, edge cases, error conditions, and possible points of failure in the task. For each identified risk, include specific preventive measures, fallback approaches, and recovery procedures to ensure robustness and reliability."
)
rationale: str = Field(
description="The detailed reasoning and justification for why this specific task design is optimal for the given task. This should explain the key architectural decisions, tradeoffs considered, alternatives evaluated, and why this approach best satisfies the requirements. Include both technical and business factors that influenced the design."
)
code: str = Field(
description="Generate the code for the task. This should be a python function that takes in a task and returns a result. The code should be a complete and working implementation of the task. Include all necessary imports and dependencies and add types, docstrings, and comments to the code. Make sure the main code executes successfully. No placeholders or comments. Make sure the main function executes successfully."
)
def setup_model(base_model: BaseModel = Tool):
model = OpenAIFunctionCaller(
system_prompt="""You are an expert Python developer specializing in building reliable API integrations and developer tools. Your role is to generate production-ready code that follows best practices for API interactions and tool development.
When given a task, you will:
1. Design robust error handling and retry mechanisms for API calls
2. Implement proper authentication and security measures
3. Structure code for maintainability and reusability
4. Add comprehensive logging and monitoring
5. Include detailed type hints and documentation
6. Write unit tests to verify functionality
Your code should follow these principles:
- Use modern Python features and idioms
- Handle rate limits and API quotas gracefully
- Validate inputs and outputs thoroughly
- Follow security best practices for API keys and secrets
- Include clear error messages and debugging info
- Be well-documented with docstrings and comments
- Use appropriate design patterns
- Follow PEP 8 style guidelines
The generated code should be complete, tested, and ready for production use. Include all necessary imports, error handling, and helper functions.
""",
base_model=base_model,
openai_api_key=os.getenv("OPENAI_API_KEY"),
temperature=0.5,
)
return model
def generate_tool(task: str) -> Any:
model = setup_model()
response = model.run(task)
logger.info(f"Response: {response}")
# If response is a dict, get code directly
if isinstance(response, dict):
# return response.get("code", "")
code = response.get("code", "")
logger.info(f"Code: {code}")
return code
# If response is a Tool object, access code attribute
elif isinstance(response, Tool):
code = response.code
logger.info(f"Code: {code}")
return code
# If response is a string (raw code)
elif isinstance(response, str):
code = response
logger.info(f"Code: {code}")
return code
logger.error(f"Unexpected response type: {type(response)}")
return ""
def execute_generated_code(code: str) -> Any:
"""
Attempts to execute the generated Python code, handling errors and retrying if necessary.
Args:
code (str): The Python code to be executed.
Returns:
Any: Output of the code execution, or error details if execution fails.
"""
logger.info("Starting code execution")
try:
exec_namespace = {}
exec(code, exec_namespace)
# Check for any callable functions in the namespace
main_function = None
for item in exec_namespace.values():
if callable(item) and not item.__name__.startswith("__"):
main_function = item
break
if main_function:
result = main_function()
logger.info(
f"Code execution successful. Function result: {result}"
)
return result
elif "result" in exec_namespace:
logger.info(
f"Code execution successful. Result variable: {exec_namespace['result']}"
)
return exec_namespace["result"]
else:
logger.warning(
"Code execution completed but no result found"
)
return "No result or function found in executed code."
except Exception as e:
logger.error(
f"Code execution failed with error: {str(e)}",
exc_info=True,
)
return e
def retry_until_success(task: str, max_retries: int = 5):
"""
Generates and executes code until the execution is successful.
Args:
task (str): Task description to generate the required code.
"""
attempts = 0
while attempts < max_retries:
logger.info(f"Attempt {attempts + 1} of {max_retries}")
tool = generate_tool(task)
logger.debug(f"Generated code:\n{tool}")
# result = execute_generated_code(tool)
result = CodeExecutor().execute(code=tool)
logger.info(f"Result: {result}")
if isinstance(result, Exception):
logger.error(
f"Attempt {attempts + 1} failed: {str(result)}"
)
print("Retrying with updated code...")
attempts += 1
else:
logger.info(
f"Success on attempt {attempts + 1}. Result: {result}"
)
print(f"Code executed successfully: {result}")
break
else:
logger.error("Max retries reached. Execution failed.")
print("Max retries reached. Execution failed.")
# Usage
retry_until_success(
"Write a function to fetch and display weather information from a given API."
)