jkorstad commited on
Commit
2994b0b
·
verified ·
1 Parent(s): 39cdcf6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +39 -34
app.py CHANGED
@@ -58,7 +58,12 @@ for space_info in spaces:
58
  @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
59
  def create_tool_with_retry(repo_id, name, description, api_name):
60
  # If api_name is None, Tool.from_space will try to find a public API endpoint.
61
- return Tool.from_space(repo_id, name=name, description=description, api_name=api_name)
 
 
 
 
 
62
 
63
  try:
64
  tool = create_tool_with_retry(repo_id, name, description, api_name)
@@ -67,10 +72,9 @@ for space_info in spaces:
67
  except Exception as e:
68
  print(f"Failed to load predefined tool from {repo_id}. Error: {str(e)}. Continuing with available tools.")
69
 
70
- # Load tools from a Hugging Face Collection
71
  #collection_slug = "jkorstad/tools-680127d17eed47e759549ff4"
72
  #try:
73
- # Added trust_remote_code=True
74
  # collection = ToolCollection.from_hub(collection_slug=collection_slug, trust_remote_code=True)
75
  # tools.extend(collection.tools)
76
  # print(f"Successfully loaded tools from collection: {collection_slug}")
@@ -89,19 +93,16 @@ def search_hf_spaces(query: str, top_k: int = 3) -> str:
89
  """
90
  try:
91
  print(f"Searching spaces with query: {query}, top_k: {top_k}")
92
- # Using list_spaces, ensure it's imported: from huggingface_hub import list_spaces
93
- # full=True gives more metadata, sort by likes, direction=-1 for descending
94
  spaces_found = list(list_spaces(search=query, full=True, limit=top_k, sort="likes", direction=-1))
95
  if not spaces_found:
96
  return "No Spaces found for your query."
97
 
98
  results = "Found the following Spaces (sorted by likes):\n"
99
  for i, space_data in enumerate(spaces_found):
100
- # Safely access attributes, as they might not always be present
101
  description = "No description provided."
102
  if hasattr(space_data, 'cardData') and space_data.cardData and 'description' in space_data.cardData:
103
  description = space_data.cardData['description']
104
- elif hasattr(space_data, 'title') and space_data.title: # Fallback to title
105
  description = space_data.title
106
 
107
  results += (
@@ -118,7 +119,6 @@ def search_hf_spaces(query: str, top_k: int = 3) -> str:
118
  return results
119
  except Exception as e:
120
  print(f"Error searching Spaces: {str(e)}")
121
- # traceback.print_exc() # Uncomment for detailed search error debugging
122
  return f"Error searching Spaces: {str(e)}"
123
 
124
  space_search_tool = Tool(
@@ -128,6 +128,23 @@ space_search_tool = Tool(
128
  )
129
  tools.append(space_search_tool)
130
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
  # Initialize the model - Use InferenceClientModel
133
  model = InferenceClientModel(model_id="Qwen/Qwen2.5-Coder-32B-Instruct") # Or your preferred model
@@ -191,11 +208,9 @@ def gradio_interface(user_prompt, input_image_path, input_audio_path, input_vide
191
  full_prompt_with_instructions = f"{AGENT_INSTRUCTIONS}\n\nUSER PROMPT: {user_prompt}"
192
 
193
  # Prepare a dictionary of potential inputs for the agent's execution scope
194
- # These will be available as global variables in the agent's Python execution environment
195
- # when agent.run is called with keyword arguments.
196
  agent_kwargs = {}
197
  if input_image_path:
198
- agent_kwargs["input_image_path"] = str(input_image_path) # Ensure it's a string path
199
  if input_audio_path:
200
  agent_kwargs["input_audio_path"] = str(input_audio_path)
201
  if input_video_path:
@@ -206,19 +221,16 @@ def gradio_interface(user_prompt, input_image_path, input_audio_path, input_vide
206
  agent_kwargs["input_file_path"] = str(input_file_path)
207
 
208
  progress(0.2, desc="Agent processing request...")
209
- # The first argument to agent.run is the main prompt.
210
- # Other kwargs are set as global variables in the agent's execution context.
211
  result = agent.run(full_prompt_with_instructions, **agent_kwargs)
212
 
213
  progress(0.8, desc="Processing result...")
214
- # Default all outputs to invisible and None
215
  outputs = {
216
  "image": gr.update(value=None, visible=False),
217
  "file": gr.update(value=None, visible=False),
218
  "path": gr.update(value=None, visible=False),
219
  "audio": gr.update(value=None, visible=False),
220
  "model3d": gr.update(value=None, visible=False),
221
- "text": gr.update(value=None, visible=True), # Text output is often default
222
  }
223
 
224
  if isinstance(result, str):
@@ -226,21 +238,20 @@ def gradio_interface(user_prompt, input_image_path, input_audio_path, input_vide
226
  file_path = result
227
  outputs["file"] = gr.update(value=file_path, visible=True)
228
  outputs["path"] = gr.update(value=file_path, visible=True)
229
- ext = os.path.splitext(file_path.lower())[1] # Get extension like .png
230
  if ext in ('.png', '.jpg', '.jpeg', '.gif', '.webp'):
231
  outputs["image"] = gr.update(value=file_path, visible=True)
232
  elif ext in ('.mp3', '.wav', '.ogg', '.flac'):
233
  outputs["audio"] = gr.update(value=file_path, visible=True)
234
- elif ext == '.glb': # Common format for Model3D
235
  outputs["model3d"] = gr.update(value=file_path, visible=True)
236
- else: # Other file types like PDF, TXT - user can download via file component
237
  outputs["text"] = gr.update(value=f"Output is a file: {os.path.basename(file_path)}. Download it using the 'Download File Output' component.", visible=True)
238
  else:
239
- # Result is a string (e.g., text output from a tool or an error message from the agent)
240
  outputs["text"] = gr.update(value=result, visible=True)
241
  elif result is None:
242
  outputs["text"] = gr.update(value="Agent returned no result (None). This might indicate an issue or that the task didn't produce a specific output string/file.", visible=True)
243
- else: # Other types (e.g. if agent returns a dict or list by mistake)
244
  outputs["text"] = gr.update(value=f"Unexpected result type from agent: {type(result)}. Content: {str(result)}", visible=True)
245
 
246
  progress(1, desc="Done!")
@@ -251,12 +262,12 @@ def gradio_interface(user_prompt, input_image_path, input_audio_path, input_vide
251
 
252
  except Exception as e:
253
  error_msg = f"An error occurred in the Gradio interface or agent execution: {str(e)}"
254
- print(error_msg) # Also print to console for server-side logs
255
- traceback.print_exc() # For more detailed debugging
256
  return (
257
  gr.update(value=None, visible=False), gr.update(value=None, visible=False), gr.update(value=None, visible=False),
258
  gr.update(value=None, visible=False), gr.update(value=None, visible=False),
259
- gr.update(value=error_msg, visible=True) # Show error in the text output
260
  )
261
 
262
  # Create the Gradio app
@@ -277,8 +288,8 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
277
  input_image = gr.Image(label="Image Input", type="filepath", sources=["upload", "clipboard"], elem_id="input_image_upload")
278
  input_audio = gr.Audio(label="Audio Input", type="filepath", sources=["upload", "microphone"], elem_id="input_audio_upload")
279
  with gr.Row():
280
- input_video = gr.Video(label="Video Input", type="filepath", sources=["upload"], elem_id="input_video_upload") # Gradio Video component might have limitations
281
- input_model3d = gr.Model3D(label="3D Model Input (.glb, .obj, etc.)", type="filepath", elem_id="input_model3d_upload") # Check Gradio docs for supported Model3D types
282
  with gr.Row():
283
  input_file = gr.File(label="Generic File Input (PDF, TXT, etc.)", type="filepath", elem_id="input_file_upload")
284
 
@@ -290,12 +301,11 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
290
  audio_output = gr.Audio(label="Audio Output", interactive=False, visible=False, show_download_button=True, elem_id="output_audio_display")
291
  with gr.Row():
292
  model3d_output = gr.Model3D(label="3D Model Output", interactive=False, visible=False, show_download_button=True, elem_id="output_model3d_display")
293
- text_output = gr.Textbox(label="Text / Log Output", interactive=False, visible=True, lines=5, max_lines=20, elem_id="output_text_log") # Start visible for logs/text
294
  with gr.Row():
295
  file_output = gr.File(label="Download File Output", interactive=False, visible=False, elem_id="output_file_download")
296
- path_output = gr.Textbox(label="Output File Path (Copyable)", interactive=False, visible=False, elem_id="output_file_path_text") # Keep for copying if needed
297
 
298
- # Link button click to the interface function
299
  submit_button.click(
300
  fn=gradio_interface,
301
  inputs=[prompt_input, input_image, input_audio, input_video, input_model3d, input_file],
@@ -307,16 +317,11 @@ with gr.Blocks(theme=gr.themes.Soft()) as app:
307
  ["Generate an image of a happy robot coding on a laptop, cyberpunk style.", None, None, None, None, None],
308
  ["Convert the following text to speech: 'Smolagents are amazing for building AI applications.'", None, None, None, None, None],
309
  ["Search for a Hugging Face Space that can perform image captioning. Describe the first result.", None, None, None, None, None],
310
- # For examples with file inputs, the user needs to upload a file manually.
311
- # The string path here is just a placeholder for the example text.
312
  ["I have an image of a cat. Find a space that can make it look like a painting and apply it. You will need to use the 'input_image_path' variable which will contain the path to the uploaded cat image.", "path/to/your/cat_image.png", None, None, None, None],
313
  ],
314
  inputs=[prompt_input, input_image, input_audio, input_video, input_model3d, input_file],
315
  label="Example Prompts (Note: For examples with file inputs, you'll need to upload a relevant file first using the 'Optional File Inputs' section)"
316
  )
317
 
318
- # Launch the app
319
  if __name__ == "__main__":
320
- # share=True can be used to create a public link if you're running this locally and want to test from another device.
321
- # debug=True provides more detailed Gradio logs.
322
- app.launch(debug=True)
 
58
  @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
59
  def create_tool_with_retry(repo_id, name, description, api_name):
60
  # If api_name is None, Tool.from_space will try to find a public API endpoint.
61
+ print(f"Attempting to create tool: '{name}' from space: {repo_id} with api_name: {api_name}")
62
+ new_tool = Tool.from_space(repo_id, name=name, description=description, api_name=api_name)
63
+ # Explicitly check if name attribute is set after creation by Tool.from_space
64
+ if not hasattr(new_tool, 'name') or new_tool.name != name:
65
+ print(f"WARNING: Tool '{name}' from space {repo_id} might have a name mismatch or missing name attribute after creation. Actual name: {getattr(new_tool, 'name', 'MISSING')}")
66
+ return new_tool
67
 
68
  try:
69
  tool = create_tool_with_retry(repo_id, name, description, api_name)
 
72
  except Exception as e:
73
  print(f"Failed to load predefined tool from {repo_id}. Error: {str(e)}. Continuing with available tools.")
74
 
75
+ # Load tools from a Hugging Face Collection (User has this commented out)
76
  #collection_slug = "jkorstad/tools-680127d17eed47e759549ff4"
77
  #try:
 
78
  # collection = ToolCollection.from_hub(collection_slug=collection_slug, trust_remote_code=True)
79
  # tools.extend(collection.tools)
80
  # print(f"Successfully loaded tools from collection: {collection_slug}")
 
93
  """
