Tachi67 commited on
Commit
3f6b5c2
·
1 Parent(s): 84f1679

Upload 5 files

Browse files
InterpreterAtomicFlow.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import traceback
2
+ from copy import deepcopy
3
+ from typing import Dict, Any
4
+
5
+ from .code_interpreters.create_code_interpreter import create_code_interpreter
6
+
7
+ from aiflows.base_flows import AtomicFlow
8
+
9
+ def truncate_output(data, max_output_chars=2000):
10
+ needs_truncation = False
11
+
12
+ message = f'Output truncated. Showing the last {max_output_chars} characters.\n\n'
13
+
14
+ # Remove previous truncation message if it exists
15
+ if data.startswith(message):
16
+ data = data[len(message):]
17
+ needs_truncation = True
18
+
19
+ # If data exceeds max length, truncate it and add message
20
+ if len(data) > max_output_chars or needs_truncation:
21
+ data = message + data[-max_output_chars:]
22
+
23
+ return data
24
+
25
+
26
+ class InterpreterAtomicFlow(AtomicFlow):
27
+ """This flow is used to run the code passed from the caller.
28
+ *Expected Input*:
29
+ - `code`
30
+ - `language_of_code`
31
+
32
+ *Expected Output*:
33
+ - `interpreter_output`: output of the code interpreter
34
+
35
+ **Full credits to open-interpreter (https://github.com/KillianLucas/open-interpreter)
36
+ for the usage of code interpreters (package `code_interpreters`) and the function truncate_output()**
37
+
38
+ I'm extracting the code interpreter part from open-interpreter because the litellm version of open-interpreter
39
+ is not compatible with that of the current version of aiflows(v.0.1.7).
40
+ """
41
+ def __init__(self,
42
+ max_output=2000,
43
+ **kwargs):
44
+ super().__init__(**kwargs)
45
+ self.max_output = max_output
46
+ self._code_interpreters = {}
47
+
48
+ @classmethod
49
+ def instantiate_from_config(cls, config):
50
+ flow_config = deepcopy(config)
51
+
52
+ kwargs = {"flow_config": flow_config}
53
+
54
+ # ~~~ Instantiate flow ~~~
55
+ return cls(**kwargs)
56
+
57
+
58
+ def set_up_flow_state(self):
59
+ """
60
+ class-specific flow state: language and code,
61
+ which describes the programming language and the code to run.
62
+ """
63
+ super().set_up_flow_state()
64
+ self.flow_state["language"] = None
65
+ self.flow_state["code"] = ""
66
+
67
+ def _state_update_add_language_and_code(self,
68
+ language: str,
69
+ code: str) -> None:
70
+ """
71
+ updates the language and code passed from _process_input_data
72
+ to the flow state
73
+ """
74
+ self.flow_state["language"] = language
75
+ self.flow_state["code"] = code
76
+
77
+ def _check_input(self, input_data: Dict[str, Any]):
78
+ """
79
+ Sanity check of input data
80
+ """
81
+ # ~~~ Sanity check of input_data ~~~
82
+ assert "language" in input_data, "attribute 'language' not in input data."
83
+ assert "code" in input_data, "attribute 'code' not in input data."
84
+
85
+
86
+ def _process_input_data(self, input_data: Dict[str, Any]):
87
+ """
88
+ Allocate interpreter if any, pass input data into flow state
89
+ """
90
+ # code in Jupyter notebook that starts with '!' is actually shell command.
91
+ if input_data["language"] == "python" and input_data["code"].startswith("!"):
92
+ input_data["language"] = "shell"
93
+ input_data["code"] = input_data["code"][1:]
94
+
95
+ # ~~~ Allocate interpreter ~~~
96
+ # interpreter existence is checked in create_code_interpreter()
97
+ # TODO: consider: should we put language not supported error into output?
98
+ language = input_data["language"]
99
+ if language not in self._code_interpreters:
100
+ self._code_interpreters[language] = create_code_interpreter(language)
101
+
102
+ # ~~~ Pass input data to flow state ~~~
103
+ self._state_update_add_language_and_code(
104
+ language=language,
105
+ code=input_data["code"]
106
+ )
107
+
108
+ def _call(self):
109
+ output = ""
110
+ try:
111
+ code_interpreter = self._code_interpreters[self.flow_state["language"]]
112
+ code = self.flow_state["code"]
113
+ for line in code_interpreter.run(code):
114
+ if "output" in line:
115
+ output += "\n" + line["output"]
116
+ # Truncate output
117
+ output = truncate_output(output, self.max_output)
118
+ output = output.strip()
119
+ except:
120
+ output = traceback.format_exc()
121
+ output = output.strip()
122
+ return output
123
+
124
+ def run(
125
+ self,
126
+ input_data: Dict[str, Any]):
127
+ self._check_input(input_data)
128
+ self._process_input_data(input_data)
129
+ response = self._call()
130
+ return {"interpreter_output": response}
InterpreterAtomicFlow.yaml ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ name: "InterpreterAtomicFlow"
2
+ description: "A flow that compiles and runs codes"
README.md ADDED
@@ -0,0 +1,363 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Table of Contents
2
+
3
+ * [InterpreterAtomicFlow](#InterpreterAtomicFlow)
4
+ * [InterpreterAtomicFlow](#InterpreterAtomicFlow.InterpreterAtomicFlow)
5
+ * [set\_up\_flow\_state](#InterpreterAtomicFlow.InterpreterAtomicFlow.set_up_flow_state)
6
+ * [\_\_init\_\_](#__init__)
7
+ * [code\_interpreters](#code_interpreters)
8
+ * [code\_interpreters.language\_map](#code_interpreters.language_map)
9
+ * [code\_interpreters.create\_code\_interpreter](#code_interpreters.create_code_interpreter)
10
+ * [code\_interpreters.languages.javascript](#code_interpreters.languages.javascript)
11
+ * [preprocess\_javascript](#code_interpreters.languages.javascript.preprocess_javascript)
12
+ * [code\_interpreters.languages.shell](#code_interpreters.languages.shell)
13
+ * [preprocess\_shell](#code_interpreters.languages.shell.preprocess_shell)
14
+ * [add\_active\_line\_prints](#code_interpreters.languages.shell.add_active_line_prints)
15
+ * [code\_interpreters.languages.python](#code_interpreters.languages.python)
16
+ * [preprocess\_python](#code_interpreters.languages.python.preprocess_python)
17
+ * [add\_active\_line\_prints](#code_interpreters.languages.python.add_active_line_prints)
18
+ * [AddLinePrints](#code_interpreters.languages.python.AddLinePrints)
19
+ * [insert\_print\_statement](#code_interpreters.languages.python.AddLinePrints.insert_print_statement)
20
+ * [process\_body](#code_interpreters.languages.python.AddLinePrints.process_body)
21
+ * [visit](#code_interpreters.languages.python.AddLinePrints.visit)
22
+ * [code\_interpreters.languages.html](#code_interpreters.languages.html)
23
+ * [code\_interpreters.languages.r](#code_interpreters.languages.r)
24
+ * [R](#code_interpreters.languages.r.R)
25
+ * [preprocess\_code](#code_interpreters.languages.r.R.preprocess_code)
26
+ * [code\_interpreters.languages.powershell](#code_interpreters.languages.powershell)
27
+ * [preprocess\_powershell](#code_interpreters.languages.powershell.preprocess_powershell)
28
+ * [add\_active\_line\_prints](#code_interpreters.languages.powershell.add_active_line_prints)
29
+ * [wrap\_in\_try\_catch](#code_interpreters.languages.powershell.wrap_in_try_catch)
30
+ * [code\_interpreters.languages](#code_interpreters.languages)
31
+ * [code\_interpreters.languages.applescript](#code_interpreters.languages.applescript)
32
+ * [AppleScript](#code_interpreters.languages.applescript.AppleScript)
33
+ * [preprocess\_code](#code_interpreters.languages.applescript.AppleScript.preprocess_code)
34
+ * [add\_active\_line\_indicators](#code_interpreters.languages.applescript.AppleScript.add_active_line_indicators)
35
+ * [detect\_active\_line](#code_interpreters.languages.applescript.AppleScript.detect_active_line)
36
+ * [detect\_end\_of\_execution](#code_interpreters.languages.applescript.AppleScript.detect_end_of_execution)
37
+ * [code\_interpreters.subprocess\_code\_interpreter](#code_interpreters.subprocess_code_interpreter)
38
+ * [SubprocessCodeInterpreter](#code_interpreters.subprocess_code_interpreter.SubprocessCodeInterpreter)
39
+ * [preprocess\_code](#code_interpreters.subprocess_code_interpreter.SubprocessCodeInterpreter.preprocess_code)
40
+ * [code\_interpreters.base\_code\_interpreter](#code_interpreters.base_code_interpreter)
41
+ * [BaseCodeInterpreter](#code_interpreters.base_code_interpreter.BaseCodeInterpreter)
42
+
43
+ <a id="InterpreterAtomicFlow"></a>
44
+
45
+ # InterpreterAtomicFlow
46
+
47
+ <a id="InterpreterAtomicFlow.InterpreterAtomicFlow"></a>
48
+
49
+ ## InterpreterAtomicFlow Objects
50
+
51
+ ```python
52
+ class InterpreterAtomicFlow(AtomicFlow)
53
+ ```
54
+
55
+ This flow is used to run the code passed from the caller.
56
+ *Expected Input*:
57
+ - `code`
58
+ - `language_of_code`
59
+
60
+ *Expected Output*:
61
+ - `interpreter_output`: output of the code interpreter
62
+
63
+ **Full credits to open-interpreter (https://github.com/KillianLucas/open-interpreter)
64
+ for the usage of code interpreters (package `code_interpreters`) and the function truncate_output()**
65
+
66
+ I'm extracting the code interpreter part from open-interpreter because the litellm version of open-interpreter
67
+ is not compatible with that of the current version of aiflows(v.0.1.7).
68
+
69
+ <a id="InterpreterAtomicFlow.InterpreterAtomicFlow.set_up_flow_state"></a>
70
+
71
+ #### set\_up\_flow\_state
72
+
73
+ ```python
74
+ def set_up_flow_state()
75
+ ```
76
+
77
+ class-specific flow state: language and code,
78
+ which describes the programming language and the code to run.
79
+
80
+ <a id="__init__"></a>
81
+
82
+ # \_\_init\_\_
83
+
84
+ <a id="code_interpreters"></a>
85
+
86
+ # code\_interpreters
87
+
88
+ <a id="code_interpreters.language_map"></a>
89
+
90
+ # code\_interpreters.language\_map
91
+
92
+ <a id="code_interpreters.create_code_interpreter"></a>
93
+
94
+ # code\_interpreters.create\_code\_interpreter
95
+
96
+ <a id="code_interpreters.languages.javascript"></a>
97
+
98
+ # code\_interpreters.languages.javascript
99
+
100
+ <a id="code_interpreters.languages.javascript.preprocess_javascript"></a>
101
+
102
+ #### preprocess\_javascript
103
+
104
+ ```python
105
+ def preprocess_javascript(code)
106
+ ```
107
+
108
+ Add active line markers
109
+ Wrap in a try catch
110
+ Add end of execution marker
111
+
112
+ <a id="code_interpreters.languages.shell"></a>
113
+
114
+ # code\_interpreters.languages.shell
115
+
116
+ <a id="code_interpreters.languages.shell.preprocess_shell"></a>
117
+
118
+ #### preprocess\_shell
119
+
120
+ ```python
121
+ def preprocess_shell(code)
122
+ ```
123
+
124
+ Add active line markers
125
+ Wrap in a try except (trap in shell)
126
+ Add end of execution marker
127
+
128
+ <a id="code_interpreters.languages.shell.add_active_line_prints"></a>
129
+
130
+ #### add\_active\_line\_prints
131
+
132
+ ```python
133
+ def add_active_line_prints(code)
134
+ ```
135
+
136
+ Add echo statements indicating line numbers to a shell string.
137
+
138
+ <a id="code_interpreters.languages.python"></a>
139
+
140
+ # code\_interpreters.languages.python
141
+
142
+ <a id="code_interpreters.languages.python.preprocess_python"></a>
143
+
144
+ #### preprocess\_python
145
+
146
+ ```python
147
+ def preprocess_python(code)
148
+ ```
149
+
150
+ Add active line markers
151
+ Wrap in a try except
152
+ Add end of execution marker
153
+
154
+ <a id="code_interpreters.languages.python.add_active_line_prints"></a>
155
+
156
+ #### add\_active\_line\_prints
157
+
158
+ ```python
159
+ def add_active_line_prints(code)
160
+ ```
161
+
162
+ Add print statements indicating line numbers to a python string.
163
+
164
+ <a id="code_interpreters.languages.python.AddLinePrints"></a>
165
+
166
+ ## AddLinePrints Objects
167
+
168
+ ```python
169
+ class AddLinePrints(ast.NodeTransformer)
170
+ ```
171
+
172
+ Transformer to insert print statements indicating the line number
173
+ before every executable line in the AST.
174
+
175
+ <a id="code_interpreters.languages.python.AddLinePrints.insert_print_statement"></a>
176
+
177
+ #### insert\_print\_statement
178
+
179
+ ```python
180
+ def insert_print_statement(line_number)
181
+ ```
182
+
183
+ Inserts a print statement for a given line number.
184
+
185
+ <a id="code_interpreters.languages.python.AddLinePrints.process_body"></a>
186
+
187
+ #### process\_body
188
+
189
+ ```python
190
+ def process_body(body)
191
+ ```
192
+
193
+ Processes a block of statements, adding print calls.
194
+
195
+ <a id="code_interpreters.languages.python.AddLinePrints.visit"></a>
196
+
197
+ #### visit
198
+
199
+ ```python
200
+ def visit(node)
201
+ ```
202
+
203
+ Overridden visit to transform nodes.
204
+
205
+ <a id="code_interpreters.languages.html"></a>
206
+
207
+ # code\_interpreters.languages.html
208
+
209
+ <a id="code_interpreters.languages.r"></a>
210
+
211
+ # code\_interpreters.languages.r
212
+
213
+ <a id="code_interpreters.languages.r.R"></a>
214
+
215
+ ## R Objects
216
+
217
+ ```python
218
+ class R(SubprocessCodeInterpreter)
219
+ ```
220
+
221
+ <a id="code_interpreters.languages.r.R.preprocess_code"></a>
222
+
223
+ #### preprocess\_code
224
+
225
+ ```python
226
+ def preprocess_code(code)
227
+ ```
228
+
229
+ Add active line markers
230
+ Wrap in a tryCatch for better error handling in R
231
+ Add end of execution marker
232
+
233
+ <a id="code_interpreters.languages.powershell"></a>
234
+
235
+ # code\_interpreters.languages.powershell
236
+
237
+ <a id="code_interpreters.languages.powershell.preprocess_powershell"></a>
238
+
239
+ #### preprocess\_powershell
240
+
241
+ ```python
242
+ def preprocess_powershell(code)
243
+ ```
244
+
245
+ Add active line markers
246
+ Wrap in try-catch block
247
+ Add end of execution marker
248
+
249
+ <a id="code_interpreters.languages.powershell.add_active_line_prints"></a>
250
+
251
+ #### add\_active\_line\_prints
252
+
253
+ ```python
254
+ def add_active_line_prints(code)
255
+ ```
256
+
257
+ Add Write-Output statements indicating line numbers to a PowerShell script.
258
+
259
+ <a id="code_interpreters.languages.powershell.wrap_in_try_catch"></a>
260
+
261
+ #### wrap\_in\_try\_catch
262
+
263
+ ```python
264
+ def wrap_in_try_catch(code)
265
+ ```
266
+
267
+ Wrap PowerShell code in a try-catch block to catch errors and display them.
268
+
269
+ <a id="code_interpreters.languages"></a>
270
+
271
+ # code\_interpreters.languages
272
+
273
+ <a id="code_interpreters.languages.applescript"></a>
274
+
275
+ # code\_interpreters.languages.applescript
276
+
277
+ <a id="code_interpreters.languages.applescript.AppleScript"></a>
278
+
279
+ ## AppleScript Objects
280
+
281
+ ```python
282
+ class AppleScript(SubprocessCodeInterpreter)
283
+ ```
284
+
285
+ <a id="code_interpreters.languages.applescript.AppleScript.preprocess_code"></a>
286
+
287
+ #### preprocess\_code
288
+
289
+ ```python
290
+ def preprocess_code(code)
291
+ ```
292
+
293
+ Inserts an end_of_execution marker and adds active line indicators.
294
+
295
+ <a id="code_interpreters.languages.applescript.AppleScript.add_active_line_indicators"></a>
296
+
297
+ #### add\_active\_line\_indicators
298
+
299
+ ```python
300
+ def add_active_line_indicators(code)
301
+ ```
302
+
303
+ Adds log commands to indicate the active line of execution in the AppleScript.
304
+
305
+ <a id="code_interpreters.languages.applescript.AppleScript.detect_active_line"></a>
306
+
307
+ #### detect\_active\_line
308
+
309
+ ```python
310
+ def detect_active_line(line)
311
+ ```
312
+
313
+ Detects active line indicator in the output.
314
+
315
+ <a id="code_interpreters.languages.applescript.AppleScript.detect_end_of_execution"></a>
316
+
317
+ #### detect\_end\_of\_execution
318
+
319
+ ```python
320
+ def detect_end_of_execution(line)
321
+ ```
322
+
323
+ Detects end of execution marker in the output.
324
+
325
+ <a id="code_interpreters.subprocess_code_interpreter"></a>
326
+
327
+ # code\_interpreters.subprocess\_code\_interpreter
328
+
329
+ <a id="code_interpreters.subprocess_code_interpreter.SubprocessCodeInterpreter"></a>
330
+
331
+ ## SubprocessCodeInterpreter Objects
332
+
333
+ ```python
334
+ class SubprocessCodeInterpreter(BaseCodeInterpreter)
335
+ ```
336
+
337
+ <a id="code_interpreters.subprocess_code_interpreter.SubprocessCodeInterpreter.preprocess_code"></a>
338
+
339
+ #### preprocess\_code
340
+
341
+ ```python
342
+ def preprocess_code(code)
343
+ ```
344
+
345
+ This needs to insert an end_of_execution marker of some kind,
346
+ which can be detected by detect_end_of_execution.
347
+
348
+ Optionally, add active line markers for detect_active_line.
349
+
350
+ <a id="code_interpreters.base_code_interpreter"></a>
351
+
352
+ # code\_interpreters.base\_code\_interpreter
353
+
354
+ <a id="code_interpreters.base_code_interpreter.BaseCodeInterpreter"></a>
355
+
356
+ ## BaseCodeInterpreter Objects
357
+
358
+ ```python
359
+ class BaseCodeInterpreter()
360
+ ```
361
+
362
+ .run is a generator that yields a dict with attributes: active_line, output
363
+
__init__.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .InterpreterAtomicFlow import InterpreterAtomicFlow
2
+ from .code_interpreters import base_code_interpreter
3
+ from .code_interpreters import languages
4
+ from .code_interpreters.languages import python
5
+ from .code_interpreters.languages import r
6
+ from .code_interpreters.languages import applescript
7
+ from .code_interpreters.languages import html
8
+ from .code_interpreters.languages import javascript
9
+ from .code_interpreters.languages import powershell
10
+ from .code_interpreters.languages import shell
11
+ from .code_interpreters import create_code_interpreter
12
+ from .code_interpreters import language_map
13
+ from .code_interpreters import subprocess_code_interpreter
pip_requirements.txt ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ colorama==0.4.6
2
+ pytest==7.3.1
3
+ pytest-cov==4.1.0
4
+ hydra-core==1.3.2
5
+ hydra-colorlog==1.1.0
6
+ wrapt-timeout-decorator==1.3.12.2
7
+ diskcache==5.6.1
8
+ openai==1.0.0
9
+ huggingface_hub==0.19.4
10
+ jsonlines==3.1.0
11
+ jinja2==3.1.2
12
+ mock==5.0.2
13
+ rich==12.6.0
14
+ litellm==1.0.0
15
+ aiflows