johann22 commited on
Commit
7919c19
1 Parent(s): f398d9d

Create main.py

Browse files
Files changed (1) hide show
  1. main.py +297 -0
main.py ADDED
@@ -0,0 +1,297 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import subprocess
3
+ #import openai
4
+ from huggingface_hub import InferenceClient
5
+ import gradio as gr
6
+ import prompts
7
+ client = InferenceClient(
8
+ "mistralai/Mixtral-8x7B-Instruct-v0.1"
9
+ )
10
+
11
+ from agent.prompts import (
12
+ ACTION_PROMPT,
13
+ ADD_PROMPT,
14
+ COMPRESS_HISTORY_PROMPT,
15
+ LOG_PROMPT,
16
+ LOG_RESPONSE,
17
+ MODIFY_PROMPT,
18
+ PREFIX,
19
+ READ_PROMPT,
20
+ TASK_PROMPT,
21
+ UNDERSTAND_TEST_RESULTS_PROMPT,
22
+ )
23
+ from agent.utils import parse_action, parse_file_content, read_python_module_structure
24
+
25
+ VERBOSE = False
26
+ MAX_HISTORY = 100
27
+ MODEL = "gpt-3.5-turbo" # "gpt-4"
28
+
29
+
30
+ def run_gpt(
31
+ prompt_template,
32
+ stop_tokens,
33
+ max_tokens,
34
+ module_summary,
35
+ purpose,
36
+ **prompt_kwargs,
37
+ ):
38
+ content = PREFIX.format(
39
+ module_summary=module_summary,
40
+ purpose=purpose,
41
+ ) + prompt_template.format(**prompt_kwargs)
42
+ if VERBOSE:
43
+ print(LOG_PROMPT.format(content))
44
+
45
+
46
+ #formatted_prompt = format_prompt(f"{system_prompt}, {prompt}", history)
47
+ stream = client.text_generation({"role": "system", "content": content}, **generate_kwargs, stream=True, details=True, return_full_text=False)["choices"][0]["message"]["content"]
48
+ output = ""
49
+
50
+ '''
51
+ resp = openai.ChatCompletion.create(
52
+ model=MODEL,
53
+ messages=[
54
+ {"role": "system", "content": content},
55
+ ],
56
+ temperature=0.0,
57
+ max_tokens=max_tokens,
58
+ stop=stop_tokens if stop_tokens else None,
59
+ )["choices"][0]["message"]["content"]
60
+ '''
61
+ if VERBOSE:
62
+ print(LOG_RESPONSE.format(resp))
63
+ return resp
64
+
65
+
66
+ def compress_history(purpose, task, history, directory):
67
+ module_summary, _, _ = read_python_module_structure(directory)
68
+ resp = run_gpt(
69
+ COMPRESS_HISTORY_PROMPT,
70
+ stop_tokens=["observation:", "task:", "action:", "thought:"],
71
+ max_tokens=512,
72
+ module_summary=module_summary,
73
+ purpose=purpose,
74
+ task=task,
75
+ history=history,
76
+ )
77
+ history = "observation: {}\n".format(resp)
78
+ return history
79
+
80
+
81
+ def call_main(purpose, task, history, directory, action_input):
82
+ module_summary, _, _ = read_python_module_structure(directory)
83
+ resp = run_gpt(
84
+ ACTION_PROMPT,
85
+ stop_tokens=["observation:", "task:"],
86
+ max_tokens=256,
87
+ module_summary=module_summary,
88
+ purpose=purpose,
89
+ task=task,
90
+ history=history,
91
+ )
92
+ lines = resp.strip().strip("\n").split("\n")
93
+ for line in lines:
94
+ if line == "":
95
+ continue
96
+ if line.startswith("thought: "):
97
+ history += "{}\n".format(line)
98
+ elif line.startswith("action: "):
99
+ action_name, action_input = parse_action(line)
100
+ history += "{}\n".format(line)
101
+ return action_name, action_input, history, task
102
+ else:
103
+ assert False, "unknown action: {}".format(line)
104
+ return "MAIN", None, history, task
105
+
106
+
107
+ def call_test(purpose, task, history, directory, action_input):
108
+ result = subprocess.run(
109
+ ["python", "-m", "pytest", "--collect-only", directory],
110
+ capture_output=True,
111
+ text=True,
112
+ )
113
+ if result.returncode != 0:
114
+ history += "observation: there are no tests! Test should be written in a test folder under {}\n".format(
115
+ directory
116
+ )
117
+ return "MAIN", None, history, task
118
+ result = subprocess.run(
119
+ ["python", "-m", "pytest", directory], capture_output=True, text=True
120
+ )
121
+ if result.returncode == 0:
122
+ history += "observation: tests pass\n"
123
+ return "MAIN", None, history, task
124
+ module_summary, content, _ = read_python_module_structure(directory)
125
+ resp = run_gpt(
126
+ UNDERSTAND_TEST_RESULTS_PROMPT,
127
+ stop_tokens=[],
128
+ max_tokens=256,
129
+ module_summary=module_summary,
130
+ purpose=purpose,
131
+ task=task,
132
+ history=history,
133
+ stdout=result.stdout[:5000], # limit amount of text
134
+ stderr=result.stderr[:5000], # limit amount of text
135
+ )
136
+ history += "observation: tests failed: {}\n".format(resp)
137
+ return "MAIN", None, history, task
138
+
139
+
140
+ def call_set_task(purpose, task, history, directory, action_input):
141
+ module_summary, content, _ = read_python_module_structure(directory)
142
+ task = run_gpt(
143
+ TASK_PROMPT,
144
+ stop_tokens=[],
145
+ max_tokens=64,
146
+ module_summary=module_summary,
147
+ purpose=purpose,
148
+ task=task,
149
+ history=history,
150
+ ).strip("\n")
151
+ history += "observation: task has been updated to: {}\n".format(task)
152
+ return "MAIN", None, history, task
153
+
154
+
155
+ def call_read(purpose, task, history, directory, action_input):
156
+ if not os.path.exists(action_input):
157
+ history += "observation: file does not exist\n"
158
+ return "MAIN", None, history, task
159
+ module_summary, content, _ = read_python_module_structure(directory)
160
+ f_content = (
161
+ content[action_input] if content[action_input] else "< document is empty >"
162
+ )
163
+ resp = run_gpt(
164
+ READ_PROMPT,
165
+ stop_tokens=[],
166
+ max_tokens=256,
167
+ module_summary=module_summary,
168
+ purpose=purpose,
169
+ task=task,
170
+ history=history,
171
+ file_path=action_input,
172
+ file_contents=f_content,
173
+ ).strip("\n")
174
+ history += "observation: {}\n".format(resp)
175
+ return "MAIN", None, history, task
176
+
177
+
178
+ def call_modify(purpose, task, history, directory, action_input):
179
+ if not os.path.exists(action_input):
180
+ history += "observation: file does not exist\n"
181
+ return "MAIN", None, history, task
182
+ (
183
+ module_summary,
184
+ content,
185
+ _,
186
+ ) = read_python_module_structure(directory)
187
+ f_content = (
188
+ content[action_input] if content[action_input] else "< document is empty >"
189
+ )
190
+ resp = run_gpt(
191
+ MODIFY_PROMPT,
192
+ stop_tokens=["action:", "thought:", "observation:"],
193
+ max_tokens=2048,
194
+ module_summary=module_summary,
195
+ purpose=purpose,
196
+ task=task,
197
+ history=history,
198
+ file_path=action_input,
199
+ file_contents=f_content,
200
+ )
201
+ new_contents, description = parse_file_content(resp)
202
+ if new_contents is None:
203
+ history += "observation: failed to modify file\n"
204
+ return "MAIN", None, history, task
205
+
206
+ with open(action_input, "w") as f:
207
+ f.write(new_contents)
208
+
209
+ history += "observation: file successfully modified\n"
210
+ history += "observation: {}\n".format(description)
211
+ return "MAIN", None, history, task
212
+
213
+
214
+ def call_add(purpose, task, history, directory, action_input):
215
+ d = os.path.dirname(action_input)
216
+ if not d.startswith(directory):
217
+ history += "observation: files must be under directory {}\n".format(directory)
218
+ elif not action_input.endswith(".py"):
219
+ history += "observation: can only write .py files\n"
220
+ else:
221
+ if d and not os.path.exists(d):
222
+ os.makedirs(d)
223
+ if not os.path.exists(action_input):
224
+ module_summary, _, _ = read_python_module_structure(directory)
225
+ resp = run_gpt(
226
+ ADD_PROMPT,
227
+ stop_tokens=["action:", "thought:", "observation:"],
228
+ max_tokens=2048,
229
+ module_summary=module_summary,
230
+ purpose=purpose,
231
+ task=task,
232
+ history=history,
233
+ file_path=action_input,
234
+ )
235
+ new_contents, description = parse_file_content(resp)
236
+ if new_contents is None:
237
+ history += "observation: failed to write file\n"
238
+ return "MAIN", None, history, task
239
+
240
+ with open(action_input, "w") as f:
241
+ f.write(new_contents)
242
+
243
+ history += "observation: file successfully written\n"
244
+ history += "obsertation: {}\n".format(description)
245
+ else:
246
+ history += "observation: file already exists\n"
247
+ return "MAIN", None, history, task
248
+
249
+
250
+ NAME_TO_FUNC = {
251
+ "MAIN": call_main,
252
+ "UPDATE-TASK": call_set_task,
253
+ "MODIFY-FILE": call_modify,
254
+ "READ-FILE": call_read,
255
+ "ADD-FILE": call_add,
256
+ "TEST": call_test,
257
+ }
258
+
259
+
260
+ def run_action(purpose, task, history, directory, action_name, action_input):
261
+ if action_name == "COMPLETE":
262
+ exit(0)
263
+
264
+ # compress the history when it is long
265
+ if len(history.split("\n")) > MAX_HISTORY:
266
+ if VERBOSE:
267
+ print("COMPRESSING HISTORY")
268
+ history = compress_history(purpose, task, history, directory)
269
+
270
+ assert action_name in NAME_TO_FUNC
271
+
272
+ print("RUN: ", action_name, action_input)
273
+ return NAME_TO_FUNC[action_name](purpose, task, history, directory, action_input)
274
+
275
+
276
+ def run(purpose, directory, task=None):
277
+ history = ""
278
+ action_name = "UPDATE-TASK" if task is None else "MAIN"
279
+ action_input = None
280
+ while True:
281
+ print("")
282
+ print("")
283
+ print("---")
284
+ print("purpose:", purpose)
285
+ print("task:", task)
286
+ print("---")
287
+ print(history)
288
+ print("---")
289
+
290
+ action_name, action_input, history, task = run_action(
291
+ purpose,
292
+ task,
293
+ history,
294
+ directory,
295
+ action_name,
296
+ action_input,
297
+ )