Assistent D’en Iman
— Xatbot Integrat —
Widget de IA · Flask + Gemini · ngrok · WordPress · WPCode
Objectiu del Projecte
L’objectiu d’aquest projecte era dissenyar, programar i integrar un xatbot basat en IA dins d’una pàgina web real. El xatbot, anomenat Assistent D’en Iman, utilitza la API de Google Gemini per generar respostes intel·ligents en temps real.
Per fer-ho possible, cal resoldre un problema tècnic fonamental: un navegador web no pot parlar directament amb una API externa sense exposar les claus secretes. La solució és crear un servidor intermediari (BackEnd) que faci de pont segur entre el widget del lloc web i la IA.
Repte PRO+: No és suficient fer que “funcioni”. Cal entendre per què cada peça de l’arquitectura és necessària, garantir la seguretat de les claus API, i integrar-ho de manera professional dins d’un CMS real com WordPress.
Tecnologies Utilitzades
- ✓Google Gemini Flash 1.5 — Model d’IA per generar les respostes del xatbot
- ✓Python + Flask — Servidor BackEnd lleuger per gestionar les peticions REST
- ✓Flask-CORS — Permet peticions cross-origin des del widget
- ✓ngrok — Crea un túnel HTTPS públic per exposar el servidor local
- ✓Google Colab — Entorn d’execució gratuït al núvol per al servidor Flask
- ✓WordPress — CMS on s’integra el widget
- ✓WPCode — Plugin per injectar codi HTML/JS/CSS sense modificar el tema
- ✓HTML + CSS + JS — FrontEnd del widget de xat
Arquitectura i Flux de Dades
El sistema es divideix en tres capes independents que es comuniquen entre elles. Entendre aquesta separació és clau per poder argumentar la solidesa del disseny.
Flux pas a pas
-
Usuari escriu un missatge
L’usuari introdueix una pregunta al widget de xat integrat a la web de WordPress. El JavaScript captura l’event
clickdel botó d’enviament. -
Fetch POST → BackEnd (via ngrok)
El JS envia una petició
POSTa l’endpoint/askdel servidor Flask, amb el missatge en format JSON. La URL és el túnel públic generat per ngrok. -
Flask rep la petició i crida Gemini
El servidor extreu el missatge, l’envia a la API de Gemini (model
gemini-1.5-flash) i espera la resposta. La clau API mai surt del servidor. -
Resposta retorna al widget
Flask retorna la resposta en JSON (
{"reply": "..."}). El JavaScript la rep i la mostra al xat en temps real.
Per què ngrok? Google Colab s’executa en servidors privats sense una adreça pública. ngrok crea un túnel HTTPS que redirigeix el tràfic d’internet cap al servidor Flask de Colab, fent-lo accessible des de qualsevol lloc web.
BackEnd: Servidor Flask a Google Colab
Pas 1 — Instal·lació de dependències
El primer pas al notebook de Colab és instal·lar les llibreries necessàries. Cada una té un rol específic i necessari:
# Instal·lació de totes les dependències necessàries !pip install flask flask-cors google-generativeai pyngrok
📦 Per què cada llibreria?
- flask — Micro-framework per crear el servidor web amb Python. Defineix les rutes i gestiona les peticions HTTP.
- flask-cors — Habilita CORS (Cross-Origin Resource Sharing): sense això, el navegador bloquejarà les peticions del widget cap al servidor per motius de seguretat.
- google-generativeai — SDK oficial de Google per comunicar-se amb la API de Gemini de manera senzilla.
- pyngrok — Interfície Python de ngrok. Permet crear el túnel HTTPS des del codi Python sense configuració manual.
Pas 2 — Codi principal del servidor
import os from flask import Flask, request, jsonify from flask_cors import CORS from pyngrok import ngrok import google.generativeai as genai from google.colab import userdata # 1. Carreguem les claus des dels Secrets de Colab (mai hardcoded!) GOOGLE_DATA = userdata.get('GOOGLE_API_KEY') NGROK_TOKEN = userdata.get('NGROK_AUTH') genai.configure(api_key=GOOGLE_DATA) ngrok.set_auth_token(NGROK_TOKEN) # 2. Creem l'aplicació Flask i habilitem CORS app = Flask(__name__) CORS(app) # 3. Definim l'endpoint /ask @app.route('/ask', methods=['POST']) def ask_api(): try: user_data = request.json user_prompt = user_data.get("message") # 4. Cridem Gemini amb el model flash (ràpid i eficient) ai_model = genai.GenerativeModel('gemini-1.5-flash') response = ai_model.generate_content(user_prompt) return jsonify({"reply": response.text}) except Exception as e: return jsonify({"error": str(e)}), 500 # 5. Obrim el túnel ngrok i arrenquem Flask public_url = ngrok.connect(5000) print(f"URL pública: {public_url}") app.run(port=5000)
Gestió d’errors i robustesa
Un servidor de producció ha de gestionar els errors correctament. El bloc try/except garanteix que si la API de Gemini falla, el widget rebrà un missatge d’error llegible en lloc de quedar-se penjat. El codi HTTP 500 informa el FrontEnd que hi ha hagut un error al servidor.
FrontEnd: Widget de Xat
El FrontEnd és la capa visible per a l’usuari: un widget de xat flotant que apareix a la cantonada de la web i permet interactuar amb l’assistent de IA. Està fet amb HTML, CSS i JavaScript pur, sense cap framework extern.
Estructura HTML
<!-- Contenidor principal del widget --> <div id="iman-chat-container"> <!-- Finestra del xat (inicialment amagada) --> <div id="iman-chat-window" style="display: none;"> <div id="iman-chat-header"> <img src="[logo]"> <span>Assistent d'en Iman</span> </div> <!-- Aquí apareixeran els missatges dinàmicament --> <div id="iman-chat-messages"></div> <div id="iman-chat-footer"> <input type="text" id="iman-chat-input" placeholder="Escriu aquí..."> <button id="iman-chat-send">►</button> </div> </div> <!-- Botó flotant per obrir/tancar el xat --> <button id="iman-chat-trigger">[logo]</button> </div>
Lògica JavaScript
// Referència als elements del DOM const triggerBtn = document.getElementById('iman-chat-trigger'); const chatWin = document.getElementById('iman-chat-window'); const chatInput = document.getElementById('iman-chat-input'); const chatSend = document.getElementById('iman-chat-send'); const chatMessages = document.getElementById('iman-chat-messages'); // Obrir / tancar el widget en clicar el botó flotant triggerBtn.onclick = (e) => { e.preventDefault(); chatWin.style.display = (chatWin.style.display === 'none' || chatWin.style.display === '') ? 'flex' : 'none'; }; // Enviar missatge al BackEnd i mostrar la resposta chatSend.onclick = async () => { const msg = chatInput.value.trim(); if (!msg) return; addMessage(msg, 'user'); chatInput.value = ''; const res = await fetch('[URL_NGROK]/ask', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: msg }) }); const data = await res.json(); addMessage(data.reply, 'bot'); }; // Helper per afegir un missatge al xat function addMessage(text, sender) { const div = document.createElement('div'); div.className = `msg ${sender}`; div.textContent = text; chatMessages.appendChild(div); chatMessages.scrollTop = chatMessages.scrollHeight; }
Seguretat de les Claus API
La seguretat és un dels punts crítics del projecte. Una clau API exposada pot generar costos econòmics importants i comprometre el compte de Google. Per això, es van implementar dos nivells de protecció:
Nivell 1 — Secrets de Google Colab
Les claus API es guarden al gestor de Secrets de Colab (icona del cadenat) i s’accedeix a elles amb userdata.get('NOM_SECRET'). Això significa que:
- Les claus mai apareixen al codi font del notebook.
- Si es comparteix el notebook, les claus no es comparteixen.
- El codi font és llegible sense risc de seguretat.
# ✅ Correcte: carregant des de Secrets GOOGLE_DATA = userdata.get('GOOGLE_API_KEY') NGROK_TOKEN = userdata.get('NGROK_AUTH') # ❌ Incorrecte (mai fer això!): clau hardcoded al codi # GOOGLE_DATA = "AIzaSy..." ← RISC DE SEGURETAT GREU
Nivell 2 — Arquitectura BackEnd com a escud
El disseny de separar FrontEnd i BackEnd garanteix que la clau API de Gemini mai arribi al navegador de l’usuari. Si s’hagués cridat la API de Gemini directament des del JavaScript del widget, qualsevol persona podria obrir les DevTools del navegador i robar la clau.
✅ Arquitectura Segura (la nostra)
Widget JS → Servidor Flask → Gemini API
La clau API només existeix al servidor. L’usuari mai la veu.
❌ Arquitectura Insegura
Widget JS → Gemini API directament
La clau API és visible al codi font del navegador. Risc crític.
Reflexió ètica: Exposar una clau API no és només un risc tècnic — és una responsabilitat professional. Un desenvolupador ha de protegir els recursos del client amb la mateixa cura que un banquer protegeix els diners. L’arquitectura triada és l’estàndard de la indústria precisament per aquest motiu.
Integració a WordPress via WPCode
Per què WPCode i no editar el tema?
WordPress permet afegir codi directament als fitxers del tema (functions.php, header.php…), però aquesta pràctica té desavantatges importants:
- Si actualitzes el tema, perds els canvis — els temes s’actualitzen i sobreescriuen els fitxers modificats.
- Dificultat de manteniment — barrejar codi propi amb el del tema fa difícil depurar errors.
WPCode soluciona tots dos problemes: permet afegir snippets de codi que sobreviuen a les actualitzacions del tema i estan organitzats de manera independent.
Estructura d’injecció
📍 On s’insereix cada peça
- Header (CSS) — Els estils del widget s’insereixen a
<head>per evitar el “flash” visual en carregar la pàgina. - Body / Header (HTML) — L’estructura del widget s’insereix just abans del tancament de
</body>per no bloquejar el renderitzat de la pàgina. - Footer (JavaScript) — El codi JS s’insereix al final del
<body>per garantir que tots els elements HTML ja existeixin quan el JS intenti accedir-hi.
Posar el JavaScript al footer és una bona pràctica de rendiment web. Si el JS s’inserís a <head>, el navegador l’executaria abans de construir el DOM, causant errors de null en intentar accedir als elements del widget.
Reflexió i Justificació Tècnica
Per què aquesta arquitectura?
La separació en tres capes (Widget ↔ Flask ↔ Gemini) no és una elecció arbitrària — és el patró arquitectònic estàndard de qualsevol aplicació web moderna. Cada capa té una responsabilitat única i ben definida:
- ✓Widget (FrontEnd): Presentació i experiència d’usuari. No sap res de com funciona la IA — només sap enviar missatges i mostrar respostes.
- ✓Flask (BackEnd): Lògica de negoci i seguretat. Valida les peticions, protegeix les claus, gestiona errors. Actua com a “guarda de seguretat”.
- ✓Gemini (API externa): Servei especialitzat. Fa la part computacionalment costosa (la IA) sense que el nostre codi n’hagi de tenir res.
Funció d’ngrok i la seva importància
ngrok no és un “hack” ni una solució temporal — és una eina professional àmpliament utilitzada en el món del desenvolupament per a prototipatge, demos i proves. La seva funció en aquest projecte és clara: Google Colab proporciona potència computacional gratuïta però en un entorn aïllat sense IP pública. ngrok connecta aquest entorn aïllat amb el món exterior de manera segura.
Limitacions actuals i millores futures
⚠️ Limitació — Inestabilitat del túnel
La URL de ngrok canvia cada vegada que es reinicia Colab. En un entorn de producció real, caldria un servidor permanent (p. ex. Google Cloud Run, AWS Lambda o un VPS).
🚀 Millora futura — Historial de conversa
Actualment el xatbot no recorda el context de la conversa. La millora seria enviar tot l’historial de missatges a la API per generar respostes contextuals.
Connexió amb el món professional: Grans empreses com Intercom, Zendesk o Crisp utilitzen exactament la mateixa arquitectura (widget embegut + servidor intermediari + API de IA) per als seus productes de xat intel·ligent. El que hem construït en petita escala és la mateixa lògica que alimenta productes de milions d’usuaris.
Resum d’Evidències
A continuació es presenta un resum organitzat de totes les captures de pantalla incloses en aquesta documentació, amb la seva localització dins del document.
Criteris PRO+ assolits
- ✓Arquitectura justificada: Cada component (Widget, Flask, JSON) ha estat explicat com a part d’un ecosistema, no com a element aïllat.
- ✓Connexió robusta i estable: L’endpoint de Flask rep les dades i les retorna correctament via el túnel ngrok.
- ✓Integració perfecta a WordPress: El xatbot s’insereix via WPCode sense conflictes ni errors.
- ✓Claus API protegides: Les claus de Gemini i ngrok estan als Secrets de Colab, invisibles al JS del client.
- ✓Gestió d’errors: El servidor retorna errors HTTP estàndard i el FrontEnd els gestiona adequadament.
- ✓Reflexió i responsabilitat ètica: S’ha argumentat la importància de la seguretat de les claus API com a responsabilitat professional.
- ✓Documentació completa: Captures de pantalla, codi comentat, explicacions de cada decisió tècnica.
