Spaces:
Sleeping
Sleeping
download conversazione e audio conversazione
Browse files- app/configs/prompts.py +10 -0
- app/llm_handling.py +108 -13
- temp_audio/speech_7579359131755957934.mp3 +0 -0
- temp_audio/speech_8367152923735697791.mp3 +0 -0
- ui/chatbot_tab.py +133 -5
app/configs/prompts.py
CHANGED
@@ -43,5 +43,15 @@ SYSTEM_PROMPTS = {
|
|
43 |
Quando comunichi con lo studente, usa un linguaggio che stimoli la riflessione interiore. Non offrire soluzioni immediate, ma guida verso una comprensione più profonda delle emozioni e dei pensieri che emergono durante lo studio. Il tuo tono deve essere calmo e riflessivo, invitando lo studente a esplorare le proprie sensazioni con curiosità invece che con giudizio.
|
44 |
Esempio: “Lo studio non è solo l'acquisizione di nozioni, ma un viaggio di scoperta di te stesso e del mondo che ti circonda. Ogni momento di difficoltà è un'opportunità per comprendere meglio come la tua mente lavora e apprende. Cosa ti sta insegnando questa esperienza su di te?”
|
45 |
Esempio n°2: “Osserva questi pensieri con curiosità, come faresti con un fenomeno interessante che stai studiando. Cosa noti di particolare nel modo in cui la tua mente sta processando questa situazione?"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
Usa questo contesto per rispondere: {context}"""
|
47 |
}
|
|
|
43 |
Quando comunichi con lo studente, usa un linguaggio che stimoli la riflessione interiore. Non offrire soluzioni immediate, ma guida verso una comprensione più profonda delle emozioni e dei pensieri che emergono durante lo studio. Il tuo tono deve essere calmo e riflessivo, invitando lo studente a esplorare le proprie sensazioni con curiosità invece che con giudizio.
|
44 |
Esempio: “Lo studio non è solo l'acquisizione di nozioni, ma un viaggio di scoperta di te stesso e del mondo che ti circonda. Ogni momento di difficoltà è un'opportunità per comprendere meglio come la tua mente lavora e apprende. Cosa ti sta insegnando questa esperienza su di te?”
|
45 |
Esempio n°2: “Osserva questi pensieri con curiosità, come faresti con un fenomeno interessante che stai studiando. Cosa noti di particolare nel modo in cui la tua mente sta processando questa situazione?"
|
46 |
+
Usa questo contesto per rispondere: {context}""",
|
47 |
+
"Choch didattico": """Sei un amichevole e disponibile coach didattico che aiuta gli insegnanti a pianificare una lezione.
|
48 |
+
Inizia presentandoti e chiedendo all'insegnante quale argomento desidera insegnare e a quale livello di grado si rivolge la sua classe. Aspetta la risposta dell'insegnante e non procedere fino a quando l'insegnante non risponde.
|
49 |
+
Successivamente, chiedi all'insegnante se gli studenti hanno conoscenze pregresse sull'argomento o se si tratta di un argomento completamente nuovo. Se gli studenti hanno conoscenze pregresse sull'argomento, chiedi all'insegnante di spiegare brevemente cosa pensa che gli studenti sappiano a riguardo. Aspetta la risposta dell'insegnante e non rispondere al posto dell'insegnante.
|
50 |
+
Dopo di che, chiedi all'insegnante quale sia il loro obiettivo di apprendimento per la lezione; cioè cosa vorrebbero che gli studenti capissero o fossero in grado di fare dopo la lezione. Aspetta una risposta.
|
51 |
+
Sulla base di queste informazioni, crea un piano di lezione personalizzato che includa una varietà di tecniche di insegnamento e modalità, tra cui l'istruzione diretta, la verifica della comprensione (compresa la raccolta di prove di comprensione da un campione ampio di studenti), la discussione, un'attività coinvolgente in classe e un compito.
|
52 |
+
Spiega perché stai scegliendo ciascuno di questi. Chiedi all'insegnante se desidera apportare modifiche o se sono a conoscenza di eventuali concezioni errate sull'argomento che gli studenti potrebbero incontrare. Aspetta una risposta.
|
53 |
+
Se l'insegnante desidera apportare modifiche o elenca eventuali concezioni errate, collabora con l'insegnante per modificare la lezione e affrontare le concezioni errate.
|
54 |
+
Successivamente, chiedi all'insegnante se desidera ricevere consigli su come assicurarsi che l'obiettivo di apprendimento venga raggiunto. Aspetta una risposta.
|
55 |
+
Se l'insegnante è soddisfatto della lezione, informa l'insegnante che può tornare a questa istruzione e contattarti nuovamente per condividere come è andata la lezione.
|
56 |
Usa questo contesto per rispondere: {context}"""
|
57 |
}
|
app/llm_handling.py
CHANGED
@@ -7,6 +7,9 @@ from openai import OpenAI
|
|
7 |
from langchain_community.vectorstores import FAISS
|
8 |
from langchain_community.embeddings import HuggingFaceEmbeddings
|
9 |
import gradio as gr
|
|
|
|
|
|
|
10 |
|
11 |
from app.config import OPENAI_API_KEY
|
12 |
from app.functions.database_handling import BASE_DB_PATH # Aggiungi questo import
|
@@ -27,6 +30,84 @@ local_client = OpenAI(
|
|
27 |
api_key="not-needed"
|
28 |
)
|
29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
def get_system_prompt(prompt_type="tutor"):
|
31 |
"""Seleziona il prompt di sistema appropriato"""
|
32 |
return SYSTEM_PROMPTS.get(prompt_type, SYSTEM_PROMPTS["tutor"])
|
@@ -76,31 +157,45 @@ def answer_question(question, db_name, prompt_type="tutor", chat_history=None, l
|
|
76 |
context = "\n".join([doc.page_content for doc in relevant_docs])
|
77 |
prompt = SYSTEM_PROMPTS[prompt_type].format(context=context)
|
78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
if llm_type == LLMType.OPENAI:
|
80 |
response = openai_client.chat.completions.create(
|
81 |
-
model="gpt-
|
82 |
-
messages=
|
83 |
-
|
84 |
-
|
85 |
-
],
|
86 |
-
temperature=0.7
|
87 |
)
|
88 |
answer = response.choices[0].message.content
|
89 |
|
90 |
else: # LOCAL
|
91 |
response = local_client.chat.completions.create(
|
92 |
model="qwen2.5-coder-7b-instruct",
|
93 |
-
messages=
|
94 |
-
{"role": "system", "content": prompt},
|
95 |
-
{"role": "user", "content": question}
|
96 |
-
],
|
97 |
temperature=0.7
|
98 |
)
|
99 |
answer = response.choices[0].message.content
|
100 |
-
|
|
|
|
|
|
|
|
|
101 |
return [
|
102 |
-
{"role": "user", "content": question},
|
103 |
-
{"role": "assistant", "content": answer}
|
104 |
]
|
105 |
|
106 |
except Exception as e:
|
|
|
7 |
from langchain_community.vectorstores import FAISS
|
8 |
from langchain_community.embeddings import HuggingFaceEmbeddings
|
9 |
import gradio as gr
|
10 |
+
import asyncio
|
11 |
+
import edge_tts
|
12 |
+
from pathlib import Path
|
13 |
|
14 |
from app.config import OPENAI_API_KEY
|
15 |
from app.functions.database_handling import BASE_DB_PATH # Aggiungi questo import
|
|
|
30 |
api_key="not-needed"
|
31 |
)
|
32 |
|
33 |
+
# Voci italiane edge-tts
|
34 |
+
VOICE_USER = "it-IT-DiegoNeural" # Voce maschile utente
|
35 |
+
VOICE_ASSISTANT = "it-IT-ElsaNeural" # Voce femminile assistente
|
36 |
+
|
37 |
+
async def text_to_speech(text, voice_name, output_file):
|
38 |
+
"""Genera audio usando edge-tts"""
|
39 |
+
communicate = edge_tts.Communicate(text, voice_name)
|
40 |
+
await communicate.save(output_file)
|
41 |
+
|
42 |
+
def generate_speech(text, is_user=True):
|
43 |
+
try:
|
44 |
+
# Crea directory per audio temporanei
|
45 |
+
audio_dir = Path("temp_audio")
|
46 |
+
audio_dir.mkdir(exist_ok=True)
|
47 |
+
|
48 |
+
# Seleziona voce e genera nome file
|
49 |
+
voice = VOICE_USER if is_user else VOICE_ASSISTANT
|
50 |
+
file_name = f"speech_{hash(text)}.mp3"
|
51 |
+
output_path = audio_dir / file_name
|
52 |
+
|
53 |
+
# Genera audio
|
54 |
+
asyncio.run(text_to_speech(text, voice, str(output_path)))
|
55 |
+
return str(output_path)
|
56 |
+
|
57 |
+
except Exception as e:
|
58 |
+
logging.error(f"Errore TTS: {e}")
|
59 |
+
return None
|
60 |
+
|
61 |
+
import re
|
62 |
+
|
63 |
+
def clean_markdown(text):
|
64 |
+
"""Rimuove markdown dal testo"""
|
65 |
+
text = re.sub(r'```[\s\S]*?```', '', text) # blocchi codice
|
66 |
+
text = re.sub(r'`.*?`', '', text) # codice inline
|
67 |
+
text = re.sub(r'\[([^\]]+)\]\([^\)]+\)', r'\1', text) # link
|
68 |
+
text = re.sub(r'\*\*(.*?)\*\*', r'\1', text) # bold
|
69 |
+
text = re.sub(r'\*(.*?)\*', r'\1', text) # italic
|
70 |
+
return text.strip()
|
71 |
+
|
72 |
+
def generate_chat_audio(chat_history):
|
73 |
+
"""Genera audio della conversazione con voci alternate"""
|
74 |
+
try:
|
75 |
+
audio_files = []
|
76 |
+
audio_dir = Path("temp_audio")
|
77 |
+
audio_dir.mkdir(exist_ok=True)
|
78 |
+
|
79 |
+
# Genera audio per ogni messaggio
|
80 |
+
for msg in chat_history:
|
81 |
+
content = clean_markdown(msg["content"])
|
82 |
+
if not content.strip():
|
83 |
+
continue
|
84 |
+
|
85 |
+
voice = VOICE_USER if msg["role"] == "user" else VOICE_ASSISTANT
|
86 |
+
file_name = f"chat_{msg['role']}_{hash(content)}.mp3"
|
87 |
+
output_path = audio_dir / file_name
|
88 |
+
|
89 |
+
# Genera audio senza prefissi
|
90 |
+
asyncio.run(text_to_speech(content, voice, str(output_path)))
|
91 |
+
audio_files.append(str(output_path))
|
92 |
+
|
93 |
+
# Combina tutti gli audio
|
94 |
+
if audio_files:
|
95 |
+
from pydub import AudioSegment
|
96 |
+
combined = AudioSegment.empty()
|
97 |
+
for audio_file in audio_files:
|
98 |
+
segment = AudioSegment.from_mp3(audio_file)
|
99 |
+
combined += segment
|
100 |
+
|
101 |
+
final_path = audio_dir / f"chat_complete_{hash(str(chat_history))}.mp3"
|
102 |
+
combined.export(str(final_path), format="mp3")
|
103 |
+
return str(final_path)
|
104 |
+
|
105 |
+
return None
|
106 |
+
|
107 |
+
except Exception as e:
|
108 |
+
logging.error(f"Errore generazione audio: {e}")
|
109 |
+
return None
|
110 |
+
|
111 |
def get_system_prompt(prompt_type="tutor"):
|
112 |
"""Seleziona il prompt di sistema appropriato"""
|
113 |
return SYSTEM_PROMPTS.get(prompt_type, SYSTEM_PROMPTS["tutor"])
|
|
|
157 |
context = "\n".join([doc.page_content for doc in relevant_docs])
|
158 |
prompt = SYSTEM_PROMPTS[prompt_type].format(context=context)
|
159 |
|
160 |
+
# Prepara la cronologia completa delle conversazioni
|
161 |
+
conversation_history = []
|
162 |
+
for msg in chat_history: # Rimuovo limite di 4 messaggi
|
163 |
+
conversation_history.append({
|
164 |
+
"role": msg["role"],
|
165 |
+
"content": msg["content"]
|
166 |
+
})
|
167 |
+
|
168 |
+
# Costruisci messaggio con contesto completo
|
169 |
+
messages = [
|
170 |
+
{"role": "system", "content": prompt},
|
171 |
+
*conversation_history, # Includi tutta la cronologia
|
172 |
+
{"role": "user", "content": question}
|
173 |
+
]
|
174 |
+
|
175 |
if llm_type == LLMType.OPENAI:
|
176 |
response = openai_client.chat.completions.create(
|
177 |
+
model="gpt-4o-mini",
|
178 |
+
messages=messages,
|
179 |
+
temperature=0.7,
|
180 |
+
max_tokens=2048 # Aumenta token per gestire conversazioni lunghe
|
|
|
|
|
181 |
)
|
182 |
answer = response.choices[0].message.content
|
183 |
|
184 |
else: # LOCAL
|
185 |
response = local_client.chat.completions.create(
|
186 |
model="qwen2.5-coder-7b-instruct",
|
187 |
+
messages=messages,
|
|
|
|
|
|
|
188 |
temperature=0.7
|
189 |
)
|
190 |
answer = response.choices[0].message.content
|
191 |
+
|
192 |
+
# Genera audio per domanda e risposta
|
193 |
+
user_audio = generate_speech(question, is_user=True)
|
194 |
+
assistant_audio = generate_speech(answer, is_user=False)
|
195 |
+
|
196 |
return [
|
197 |
+
{"role": "user", "content": question, "audio": user_audio},
|
198 |
+
{"role": "assistant", "content": answer, "audio": assistant_audio}
|
199 |
]
|
200 |
|
201 |
except Exception as e:
|
temp_audio/speech_7579359131755957934.mp3
ADDED
Binary file (35.6 kB). View file
|
|
temp_audio/speech_8367152923735697791.mp3
ADDED
Binary file (17 kB). View file
|
|
ui/chatbot_tab.py
CHANGED
@@ -1,11 +1,14 @@
|
|
1 |
# ui/chatbot_tab.py
|
2 |
|
|
|
3 |
import gradio as gr
|
4 |
from app.functions.database_handling import list_databases
|
5 |
-
from app.configs.prompts import SYSTEM_PROMPTS
|
6 |
-
from app.llm_handling import answer_question, LLMType
|
7 |
from utils.helpers import extract_text_from_files
|
8 |
|
|
|
|
|
9 |
def create_chatbot_tab():
|
10 |
"""Crea il tab 'Chatbot' dell'interfaccia Gradio."""
|
11 |
|
@@ -31,13 +34,16 @@ def create_chatbot_tab():
|
|
31 |
# Converti stringa in enum
|
32 |
selected_llm = LLMType.LOCAL if llm_type == "local" else LLMType.OPENAI
|
33 |
|
34 |
-
|
|
|
35 |
message,
|
36 |
db_name,
|
37 |
prompt_type,
|
|
|
38 |
llm_type=selected_llm
|
39 |
)
|
40 |
-
|
|
|
41 |
|
42 |
return "", chat_history
|
43 |
|
@@ -45,6 +51,98 @@ def create_chatbot_tab():
|
|
45 |
"""Pulisce la cronologia della chat."""
|
46 |
return [], []
|
47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
# Ottieni la lista aggiornata dei database
|
49 |
databases = list_databases()
|
50 |
|
@@ -84,7 +182,7 @@ def create_chatbot_tab():
|
|
84 |
with gr.Row():
|
85 |
ask_button = gr.Button("Invia")
|
86 |
clear_button = gr.Button("Pulisci Chat")
|
87 |
-
|
88 |
# Upload file con dimensioni ridotte
|
89 |
with gr.Row():
|
90 |
file_input = gr.File(
|
@@ -99,6 +197,28 @@ def create_chatbot_tab():
|
|
99 |
# Stato della chat
|
100 |
chat_state = gr.State([])
|
101 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
# Eventi per i bottoni
|
103 |
upload_button.click(
|
104 |
fn=chat_upload_and_respond,
|
@@ -117,5 +237,13 @@ def create_chatbot_tab():
|
|
117 |
outputs=[chatbot, chat_state]
|
118 |
)
|
119 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
# Ritorna il riferimento al dropdown corretto
|
121 |
return {"db_selector": db_name_chat}
|
|
|
1 |
# ui/chatbot_tab.py
|
2 |
|
3 |
+
import logging
|
4 |
import gradio as gr
|
5 |
from app.functions.database_handling import list_databases
|
6 |
+
from app.configs.prompts import SYSTEM_PROMPTS
|
7 |
+
from app.llm_handling import answer_question, LLMType, generate_chat_audio
|
8 |
from utils.helpers import extract_text_from_files
|
9 |
|
10 |
+
logging.basicConfig(level=logging.INFO)
|
11 |
+
|
12 |
def create_chatbot_tab():
|
13 |
"""Crea il tab 'Chatbot' dell'interfaccia Gradio."""
|
14 |
|
|
|
34 |
# Converti stringa in enum
|
35 |
selected_llm = LLMType.LOCAL if llm_type == "local" else LLMType.OPENAI
|
36 |
|
37 |
+
# Ottieni risposta con audio
|
38 |
+
messages = answer_question(
|
39 |
message,
|
40 |
db_name,
|
41 |
prompt_type,
|
42 |
+
chat_history=chat_history, # Passa la cronologia
|
43 |
llm_type=selected_llm
|
44 |
)
|
45 |
+
|
46 |
+
chat_history.extend(messages)
|
47 |
|
48 |
return "", chat_history
|
49 |
|
|
|
51 |
"""Pulisce la cronologia della chat."""
|
52 |
return [], []
|
53 |
|
54 |
+
def format_conversation_for_download(chat_history):
|
55 |
+
"""Formatta la cronologia della chat per il download."""
|
56 |
+
if not chat_history:
|
57 |
+
return "Nessuna conversazione da scaricare"
|
58 |
+
|
59 |
+
formatted_text = []
|
60 |
+
for msg in chat_history:
|
61 |
+
role = "User" if msg["role"] == "user" else "Assistant"
|
62 |
+
content = msg["content"]
|
63 |
+
formatted_text.append(f"{role}: {content}\n")
|
64 |
+
|
65 |
+
return "\n".join(formatted_text)
|
66 |
+
|
67 |
+
def download_conversation(chat_history):
|
68 |
+
"""Prepara il file di testo per il download."""
|
69 |
+
conversation_text = format_conversation_for_download(chat_history)
|
70 |
+
|
71 |
+
# Crea un file temporaneo con la conversazione
|
72 |
+
import tempfile
|
73 |
+
import os
|
74 |
+
from pathlib import Path
|
75 |
+
|
76 |
+
temp_dir = tempfile.gettempdir()
|
77 |
+
temp_path = os.path.join(temp_dir, "conversazione.txt")
|
78 |
+
|
79 |
+
# Assicurati che il contenuto sia in UTF-8
|
80 |
+
with open(temp_path, "w", encoding="utf-8") as f:
|
81 |
+
f.write(conversation_text)
|
82 |
+
|
83 |
+
return str(Path(temp_path).absolute())
|
84 |
+
|
85 |
+
def download_audio(chat_history):
|
86 |
+
"""Scarica l'ultimo messaggio audio dalla chat"""
|
87 |
+
try:
|
88 |
+
if not chat_history:
|
89 |
+
gr.Warning("Nessun messaggio nella chat")
|
90 |
+
return None
|
91 |
+
|
92 |
+
# Prendi l'ultimo messaggio assistant
|
93 |
+
for msg in reversed(chat_history):
|
94 |
+
if msg["role"] == "assistant" and "audio" in msg:
|
95 |
+
audio_path = msg["audio"]
|
96 |
+
if audio_path and os.path.exists(audio_path):
|
97 |
+
return audio_path
|
98 |
+
|
99 |
+
gr.Warning("Nessun audio disponibile per l'ultima risposta")
|
100 |
+
return None
|
101 |
+
|
102 |
+
except Exception as e:
|
103 |
+
gr.Error(f"Errore durante il download dell'audio: {str(e)}")
|
104 |
+
return None
|
105 |
+
|
106 |
+
def format_conversation_for_audio(chat_history):
|
107 |
+
"""Formatta la conversazione per la sintesi vocale"""
|
108 |
+
audio_text = []
|
109 |
+
for msg in chat_history:
|
110 |
+
role = "Utente" if msg["role"] == "user" else "Assistente"
|
111 |
+
audio_text.append(f"{role} dice: {msg['content']}")
|
112 |
+
return "\n".join(audio_text)
|
113 |
+
|
114 |
+
def generate_conversation_audio(chat_history):
|
115 |
+
"""Genera audio della conversazione completa"""
|
116 |
+
try:
|
117 |
+
if not chat_history:
|
118 |
+
gr.Warning("Nessun messaggio nella chat")
|
119 |
+
return None
|
120 |
+
|
121 |
+
conversation_text = format_conversation_for_audio(chat_history)
|
122 |
+
audio_path = generate_speech(conversation_text, is_user=False)
|
123 |
+
|
124 |
+
if audio_path and os.path.exists(audio_path):
|
125 |
+
return audio_path
|
126 |
+
else:
|
127 |
+
gr.Warning("Errore nella generazione dell'audio")
|
128 |
+
return None
|
129 |
+
|
130 |
+
except Exception as e:
|
131 |
+
gr.Error(f"Errore: {str(e)}")
|
132 |
+
return None
|
133 |
+
|
134 |
+
def convert_chat_to_audio(chat_history):
|
135 |
+
if not chat_history:
|
136 |
+
gr.Warning("Nessun messaggio da convertire")
|
137 |
+
return None
|
138 |
+
|
139 |
+
audio_path = generate_chat_audio(chat_history)
|
140 |
+
if audio_path:
|
141 |
+
return audio_path
|
142 |
+
else:
|
143 |
+
gr.Warning("Errore nella generazione dell'audio")
|
144 |
+
return None
|
145 |
+
|
146 |
# Ottieni la lista aggiornata dei database
|
147 |
databases = list_databases()
|
148 |
|
|
|
182 |
with gr.Row():
|
183 |
ask_button = gr.Button("Invia")
|
184 |
clear_button = gr.Button("Pulisci Chat")
|
185 |
+
|
186 |
# Upload file con dimensioni ridotte
|
187 |
with gr.Row():
|
188 |
file_input = gr.File(
|
|
|
197 |
# Stato della chat
|
198 |
chat_state = gr.State([])
|
199 |
|
200 |
+
|
201 |
+
# Download e Audio in due righe separate
|
202 |
+
with gr.Row():
|
203 |
+
with gr.Column(scale=1):
|
204 |
+
download_button = gr.Button("💾 Scarica Conversazione")
|
205 |
+
download_file = gr.File(
|
206 |
+
label="Download Conversazione",
|
207 |
+
visible=True,
|
208 |
+
interactive=False
|
209 |
+
)
|
210 |
+
|
211 |
+
with gr.Row():
|
212 |
+
with gr.Column(scale=1):
|
213 |
+
audio_button = gr.Button("🎤 Genera Audio Chat")
|
214 |
+
audio_output = gr.Audio(label="Audio", visible=True)
|
215 |
+
|
216 |
+
audio_button.click(
|
217 |
+
fn=convert_chat_to_audio,
|
218 |
+
inputs=[chatbot],
|
219 |
+
outputs=[audio_output]
|
220 |
+
)
|
221 |
+
|
222 |
# Eventi per i bottoni
|
223 |
upload_button.click(
|
224 |
fn=chat_upload_and_respond,
|
|
|
237 |
outputs=[chatbot, chat_state]
|
238 |
)
|
239 |
|
240 |
+
# Aggiungi evento per il download
|
241 |
+
download_button.click(
|
242 |
+
fn=download_conversation,
|
243 |
+
inputs=[chatbot],
|
244 |
+
outputs=[download_file]
|
245 |
+
)
|
246 |
+
|
247 |
+
|
248 |
# Ritorna il riferimento al dropdown corretto
|
249 |
return {"db_selector": db_name_chat}
|