piotrekgrl commited on
Commit
85bccd0
·
verified ·
1 Parent(s): 1961636

Upload tool

Browse files
Files changed (3) hide show
  1. app.py +7 -0
  2. requirements.txt +1 -0
  3. tool.py +136 -0
app.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ from smolagents import launch_gradio_demo
2
+ from typing import Optional
3
+ from tool import LocalPythonDebuggerTool
4
+
5
+ tool = LocalPythonDebuggerTool()
6
+
7
+ launch_gradio_demo(tool)
requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ smolagents
tool.py ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from smolagents.tools import Tool
2
+ import pdb
3
+ import smolagents
4
+ import io
5
+ import sys
6
+
7
+ class LocalPythonDebuggerTool(Tool):
8
+ name = "local-python-debugger"
9
+ description = """
10
+ The Local Python Debugger Tool is designed to assist in debugging InterpreterErrors—specifically, errors related to "Code execution failed at line".
11
+ It is not intended for other types of InterpreterErrors, such as:
12
+ - "Reached the max number of operations"
13
+ - "Code parsing failed on line"
14
+
15
+ The tool debugs code executed in the following manner:
16
+ ```python
17
+ expression = ast.parse(code)
18
+ for node in expression.body:
19
+ result = evaluate_ast(node, ...)
20
+ ```
21
+ where evaluate_ast processes the Abstract Syntax Tree (AST) by evaluating AST functions like: ast.Assign, ast.AugAssign, ast.Call, ast.Constant, ast.Name, ast.BinOp, etc.
22
+ As a result, the debugger output reflects the evaluate_ast execution context rather than a direct Python runtime environment.
23
+
24
+ Possible debugger commands:
25
+ - bt - Shows the full stack trace, helping to understand where the error occurred in the call stack.
26
+ - args - Shows the arguments passed to the function.
27
+ - l - Lists the source code of the current file.
28
+ - p {variable} - Prints the value of the variable. NOTE: variable names are different than in the code. They should be inspected first with `l` command.
29
+
30
+ """
31
+ inputs = {'code': {'type': 'string', 'description': 'code to debug'}, 'command': {'type': 'string', 'description': 'pdb command to execute'}}
32
+ output_type = "string"
33
+
34
+ def setup(self):
35
+ from smolagents import LocalPythonInterpreter
36
+ from smolagents.default_tools import FinalAnswerTool
37
+
38
+ import io
39
+ import pdb
40
+
41
+ self.python_executor = LocalPythonInterpreter(
42
+ [],
43
+ {"final_answer": FinalAnswerTool()},
44
+ max_print_outputs_length=None,
45
+ )
46
+
47
+ self.output_capture = io.StringIO()
48
+
49
+ self.pdb_instance = pdb.Pdb(stdout=self.output_capture)
50
+
51
+ def wrap_code_with_trycatch(self, code: str) -> str:
52
+ from smolagents.utils import parse_code_blobs
53
+
54
+ try:
55
+ code = parse_code_blobs(code)
56
+ except Exception as e:
57
+ pass
58
+
59
+ code_lines = code.split("\n")
60
+ for i, line in enumerate(code_lines):
61
+ code_lines[i] = f"\t{line}"
62
+ code = "\n".join(code_lines)
63
+
64
+ # add extra indentation
65
+ code = (
66
+ f"try:\n{code}\n" + "except Exception as e:" + "\n\t" + "out=sys.exc_info()"
67
+ )
68
+ code = "out=None" + "\n" + code + "\n" + "out" # provide results in output
69
+
70
+ return code
71
+
72
+ def execute_code(self, code: str, state: dict):
73
+ from smolagents.utils import parse_code_blobs
74
+
75
+ code = parse_code_blobs(code)
76
+
77
+ # Silencing the tool_validation error: execute_code: Name '' is undefined.
78
+ py_executor_output = None
79
+ py_executor_logs = None
80
+ py_executor_is_final_answer = None
81
+
82
+ py_executor_output, py_executor_logs, py_executor_is_final_answer = (
83
+ self.python_executor(code, state)
84
+ )
85
+
86
+ return py_executor_output, py_executor_logs, py_executor_is_final_answer
87
+
88
+ def execude_pdb_command(
89
+ self, command: str, traceback
90
+ ):
91
+ output = None
92
+ try:
93
+ # Set up the pdb instance with the current frame and traceback
94
+ frame = traceback.tb_frame
95
+ while frame.f_back:
96
+ frame = frame.f_back
97
+ self.pdb_instance.reset()
98
+ self.pdb_instance.setup(frame, traceback)
99
+ # Execute the pdb command
100
+ self.pdb_instance.onecmd(command)
101
+ # Retrieve the output
102
+ output = self.output_capture.getvalue()
103
+ finally:
104
+ # Clear the output capture for future use
105
+ self.output_capture.truncate(0)
106
+ self.output_capture.seek(0)
107
+
108
+ return output
109
+
110
+ def forward(self, code: str, command: str):
111
+ import sys
112
+
113
+ code = self.wrap_code_with_trycatch(code)
114
+
115
+ state = {"sys": sys}
116
+
117
+ # Silencing the tool_validation error: execute_code: Name '' is undefined.
118
+ py_executor_output = None
119
+ tb = None
120
+
121
+ py_executor_output, py_executor_logs, py_executor_is_final_answer = (
122
+ self.execute_code(code, state)
123
+ )
124
+
125
+ if py_executor_output is not None:
126
+ try:
127
+ exc_type, exc_value, tb = py_executor_output
128
+ except Exception as e:
129
+ return "No traceback found"
130
+ pdb_result = self.execude_pdb_command(command, tb)
131
+ return pdb_result
132
+
133
+ return "No traceback found"
134
+
135
+ def __init__(self, *args, **kwargs):
136
+ self.is_initialized = False