1 – Frontend
Construcció del Widget (Frontend/HTML)
Per crear la interfície del xatbot de la LAN Party Castellbisbal 2026, he desenvolupat un widget web des de zero utilitzant HTML, CSS i JavaScript. Com que tot l’entorn de desenvolupament i execució de la IA el tenim centralitzat a Google Colab, he dissenyat aquest FrontEnd perquè s’executi directament dins de les cel·les del notebook mitjançant la llibreria IPython.display
Disseny i Usabilitat (CSS)
He evitat plantilles prefabricades pesades per fer un codi modular. Visualment, he aplicat una paleta de colors blava per donar-hi un toc tecnològic i corporatiu, assegurant que els missatges de l’usuari i els del bot estiguin clarament diferenciats (blau fosc per a l’usuari i blau clar per al bot) per a una lectura còmoda.
Funcionalitats Principals (JavaScript)
El codi JS està totalment comentat i estructurat. Les funcions clau que he programat són:
enviarMissatge(): Captura el text de l’usuari. He utilitzat la IA per fer el codi més robust afegint el mètode.trim(), que evita l’enviament accidental de missatges en blanc.netejarXat(): Una funció essencial per a l’experiència d’usuari (UX). Buidem el DOM ràpidament utilitzantinnerHTMLper reiniciar la conversa sense recarregar l’entorn.gestionarEnter(): Permet als usuaris enviar missatges prement la tecla “Enter”, fent la interacció molt més natural i ràpida.- Auto-scroll: Implementat amb l’ajuda de la IA perquè la finestra baixi automàticament a mesura que la conversa avança.
from IPython.display import display, HTML
codi_frontend = """
<!DOCTYPE html>
<html lang="ca">
<head>
<meta charset="UTF-8">
<title>Xatbot LAN Party Castellbisbal 2026 </title>
<style>
/* [ÚS DE LA IA] - Estils: Modificats a una paleta de colors blava per millorar la cohesió visual segons les instruccions. */
body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
#chat-widget {
width: 100%;
max-width: 400px;
background: #ffffff;
border-radius: 10px;
border: 1px solid #ccc;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
display: flex;
flex-direction: column;
overflow: hidden;
margin: 10px 0;
}
/* Capçalera del mateix blau que el botó d'enviar */
#chat-header { background: #1976d2; color: white; padding: 15px; text-align: center; font-weight: bold; }
#chat-messages { height: 350px; overflow-y: auto; padding: 15px; display: flex; flex-direction: column; gap: 10px; background: #f9f9f9; }
.message { padding: 10px; border-radius: 8px; max-width: 85%; word-wrap: break-word; font-size: 14px; }
/* Missatge del bot en blau molt claret */
.bot-msg { background: #e3f2fd; border-bottom-left-radius: 0; align-self: flex-start; border: 1px solid #bbdefb; color: #000; }
/* Missatge de l'usuari del mateix blau que el botó d'enviar */
.user-msg { background: #1976d2; color: white; border-bottom-right-radius: 0; align-self: flex-end; }
#chat-controls { display: flex; padding: 10px; border-top: 1px solid #ddd; background: #fff; }
#user-input { flex: 1; padding: 10px; border: 1px solid #ccc; border-radius: 5px; outline: none; font-size: 14px; }
/* Botons */
button { padding: 10px 15px; margin-left: 5px; border: none; border-radius: 5px; cursor: pointer; color: white; font-weight: bold; transition: 0.2s; }
.btn-send { background: #1976d2; }
.btn-send:hover { background: #1565c0; }
.btn-clear { background: #d32f2f; }
.btn-clear:hover { background: #c62828; }
</style>
</head>
<body>
<div id="chat-widget">
<div id="chat-header">Assistent LAN Party Castellbisbal 2026 🔌</div>
<div id="chat-messages">
<div class="message bot-msg">Hola! Soc l'assistent oficial de la LAN. Necessites ajuda amb la IP, els horaris o la normativa de residu zero?</div>
</div>
<div id="chat-controls">
<input type="text" id="user-input" placeholder="Escriu el teu dubte aquí..." onkeypress="gestionarEnter(event)">
<button class="btn-send" onclick="enviarMissatge()">Enviar</button>
<button class="btn-clear" onclick="netejarXat()">Netejar</button>
</div>
</div>
<script>
// ==========================================
// LÒGICA DEL FRONTEND (JAVASCRIPT)
// ==========================================
function enviarMissatge() {
// [ÚS DE LA IA] - Robustesa: Ús de .trim() suggerit per la IA per evitar l'enviament de missatges en blanc.
const inputElement = document.getElementById("user-input");
const missatge = inputElement.value.trim();
if (missatge === "") return;
afegirMissatgeAlDOM("user-msg", missatge);
inputElement.value = "";
// Simulem que el bot està "pensant"
setTimeout(() => {
afegirMissatgeAlDOM("bot-msg", "Ho estic consultant... (Això s'enllaçarà amb Gemini en el següent pas!)");
}, 500);
}
function afegirMissatgeAlDOM(classeRemitent, text) {
const contenidor = document.getElementById("chat-messages");
const nouMissatge = document.createElement("div");
nouMissatge.classList.add("message", classeRemitent);
nouMissatge.innerText = text;
contenidor.appendChild(nouMissatge);
// [ÚS DE LA IA] - UX/UI: Auto-scroll cap avall quan s'afegeixen nous missatges.
contenidor.scrollTop = contenidor.scrollHeight;
}
function netejarXat() {
// [ÚS DE LA IA] - Funcionalitat: Ús d'innerHTML per buidar ràpidament el contenidor del DOM.
const contenidor = document.getElementById("chat-messages");
contenidor.innerHTML = '<div class="message bot-msg">Historial netejat. Com et puc ajudar ara?</div>';
}
function gestionarEnter(event) {
if (event.key === "Enter") {
enviarMissatge();
}
}
</script>
</body>
</html>
"""
display(HTML(codi_frontend))

