json-cho commited on
Commit
76fbff7
·
1 Parent(s): d28cecd

Updated python code to be able to update vercel code

Browse files
Files changed (2) hide show
  1. smol.py +9 -7
  2. tool.py +64 -114
smol.py CHANGED
@@ -3,7 +3,7 @@ import shutil
3
 
4
  from smolagents import CodeAgent, DuckDuckGoSearchTool, Tool, HfApiModel
5
  from dotenv import load_dotenv, dotenv_values
6
- from tool import GetGameFileNamesTool, FindFilesTool, GitPushTool, FileReplaceTool, ProcessFlowIdentifierTool, GetImageDimensionsTool, FileModifyTool
7
 
8
  load_dotenv()
9
 
@@ -29,19 +29,21 @@ step 5: upload changes to github
29
  """
30
 
31
  get_game_file_names_tool = GetGameFileNamesTool()
32
- find_files_tool = FindFilesTool()
33
- file_replace_tool = FileReplaceTool()
34
  process_identifier_tool= ProcessFlowIdentifierTool()
35
  get_image_dimensions_tool= GetImageDimensionsTool()
36
- file_modify_tool = FileModifyTool()
 
 
37
 
38
  def ChatAgent(userPrompt):
39
  #Identify purpose of prompt
40
  promptCleanerAgent = CodeAgent(tools=[], model=model)
41
 
42
  instructions = promptCleanerAgent.run(f"""
43
- determine the purpose of the following string "{userPrompt}" if it is one of the following: [asset_change, script_update, conversation].
44
- asset_change: The user wants to change an asset in the game.
 
45
  script_update: The user wants to update the game script.
46
  conversation: The user wants to have a conversation with the AI by asking general questions or greetings.
47
  """)
@@ -63,7 +65,7 @@ def ChatAgent(userPrompt):
63
  else:
64
  contextPrompt = f'using process_identifier_tool look for the appropriate instructions for "{instructions}" and apply it to the user prompt after this'
65
 
66
- agent = CodeAgent(tools=[get_game_file_names_tool, find_files_tool, process_identifier_tool, image_generation_tool, file_modify_tool, get_image_dimensions_tool, file_replace_tool], model=model)
67
 
68
  if instructions == "conversation":
69
  response = agent.run(f"{contextPrompt}")
 
3
 
4
  from smolagents import CodeAgent, DuckDuckGoSearchTool, Tool, HfApiModel
5
  from dotenv import load_dotenv, dotenv_values
6
+ from tool import GetGameFileNamesTool, ReadFilesTool, UpdateGameFileTool, GitPushTool, ProcessFlowIdentifierTool, GetImageDimensionsTool
7
 
8
  load_dotenv()
9
 
 
29
  """
30
 
31
  get_game_file_names_tool = GetGameFileNamesTool()
32
+ read_files_tool = ReadFilesTool()
 
33
  process_identifier_tool= ProcessFlowIdentifierTool()
34
  get_image_dimensions_tool= GetImageDimensionsTool()
35
+ update_game_file_tool = UpdateGameFileTool()
36
+ # file_replace_tool = FileReplaceTool()
37
+ # file_modify_tool = FileModifyTool()
38
 
39
  def ChatAgent(userPrompt):
40
  #Identify purpose of prompt
41
  promptCleanerAgent = CodeAgent(tools=[], model=model)
42
 
43
  instructions = promptCleanerAgent.run(f"""
44
+ determine the purpose of the following string "{userPrompt}" if it is one of the following: [asset_change, read_file, script_update, conversation].
45
+ asset_change: The user wants to change an asset from the game.
46
+ read_file: The user wants to read a file from the game.
47
  script_update: The user wants to update the game script.
48
  conversation: The user wants to have a conversation with the AI by asking general questions or greetings.
49
  """)
 
65
  else:
66
  contextPrompt = f'using process_identifier_tool look for the appropriate instructions for "{instructions}" and apply it to the user prompt after this'
67
 
68
+ agent = CodeAgent(tools=[get_game_file_names_tool, read_files_tool, update_game_file_tool, process_identifier_tool, image_generation_tool, get_image_dimensions_tool], model=model)
69
 
70
  if instructions == "conversation":
71
  response = agent.run(f"{contextPrompt}")
tool.py CHANGED
@@ -8,36 +8,20 @@ load_dotenv()
8
  HF_TOKEN = os.getenv("HF_TOKEN")
9
  NOODLE_PUBLIC_API_URL = os.getenv("NOODLE_PUBLIC_API_URL")
10
 
11
- class FileReaderTool(Tool):
12
- name = "file_reader_tool"
13
- description = """
14
- This tool will be used by the LLM Agent to read files to help analyze files for its task.
15
- """
16
- inputs = {
17
- "file_location": {
18
- "type": "string",
19
- "description": "The location of the file that will be read/analyzed"
20
- }
21
- }
22
- output_type = "string"
23
-
24
- def forward(self,file_location ) -> str:
25
- with open(file_location, "r") as file:
26
- return file.read()
27
 
28
  class FileWriteTool(Tool):
29
  name = "file_write_tool"
