Leonardo commited on
Commit
de1d827
Β·
verified Β·
1 Parent(s): ab8d243

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +129 -83
app.py CHANGED
@@ -33,7 +33,7 @@ from smolagents import (
33
  GoogleSearchTool,
34
  Tool,
35
  )
36
- from smolagents.agent_types import AgentText, AgentImage, AgentAudio
37
  from smolagents.gradio_ui import pull_messages_from_step, handle_agent_output_types
38
 
39
 
@@ -162,8 +162,8 @@ class ModelManager:
162
  )
163
 
164
  raise ValueError(f"Invalid inference type: {chosen_inference}")
165
- except Exception as e:
166
- print(f"βœ— Couldn't load model: {e}")
167
  raise
168
 
169
 
@@ -191,7 +191,10 @@ class ToolRegistry:
191
  return Tool.from_space(
192
  space_id="xkerser/FLUX.1-dev",
193
  name="image_generator",
194
- description="Generates high-quality AgentImage with text prompt (77 token limit).",
 
 
 
195
  )
196
  except Exception as e:
197
  print(f"βœ— Couldn't initialize image generation tool: {e}")
@@ -251,43 +254,68 @@ def stream_to_gradio(
251
  reset_agent_memory: bool = False,
252
  additional_args: Optional[dict] = None,
253
  ):
254
- """Runs an agent with the given task and streams messages as Gradio ChatMessages."""
255
- for step_log in agent.run(
256
- task, stream=True, reset=reset_agent_memory, additional_args=additional_args
257
- ):
258
- yield from pull_messages_from_step(step_log)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
 
260
- # Process final answer : Use a more comprehensive media output
261
- final_answer = step_log # Last log is the run's final_answer
262
- final_answer = handle_agent_output_types(final_answer)
 
 
263
 
264
- if isinstance(final_answer, AgentText):
265
- yield gr.ChatMessage(
266
- role="assistant",
267
- content=f"**Final answer:**\n{final_answer.to_string()}\n",
268
- )
269
- elif isinstance(final_answer, AgentImage):
270
- yield gr.ChatMessage(
271
- role="assistant",
272
- content={"image": final_answer.to_string(), "type": "file"},
273
- ) # Send as Gradio-compatible file object:
274
- elif isinstance(final_answer, AgentAudio):
 
 
 
 
 
275
  yield gr.ChatMessage(
276
  role="assistant",
277
- content={"audio": final_answer.to_string(), "type": "file"},
278
- ) # Send as Gradio-compatible file object
279
- else:
280
- yield gr.ChatMessage(
281
- role="assistant", content=f"**Final answer:** {str(final_answer)}"
282
  )
283
 
284
 
285
  class GradioUI:
286
- """A one-line interface to launch your agent in Gradio."""
287
-
288
- def __init__(self, file_upload_folder: str | None = None):
289
- """Initialize the Gradio UI with optional file upload functionality."""
290
  self.file_upload_folder = file_upload_folder
 
 
 
 
 
 
 
 
 
291
 
292
  if self.file_upload_folder is not None:
293
  os.makedirs(file_upload_folder, exist_ok=True)
@@ -377,7 +405,7 @@ class GradioUI:
377
 
378
  def log_user_message(self, text_input, file_uploads_log):
379
  """Process user message and handle file references."""