Tots aquests canvis han estat documentats com una nova versió del Xatbot a l’arxiu CHANGELOG amb ajuda de la IA.

2 – Bases de dades: estructura i ús del JSON
Per guardar la informació de la LAN Party Castellbisbal 2026, he creat un arxiu dades_lan.json. És la manera més eficient i lleugera de tenir-ho tot endreçat sense necessitar una base de dades complexa com SQL.
He organitzat l’arxiu en categories (horaris, IPs, normes, jocs…). Així, l’script de Python del xatbot pot buscar ràpidament la informació que necessita per respondre.
He programat la lectura del fitxer perquè sigui segura fent servir blocs try-except. Així evito que el programa “peti”:
- Si el fitxer s’esborra per error (
FileNotFoundError), avisa per consola. - Si l’arxiu està mal escrit o li falta una coma (
JSONDecodeError), detecta que està corrupte.
Ús de la Intel·ligència Artificial
He utilitzat la IA per generar ràpidament l’estructura del JSON i per ajudar-me a programar la lògica dels blocs
try-except. També em va recomanar afegirencoding="utf-8"a l’hora de guardar el fitxer perquè els accents en català no em donessin problemes de lectura.



Part del codi del JSON com a exemple:
{
"esdeveniment": "LAN Party Castellbisbal 2026",
"ubicacio": "Pavelló Municipal d'Esports de Castellbisbal",
"connexio": {
"xarxa": "LAN_CBAL_5G",
"ip_servidor_jocs": "192.168.1.100"
}
}
3 – Arquitectura i flux de dades entre FrontEnd i BackEnd
3.1 – El BackEnd: Flask, ngrok i l’API de Gemini
Nota de desenvolupament: Tot el disseny d’aquesta arquitectura, la redacció del codi i, especialment, la depuració d’errors complexos de xarxa, s’han dut a terme amb l’assistència de la IA, concretament utilitzant el model Gemini 3.1 Pro com a copilot de programació
Per aconseguir que el nostre assistent virtual funcionés perfectament dins d’un entorn com Google Colab, hem dissenyat una arquitectura basada en un model Client-Servidor.
El servidor està programat en Python i utilitza la llibreria Flask per crear una API REST molt lleugera. Aquí una part del codi.
try:
api_key = userdata.get('GOOGLE_API_KEY')
genai.configure(api_key=api_key)
# AQUÍ ESTÀ EL TEU MODEL CORRECTE:
model = genai.GenerativeModel('gemini-flash-latest')
except Exception as e:
print(f"❌ Error amb la clau: {e}")

Com m’ha ajudat la IA aquí?
He utilitzat el model Gemini 3.1 Pro per escriure l’estructura base del servidor Flask i, sobretot, per solucionar el gran repte de connexió: com exposar aquest servidor local de Colab a internet. La IA em va guiar pas a pas per implementar ngrok, creant un túnel segur i proporcionant una URL pública. També vaig utilitzar l’assistent per identificar processos d’ngrok penjats a la memòria del Colab i programar instruccions de neteja automàtica
Prompt utilitzat
Estic programant en Google Colab i necessito crear un servidor web lleuger amb Flask que es connecti a l'API de Gemini. El problema és que necessito que aquest servidor local de Colab sigui accessible des d'una interfície HTML/JS que tinc en una altra cel·la. Com puc utilitzar 'pyngrok' per obrir un túnel públic al port 8000? Escriu-me el codi de Python necessari i afegeix una comanda per matar processos antics de ngrok abans d'arrencar per evitar que el port quedi bloquejat al reiniciar la cel·la.

