import gradio as gr import torch from transformers import AutoTokenizer, AutoModelForCausalLM from peft import PeftModel # 1. Configurazioni iniziali BASE_MODEL = "Qwen/Qwen2.5-1.5B-Instruct" ADAPTER_CIRO = "YecoAI/napoletano-ciro" ADAPTER_GIOAN = "YecoAI/piemontese-gioan" print("Caricamento del Tokenizer...") tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL) print("Caricamento del Modello Base (Qwen2.5-1.5B)...") base_model = AutoModelForCausalLM.from_pretrained( BASE_MODEL, dtype=torch.float32, device_map="cpu" ) print("Caricamento degli Adapter LoRA...") model = PeftModel.from_pretrained(base_model, ADAPTER_CIRO, adapter_name="ciro") model.load_adapter(ADAPTER_GIOAN, adapter_name="gioan") def respond(message, history, persona): selected_persona = persona if persona is not None else "🌋 Ciro (Napoletano)" if "Ciro" in selected_persona: model.set_adapter("ciro") system_prompt = "Sei Ciro, un ragazzo di Napoli verace, amichevole e ironico. Parli in dialetto napoletano. Rispondi in modo breve e simpatico." else: model.set_adapter("gioan") system_prompt = "Sei Gioan, un signore del Piemonte cordiale, pacato e ironico. Parli in dialetto piemontese. Rispondi in modo breve e gentile." messages = [{"role": "system", "content": system_prompt}] # Gradio 6.0 può inviare history come lista di dizionari con content come stringa o lista for msg in history: content = msg.get("content", "") if isinstance(content, list): # Estraiamo il testo dal formato lista di dict text_content = " ".join([item.get("text", "") for item in content if item.get("type") == "text"]) messages.append({"role": msg["role"], "content": text_content}) else: messages.append({"role": msg["role"], "content": content}) messages.append({"role": "user", "content": message}) text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) model_inputs = tokenizer([text], return_tensors="pt").to(model.device) with torch.no_grad(): generated_ids = model.generate( **model_inputs, max_new_tokens=150, temperature=0.8, top_p=0.9, repetition_penalty=1.1, pad_token_id=tokenizer.eos_token_id ) generated_ids = [output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)] return tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0] # Interfaccia custom custom_css = """ .gradio-container { background-color: #0f1115 !important; font-family: 'Inter', system-ui, -apple-system, sans-serif !important; } .main-header { text-align: center; padding: 40px 20px; background: linear-gradient(135deg, #1e293b 0%, #0f172a 100%); border-radius: 20px; margin-bottom: 30px; border: 1px solid #334155; } .chatbot-container { border-radius: 20px !important; border: 1px solid #334155 !important; overflow: hidden; } .persona-card { background: #1e293b; padding: 15px; border-radius: 15px; border: 1px solid #334155; } .footer-text { text-align: center; margin-top: 30px; color: #94a3b8; font-size: 0.9rem; } """ with gr.Blocks() as demo: with gr.Column(elem_classes="main-header"): gr.HTML("""

YecoAI | Ciro & Gioan

La prima intelligenza artificiale a parlare il dialetto in modo ironico.
L'unica AI che ti risponde col cuore (e un po' di pregiudizio regionale).

""") with gr.Row(): with gr.Column(scale=1): with gr.Column(elem_classes="persona-card"): persona_radio = gr.Radio( choices=["🌋 Ciro (Napoletano)", "🍷 Gioan (Piemontese)"], value="🌋 Ciro (Napoletano)", label="Seleziona la Personalità", info="Il cambio di personalità resetterà la conversazione." ) gr.Markdown(""" ### 💡 Info Rapide - **Ciro**: Napoletano, ironico, probabilmente sta mangiando una sfogliatella. - **Gioan**: Piemontese, garbato, ti corregge la grammatica con eleganza. """) with gr.Column(scale=3): chatbot = gr.Chatbot( label="Regional Conversation", height=500, avatar_images=(None, "https://www.yecoai.com/favicon.ico"), elem_classes="chatbot-container" ) # Definiamo i componenti prima ma senza renderizzarli subito msg = gr.Textbox( placeholder="Type your message here... (e.g. 'Uè wagliò' or 'Bondì binel')", label=None, container=False, scale=10, render=False ) submit = gr.Button("Send 🚀", variant="primary", scale=2, render=False) # Suggerimenti di messaggi (Esempi) sopra l'input, stile ChatGPT gr.Examples( examples=[ ["Uè Ciro, comm'a va?"], ["Mi consigli un posto dove mangiare una pizza vera?"], ["Bondì Gioan, com'a va?"], ["Gioan, cosa vuol dire 'bogia nen'?"], ], inputs=msg, label=None ) with gr.Row(): msg.render() submit.render() with gr.Row(): clear = gr.Button("🗑️ Reset Chat", variant="secondary", size="sm") # Rimosso il vecchio Row degli esempi # Logica di reset al cambio modello def reset_chat(): return [], "" persona_radio.change(fn=reset_chat, inputs=None, outputs=[chatbot, msg]) # Logica di invio (Formato Gradio 6.0: lista di dict) def user_msg(user_input, history): if not user_input: return "", history history.append({"role": "user", "content": user_input}) return "", history def bot_msg(history, persona): if not history or history[-1]["role"] == "assistant": return history # Estraiamo l'ultimo messaggio dell'utente correttamente last_user_msg = history[-1]["content"] if isinstance(last_user_msg, list): last_user_msg = " ".join([item.get("text", "") for item in last_user_msg if item.get("type") == "text"]) bot_response = respond(last_user_msg, history[:-1], persona) history.append({"role": "assistant", "content": bot_response}) return history msg.submit(user_msg, [msg, chatbot], [msg, chatbot], queue=False).then( bot_msg, [chatbot, persona_radio], chatbot ) submit.click(user_msg, [msg, chatbot], [msg, chatbot], queue=False).then( bot_msg, [chatbot, persona_radio], chatbot ) clear.click(lambda: [], None, chatbot, queue=False) gr.HTML(""" """) if __name__ == "__main__": demo.launch( server_name="0.0.0.0", server_port=7860, theme=gr.themes.Soft(primary_hue="orange", secondary_hue="slate"), css=custom_css )