94
  try:
95
  print(f"Searching spaces with query: {query}, top_k: {top_k}")
 
 
96
  spaces_found = list(list_spaces(search=query, full=True, limit=top_k, sort="likes", direction=-1))
97
  if not spaces_found:
98
  return "No Spaces found for your query."
99
 
100
  results = "Found the following Spaces (sorted by likes):\n"
101
  for i, space_data in enumerate(spaces_found):
 
102
  description = "No description provided."
103
  if hasattr(space_data, 'cardData') and space_data.cardData and 'description' in space_data.cardData:
104
  description = space_data.cardData['description']
105
+ elif hasattr(space_data, 'title') and space_data.title:
106
  description = space_data.title
107
 
108
  results += (
 
119
  return results
120
  except Exception as e:
121
  print(f"Error searching Spaces: {str(e)}")
 
122
  return f"Error searching Spaces: {str(e)}"
123
 
124
  space_search_tool = Tool(
 
128
  )
129
  tools.append(space_search_tool)
130
 
131
+ # --- Debugging: Inspect tools before CodeAgent initialization ---
132
+ print("\n--- Inspecting tools before CodeAgent initialization ---")
133
+ for i, t in enumerate(tools):
134
+ if t is None:
135
+ print(f"Tool at index {i} is None!")
136
+ # This would cause an error later, but the current error is 'Tool' object has no attribute 'name'
137
+ continue
138
+ try:
139
+ # Attempt to access the name attribute
140
+ tool_name = t.name
141
+ print(f"Tool {i}: Name='{tool_name}', Type={type(t)}")
142
+ except AttributeError:
143
+ print(f"!!! CRITICAL: Tool at index {i} (Type={type(t)}) is missing 'name' attribute.")
144
+ except Exception as e:
145
+ print(f"!!! ERROR inspecting tool at index {i} (Type={type(t)}): {str(e)}")
146
+ print("-------------------------------------------------------\n")
147
+
148
 
149
  # Initialize the model - Use InferenceClientModel
150
  model = InferenceClientModel(model_id="Qwen/Qwen2.5-Coder-32B-Instruct") # Or your preferred model
 
208
  full_prompt_with_instructions = f"{AGENT_INSTRUCTIONS}\n\nUSER PROMPT: {user_prompt}"
209
 
210
  # Prepare a dictionary of potential inputs for the agent's execution scope
 
 
211
  agent_kwargs = {}
212
  if input_image_path:
213
+ agent_kwargs["input_image_path"] = str(input_image_path)
214
  if input_audio_path:
215
  agent_kwargs["input_audio_path"] = str(input_audio_path)
216
  if input_video_path:
 
221
  agent_kwargs["input_file_path"] = str(input_file_path)
222
 
223
  progress(0.2, desc="Agent processing request...")
 
 
224
  result = agent.run(full_prompt_with_instructions, **agent_kwargs)
225
 
226
  progress(0.8, desc="Processing result...")
 
227
  outputs = {
228
  "image": gr.update(value=None, visible=False),
229
  "file": gr.update(value=None, visible=False),
230
  "path": gr.update(value=None, visible=False),
231
  "audio": gr.update(value=None, visible=False),
232
  "model3d": gr.update(value=None, visible=False),
233
+ "text": gr.update(value=None, visible=True),
234
  }
235
 
236
  if isinstance(result, str):
 
238
  file_path = result
239
  outputs["file"] = gr.update(value=file_path, visible=True)
240
  outputs["path"] = gr.update(value=file_path, visible=True)
241
+ ext = os.path.splitext(file_path.lower())[1]
242
  if ext in ('.png', '.jpg', '.jpeg', '.gif', '.webp'):
243
  outputs["image"] = gr.update(value=file_path, visible=True)
244
  elif ext in ('.mp3', '.wav', '.ogg', '.flac'):
245
  outputs["audio"] = gr.update(value=file_path, visible=True)
246
+ elif ext == '.glb':
247
  outputs["model3d"] = gr.update(value=file_path, visible=True)
248
+ else:
249
  outputs["text"] = gr.update(value=f"Output is a file: {os.path.basename(file_path)}. Download it using the 'Download File Output' component.", visible=True)
250
  else:
 
251
  outputs["text"] = gr.update(value=result, visible=True)
252
  elif result is None:
253
  outputs["text"] = gr.update(value="Agent returned no result (None). This might indicate an issue or that the task didn't produce a specific output string/file.", visible=True)
254
+ else:
255
  outputs["text"] = gr.update(value=f"Unexpected result type from agent: {type(result)}. Content: {str(result)}", visible=True)
256
 
257
  progress(1, desc="Done!")
 
262
 
263
  except Exception as e:
264
  error_msg = f"An error occurred in the Gradio interface or agent execution: {str(e)}"
265
+ print(error_msg)
266
+ traceback.print_exc()
267
  return (
268
  gr.update(value=None, visible=False), gr.update(value=None, visible=False), gr.update(value=None, visible=False),
269
  gr.update(value=None, visible=False), gr.update(value=None, visible=False),
270
+ gr.update(value=error_msg, visible=True)
271
  )
272
 
273
  # Create the Gradio app
 
288
  input_image = gr.Image(label="Image Input", type="filepath", sources=["upload", "clipboard"], elem_id="input_image_upload")
289
  input_audio = gr.Audio(label="Audio Input", type="filepath", sources=["upload", "microphone"], elem_id="input_audio_upload")
290
  with gr.Row():
291
+ input_video = gr.Video(label="Video Input", type="filepath", sources=["upload"], elem_id="input_video_upload")
292
+ input_model3d = gr.Model3D(label="3D Model Input (.glb, .obj, etc.)", type="filepath", elem_id="input_model3d_upload")
293
  with gr.Row():
294
  input_file = gr.File(label="Generic File Input (PDF, TXT, etc.)", type="filepath", elem_id="input_file_upload")
295
 
 
301
  audio_output = gr.Audio(label="Audio Output", interactive=False, visible=False, show_download_button=True, elem_id="output_audio_display")
302
  with gr.Row():
303
  model3d_output = gr.Model3D(label="3D Model Output", interactive=False, visible=False, show_download_button=True, elem_id="output_model3d_display")
304
+ text_output = gr.Textbox(label="Text / Log Output", interactive=False, visible=True, lines=5, max_lines=20, elem_id="output_text_log")
305
  with gr.Row():
306
  file_output = gr.File(label="Download File Output", interactive=False, visible=False, elem_id="output_file_download")
307
+ path_output = gr.Textbox(label="Output File Path (Copyable)", interactive=False, visible=False, elem_id="output_file_path_text")
308
 
 
309
  submit_button.click(
310
  fn=gradio_interface,
311
  inputs=[prompt_input, input_image, input_audio, input_video, input_model3d, input_file],
 
317
  ["Generate an image of a happy robot coding on a laptop, cyberpunk style.", None, None, None, None, None],
318
  ["Convert the following text to speech: 'Smolagents are amazing for building AI applications.'", None, None, None, None, None],
319
  ["Search for a Hugging Face Space that can perform image captioning. Describe the first result.", None, None, None, None, None],
 
 
320
  ["I have an image of a cat. Find a space that can make it look like a painting and apply it. You will need to use the 'input_image_path' variable which will contain the path to the uploaded cat image.", "path/to/your/cat_image.png", None, None, None, None],
321
  ],
322
  inputs=[prompt_input, input_image, input_audio, input_video, input_model3d, input_file],
323
  label="Example Prompts (Note: For examples with file inputs, you'll need to upload a relevant file first using the 'Optional File Inputs' section)"
324
  )
325
 
 
326
  if __name__ == "__main__":
327
+ app.launch(debug=True)