Chat24-7 / Gradio_UI.py
MuhammadQASIM111's picture
Update Gradio_UI.py
e920e8d verified
import gradio as gr
import mimetypes
import os
import re
import shutil
from typing import Optional
from smolagents.agent_types import AgentAudio, AgentImage, AgentText, handle_agent_output_types
from smolagents.agents import ActionStep, MultiStepAgent
from smolagents.memory import MemoryStep
from smolagents.utils import _is_package_available
# ... (keep your existing pull_messages_from_step and stream_to_gradio functions as they are)
class GradioUI:
def __init__(self, agent: MultiStepAgent, file_upload_folder: str | None = None):
if not _is_package_available("gradio"):
raise ModuleNotFoundError("Please install 'gradio' extra to use the GradioUI: `pip install 'smolagents[gradio]'`")
self.agent = agent
self.file_upload_folder = file_upload_folder
if self.file_upload_folder is not None and not os.path.exists(file_upload_folder):
os.mkdir(file_upload_folder)
# Your existing interact_with_agent, upload_file, and log_user_message methods remain the same
def interact_with_agent(self, prompt, chat_history): # Renamed 'messages' to 'chat_history' for clarity with ChatInterface
# The chat_history from ChatInterface is a list of [user_message, agent_response] tuples
# You'll need to adapt your processing slightly
yield chat_history # Yield initial history to show user message
# The prompt here will already be the user's input, so no need to append it to messages again
# For demonstration, I'll assume stream_to_gradio directly yields content for the chatbot
# You might need to adjust stream_to_gradio if it yields gr.ChatMessage objects directly,
# as gr.ChatInterface expects tuples.
# Example adaptation (might need further refinement based on stream_to_gradio's exact output)
full_response_content = ""
for msg_obj in stream_to_gradio(self.agent, task=prompt, reset_agent_memory=False):
if isinstance(msg_obj, gr.ChatMessage):
# For simplicity, concatenate text content. For images/audio, you'd need more complex handling
if isinstance(msg_obj.content, str):
full_response_content += msg_obj.content + "\n"
elif isinstance(msg_obj.content, dict) and 'path' in msg_obj.content:
# Handle image/audio paths
full_response_content += f"[{msg_obj.content['mime_type']} at {msg_obj.content['path']}]\n"
# Update the last assistant message in the chat history
if chat_history and chat_history[-1][1] is None: # If the last assistant message is empty
chat_history[-1][1] = full_response_content
else:
chat_history.append([prompt, full_response_content]) # Append new turn
yield chat_history
def upload_file(self, file, file_uploads_log, allowed_file_types=None):
import gradio as gr
if allowed_file_types is None:
allowed_file_types = ["application/pdf", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "text/plain"]
if file is None:
return gr.Textbox("No file uploaded", visible=True), file_uploads_log
try:
mime_type, _ = mimetypes.guess_type(file.name)
except Exception as e:
return gr.Textbox(f"Error: {e}", visible=True), file_uploads_log
if mime_type not in allowed_file_types:
return gr.Textbox("File type disallowed", visible=True), file_uploads_log
original_name = os.path.basename(file.name)
sanitized_name = re.sub(r"[^\w\-.]", "_", original_name)
ext_map = {v: k for k, v in mimetypes.types_map.items()}
# Fix for sanitized_name generation
base_name, ext = os.path.splitext(original_name)
if not ext: # No extension, use 'txt' as default if mime_type is not specific
ext = "." + ext_map.get(mime_type, "txt")
sanitized_name = re.sub(r"[^\w\-.]", "_", base_name) + ext
file_path = os.path.join(self.file_upload_folder, sanitized_name)
shutil.copy(file.name, file_path)
return gr.Textbox(f"File uploaded: {file_path}", visible=True), file_uploads_log + [file_path]
def log_user_message(self, text_input, file_uploads_log):
context = text_input
if file_uploads_log:
context += f"\nAttached files: {file_uploads_log}"
return context, ""
def launch(self, **kwargs):
import gradio as gr
with gr.Blocks(fill_height=True) as demo:
file_uploads_log = gr.State([])
# Use gr.ChatInterface directly for the main chat
# This function will be called with the user's message and the current chat history
gr.ChatInterface(
fn=self.interact_with_agent,
chatbot=gr.Chatbot(
label="Agent",
avatar_images=(
None,
"https://huggingface.co/datasets/agents-course/course-images/resolve/main/en/communication/Alfred.png",
),
resizeable=True,
scale=1,
),
textbox=gr.Textbox(lines=1, label="Chat Message"),
title="Agent Chat", # You can set a title for your app
# Additional components can be added here using `gr.Row`, `gr.Column`, etc.
)
# Add file upload outside ChatInterface if desired, and link it
if self.file_upload_folder is not None:
with gr.Row():
upload_file = gr.File(label="Upload a file", file_count="multiple") # Allow multiple files
upload_status = gr.Textbox(label="Upload Status", interactive=False, visible=False)
upload_file.upload(self.upload_file, [upload_file, file_uploads_log], [upload_status, file_uploads_log])
# You'll need to figure out how to pass file_uploads_log to interact_with_agent
# One way is to modify interact_with_agent to accept it, or use a global/class variable if appropriate.
# For now, I'm just showing how to add it to the UI.
demo.launch(debug=True, share=True, **kwargs)
__all__ = ["stream_to_gradio", "GradioUI"]