Leonardo commited on
Commit
6447354
·
verified ·
1 Parent(s): 60333d1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -53
app.py CHANGED
@@ -1,3 +1,5 @@
 
 
1
  import mimetypes
2
  import os
3
  import re
@@ -122,7 +124,6 @@ class ModelManager:
122
  if chosen_inference == "openai":
123
  if not key_manager:
124
  raise ValueError("Key manager required for OpenAI model")
125
-
126
  return OpenAIServerModel(
127
  model_id=model_id, api_key=key_manager.get_key("openai_api_key")
128
  )
@@ -135,7 +136,6 @@ class ModelManager:
135
  )
136
 
137
  raise ValueError(f"Invalid inference type: {chosen_inference}")
138
-
139
  except Exception as e:
140
  print(f"✗ Couldn't load model: {e}")
141
  raise
@@ -165,7 +165,7 @@ class ToolRegistry:
165
  return Tool.from_space(
166
  space_id="xkerser/FLUX.1-dev",
167
  name="image_generator",
168
- description="Generates high-quality AgentImage using the FLUX.1-dev model based on text prompts.",
169
  )
170
  except Exception as e:
171
  print(f"✗ Couldn't initialize image generation tool: {e}")
@@ -196,16 +196,17 @@ def create_agent():
196
  # Collect all tools in a single list
197
  web_tools = ToolRegistry.load_web_tools(model, browser, text_limit)
198
  image_generator = ToolRegistry.load_image_generation_tools()
199
- clean_text = ToolRegistry.load_clean_text_tool()
200
 
201
  # Combine all tools into a single list (not a tuple)
202
- all_tools = [visualizer, web_tools, image_generator, clean_text]
203
 
204
  # Validate tools before creating agent
205
  for tool in all_tools:
206
  if not isinstance(tool, Tool):
207
  raise ValueError(
208
- f"Invalid tool type: {type(tool)}. All tools must be instances of Tool class."
 
209
  )
210
 