3.2 – El FrontEnd: Interfície de l’Usuari i Connexió HTTP
La interfície s’executa en una cel·la independent utilitzant codi HTML, CSS i JavaScript. L’objectiu d’aquest FrontEnd és capturar el text introduït per l’usuari i enviar-lo de manera asíncrona al BackEnd sense recarregar la pàgina. Durant el desenvolupament, ens vam trobar que ngrok interceptava la primera petició per mostrar una pàgina web d’advertència (“Visit Site”), la qual cosa trencava el nostre codi perquè esperava rebre un JSON i rebia HTML. La solució tècnica va ser injectar una capçalera HTTP específica (ngrok-skip-browser-warning) que força a ngrok a ignorar aquesta pantalla i lliurar la petició directament al nostre codi Flask.
Part del codi utilitzat:

const urlBase = "https://LA-TEVA-URL-NGROK.ngrok-free.dev";
const resposta = await fetch(`${urlBase}/chat`, {
method: "POST",
headers: {
"Content-Type": "application/json",
// Capçalera imprescindible per evitar l'error de parseig de ngrok
"ngrok-skip-browser-warning": "true"
},
body: JSON.stringify({ missatge: msg })
});
Com m’ha ajudat la IA aquí?
La IA ha ajudat a depurar l’error de bloqueig de CORS/ngrok, analitzant l’error de la consola i suggerint la inclusió de la capçalera de salt (bypass). Durant la integració entre el FrontEnd i el BackEnd, va sorgir un error crític que impedia la comunicació bidireccional. En lloc de modificar cegament el codi de l’API en Python, es va utilitzar la IA com a eina de diagnòstic, proporcionant-li tant l’error exacte de la consola com el codi de la petició fetch. La IA va analitzar la traça de l’error i va identificar que el problema no era del servidor Flask, sinó del comportament de la versió gratuïta d’ngrok.
Prompt utilitzat
Necessito crear la interfície d'un xatbot en una cel·la de Google Colab. Escriu l'HTML, el CSS i el JavaScript necessaris per tenir una caixa de text, un botó d'enviar i una zona on apareguin els missatges. El JavaScript ha de capturar el missatge de l'usuari i enviar-lo mitjançant una petició asíncrona (fetch) de tipus POST a una URL pública d'ngrok que connecta amb el meu backend de Flask. A més, tinc un problema crític: quan faig el fetch, ngrok em bloqueja la petició retornant una pàgina web HTML d'advertència de seguretat en comptes de lliurar les dades a la meva API, generant un error de parseig.

3.3 – Configuració de l’API de Gemini: Gestió de Límits i Prevenció d’Al·lucinacions
L’ultima part era la comunicació directa entre el nostre servidor Flask i l’API de Google Generative AI. En aquesta fase, vam haver de resoldre dos reptes tècnics importants relacionats amb la naturalesa dels Grans Models de Llenguatge (LLM) i les polítiques d’ús de les API:
3.3.1 – Diagnòstic i Resolució de l’Error 429 (Límit de Quota):
Inicialment, el servidor estava configurat per sol·licitar el model gemini-pro-latest. Malgrat que el codi era correcte, l’API retornava constantment un error HTTP 429 amb el missatge “Quota exceeded”. Després d’analitzar el payload de l’error, es va identificar que la mètrica de la capa gratuïta (Free Tier) per a les sol·licituds d’aquest model específic tenia un límit estricte fixat en zero (limit: 0). Llavors he decidit canviar al model gemini-flash-latest que si que ha funcionat. Aquesta versió està dissenyada per oferir respostes de baixa latència i disposa d’una quota gratuïta generosa, restaurant immediatament la funcionalitat del xat.
IA: 429 POST
https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-latest:generateContent?%24alt=json%3Benum-encoding%3Dint:
You exceeded your current quota, please check your plan and billing
details. For more information on this error, head to:
https://ai.google.dev/gemini-api/docs/rate-limits. To monitor your
current usage, head to: https://ai.dev/rate-limit.
* Quota exceeded for metric:
generativelanguage.googleapis.com/generate_content_free_tier_input_token_count,
limit: 0, model: gemini-3.1-pro
* Quota exceeded for metric:
generativelanguage.googleapis.com/generate_content_free_tier_requests,
limit: 0, model: gemini-3.1-pro
* Quota exceeded for metric:
generativelanguage.googleapis.com/generate_content_free_tier_requests,
limit: 0, model: gemini-3.1-pro
* Quota exceeded for metric:
generativelanguage.googleapis.com/generate_content_free_tier_input_token_count,
limit: 0, model: gemini-3.1-pro
Please retry in 49.592819436s.
Com m’ha ajudat la IA aquí?
Es va utilitzar Gemini per desxifrar que l’error 429 amagava una restricció de model i no un excés de trànsit real. A més, la IA va actuar com a consultora per dissenyar l’estructura òptima del System Prompt que evita les al·lucinacions.
Prompt utilitzat
El meu servidor Flask està llançant un error a l'hora de comunicar-se amb l'API de Google Generative AI. L'error complet a la consola de Python és: 'Error 429 POST: You exceeded your current quota... limit: 0, model: gemini-3.1-pro'. Actualment estic utilitzant el tier gratuït (Free Tier) i al meu codi tinc definit model = genai.GenerativeModel('gemini-pro-latest'). Com que el límit per a aquest model sembla ser zero, quin és el nom exacte del model alternatiu (versió Flash) que he de posar al codi per aprofitar els límits gratuïts i solucionar aquest bloqueig de l'API?"

