Nugh75 commited on
Commit
e6b7117
·
1 Parent(s): 07697cb

Da controllare

Browse files
app.py CHANGED
@@ -1,5 +1,3 @@
1
- # app.py nuovo
2
-
3
  import gradio as gr
4
  import logging
5
  from app.logging_config import configure_logging
 
 
 
1
  import gradio as gr
2
  import logging
3
  from app.logging_config import configure_logging
app/config.py CHANGED
@@ -11,13 +11,17 @@ load_dotenv()
11
 
12
  # Configurazione del modello
13
  OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
 
14
  if not OPENAI_API_KEY:
15
  raise ValueError("OPENAI_API_KEY non trovata. Verifica il file .env")
 
 
16
 
17
  class LLMType(Enum):
18
  OPENAI_GPT_4O_MINI = "openai - GPT-4o-mini"
19
  LOCAL_QWEN = "local - Qwen 7B"
20
  LOCAL_PHI = "local - Phi-3 Mini"
 
21
 
22
  # Configurazione modelli
23
  LLM_CONFIGS = {
@@ -35,6 +39,11 @@ LLM_CONFIGS = {
35
  "client": lambda: OpenAI(base_url="http://192.168.43.199:1234/v1", api_key="not-needed"),
36
  "model": "phi-3.5-mini-ita",
37
  "base_url": "http://192.168.43.199:1234/v1"
 
 
 
 
 
38
  }
39
  }
40
 
@@ -42,10 +51,14 @@ EMBEDDING_CONFIG = {
42
  "model_name": "sentence-transformers/multi-qa-mpnet-base-dot-v1",
43
  "chunk_size": 2000,
44
  "chunk_overlap": 100,
45
- "k_documents": 5,
46
  "min_similarity": 0.7
47
  }
48
 
 
 
 
 
 
49
  # Aggiungi questa costante
50
  EMBEDDING_MODEL = "sentence-transformers/multi-qa-mpnet-base-dot-v1"
51
 
 
11
 
12
  # Configurazione del modello
13
  OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
14
+ DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
15
  if not OPENAI_API_KEY:
16
  raise ValueError("OPENAI_API_KEY non trovata. Verifica il file .env")
17
+ if not DEEPSEEK_API_KEY:
18
+ raise ValueError("DEEPSEEK_API_KEY non trovata. Verifica il file .env")
19
 
20
  class LLMType(Enum):
21
  OPENAI_GPT_4O_MINI = "openai - GPT-4o-mini"
22
  LOCAL_QWEN = "local - Qwen 7B"
23
  LOCAL_PHI = "local - Phi-3 Mini"
24
+ DEEPSEEK = "deepseek - DeepSeek Chat"
25
 
26
  # Configurazione modelli
27
  LLM_CONFIGS = {
 
39
  "client": lambda: OpenAI(base_url="http://192.168.43.199:1234/v1", api_key="not-needed"),
40
  "model": "phi-3.5-mini-ita",
41
  "base_url": "http://192.168.43.199:1234/v1"
42
+ },
43
+ LLMType.DEEPSEEK: {
44
+ "client": lambda: OpenAI(api_key=DEEPSEEK_API_KEY, base_url="https://api.deepseek.com/v1"),
45
+ "model": "deepseek-chat",
46
+ "base_url": "https://api.deepseek.com/v1"
47
  }
48
  }
49
 
 
51
  "model_name": "sentence-transformers/multi-qa-mpnet-base-dot-v1",
52
  "chunk_size": 2000,
53
  "chunk_overlap": 100,
 
54
  "min_similarity": 0.7
55
  }
56
 
57
+ LLM_CONFIGS_EXTENDED = {
58
+ "temperature": 0.7,
59
+ "max_tokens": 2048
60
+ }
61
+
62
  # Aggiungi questa costante
63
  EMBEDDING_MODEL = "sentence-transformers/multi-qa-mpnet-base-dot-v1"
64
 