211
  return CodeAgent(
@@ -228,8 +229,7 @@ def stream_to_gradio(
228
  for step_log in agent.run(
229
  task, stream=True, reset=reset_agent_memory, additional_args=additional_args
230
  ):
231
- for message in pull_messages_from_step(step_log):
232
- yield message
233
 
234
  # Process final answer : Use a more comprehensive media output
235
  final_answer = step_log # Last log is the run's final_answer
@@ -295,11 +295,7 @@ class GradioUI:
295
  print(f"Error in interaction: {str(e)}")
296
  raise
297
 
298
- def upload_file(
299
- self,
300
- file,
301
- file_uploads_log,
302
- ):
303
  """Handle file uploads with proper validation and security."""
304
  if file is None:
305
  return gr.Textbox("No file uploaded", visible=True), file_uploads_log
@@ -314,9 +310,7 @@ class GradioUI:
314
 
315
  # Sanitize file name
316
  original_name = os.path.basename(file.name)
317
- sanitized_name = re.sub(
318
- r"[^\w\-.]", "_", original_name
319
- ) # Replace invalid chars with underscores
320
 
321
  # Ensure the extension correlates to the mime type
322
  type_to_ext = {}
@@ -331,15 +325,11 @@ class GradioUI:
331
 
332
  # Limit File Size, and Throw Error
333
  max_file_size_mb = 50 # Define the limit
334
- file_size_mb = os.path.getsize(file.name) / (1024 * 1024) # Size in MB
335
 
336
  if file_size_mb > max_file_size_mb:
337
- return (
338
- gr.Textbox(
339
- f"File size exceeds {max_file_size_mb} MB limit.", visible=True
340
- ),
341
- file_uploads_log,
342
- )
343
 
344
  # Save the uploaded file to the specified folder
345
  file_path = os.path.join(self.file_upload_folder, sanitized_name)
@@ -354,14 +344,17 @@ class GradioUI:
354
  message = text_input
355
 
356
  if file_uploads_log:
357
- message += f"\nYou have been provided with these files, which might be helpful or not: {file_uploads_log}" # Added file list
 
 
 
358
 
359
  return (
360
  message,
361
  gr.Textbox(
362
  value="",
363
  interactive=False,
364
- placeholder="Processing...", # Changed placeholder.
365
  ),
366
  gr.Button(interactive=False),
367
  )
@@ -369,29 +362,26 @@ class GradioUI:
369
  def detect_device(self, request: gr.Request):
370
  """Detect whether the user is on mobile or desktop device."""
371
  if not request:
372
- return "Unknown device" # Handle case where request is none.
373
 
374
- # Method 1: Check sec-ch-ua-mobile header
375
  is_mobile_header = request.headers.get("sec-ch-ua-mobile")
376
  if is_mobile_header:
377
  return "Mobile" if "?1" in is_mobile_header else "Desktop"
378
 
379
- # Method 2: Check user-agent string
380
  user_agent = request.headers.get("user-agent", "").lower()
381
  mobile_keywords = ["android", "iphone", "ipad", "mobile", "phone"]
382
 
383
  if any(keyword in user_agent for keyword in mobile_keywords):
384
  return "Mobile"
385
 
386
- # Method 3: Check platform
387
  platform = request.headers.get("sec-ch-ua-platform", "").lower()
388
  if platform:
389
  if platform in ['"android"', '"ios"']:
390
  return "Mobile"
391
- elif platform in ['"windows"', '"macos"', '"linux"']:
 
392
  return "Desktop"
393
 
394
- # Default case if no clear indicators
395
  return "Desktop"
396
 
397
  def launch(self, **kwargs):
@@ -405,8 +395,8 @@ class GradioUI:
405
  # Render layout with sidebar
406
  if device == "Desktop":
407
  return self._create_desktop_layout()
408
- else:
409
- return self._create_mobile_layout()
410
 
411
  demo.queue(max_size=20).launch(
412
  debug=True, **kwargs
@@ -431,7 +421,7 @@ class GradioUI:
431
  launch_research_btn = gr.Button("Run", variant="primary")
432
 
433
  # If an upload folder is provided, enable the upload feature
434
- if self.file_upload_folder is not None:
435
  upload_file = gr.File(label="Upload a file")
436
  upload_status = gr.Textbox(
437
  label="Upload Status", interactive=False, visible=False
@@ -507,7 +497,7 @@ class GradioUI:
507
  )
508
 
509
  # If an upload folder is provided, enable the upload feature
510
- if self.file_upload_folder is not None:
511
  upload_file = gr.File(label="Upload a file")
512
  upload_status = gr.Textbox(
513
  label="Upload Status", interactive=False, visible=False
@@ -546,44 +536,49 @@ class GradioUI:
546
  session_state,
547
  ):
548
  """Connect the event handlers for input elements."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
549
  # Connect text input submit event
550
  text_input.submit(
551
- self.log_user_message,
552
  [text_input, file_uploads_log],
553
  [stored_messages, text_input, launch_research_btn],
554
  ).then(
555
- self.interact_with_agent,
556
  [stored_messages, chatbot, session_state],
557
  [chatbot],
558
  ).then(
559
- lambda: (
560
- gr.Textbox(
561
- interactive=True,
562
- placeholder="Enter your prompt here and press the button",
563
- ),
564
- gr.Button(interactive=True),
565
- ),
566
  None,
567
  [text_input, launch_research_btn],
568
  )
569
 
570
  # Connect button click event
571
  launch_research_btn.click(
572
- self.log_user_message,
573
  [text_input, file_uploads_log],
574
  [stored_messages, text_input, launch_research_btn],
575
  ).then(
576
- self.interact_with_agent,
577
  [stored_messages, chatbot, session_state],
578
  [chatbot],
579
  ).then(
580
- lambda: (
581
- gr.Textbox(
582
- interactive=True,
583
- placeholder="Enter your prompt here and press the button",
584
- ),
585
- gr.Button(interactive=True),
586
- ),
587
  None,
588
  [text_input, launch_research_btn],
589
  )
 
1
+ """Main application for the OpenDeepResearch Gradio interface."""
2
+
3
  import mimetypes
4
  import os
5
  import re
 
124
  if chosen_inference == "openai":
125
  if not key_manager:
126
  raise ValueError("Key manager required for OpenAI model")
 
127
  return OpenAIServerModel(
128
  model_id=model_id, api_key=key_manager.get_key("openai_api_key")
129
  )
 
136
  )
137
 
138
  raise ValueError(f"Invalid inference type: {chosen_inference}")
 
139
  except Exception as e:
140
  print(f"✗ Couldn't load model: {e}")
141
  raise
 
165
  return Tool.from_space(
166
  space_id="xkerser/FLUX.1-dev",
167
  name="image_generator",
168
+ description="Generates high-quality AgentImage with text prompt (77 token limit).",
169
  )
170
  except Exception as e:
171
  print(f"✗ Couldn't initialize image generation tool: {e}")
 
196
  # Collect all tools in a single list
197
  web_tools = ToolRegistry.load_web_tools(model, browser, text_limit)
198
  image_generator = ToolRegistry.load_image_generation_tools()
199
+ clean_text = TextCleanerTool() # Instantiate TextCleanerTool
200
 
201
  # Combine all tools into a single list (not a tuple)
202
+ all_tools = [visualizer] + web_tools + [image_generator] + [clean_text]
203
 
204
  # Validate tools before creating agent
205
  for tool in all_tools:
206
  if not isinstance(tool, Tool):
207
  raise ValueError(
208
+ "Invalid tool type: "
209
+ f"{type(tool)}. All tools must be instances of Tool class."
210
  )
211
 
212
  return CodeAgent(
 
229
  for step_log in agent.run(
230
  task, stream=True, reset=reset_agent_memory, additional_args=additional_args
231
  ):
232
+ yield from pull_messages_from_step(step_log)
 
233
 
234
  # Process final answer : Use a more comprehensive media output
235
  final_answer = step_log # Last log is the run's final_answer
 
295
  print(f"Error in interaction: {str(e)}")
296
  raise
297
 
298
+ def upload_file(self, file, file_uploads_log):
 
 
 
 
299
  """Handle file uploads with proper validation and security."""
300
  if file is None:
301
  return gr.Textbox("No file uploaded", visible=True), file_uploads_log
 
310
 
311
  # Sanitize file name
312
  original_name = os.path.basename(file.name)
313
+ sanitized_name = re.sub(r"[^\w\-.]", "_", original_name)
 
 
314
 
315
  # Ensure the extension correlates to the mime type
316
  type_to_ext = {}
 
325
 
326
  # Limit File Size, and Throw Error
327
  max_file_size_mb = 50 # Define the limit
328
+ file_size_mb = os.path.getsize(file.name) / (1024 * 1024)
329
 
330
  if file_size_mb > max_file_size_mb:
331
+ error_msg = f"File size exceeds {max_file_size_mb} MB limit."
332
+ return gr.Textbox(error_msg, visible=True), file_uploads_log
 
 
 
 
333
 
334
  # Save the uploaded file to the specified folder
335
  file_path = os.path.join(self.file_upload_folder, sanitized_name)
 
344
  message = text_input
345
 
346
  if file_uploads_log:
347
+ message += (
348
+ "\nYou have been provided with these files, which might be helpful"
349
+ f" or not: {file_uploads_log}"
350
+ )
351
 
352
  return (
353
  message,
354
  gr.Textbox(
355
  value="",
356
  interactive=False,
357
+ placeholder="Processing...",
358
  ),
359
  gr.Button(interactive=False),
360
  )
 
362
  def detect_device(self, request: gr.Request):
363
  """Detect whether the user is on mobile or desktop device."""
364
  if not request:
365
+ return "Unknown device"
366
 
 
367
  is_mobile_header = request.headers.get("sec-ch-ua-mobile")
368
  if is_mobile_header:
369
  return "Mobile" if "?1" in is_mobile_header else "Desktop"
370
 
 
371
  user_agent = request.headers.get("user-agent", "").lower()
372
  mobile_keywords = ["android", "iphone", "ipad", "mobile", "phone"]
373
 
374
  if any(keyword in user_agent for keyword in mobile_keywords):
375
  return "Mobile"
376
 
 
377
  platform = request.headers.get("sec-ch-ua-platform", "").lower()
378
  if platform:
379
  if platform in ['"android"', '"ios"']:
380
  return "Mobile"
381
+ # Remove unnecessary elif
382
+ if platform in ['"windows"', '"macos"', '"linux"']:
383
  return "Desktop"
384
 
 
385
  return "Desktop"
386
 
387
  def launch(self, **kwargs):
 
395
  # Render layout with sidebar
396
  if device == "Desktop":
397
  return self._create_desktop_layout()
398
+ # Replace unnecessary else
399
+ return self._create_mobile_layout()
400
 
401
  demo.queue(max_size=20).launch(
402
  debug=True, **kwargs
 
421
  launch_research_btn = gr.Button("Run", variant="primary")
422
 
423
  # If an upload folder is provided, enable the upload feature
424
+ if self.file_upload_folder:
425
  upload_file = gr.File(label="Upload a file")
426
  upload_status = gr.Textbox(
427
  label="Upload Status", interactive=False, visible=False
 
497
  )
498
 
499
  # If an upload folder is provided, enable the upload feature
500
+ if self.file_upload_folder:
501
  upload_file = gr.File(label="Upload a file")
502
  upload_status = gr.Textbox(
503
  label="Upload Status", interactive=False, visible=False
 
536
  session_state,
537
  ):
538
  """Connect the event handlers for input elements."""
539
+
540
+ # Helper function to avoid duplicated code.
541
+ def process_message():
542
+ return self.log_user_message(text_input, file_uploads_log)
543
+
544
+ def interact():
545
+ return self.interact_with_agent(stored_messages, chatbot, session_state)
546
+
547
+ def reset_input():
548
+ return (
549
+ gr.Textbox(
550
+ interactive=True,
551
+ placeholder="Enter your prompt here and press the button",
552
+ ),
553
+ gr.Button(interactive=True),
554
+ )
555
+
556
  # Connect text input submit event
557
  text_input.submit(
558
+ process_message,
559
  [text_input, file_uploads_log],
560
  [stored_messages, text_input, launch_research_btn],
561
  ).then(
562
+ interact,
563
  [stored_messages, chatbot, session_state],
564
  [chatbot],
565
  ).then(
566
+ reset_input,
 
 
 
 
 
 
567
  None,
568
  [text_input, launch_research_btn],
569
  )
570
 
571
  # Connect button click event
572
  launch_research_btn.click(
573
+ process_message,
574
  [text_input, file_uploads_log],
575
  [stored_messages, text_input, launch_research_btn],
576
  ).then(
577
+ interact,
578
  [stored_messages, chatbot, session_state],
579
  [chatbot],
580
  ).then(
581
+ reset_input,
 
 
 
 
 
 
582
  None,
583
  [text_input, launch_research_btn],
584
  )