3.3.2 – Injecció de Context i Enginyeria de Prompts (Control d’Al·lucinacions)
Un cop establerta la connexió, ens vam trobar amb el repte inherent de la IA: la tendència a “al·lucinar” (inventar-se informació per intentar donar sempre una resposta) i l’ús d’un to massa col·loquial, farcit d’emojis. Per transformar aquest model genèric en un assistent fiable i professional per a la LAN Party 2026, vam implementar un patró d’injecció de context. Li hem donat les següents pautes:
- Ets el portaveu i assistent oficial de la LAN Party 2026.
- El teu to ha de ser educat i professional, adreçat a un públic jove pero serios, pero amb una mica de gracia.
- Amb respostes més curtes que llargues, sense saludar en cada missatge, només donant la informació i sense donar cap concell.
- En cas de que et preguntin qui ets o el primer missatge que envies abans de que la persona ho fagi (la teva presentació) ha de ser aquest: Hola, soc l’assistent de la LAN Party Castellbisbal 2026. En què et puc ajudar

Com m’ha ajudat la IA aquí?
He utilitzat la IA per definir una arquitectura de seguretat lògica que impedeixi les al·lucinacions del model, un problema inherent als LLM. L’assistent m’ha permès dissenyar un System Prompt robust que actua com a filtre previ, garantint que el xatbot no se surti del guió establert. En lloc de programar restriccions manuals complexes, la IA m’ha ajudat a redactar les instruccions de context que forcen el to formal, eliminen els emojis i restringeixen les respostes exclusivament a la informació oficial de la LAN Party 2026.
Prompt utilitzat
La IA de Gemini s'inventa dades de la LAN Party i usa un to massa informal amb emojis. Necessito que m'ajudis a dissenyar un 'System Prompt' en Python per concatenar al missatge de l'usuari. El prompt ha de definir que la IA és el portaveu oficial de la LAN Party 2026, ha d'utilitzar un to culte i formal en català, té prohibit usar emojis i, sobretot, si l'usuari pregunta una cosa que no està en la informació oficial que jo li passo, la IA ha de respondre que no ho sap en lloc d'inventar-s'ho.

3.4 – Flux d’execució i orquestració de dades
El funcionament del sistema funciona com un cicle de petició-resposta (Request-Response), que connecta el client amb la IA. Quan l’usuari utilitza la interfície, el FrontEnd encapsula el missatge com un JSON i l’envia via HTTP POST cap a l’endpoint de ngrok. Aquest actua com a túnel de xarxa per redirigir el trànsit extern cap al port local de la màquina virtual de Google Colab.
Un cop la petició arriba al BackEnd, el servidor Flask processa la dada i hi injecta el context del fitxer JSON juntament amb les restriccions del System Prompt. Aquest paquet d’informació estructurada s’envia a l’API de Gemini Flash, que realitza la inferència i retorna el text generat. Finalment, Flask retorna aquest contingut al navegador, on el JavaScript s’encarrega de renderitzar-lo dinàmicament al DOM del xat.


Deixa un comentari