app/configs/prompts.py CHANGED
@@ -3,16 +3,16 @@ SYSTEM_PROMPTS = {
3
  "tutor": "Sei un tutor didattico di nome Valter. Usa questo contesto per rispondere: {context}. Cita sempre il titolo e l'autore dei documenti da cui prendi le informazioni. Inoltre, ricorda sempre di andare ad approfondire l'argomento",
4
 
5
  # Analisi dati scientifici
6
- "scientist": "Sei uno scienziato esperto. Analizza il contesto: {context}",
7
 
8
  # Consulenza tecnica specialistica
9
- "expert": "Sei un esperto nel settore. Fornisci risposte tecniche: {context}",
10
 
11
  # Spiegazioni chiare semplici
12
- "teacher": "Sei un insegnante paziente. Spiega in modo semplice: {context}",
13
 
14
  # Guida scelte formative
15
- "orientatore": """ Sei un tutor orientatore serio e professionale, specializzato nel guidare studenti delle scuole verso scelte consapevoli per il loro percorso formativo e professionale. Il tuo compito è ascoltare con attenzione le esigenze degli studenti, comprendere le loro aspirazioni e competenze, e fornire informazioni chiare e dettagliate sulle possibili opportunità scolastiche e lavorative. Devi rispondere in modo formale, empatico e ben strutturato, fornendo consigli utili e pertinenti, tenendo conto degli interessi, dei punti di forza e delle aspirazioni di ciascun studente. Non dimenticare di incoraggiare sempre una riflessione autonoma e critica, stimolando la capacità di prendere decisioni consapevoli e responsabili.
16
 
17
  Fase 1: Accoglienza e Creazione di un Rapporto Empatico
18
  Presentati con chiarezza e professionalità, adottando un tono rassicurante e comprendendo la situazione dell’utente. Accogli le incertezze dello studente, offrigli la possibilità di esprimere dubbi, interessi e preoccupazioni, e mostrati disponibile ad accompagnarlo lungo il percorso orientativo.
@@ -55,24 +55,22 @@ Esempio n°2: “Osserva questi pensieri con curiosità, come faresti con un fen
55
  Usa questo contesto per rispondere: {context}""",
56
 
57
  # Simulazione podcast
58
- "podcaster": """Sei un podcaster esperto e carismatico che conduce conversazioni in stile podcast.
59
  Il tuo modo di parlare è naturale e informale, con occasionali "uhm", "ehm" e false partenze tipiche del parlato spontaneo.
60
 
61
  Caratteristiche del tuo stile:
62
  - dai risposte brevi
63
  - cerca l'interazione dai lo spunto per un altra domanda, osservazione o cose del genere
64
- - Inizi sempre con "Ehm... ok, mic check [pausa] Perfetto! Ciao a tutti e benvenuti a una nuova puntata..."
65
- - Usi spesso interiezioni come "uhm", "beh", "ecco"
66
- - A volte ti correggi o riparti ("Volevo dire...", "Scusate, ricomincio...")
67
  - Fai piccole pause riflessive (...) durante il discorso
68
  - Mantieni un tono conversazionale e coinvolgente
69
- - Chiedi feedback e opinioni agli ascoltatori
70
- - quando il tuo interlucore di dice di concludere o di findiri concludi sempre con "E questo è tutto per oggi! Se vi è piaciuta questa puntata... uhm... non dimenticate di seguirci!"
71
 
72
  Usa questo contesto nella conversazione: {context}""",
73
 
74
  # Supporto pianificazione didattica
75
- "Choch didattico": """Sei un amichevole e disponibile coach didattico che aiuta gli insegnanti a pianificare una lezione.
76
  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.
77
  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.
78
  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.
 
3
  "tutor": "Sei un tutor didattico di nome Valter. Usa questo contesto per rispondere: {context}. Cita sempre il titolo e l'autore dei documenti da cui prendi le informazioni. Inoltre, ricorda sempre di andare ad approfondire l'argomento",
4
 
5
  # Analisi dati scientifici
6
+ "scientist": "Sei uno scienziato esperto di nome Matteo. Analizza il contesto: {context}",
7
 
8
  # Consulenza tecnica specialistica
9
+ "expert": "Sei un esperto nel settore di nome Salvatore. Fornisci risposte tecniche: {context}",
10
 
11
  # Spiegazioni chiare semplici
12
+ "teacher": "Sei un insegnante paziente di nome Désirée. Spiega in modo semplice: {context}",
13
 
14
  # Guida scelte formative
15
+ "orientatore": """Il tuo nome è Massimo,Sei un tutor orientatore serio e professionale, specializzato nel guidare studenti delle scuole verso scelte consapevoli per il loro percorso formativo e professionale. Il tuo compito è ascoltare con attenzione le esigenze degli studenti, comprendere le loro aspirazioni e competenze, e fornire informazioni chiare e dettagliate sulle possibili opportunità scolastiche e lavorative. Devi rispondere in modo formale, empatico e ben strutturato, fornendo consigli utili e pertinenti, tenendo conto degli interessi, dei punti di forza e delle aspirazioni di ciascun studente. Non dimenticare di incoraggiare sempre una riflessione autonoma e critica, stimolando la capacità di prendere decisioni consapevoli e responsabili.
16
 
17
  Fase 1: Accoglienza e Creazione di un Rapporto Empatico
18
  Presentati con chiarezza e professionalità, adottando un tono rassicurante e comprendendo la situazione dell’utente. Accogli le incertezze dello studente, offrigli la possibilità di esprimere dubbi, interessi e preoccupazioni, e mostrati disponibile ad accompagnarlo lungo il percorso orientativo.
 
55
  Usa questo contesto per rispondere: {context}""",
56
 
57
  # Simulazione podcast
58
+ "podcaster": """Sei un podcaster, il tuo nome è Ilaria. esperto e carismatico che conduce conversazioni in stile podcast.
59
  Il tuo modo di parlare è naturale e informale, con occasionali "uhm", "ehm" e false partenze tipiche del parlato spontaneo.
60
 
61
  Caratteristiche del tuo stile:
62
  - dai risposte brevi
63
  - cerca l'interazione dai lo spunto per un altra domanda, osservazione o cose del genere
64
+ - Usi spesso interiezioni come "uhm", "beh", "ecco"
65
+
 
66
  - Fai piccole pause riflessive (...) durante il discorso
67
  - Mantieni un tono conversazionale e coinvolgente
68
+ -Cerca di essere interattivo e conivolgente con il tuo interllocutore
 
69
 
70
  Usa questo contesto nella conversazione: {context}""",
71
 
72
  # Supporto pianificazione didattica
73
+ "Assistente didattico": """Sei un amichevole e disponibile Assistente didattico di nome Sonia che aiuta gli insegnanti a pianificare una lezione.
74
  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.
75
  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.
76
  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.
app/llm_handling.py CHANGED
@@ -11,7 +11,8 @@ from app.config import (
11
  BASE_DB_PATH,
12
  LLM_CONFIGS,
13
  LLMType,
14
- EMBEDDING_CONFIG
 
15
  )
16
  from app.configs.prompts import SYSTEM_PROMPTS
17
  from app.utils.embedding_utils import get_embeddings
@@ -53,13 +54,12 @@ def read_metadata(db_path):
53
  return []
54
 
55
  def get_relevant_documents(vectorstore, question):
56
- """Retrieves relevant documents from the vectorstore"""
57
  try:
58
  enhanced_query = enhance_query(question)
59
- docs_and_scores = vectorstore.similarity_search_with_score(
60
- enhanced_query,
61
- k=EMBEDDING_CONFIG['k_documents']
62
- )
63
  filtered_docs = [
64
  doc for doc, score in docs_and_scores
65
  if score >= EMBEDDING_CONFIG['min_similarity']
@@ -83,9 +83,48 @@ def log_search_results(question, docs_and_scores):
83
  logging.info(f"Content: {doc.page_content[:100]}...")
84
 
85
  @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  def answer_question(question, db_name, prompt_type="tutor", chat_history=None, llm_type=LLMType.OPENAI_GPT_4O_MINI):
87
  if chat_history is None:
88
  chat_history = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  try:
90
  # Setup e recupero documenti
91
  db_path = os.path.join(BASE_DB_PATH, f"faiss_index_{db_name}")
@@ -141,8 +180,8 @@ def answer_question(question, db_name, prompt_type="tutor", chat_history=None, l
141
  response = client.chat.completions.create(
142
  model=model,
143
  messages=messages,
144
- temperature=0.7,
145
- max_tokens=2048
146
  )
147
 
148
  answer = response.choices[0].message.content + sources_text
@@ -169,12 +208,12 @@ class DocumentRetriever:
169
 
170
  def get_relevant_chunks(self, question):
171
  enhanced_query = enhance_query(question)
172
- docs_and_scores = self.vectorstore.similarity_search_with_score(
173
- enhanced_query,
174
- k=EMBEDDING_CONFIG['k_documents']
175
- )
176
  log_search_results(question, docs_and_scores)
177
- return [doc for doc, _ in docs_and_scores]
 
 
 
178
 
179
  if __name__ == "__main__":
180
- pass
 
11
  BASE_DB_PATH,
12
  LLM_CONFIGS,
13
  LLMType,
14
+ EMBEDDING_CONFIG,
15
+ LLM_CONFIGS_EXTENDED
16
  )
17
  from app.configs.prompts import SYSTEM_PROMPTS
18
  from app.utils.embedding_utils import get_embeddings
 
54
  return []
55
 
56
  def get_relevant_documents(vectorstore, question):
57
+ """Retrieves relevant documents from the vectorstore based on similarity threshold"""
58
  try:
59
  enhanced_query = enhance_query(question)
60
+ # Get all documents with their similarity scores
61
+ docs_and_scores = vectorstore.similarity_search_with_score(enhanced_query)
62
+ # Filter documents based on similarity threshold
 
63
  filtered_docs = [
64
  doc for doc, score in docs_and_scores
65
  if score >= EMBEDDING_CONFIG['min_similarity']
 
83
  logging.info(f"Content: {doc.page_content[:100]}...")
84
 
85
  @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
86
+ def summarize_context(messages):
87
+ """Crea un riassunto del contesto mantenendo le informazioni chiave"""
88
+ summary = []
89
+ key_info = set()
90
+
91
+ for msg in messages:
92
+ if msg["role"] == "system":
93
+ continue
94
+
95
+ # Estrai informazioni chiave
96
+ content = msg["content"]
97
+ if "fonte" in content.lower() or "fonti" in content.lower():
98
+ key_info.add(content)
99
+ elif "importante" in content.lower() or "nota" in content.lower():
100
+ key_info.add(content)
101
+
102
+ if key_info:
103
+ summary.append({
104
+ "role": "system",
105
+ "content": "Contesto riassunto:\n" + "\n".join(f"- {info}" for info in key_info)
106
+ })
107
+
108
+ return summary
109
+
110
  def answer_question(question, db_name, prompt_type="tutor", chat_history=None, llm_type=LLMType.OPENAI_GPT_4O_MINI):
111
  if chat_history is None:
112
  chat_history = []
113
+
114
+ # Configurazione dinamica della cronologia
115
+ MAX_HISTORY_TOKENS = int(LLM_CONFIGS_EXTENDED["max_tokens"] * 0.4) # 40% dei token totali
116
+ MIN_HISTORY_ITEMS = 2 # Mantieni almeno l'ultimo scambio
117
+
118
+ # Calcola la lunghezza della cronologia attuale
119
+ current_tokens = sum(len(m["content"].split()) for m in chat_history)
120
+
121
+ # Se superiamo il limite, creiamo un riassunto
122
+ if current_tokens > MAX_HISTORY_TOKENS:
123
+ summary = summarize_context(chat_history)
124
+ # Manteniamo l'ultimo scambio completo
125
+ last_exchange = chat_history[-MIN_HISTORY_ITEMS:]
126
+ chat_history = summary + last_exchange
127
+
128
  try:
129
  # Setup e recupero documenti
130
  db_path = os.path.join(BASE_DB_PATH, f"faiss_index_{db_name}")
 
180
  response = client.chat.completions.create(
181
  model=model,
182
  messages=messages,
183
+ temperature= LLM_CONFIGS_EXTENDED["temperature"],
184
+ max_tokens=LLM_CONFIGS_EXTENDED["max_tokens"]
185
  )
186
 
187
  answer = response.choices[0].message.content + sources_text
 
208
 
209
  def get_relevant_chunks(self, question):
210
  enhanced_query = enhance_query(question)
211
+ docs_and_scores = self.vectorstore.similarity_search_with_score(enhanced_query)
 
 
 
212
  log_search_results(question, docs_and_scores)
213
+ return [
214
+ doc for doc, score in docs_and_scores
215
+ if score >= EMBEDDING_CONFIG['min_similarity']
216
+ ]
217
 
218
  if __name__ == "__main__":
219
+ pass
app/utils/helpers.py CHANGED
@@ -1,7 +1,9 @@
1
- # utils/helpers.py
2
-
3
  import logging
4
  from app.document_handling import extract_text_from_pdf, extract_text_from_docx
 
 
 
 
5
 
6
  def extract_text_from_files(files):
7
  """
@@ -13,16 +15,87 @@ def extract_text_from_files(files):
13
  Returns:
14
  str: Testo concatenato estratto dai file.
15
  """
 
 
 
 
 
 
 
 
 
 
 
16
  text = ""
17
  for file in files:
18
  try:
19
- if file.name.endswith('.pdf'):
20
- text += extract_text_from_pdf(file.name)
21
- elif file.name.endswith('.docx'):
22
- text += extract_text_from_docx(file.name)
23
- else:
24
- with open(file.name, 'r', encoding='utf-8') as f:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  text += f.read()
 
 
 
 
 
 
26
  except Exception as e:
27
- logging.error(f"Errore durante la lettura del file {file.name}: {e}")
28
- return text
 
 
 
 
 
1
  import logging
2
  from app.document_handling import extract_text_from_pdf, extract_text_from_docx
3
+ import tempfile
4
+ import os
5
+ from datetime import datetime
6
+ import shutil
7
 
8
  def extract_text_from_files(files):
9
  """
 
15
  Returns:
16
  str: Testo concatenato estratto dai file.
17
  """
18
+ if not files:
19
+ logging.warning("Nessun file fornito")
20
+ return ""
21
+
22
+ logging.info(f"Ricevuti {len(files)} file da elaborare")
23
+
24
+ # Crea la cartella Temp_file se non esiste
25
+ temp_dir = os.path.join(os.path.dirname(__file__), '..', 'Temp_file')
26
+ os.makedirs(temp_dir, exist_ok=True)
27
+ logging.info(f"Cartella Temp_file: {temp_dir}")
28
+
29
  text = ""
30
  for file in files:
31
  try:
32
+ file_path = None
33
+
34
+ # Gestione degli oggetti NamedString di Gradio
35
+ if type(file).__name__ == 'NamedString':
36
+ original_name = getattr(file, 'name', 'file')
37
+ _, ext = os.path.splitext(original_name)
38
+ timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
39
+ temp_path = os.path.join(temp_dir, f"temp_{timestamp}{ext if ext else '.txt'}")
40
+
41
+ with open(temp_path, 'wb') as tmp_file:
42
+ if hasattr(file, 'encode'):
43
+ tmp_file.write(file.encode())
44
+ elif hasattr(file, 'read'):
45
+ tmp_file.write(file.read())
46
+ else:
47
+ raise ValueError("Impossibile convertire l'oggetto in bytes")
48
+ file_path = temp_path
49
+
50
+ logging.info(f"File temporaneo creato: {file_path}")
51
+
52
+ try:
53
+ if file_path.lower().endswith('.pdf'):
54
+ text += extract_text_from_pdf(file_path)
55
+ elif file_path.lower().endswith('.docx'):
56
+ text += extract_text_from_docx(file_path)
57
+ elif file_path.lower().endswith('.txt'):
58
+ with open(file_path, 'r', encoding='utf-8') as f:
59
+ text += f.read()
60
+ else:
61
+ logging.warning(f"Formato file non supportato: {file_path}")
62
+ except Exception as e:
63
+ logging.error(f"Errore durante l'elaborazione del file {file_path}: {str(e)}")
64
+
65
+ continue
66
+
67
+ # Gestione file direttamente caricati
68
+ if not hasattr(file, 'name') or not hasattr(file, 'read'):
69
+ logging.error(f"Oggetto file non valido: {type(file)}")
70
+ continue
71
+
72
+ # Salva il file originale in Temp_file
73
+ timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
74
+ file_name = f"{timestamp}_{os.path.basename(file.name)}"
75
+ temp_path = os.path.join(temp_dir, file_name)
76
+
77
+ # Salva il contenuto del file
78
+ with open(temp_path, 'wb') as f:
79
+ f.write(file.read())
80
+
81
+ logging.info(f"File salvato in Temp_file: {temp_path}")
82
+ file_path = temp_path
83
+
84
+ if file_path.lower().endswith('.pdf'):
85
+ text += extract_text_from_pdf(file_path)
86
+ elif file_path.lower().endswith('.docx'):
87
+ text += extract_text_from_docx(file_path)
88
+ elif file_path.lower().endswith('.txt'):
89
+ with open(file_path, 'r', encoding='utf-8') as f:
90
  text += f.read()
91
+ else:
92
+ logging.warning(f"Formato file non supportato: {file_path}")
93
+
94
+ if text and not text.endswith('\n\n'):
95
+ text += '\n\n'
96
+
97
  except Exception as e:
98
+ logging.error(f"Errore durante l'elaborazione del file {file_path if file_path else 'unknown'}: {str(e)}")
99
+ continue
100
+
101
+ return text.strip()
ui/chatbot_tab.py CHANGED
@@ -21,11 +21,15 @@ def create_chatbot_tab():
21
  if chat_history is None:
22
  chat_history = []
23
 
 
 
 
 
24
  text = extract_text_from_files(files)
25
 
26
  chat_history.append({
27
  "role": "assistant",
28
- "content": f"📄 Contenuto dei documenti caricati:\n{text}"
29
  })
30
 
31
  return chat_history
@@ -38,7 +42,8 @@ def create_chatbot_tab():
38
  llm_mapping = {
39
  "openai - GPT-4o-Mini": LLMType.OPENAI_GPT_4O_MINI,
40
  "local - Qwen 7B": LLMType.LOCAL_QWEN,
41
- "local - Phi-3 Mini": LLMType.LOCAL_PHI
 
42
  }
43
 
44
  selected_llm = llm_mapping.get(llm_type, LLMType.OPENAI_GPT_4O_MINI)
@@ -173,8 +178,9 @@ def create_chatbot_tab():
173
  llm_selector = gr.Dropdown(
174
  choices=[
175
  "openai - GPT-4o-Mini",
176
- "local - Qwen 7B",
177
- "local - Phi-3 Mini"
 
178
  ],
179
  label="Seleziona Modello",
180
  value="openai - GPT-4o-Mini"
@@ -252,4 +258,3 @@ def create_chatbot_tab():
252
 
253
  # Ritorna il riferimento al dropdown corretto
254
  return {"db_selector": db_name_chat}
255
-
 
21
  if chat_history is None:
22
  chat_history = []
23
 
24
+ if files is None:
25
+ files = []
26
+
27
+ file_names = "\n".join(file.name.split('/')[-1] for file in files if hasattr(file, 'name'))
28
  text = extract_text_from_files(files)
29
 
30
  chat_history.append({
31
  "role": "assistant",
32
+ "content": f"📄 File caricati:\n{file_names}\n\nContenuto dei documenti caricati.\n{text}"
33
  })
34
 
35
  return chat_history
 
42
  llm_mapping = {
43
  "openai - GPT-4o-Mini": LLMType.OPENAI_GPT_4O_MINI,
44
  "local - Qwen 7B": LLMType.LOCAL_QWEN,
45
+ "local - Phi-3 Mini": LLMType.LOCAL_PHI,
46
+ "deepseek - DeepSeek Chat": LLMType.DEEPSEEK
47
  }
48
 
49
  selected_llm = llm_mapping.get(llm_type, LLMType.OPENAI_GPT_4O_MINI)
 
178
  llm_selector = gr.Dropdown(
179
  choices=[
180
  "openai - GPT-4o-Mini",
181
+ "local - Qwen 7B",
182
+ "local - Phi-3 Mini",
183
+ "deepseek - DeepSeek Chat"
184
  ],
185
  label="Seleziona Modello",
186
  value="openai - GPT-4o-Mini"
 
258
 
259
  # Ritorna il riferimento al dropdown corretto
260
  return {"db_selector": db_name_chat}
 
ui/management_tabs.py DELETED
@@ -1,163 +0,0 @@
1
- import gradio as gr
2
- import logging
3
- from app.document_handling import upload_and_index, list_indexed_files, delete_file_from_database
4
- from app.utils.database_handling import (
5
- create_database,
6
- modify_database,
7
- delete_database,
8
- list_databases
9
- )
10
-
11
- class ManagementTabs:
12
- def __init__(self, update_all_dropdowns):
13
- self.update_all_dropdowns = update_all_dropdowns
14
- self.databases = list_databases()
15
-
16
- def create_tabs(self):
17
- with gr.Tabs():
18
- self._create_db_management_tab()
19
- self._create_document_management_tab()
20
-
21
- def _create_db_management_tab(self):
22
- with gr.Tab("Gestione Database"):
23
- gr.Markdown("## Operazioni sui Database")
24
-
25
- with gr.Row():
26
- # Creazione Database
27
- with gr.Column():
28
- gr.Markdown("### Crea Database")
29
- self.db_name_input = gr.Textbox(label="Nome Nuovo Database")
30
- self.create_db_button = gr.Button("Crea Database")
31
- self.create_output = gr.Textbox(label="Stato Creazione")
32
-
33
- # Modifica Database
34
- with gr.Column():
35
- gr.Markdown("### Rinomina Database")
36
- self.modify_db_old_name = gr.Dropdown(
37
- choices=self.databases,
38
- label="Database da Rinominare"
39
- )
40
- self.modify_db_new_name = gr.Textbox(label="Nuovo Nome")
41
- self.modify_db_button = gr.Button("Rinomina Database")
42
- self.modify_output = gr.Textbox(label="Stato Modifica")
43
-
44
- # Eliminazione Database
45
- with gr.Column():
46
- gr.Markdown("### Elimina Database")
47
- self.delete_db_dropdown = gr.Dropdown(
48
- choices=self.databases,
49
- label="Database da Eliminare"
50
- )
51
- self.delete_db_button = gr.Button("Elimina Database")
52
- self.delete_output = gr.Textbox(label="Stato Eliminazione")
53
-
54
- self._setup_db_events()
55
-
56
- def _create_document_management_tab(self):
57
- with gr.Tab("Gestione Documenti"):
58
- with gr.Column():
59
- # Upload Documenti
60
- gr.Markdown("### Carica Documenti")
61
- with gr.Row():
62
- self.file_input = gr.File(
63
- label="Carica i tuoi documenti",
64
- file_types=[".txt", ".pdf", ".docx"],
65
- file_count="multiple"
66
- )
67
- self.db_name_upload = gr.Dropdown(
68
- choices=self.databases,
69
- label="Seleziona Database",
70
- value="default_db"
71
- )
72
-
73
- with gr.Row():
74
- self.title_input = gr.Textbox(label="Titolo del documento")
75
- self.author_input = gr.Textbox(label="Autore")
76
-
77
- self.upload_button = gr.Button("Indicizza Documenti")
78
- self.upload_output = gr.Textbox(label="Stato Upload")
79
-
80
- # Gestione File
81
- self._setup_file_management()
82
-
83
- self._setup_document_events()
84
-
85
- def _setup_file_management(self):
86
- gr.Markdown("### Gestione File")
87
- with gr.Row():
88
- self.db_name_list = gr.Dropdown(
89
- choices=self.databases,
90
- label="Database",
91
- value="default_db"
92
- )
93
- self.list_button = gr.Button("Lista File")
94
- self.list_output = gr.Textbox(label="File nel Database")
95
-
96
- with gr.Row():
97
- self.delete_file_input = gr.Textbox(label="Nome File da Eliminare")
98
- self.delete_file_button = gr.Button("Elimina File")
99
- self.delete_file_output = gr.Textbox(label="Stato Eliminazione")
100
-
101
- def _setup_db_events(self):
102
- # Eventi per la gestione del database
103
- self.create_db_button.click(
104
- fn=create_database,
105
- inputs=self.db_name_input,
106
- outputs=self.create_output
107
- ).then(fn=self.update_all_dropdowns)
108
-
109
- self.modify_db_button.click(
110
- fn=modify_database,
111
- inputs=[self.modify_db_old_name, self.modify_db_new_name],
112
- outputs=self.modify_output
113
- ).then(fn=self.update_all_dropdowns)
114
-
115
- self.delete_db_button.click(
116
- fn=delete_database,
117
- inputs=self.delete_db_dropdown,
118
- outputs=self.delete_output
119
- ).then(fn=self.update_all_dropdowns)
120
-
121
- def _setup_document_events(self):
122
- # Eventi per la gestione dei documenti
123
- self.upload_button.click(
124
- fn=self._upload_and_index_callback,
125
- inputs=[self.file_input, self.title_input, self.author_input, self.db_name_upload],
126
- outputs=self.upload_output
127
- ).then(fn=self.update_all_dropdowns).then(
128
- fn=self._list_files_callback,
129
- inputs=[self.db_name_list],
130
- outputs=self.list_output
131
- )
132
-
133
- self.list_button.click(
134
- fn=self._list_files_callback,
135
- inputs=[self.db_name_list],
136
- outputs=self.list_output
137
- )
138
-
139
- self.delete_file_button.click(
140
- fn=self._delete_file_callback,
141
- inputs=[self.delete_file_input, self.db_name_list],
142
- outputs=self.delete_file_output
143
- ).then(fn=self.update_all_dropdowns)
144
-
145
- def _upload_and_index_callback(self, files, title, author, db_name):
146
- try:
147
- status = upload_and_index(files, title, author, db_name)
148
- logging.info(f"Upload completato: {status}")
149
- return status
150
- except Exception as e:
151
- logging.error(f"Errore durante l'upload: {str(e)}")
152
- return f"Errore: {str(e)}"
153
-
154
- def _list_files_callback(self, db_name):
155
- return list_indexed_files(db_name)
156
-
157
- def _delete_file_callback(self, file_name, db_name):
158
- return delete_file_from_database(file_name, db_name)
159
-
160
- def create_management_tabs(update_all_dropdowns):
161
- tabs = ManagementTabs(update_all_dropdowns)
162
- tabs.create_tabs()
163
- return tabs