380
- # Clean the user input using the TextCleanerTool
381
  cleaned_message = clean(
382
  text_input,
383
  fix_unicode=True,
@@ -431,8 +459,7 @@ class GradioUI:
431
  if platform:
432
  if platform in ['"android"', '"ios"']:
433
  return "Mobile"
434
- elif platform in ['"windows"', '"macos"', '"linux"']:
435
- return "Desktop"
436
 
437
  # Default case if no clear indicators
438
  return "Desktop"
@@ -579,56 +606,75 @@ class GradioUI:
579
 
580
  return simple_demo
581
 
582
- def _connect_event_handlers(
583
- self,
584
- text_input,
585
- launch_research_btn,
586
- file_uploads_log,
587
- stored_messages,
588
- chatbot,
589
- session_state,
590
- ):
591
- """Connect the event handlers for input elements."""
592
- # Connect text input submit event
593
- text_input.submit(
594
- self.log_user_message,
595
- [text_input, file_uploads_log],
596
- [stored_messages, text_input, launch_research_btn],
597
- ).then(
598
- self.interact_with_agent,
599
- [stored_messages, chatbot, session_state],
600
- [chatbot],
601
- ).then(
602
- lambda: (
603
- gr.Textbox(
604
- interactive=True,
605
- placeholder="Enter your prompt here and press the button",
606
- ),
607
- gr.Button(interactive=True),
608
- ),
609
- None,
610
- [text_input, launch_research_btn],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
611
  )
612
 
613
- # Connect button click event
614
- launch_research_btn.click(
615
- self.log_user_message,
616
- [text_input, file_uploads_log],
617
- [stored_messages, text_input, launch_research_btn],
618
- ).then(
619
- self.interact_with_agent,
620
- [stored_messages, chatbot, session_state],
621
- [chatbot],
622
- ).then(
623
- lambda: (
624
- gr.Textbox(
625
- interactive=True,
626
- placeholder="Enter your prompt here and press the button",
627
- ),
628
- gr.Button(interactive=True),
629
- ),
630
- None,
631
- [text_input, launch_research_btn],
632
  )
633
 
634
 
 
33
  GoogleSearchTool,
34
  Tool,
35
  )
36
+ from smolagents.agent_types import AgentText # Removed: AgentImage, AgentAudio
37
  from smolagents.gradio_ui import pull_messages_from_step, handle_agent_output_types
38
 
39
 
 
162
  )
163
 
164
  raise ValueError(f"Invalid inference type: {chosen_inference}")
165
+ except (ValueError, RuntimeError) as e: # More specific exceptions
166
+ print(f"Model loading failed: {e}")
167
  raise
168
 
169
 
 
191
  return Tool.from_space(
192
  space_id="xkerser/FLUX.1-dev",
193
  name="image_generator",
194
+ description=(
195
+ "Generates high-quality AgentImage. "
196
+ "with text prompt (77 token limit).",
197
+ ),
198
  )
199
  except Exception as e:
200
  print(f"βœ— Couldn't initialize image generation tool: {e}")
 
254
  reset_agent_memory: bool = False,
255
  additional_args: Optional[dict] = None,
256
  ):
257
+ """Streams agent responses with improved status indicators."""
258
+ try:
259
+ # Initial processing indicator
260
+ yield gr.ChatMessage(role="assistant", content="⏳ Processing your request...")
261
+
262
+ # Track what we've yielded to replace the processing indicator
263
+ first_message_yielded = False
264
+
265
+ for step_log in agent.run(
266
+ task, stream=True, reset=reset_agent_memory, additional_args=additional_args
267
+ ):
268
+ messages = pull_messages_from_step(step_log)
269
+
270
+ for message in messages:
271
+ if not first_message_yielded:
272
+ # Replace the initial "Processing" message
273
+ first_message_yielded = True
274
+ message.content = message.content.replace(
275
+ "⏳ Processing your request...", ""
276
+ )
277
 
278
+ # Add progressive status indicators for document processing steps
279
+ if "analyzing document" in step_log.get("status", ""):
280
+ message.content = f"πŸ“„ **Document Analysis:** {message.content}"
281
+ elif "searching" in step_log.get("status", ""):
282
+ message.content = f"πŸ” **Search:** {message.content}"
283
 
284
+ yield message
285
+
286
+ # Final answer with enhanced formatting
287
+ final_answer = handle_agent_output_types(step_log)
288
+
289
+ if isinstance(final_answer, AgentText):
290
+ yield gr.ChatMessage(
291
+ role="assistant",
292
+ content=f"βœ… **Final Answer:**\n\n{final_answer.to_string()}",
293
+ )
294
+ else:
295
+ yield gr.ChatMessage(
296
+ role="assistant", content=f"βœ… **Final Answer:** {str(final_answer)}"
297
+ )
298
+
299
+ except Exception as e:
300
  yield gr.ChatMessage(
301
  role="assistant",
302
+ content=f"❌ **Error:** {str(e)}\n\nPlease try again with a different query.",
 
 
 
 
303
  )
