ciro-gioan-chat / app.py
Mark3131's picture
Restore Italian language for personality and quick info sections
1df00c7
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("""
<h1 style="color: #f97316; font-size: 3.2rem; font-weight: 900; margin-bottom: 10px; letter-spacing: -1px;">
YecoAI <span style="color: #fff; font-weight: 300;">| Ciro & Gioan</span>
</h1>
<p style="color: #cbd5e1; font-size: 1.2rem; max-width: 600px; margin: 0 auto; line-height: 1.6;">
La prima intelligenza artificiale a parlare il dialetto in modo ironico. <br>
<span style="font-style: italic; opacity: 0.8;">L'unica AI che ti risponde col cuore (e un po' di pregiudizio regionale).</span>
</p>
""")
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("""
<div class="footer-text">
© 2026 <a href="https://yecoai.com" style="color: #f97316; text-decoration: none; font-weight: bold;">YecoAI Research</a>
• All rights reserved • Open Source on Hugging Face
</div>
""")
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
)