30
  description = """
31
- This tool will be used by the LLM Agent to overwrite files if needed for task.
32
  """
33
  inputs = {
34
  "file_location": {
35
  "type": "string",
36
- "description": "The location of the file that will be read/analyzed"
37
  },
38
  "new_code": {
39
  "type": "string",
40
- "description": "This is the code that will overwrite the contents of a file. If file does not exist, it is the new content."
41
  }
42
  }
43
  output_type = "string"
@@ -46,73 +30,6 @@ class FileWriteTool(Tool):
46
  with open(file_location, "w") as file:
47
  return file.write(new_code)
48
 
49
- class FileModifyTool(Tool):
50
- name = "file_modify_tool"
51
- description = """
52
- This tool will be used by the LLM Agent to modify files if needed for task.
53
- """
54
- inputs = {
55
- "file_location": {
56
- "type": "string",
57
- "description": "The location of the file that will be read/analyzed"
58
- },
59
- "prompt": {
60
- "type": "string",
61
- "description": "This is the prompt that the LLM will use to decide how to modify the code."
62
- }
63
- }
64
- output_type = "string"
65
-
66
- def forward(self,file_location, prompt) -> str:
67
- file_reader_tool = FileReaderTool()
68
- file_write_tool = FileWriteTool()
69
-
70
- model = HfApiModel("Qwen/Qwen2.5-Coder-32B-Instruct", token=HF_TOKEN)
71
- coderAgent = CodeAgent(tools=[], model=model)
72
-
73
- file_content = file_reader_tool.forward(file_location)
74
-
75
- if not file_content:
76
- return "Error: File could not be read."
77
-
78
- modified_code = coderAgent.run(f'Based on the prompt "{prompt}" \n Modify the following code:\n{file_content}\n')
79
- if "ERROR" in modified_code:
80
- return "Modification failed, please refine your request."
81
- write_result = file_write_tool.forward(file_location, modified_code)
82
- return
83
-
84
-
85
-
86
- class FileReplaceTool(Tool):
87
- name = "file_replace_tool"
88
- description ="""
89
- This tool will be used to replace the file in a given location with the provided new file location. This is not used to update files.
90
- """
91
- inputs = {
92
- "target_file_location": {
93
- "type": "string",
94
- "description": "the location of the file that will be replaced"
95
- },
96
- "new_file_location": {
97
- "type": "string",
98
- "description": "the location of the new file to replace target file location"
99
- }
100
- }
101
- output_type = "string"
102
- def forward(self, target_file_location, new_file_location) -> str:
103
- import os
104
- import shutil
105
-
106
- if os.path.exists(new_file_location):
107
- # Define the destination path for the saved image
108
- # # Create the './generatedImages' directory if it doesn't exist
109
- # # Copy the image from the temporary location to the desired directory
110
- shutil.copy(new_file_location, target_file_location)
111
-
112
- return print(f"Image saved to {target_file_location}")
113
- else:
114
- return print("Failed to generate an image or the file does not exist.")
115
-
116
  class GetImageDimensionsTool(Tool):
117
  name = "get_image_dimensions_tool"
118
  description= """
@@ -149,16 +66,25 @@ class ProcessFlowIdentifierTool(Tool):
149
  match prompt_objective:
150
  case "asset_change":
151
  instructions = """
152
- 1) use the find files tool to get a list of files containing tsx, and find the sandpack-examples.tsx file and copy its path.
153
- 2) Use the file_modify_tool to analyze and update the file.
154
- 3) End process after sucessfully modifying the file
 
 
 
 
 
 
 
 
155
  """
156
  return instructions
157
  case "script_change":
158
  instructions = """
159
- 1) use the find files tool to get a list of files containing tsx, and find the sandpack-examples.tsx file and copy its path.
160
- 2) Use the file_modify_tool to analyze and update the file.
161
- 3) End process after sucessfully modifying the file
 
162
  """
163
  return instructions
164
  case "conversation":
@@ -221,6 +147,7 @@ class GitPushTool(Tool):
221
  except subprocess.CalledProcessError as e:
222
  return print(f"An error occurred while performing Git operations: {e}")
223
 
 
224
  class GetGameFileNamesTool(Tool):
225
  name="get_game_file_names_tool"
226
  description="""
@@ -238,33 +165,56 @@ class GetGameFileNamesTool(Tool):
238
  else:
239
  print("Failed to get file content")
240
  return response.json()['content']
241
-
242
 
243
- class FindFilesTool(Tool):
244
- name = "find_files"
245
- description = "Find files with a given extension in a directory and its subdirectories"
246
- inputs = {"extension":{"type":"string","description":"the place from which you start your ride"}}
247
-
 
 
 
 
 
 
 
 
 
 
 
248
  output_type = "string"
249
 
250
- def forward(self, extension: str) -> str:
251
  """
252
- Recursively search for files with a given extension in a directory and its subdirectories.
253
-
254
- Args:
255
- extension: The file extension to look for (e.g., '.txt')
256
  """
257
- import os
 
 
 
 
258
 
259
- root_dir = "./"
260
- found_files = []
 
 
 
