Spaces:
Running
Running
# ui/chatbot_tab.py | |
import logging | |
import gradio as gr | |
from app.functions.database_handling import list_databases | |
from app.configs.prompts import SYSTEM_PROMPTS | |
from app.llm_handling import answer_question, LLMType, generate_chat_audio | |
from utils.helpers import extract_text_from_files | |
logging.basicConfig(level=logging.INFO) | |
def create_chatbot_tab(): | |
"""Crea il tab 'Chatbot' dell'interfaccia Gradio.""" | |
def chat_upload_and_respond(files, chat_history, db_name): | |
"""Gestisce il caricamento dei file e aggiorna la chat con il contenuto.""" | |
if chat_history is None: | |
chat_history = [] | |
text = extract_text_from_files(files) | |
chat_history.append({ | |
"role": "assistant", | |
"content": f"📄 Contenuto dei documenti caricati:\n{text}" | |
}) | |
return chat_history | |
def respond(message, chat_history, db_name, prompt_type, llm_type): | |
"""Genera una risposta alla domanda dell'utente e aggiorna la chat.""" | |
if chat_history is None: | |
chat_history = [] | |
# Converti stringa in enum | |
selected_llm = LLMType.LOCAL if llm_type == "local" else LLMType.OPENAI | |
# Ottieni risposta con audio | |
messages = answer_question( | |
message, | |
db_name, | |
prompt_type, | |
chat_history=chat_history, # Passa la cronologia | |
llm_type=selected_llm | |
) | |
chat_history.extend(messages) | |
return "", chat_history | |
def clear_chat(): | |
"""Pulisce la cronologia della chat.""" | |
return [], [] | |
def format_conversation_for_download(chat_history): | |
"""Formatta la cronologia della chat per il download.""" | |
if not chat_history: | |
return "Nessuna conversazione da scaricare" | |
formatted_text = [] | |
for msg in chat_history: | |
role = "User" if msg["role"] == "user" else "Assistant" | |
content = msg["content"] | |
formatted_text.append(f"{role}: {content}\n") | |
return "\n".join(formatted_text) | |
def download_conversation(chat_history): | |
"""Prepara il file di testo per il download.""" | |
conversation_text = format_conversation_for_download(chat_history) | |
# Crea un file temporaneo con la conversazione | |
import tempfile | |
import os | |
from pathlib import Path | |
temp_dir = tempfile.gettempdir() | |
temp_path = os.path.join(temp_dir, "conversazione.txt") | |
# Assicurati che il contenuto sia in UTF-8 | |
with open(temp_path, "w", encoding="utf-8") as f: | |
f.write(conversation_text) | |
return str(Path(temp_path).absolute()) | |
def download_audio(chat_history): | |
"""Scarica l'ultimo messaggio audio dalla chat""" | |
try: | |
if not chat_history: | |
gr.Warning("Nessun messaggio nella chat") | |
return None | |
# Prendi l'ultimo messaggio assistant | |
for msg in reversed(chat_history): | |
if msg["role"] == "assistant" and "audio" in msg: | |
audio_path = msg["audio"] | |
if audio_path and os.path.exists(audio_path): | |
return audio_path | |
gr.Warning("Nessun audio disponibile per l'ultima risposta") | |
return None | |
except Exception as e: | |
gr.Error(f"Errore durante il download dell'audio: {str(e)}") | |
return None | |
def format_conversation_for_audio(chat_history): | |
"""Formatta la conversazione per la sintesi vocale""" | |
audio_text = [] | |
for msg in chat_history: | |
role = "Utente" if msg["role"] == "user" else "Assistente" | |
audio_text.append(f"{role} dice: {msg['content']}") | |
return "\n".join(audio_text) | |
def generate_conversation_audio(chat_history): | |
"""Genera audio della conversazione completa""" | |
try: | |
if not chat_history: | |
gr.Warning("Nessun messaggio nella chat") | |
return None | |
conversation_text = format_conversation_for_audio(chat_history) | |
audio_path = generate_speech(conversation_text, is_user=False) | |
if audio_path and os.path.exists(audio_path): | |
return audio_path | |
else: | |
gr.Warning("Errore nella generazione dell'audio") | |
return None | |
except Exception as e: | |
gr.Error(f"Errore: {str(e)}") | |
return None | |
def convert_chat_to_audio(chat_history): | |
if not chat_history: | |
gr.Warning("Nessun messaggio da convertire") | |
return None | |
audio_path = generate_chat_audio(chat_history) | |
if audio_path: | |
return audio_path | |
else: | |
gr.Warning("Errore nella generazione dell'audio") | |
return None | |
# Ottieni la lista aggiornata dei database | |
databases = list_databases() | |
with gr.Tab("Chatbot"): | |
# Prima riga: Dropdown selettori | |
with gr.Row(): | |
with gr.Column(scale=1): | |
db_name_chat = gr.Dropdown( | |
choices=databases, | |
label="Seleziona Database", | |
value="default_db" | |
) | |
with gr.Column(scale=1): | |
prompt_selector = gr.Dropdown( | |
choices=list(SYSTEM_PROMPTS.keys()), | |
label="Seleziona Stile Risposta", | |
value="tutor" | |
) | |
with gr.Column(scale=1): | |
llm_selector = gr.Dropdown( | |
choices=["openai", "local"], | |
label="Seleziona Modello", | |
value="openai" | |
) | |
# Chatbot e input | |
chatbot = gr.Chatbot(label="Conversazione", type="messages") | |
question_input = gr.Textbox( | |
label="Fai una domanda", | |
placeholder="Scrivi qui la tua domanda...", | |
lines=2 | |
) | |
# Bottoni per azioni | |
with gr.Row(): | |
ask_button = gr.Button("Invia") | |
clear_button = gr.Button("Pulisci Chat") | |
# Upload file con dimensioni ridotte | |
with gr.Row(): | |
file_input = gr.File( | |
label="Carica PDF/Docx/TXT per la conversazione", | |
file_types=[".pdf", ".docx", ".txt"], | |
file_count="multiple", | |
height="100px", | |
scale=3 | |
) | |
upload_button = gr.Button("Carica Documenti", scale=1) | |
# Stato della chat | |
chat_state = gr.State([]) | |
# Download e Audio in due righe separate | |
with gr.Row(): | |
with gr.Column(scale=1): | |
download_button = gr.Button("💾 Scarica Conversazione") | |
download_file = gr.File( | |
label="Download Conversazione", | |
visible=True, | |
interactive=False | |
) | |
with gr.Row(): | |
with gr.Column(scale=1): | |
audio_button = gr.Button("🎤 Genera Audio Chat") | |
audio_output = gr.Audio(label="Audio", visible=True) | |
audio_button.click( | |
fn=convert_chat_to_audio, | |
inputs=[chatbot], | |
outputs=[audio_output] | |
) | |
# Eventi per i bottoni | |
upload_button.click( | |
fn=chat_upload_and_respond, | |
inputs=[file_input, chat_state, db_name_chat], | |
outputs=chatbot | |
) | |
ask_button.click( | |
fn=respond, | |
inputs=[question_input, chat_state, db_name_chat, prompt_selector, llm_selector], # Aggiungi il selettore del modello | |
outputs=[question_input, chatbot] | |
) | |
clear_button.click( | |
fn=clear_chat, | |
outputs=[chatbot, chat_state] | |
) | |
# Aggiungi evento per il download | |
download_button.click( | |
fn=download_conversation, | |
inputs=[chatbot], | |
outputs=[download_file] | |
) | |
# Ritorna il riferimento al dropdown corretto | |
return {"db_selector": db_name_chat} | |