304
 
305
 
306
  class GradioUI:
307
+ def __init__(self, file_upload_folder=None, max_queue_size=50):
308
+ # Initialize all attributes here
 
 
309
  self.file_upload_folder = file_upload_folder
310
+ self.max_queue_size = max_queue_size
311
+ self.text_input = None
312
+ self.submit_btn = None
313
+ self.stop_btn = None
314
+ self.clear_btn = None
315
+ self.status = None
316
+ self.chatbot = None
317
+ self.session_state = None
318
+ self.job = None
319
 
320
  if self.file_upload_folder is not None:
321
  os.makedirs(file_upload_folder, exist_ok=True)
 
405
 
406
  def log_user_message(self, text_input, file_uploads_log):
407
  """Process user message and handle file references."""
408
+
409
  cleaned_message = clean(
410
  text_input,
411
  fix_unicode=True,
 
459
  if platform:
460
  if platform in ['"android"', '"ios"']:
461
  return "Mobile"
462
+ return "Desktop"
 
463
 
464
  # Default case if no clear indicators
465
  return "Desktop"
 
606
 
607
  return simple_demo
608
 
609
+ def _create_common_ui_elements(self):
610
+ """Create common UI elements with control buttons."""
611
+ with gr.Group():
612
+ self.text_input = gr.Textbox(
613
+ lines=3,
614
+ label="Your request",
615
+ placeholder="Enter your question about the documents...",
616
+ elem_classes=["prompt-box"],
617
+ )
618
+
619
+ with gr.Row():
620
+ self.submit_btn = gr.Button("Run", variant="primary")
621
+ self.stop_btn = gr.Button("Stop Generation", variant="stop")
622
+ self.clear_btn = gr.Button("Clear Chat", variant="secondary")
623
+
624
+ # Status indicator for document processing
625
+ self.status = gr.Textbox(
626
+ "", label="Status", interactive=False, visible=True
627
+ )
628
+
629
+ def _connect_event_handlers(self):
630
+ """Connect event handlers with stop functionality."""
631
+ # Define the job handler for stopping generation
632
+ self.job = None
633
+
634
+ def start_processing(prompt, chat_history):
635
+ # Update UI for processing state
636
+ self.status.update(value="⏳ Processing request...", visible=True)
637
+ self.submit_btn.update(interactive=False)
638
+ self.stop_btn.update(visible=True)
639
+ return prompt, chat_history
640
+
641
+ def stop_generation():
642
+ if self.job:
643
+ self.job.cancel()
644
+ self.status.update(value="βœ‹ Generation stopped by user", visible=True)
645
+ self.submit_btn.update(interactive=True)
646
+ self.stop_btn.update(visible=False)
647
+
648
+ def clear_chat():
649
+ return [], gr.Textbox(interactive=True), gr.Button(interactive=True), ""
650
+
651
+ # Connect event handlers
652
+ process_event = (
653
+ self.text_input.submit(
654
+ start_processing,
655
+ [self.text_input, self.chatbot],
656
+ [self.text_input, self.chatbot],
657
+ )
658
+ .then(
659
+ self._interact_with_agent,
660
+ [self.text_input, self.chatbot, self.session_state],
661
+ [self.chatbot],
662
+ )
663
+ .then(
664
+ lambda: (gr.Textbox(interactive=True), gr.Button(interactive=True), ""),
665
+ None,
666
+ [self.text_input, self.submit_btn, self.status],
667
+ )
668
  )
669
 
670
+ # Store the job for cancellation
671
+ self.job = process_event
672
+
673
+ # Connect stop and clear buttons
674
+ self.stop_btn.click(stop_generation)
675
+ self.clear_btn.click(
676
+ clear_chat,
677
+ outputs=[self.chatbot, self.text_input, self.submit_btn, self.status],
 
 
 
 
 
 
 
 
 
 
 
678
  )
679
 
680