261
 
262
- # Walk through the directory tree
263
- for dirpath, dirnames, filenames in os.walk(root_dir):
264
- for filename in filenames:
265
- if filename.endswith(extension):
266
- filepath = os.path.join(dirpath, filename)
267
- absolute_path = os.path.abspath(filepath)
268
- found_files.append(absolute_path)
269
 
270
- return found_files
 
 
 
 
 
 
 
 
 
 
 
8
  HF_TOKEN = os.getenv("HF_TOKEN")
9
  NOODLE_PUBLIC_API_URL = os.getenv("NOODLE_PUBLIC_API_URL")
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
  class FileWriteTool(Tool):
13
  name = "file_write_tool"
14
  description = """
15
+ This tool will be used by the LLM Agent to create files if needed for task. Always put the files in the /ai-code directory from the root of this project.
16
  """
17
  inputs = {
18
  "file_location": {
19
  "type": "string",
20
+ "description": "The location of the file that will be written to. Please put this in the /ai-code directory."
21
  },
22
  "new_code": {
23
  "type": "string",
24
+ "description": "This is the content of the file."
25
  }
26
  }
27
  output_type = "string"
 
30
  with open(file_location, "w") as file:
31
  return file.write(new_code)
32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  class GetImageDimensionsTool(Tool):
34
  name = "get_image_dimensions_tool"
35
  description= """
 
66
  match prompt_objective:
67
  case "asset_change":
68
  instructions = """
69
+ 1) use the get_game_file_names_tool to get the list of accessible game files. If user specifies what file, do this still to check if they can access it.
70
+ 2) Use the read_file_tool to read the file contents of the file from step 1. Remember to save the path of the file, this will be used to update the file.
71
+ 3) Based on the prompt, make changes to the code from step 2 and pass it to the update_game_file_tool along with the path saved from step1.
72
+ 4) End process after sucessfully modifying the file
73
+ """
74
+ return instructions
75
+ case "read_file":
76
+ instructions = """
77
+ 1) use the get_game_file_names_tool to get the list of accessible game files. If user specifies what file, do this still to check if they can access it.
78
+ 2) Use the read_file_tool to read the file contents of the file from step 1.
79
+ 3) End process after reading the file.
80
  """
81
  return instructions
82
  case "script_change":
83
  instructions = """
84
+ 1) use the get_game_file_names_tool to get the list of accessible game files. If user specifies what file, do this still to check if they can access it.
85
+ 2) Use the read_file_tool to read the file contents of the file from step 1. Remember to save the path of the file, this will be used to update the file.
86
+ 3) Based on the prompt, make changes to the code from step 2 and use the update_game_file_tool.
87
+ 4) End process after sucessfully modifying the file
88
  """
89
  return instructions
90
  case "conversation":
 
147
  except subprocess.CalledProcessError as e:
148
  return print(f"An error occurred while performing Git operations: {e}")
149
 
150
+ # READ
151
  class GetGameFileNamesTool(Tool):
152
  name="get_game_file_names_tool"
153
  description="""
 
165
  else:
166
  print("Failed to get file content")
167
  return response.json()['content']
 
168
 
169
+ # UPDATE
170
+ class UpdateGameFileTool(Tool):
171
+ name = "update_game_file_tool"
172
+ description = """
173
+ Update the game file via an api by sending the updated code for the nextjs game app to handle.
174
+ """
175
+ inputs = {
176
+ "file_path": {
177
+ "type": "string",
178
+ "description": "The path from the game directory to update."
179
+ },
180
+ "new_content": {
181
+ "type": "string",
182
+ "description": "The updated code."
183
+ }
184
+ }
185
  output_type = "string"
186
 
187
+ def forward(self, file_path: str, new_content: str) -> str:
188
  """
189
+ Make an api call to update the file from a secure api route.
 
 
 
190
  """
191
+ update_file_contents = NOODLE_PUBLIC_API_URL + "/api/files/"
192
+ headers = {
193
+ "Content-Type": "application/octet-stream"
194
+ }
195
+ binary_data = new_content.encode("utf-8")
196
 
197
+ response = requests.put(update_file_contents, params={"path": file_path}, headers=headers, data=binary_data)
198
+ if response.status_code == 200:
199
+ return
200
+ else:
201
+ return "Failed to update file contents"
202
 
203
+ class ReadFilesTool(Tool):
204
+ name = "read_file_tool"
205
+ description = "Read the file contents of the given game file path."
206
+ inputs = {"file_path":{"type":"string","description":"the path to the directory to search in"},}
207
+
208
+ output_type = "string"
 
209
 
210
+ def forward(self, file_path: str) -> str:
211
+ """
212
+ Make an api call to browse the file from the game through an api call. The file path must be passed to view the file.
213
+ """
214
+ read_file_contents = NOODLE_PUBLIC_API_URL + "/api/files/"
215
+ response = requests.get(f"{read_file_contents}", params={"path": file_path})
216
+ if response.status_code == 200:
217
+ return response.json()['content']
218
+ else:
219
+ return "Failed to read file contents"
220
+ return