Spaces:
Runtime error
Runtime error
| # app.py - Versione completa con tutte le importazioni | |
| import gradio as gr | |
| import requests | |
| import json | |
| import os | |
| import re | |
| from typing import Dict, List, Any, Optional | |
| # Importazioni smolagents corrette | |
| from smolagents import CodeAgent, tool, TransformersModel | |
| class GAIAAgentFixed: | |
| def __init__(self): | |
| self.setup_model() | |
| self.setup_agent() | |
| def setup_model(self): | |
| """Configura il modello usando TransformersModel""" | |
| try: | |
| # Usa SmolLM che Γ¨ leggero e efficiente | |
| self.model = TransformersModel(model_id="HuggingFaceTB/SmolLM-135M-Instruct") | |
| except Exception as e: | |
| print(f"Errore caricamento modello: {e}") | |
| # Fallback a un modello piΓΉ piccolo se disponibile | |
| self.model = TransformersModel(model_id="microsoft/DialoGPT-small") | |
| def setup_agent(self): | |
| """Configura l'agente con tools""" | |
| self.agent = CodeAgent( | |
| tools=[ | |
| self.analyze_image, | |
| self.transcribe_audio, | |
| self.extract_text_from_file, | |
| self.perform_calculation, | |
| self.web_search | |
| ], | |
| model=self.model, | |
| max_iterations=8, | |
| additional_authorized_imports=['datetime', 'pandas', 'numpy', 'requests', 're'] | |
| ) | |
| def analyze_image(self, image_path: str, question: str) -> str: | |
| """Analizza immagini per domande GAIA""" | |
| try: | |
| # Per ora implementazione base - in produzione useresti un modello vision | |
| if os.path.exists(image_path): | |
| return f"Immagine analizzata: {image_path}. Domanda: {question}" | |
| else: | |
| return "File immagine non trovato" | |
| except Exception as e: | |
| return f"Errore analisi immagine: {str(e)}" | |
| def transcribe_audio(self, audio_path: str) -> str: | |
| """Trascrizione audio""" | |
| try: | |
| if os.path.exists(audio_path): | |
| return f"Audio trascritto da: {audio_path}" | |
| else: | |
| return "File audio non trovato" | |
| except Exception as e: | |
| return f"Errore trascrizione: {str(e)}" | |
| def extract_text_from_file(self, file_path: str) -> str: | |
| """Estrae testo da vari formati di file""" | |
| try: | |
| if not os.path.exists(file_path): | |
| return "File non trovato" | |
| if file_path.endswith('.txt'): | |
| with open(file_path, 'r', encoding='utf-8') as f: | |
| content = f.read() | |
| return content[:2000] + "..." if len(content) > 2000 else content | |
| elif file_path.endswith('.csv'): | |
| try: | |
| import pandas as pd | |
| df = pd.read_csv(file_path) | |
| return df.head(10).to_string() | |
| except ImportError: | |
| return "Pandas non disponibile per file CSV" | |
| elif file_path.endswith(('.xlsx', '.xls')): | |
| try: | |
| import pandas as pd | |
| df = pd.read_excel(file_path) | |
| return df.head(10).to_string() | |
| except ImportError: | |
| return "Pandas non disponibile per file Excel" | |
| else: | |
| return f"Formato file non supportato: {file_path}" | |
| except Exception as e: | |
| return f"Errore lettura file: {str(e)}" | |
| def perform_calculation(self, expression: str) -> str: | |
| """Calcoli matematici precisi""" | |
| try: | |
| # Sanitizza l'espressione per sicurezza | |
| safe_expr = re.sub(r'[^0-9+\-*/().\s]', '', expression) | |
| if not safe_expr.strip(): | |
| return "Espressione matematica non valida" | |
| result = eval(safe_expr) | |
| return str(result) | |
| except ZeroDivisionError: | |
| return "Errore: divisione per zero" | |
| except Exception as e: | |
| return f"Errore calcolo: {str(e)}" | |
| def web_search(self, query: str) -> str: | |
| """Ricerca web simulata (placeholder)""" | |
| return f"Risultati ricerca simulata per: {query}" | |
| def solve_question(self, question: str, file_path: Optional[str] = None) -> str: | |
| """Risolve domande GAIA""" | |
| system_prompt = f""" | |
| Risolvi questa domanda GAIA Level 1 fornendo una risposta precisa. | |
| REGOLE IMPORTANTI: | |
| 1. Leggi attentamente la domanda | |
| 2. Se c'Γ¨ un file, analizzalo prima di rispondere | |
| 3. Fornisci SOLO la risposta finale senza prefissi o spiegazioni | |
| 4. Per numeri: solo il valore numerico | |
| 5. Per liste: usa il formato richiesto nella domanda | |
| 6. Per Yes/No: rispondi solo "Yes" o "No" | |
| DOMANDA: {question} | |
| {f"FILE DISPONIBILE: {file_path}" if file_path else "NESSUN FILE"} | |
| Risolvi passo dopo passo e fornisci la risposta finale: | |
| """ | |
| try: | |
| response = self.agent.run(system_prompt) | |
| return self._clean_answer(response, question) | |
| except Exception as e: | |
| return f"Errore risoluzione: {str(e)}" | |
| def _clean_answer(self, raw_answer: str, question: str) -> str: | |
| """Pulisce la risposta per EXACT MATCH""" | |
| # Rimuovi prefissi comuni | |
| prefixes = [ | |
| "Final Answer:", "Risposta:", "Answer:", "Il risultato Γ¨:", | |
| "La risposta Γ¨:", "Risposta finale:", "ANSWER:", "RISPOSTA:", | |
| "The answer is:", "Result:", "Output:" | |
| ] | |
| cleaned = str(raw_answer).strip() | |
| for prefix in prefixes: | |
| if cleaned.startswith(prefix): | |
| cleaned = cleaned[len(prefix):].strip() | |
| # Formattazione specifica per tipo di domanda | |
| question_lower = question.lower() | |
| if "how many" in question_lower or "count" in question_lower: | |
| # Estrai solo il numero per domande di conteggio | |
| numbers = re.findall(r'\d+', cleaned) | |
| if numbers: | |
| return numbers[0] | |
| if "yes or no" in question_lower or ("yes" in question_lower and "no" in question_lower): | |
| # Standardizza risposte yes/no | |
| if "yes" in cleaned.lower(): | |
| return "Yes" | |
| elif "no" in cleaned.lower(): | |
| return "No" | |
| if "list" in question_lower and "comma" in question_lower: | |
| # Formatta liste separate da virgole | |
| cleaned = re.sub(r'\s*,\s*', ', ', cleaned) | |
| return cleaned.strip() | |
| class GAIAEvaluator: | |
| def __init__(self): | |
| self.base_url = "https://huggingface.co/spaces/huggingface-projects/gaia-benchmark-scoring/api" | |
| try: | |
| self.agent = GAIAAgentFixed() | |
| self.agent_ready = True | |
| except Exception as e: | |
| print(f"Errore inizializzazione agente: {e}") | |
| self.agent_ready = False | |
| def test_single_question(self, username: str) -> Dict: | |
| """Testa una singola domanda""" | |
| if not self.agent_ready: | |
| return {"error": "Agente non inizializzato correttamente"} | |
| try: | |
| # Domande di test per verificare il funzionamento | |
| test_questions = [ | |
| "What is 15 + 27?", | |
| "How many letters are in the word 'hello'?", | |
| "Is 10 greater than 5? Answer yes or no." | |
| ] | |
| results = [] | |
| for question in test_questions: | |
| answer = self.agent.solve_question(question) | |
| results.append({ | |
| "question": question, | |
| "answer": answer | |
| }) | |
| return { | |
| "username": username, | |
| "test_results": results, | |
| "status": "Test completato con successo" | |
| } | |
| except Exception as e: | |
| return {"error": str(e)} | |
| def fetch_real_question(self) -> Dict: | |
| """Prova a recuperare una domanda reale dall'API""" | |
| try: | |
| response = requests.get(f"{self.base_url}/random-question", timeout=10) | |
| if response.status_code == 200: | |
| return response.json() | |
| else: | |
| return {"error": f"API non disponibile: {response.status_code}"} | |
| except Exception as e: | |
| return {"error": f"Errore connessione API: {str(e)}"} | |
| def create_interface(): | |
| evaluator = GAIAEvaluator() | |
| def test_agent(username): | |
| if not username: | |
| return "β οΈ Inserisci il tuo username Hugging Face" | |
| # Test con domande locali | |
| result = evaluator.test_single_question(username) | |
| if "error" in result: | |
| return f"β Errore: {result['error']}" | |
| output = f""" | |
| ## π§ͺ Test Agente GAIA | |
| **Username:** {username} | |
| **Status:** β Agente funzionante | |
| ### π Risultati Test: | |
| """ | |
| for i, test in enumerate(result['test_results'], 1): | |
| output += f""" | |
| **Test {i}:** | |
| - Domanda: {test['question']} | |
| - Risposta: `{test['answer']}` | |
| """ | |
| return output | |
| def test_api_connection(): | |
| """Testa la connessione all'API GAIA""" | |
| result = evaluator.fetch_real_question() | |
| if "error" in result: | |
| return f"β API non raggiungibile: {result['error']}" | |
| else: | |
| return f"β API connessa. Domanda esempio: {result.get('Question', 'N/A')[:100]}..." | |
| # Interfaccia Gradio | |
| with gr.Blocks(title="π GAIA Agent - Fixed Version") as iface: | |
| gr.Markdown("# π GAIA Agent - Versione Corretta") | |
| gr.Markdown("Agente GAIA con importazioni corrette e gestione errori robusta") | |
| with gr.Tab("π§ͺ Test Agente"): | |
| with gr.Row(): | |
| username_input = gr.Textbox( | |
| label="Username Hugging Face", | |
| placeholder="il-tuo-username" | |
| ) | |
| test_btn = gr.Button("π§ͺ Testa Agente", variant="primary") | |
| output_display = gr.Markdown() | |
| test_btn.click( | |
| fn=test_agent, | |
| inputs=[username_input], | |
| outputs=[output_display] | |
| ) | |
| with gr.Tab("π Test API"): | |
| api_test_btn = gr.Button("π Testa Connessione API", variant="secondary") | |
| api_output = gr.Markdown() | |
| api_test_btn.click( | |
| fn=test_api_connection, | |
| outputs=[api_output] | |
| ) | |
| gr.Markdown(""" | |
| ### π§ Correzioni Implementate: | |
| - β Importazioni corrette: `from smolagents import CodeAgent, tool, TransformersModel` | |
| - β Gestione errori robusta per inizializzazione modello | |
| - β Fallback per modelli non disponibili | |
| - β Test locali per verificare funzionamento | |
| - β Validazione input e sanitizzazione | |
| ### π Requisiti: | |
| ``` | |
| smolagents>=1.8.0 | |
| transformers>=4.35.0 | |
| torch>=2.0.0 | |
| gradio==5.33.0 | |
| ``` | |
| """) | |
| return iface | |
| if __name__ == "__main__": | |
| print("===== Avvio Applicazione GAIA Agent =====") | |
| try: | |
| iface = create_interface() | |
| iface.launch() | |
| except Exception as e: | |
| print(f"Errore avvio applicazione: {e}") | |