Creare una mini-AI autonoma
Obiettivo del modulo
Progettare, addestrare e deployare una micro-AI che svolge un compito ben definito (testo, immagini o decisioni), con pipeline completa: input → decisione AI → output → validazione, interfaccia d’uso (CLI, API o web), logging e salvataggio/ripristino dei pesi. Il percorso è hands-on e progressivo: si parte da un baseline semplice, poi si estende.
Scaletta passo-passo
🕐 Scoping e setup ambiente
- Scegli il dominio:
- Testo: classificatore di notizie (politica/sport/tech).
- Immagini: generatore di descrizioni per immagini pre-caricate (feature estratte + template).
- Decisioni: AI che suggerisce azioni su una checklist (regole+modello).
- Definisci l’output: etichetta, punteggio, testo, raccomandazione con motivazione breve.
- Setup: Python 3.10+, virtualenv, pacchetti minimi:
pip install numpy pandas scikit-learn joblib fastapi uvicorn streamlit pydantic - Repo: struttura consigliata:mini_ai/├─ data/ # dataset grezzi e processati├─ models/ # pesi, vectorizer, versioni├─ src/│ ├─ config.py│ ├─ preprocess.py│ ├─ model.py│ ├─ train.py│ ├─ eval.py│ ├─ serve_api.py # FastAPI│ └─ ui_streamlit.py # interfaccia web└─ logs/
🕑 Dati e metrica di successo
- Raccolta: CSV con colonne minime (es.
text,labelper il testo;image_path,captionper immagini). - Split: train/val/test (70/15/15) con stratificazione per classi.
- Metriche:
- Classificazione: accuracy, F1 macro (classi sbilanciate), matrice di confusione.
- Generazione (caption): BLEU/ROUGE (anche valutazione umana light: 1–5 coerenza).
- Decisioni su checklist: precision@k e tasso di adozione (quante azioni proposte accettate).
🕒 Baseline funzionante (semplice & robusto)
Obiettivo: avere una prima versione end-to-end che produce un output coerente, anche se non perfetto.
- Testo (consigliato per iniziare): CountVectorizer + Logistic Regression (veloce, solido, interpretabile).# src/train.py (estratto – baseline testo)import pandas as pdfrom sklearn.model_selection import train_test_splitfrom sklearn.feature_extraction.text import CountVectorizerfrom sklearn.linear_model import LogisticRegressionfrom sklearn.pipeline import Pipelinefrom sklearn.metrics import classification_reportimport joblib, osdf = pd.read_csv("data/news.csv") # colonne: text,labeltrain, test = train_test_split(df, test_size=0.2, stratify=df.label, random_state=42)pipe = Pipeline([("vec", CountVectorizer(max_features=30000, ngram_range=(1,2))),("clf", LogisticRegression(max_iter=200, n_jobs=-1))])pipe.fit(train.text, train.label)pred = pipe.predict(test.text)print(classification_report(test.label, pred, digits=3))os.makedirs("models", exist_ok=True)joblib.dump(pipe, "models/news_baseline.joblib")
- Immagini (baseline didattico): estrai feature con un backbone pre-addestrato (es. ResNet da torchvision), poi Nearest Neighbors per suggerire la caption dell’immagine più simile (semplice ma utile per il flusso end-to-end).
- Decisioni: Rule-first + piccolo modello: regole deterministiche per i casi chiari; modello di classificazione binaria per consigliare “fai/non fare” dove le regole non bastano.
🕓 Validazione, error analysis, versioning
- Valida sullo split di test; salva classification_report in
logs/con timestamp. - Errori ricorrenti: estrai i falsi positivi/negativi, crea una “lista nera” di pattern e una todo di miglioramenti (es. pulizia testo, stopword dominio-specifiche).
- Versiona modelli/dati:# src/config.pyMODEL_VERSION = "v1.0.0"ARTIFACT_DIR = f"models/{MODEL_VERSION}/"Salva anche le feature (vectorizer) e la configurazione usata (seed, parametri, vocabolario).
🕔 Interfacce d’uso (CLI, API, Web)
- CLI (per uso locale/automazione):# src/model.py (inference)import joblib_pipe = joblib.load("models/news_baseline.joblib")def predict_text(txt: str):label = _pipe.predict([txt])[0]prob = max(_pipe.predict_proba([txt])[0])return {"label": label, "confidence": float(prob)}# cli.pyimport argparsefrom src.model import predict_textparser = argparse.ArgumentParser()parser.add_argument("--text", required=True)args = parser.parse_args()print(predict_text(args.text))
- API (per integrazioni):# src/serve_api.pyfrom fastapi import FastAPIfrom pydantic import BaseModelfrom src.model import predict_textapp = FastAPI(title="Mini-AI API")class Item(BaseModel):text: str@app.post("/predict")def predict(item: Item):return predict_text(item.text)# Avvio: uvicorn src.serve_api:app --reload --port 8000
- Web UI (demo rapida):# src/ui_streamlit.pyimport streamlit as stfrom src.model import predict_textst.title("🧠 Mini-AI Classificatore di Notizie")txt = st.text_area("Inserisci il testo della notizia")if st.button("Predici"):out = predict_text(txt)st.write(f"**Classe:** {out['label']} | **Confidenza:** {out['confidence']:.2f}")Avvio:
streamlit run src/ui_streamlit.py
🕕 Logging, debugging, salvataggio/riuso pesi
- Logging strutturato (JSON line per facile analisi):# src/logging_utils.pyimport json, time, osdef log_event(event: dict, fname="logs/events.jsonl"):os.makedirs("logs", exist_ok=True)event["ts"] = time.time()with open(fname, "a", encoding="utf-8") as f:f.write(json.dumps(event, ensure_ascii=False) + "\n")
- Usalo in API/UI:# dentro /predictres = predict_text(item.text)log_event({"route": "predict", "input_len": len(item.text), "output": res})return res
- Salvataggio & ripristino: già visto con
joblib; per reti neurali usatorch.save/model.save()(TF). Aggiungi checksum o hash del file e della config per riproducibilità. - Debugging:
- stampa le top-n feature che “spingono” la predizione (es. coef_ di Logistic Regression) per audit.
- logga eccezioni con
exc_info=True, conserva input problematica inlogs/bad_cases/.
🕖 Hardening & deploy
- Seed & determinismo: imposta random_state ovunque per esperimenti ripetibili.
- Config separata (
.yamlo.json) per parametri (feature, modello, soglie). - Test: unit test su
preprocesse su un paio di casi attesi del modello. - Docker (opzionale):# Dockerfile (minimal)FROM python:3.11-slimWORKDIR /appCOPY requirements.txt .RUN pip install -r requirements.txtCOPY . .CMD ["uvicorn", "src.serve_api:app", "--host", "0.0.0.0", "--port", "8000"]
- Deploy: locale, VM, o PaaS (Railway/Render/Cloud Run). Esporre endpoint
/predict; proteggi con chiave API se pubblico.
🔬 Lab guidato: micro-AI end-to-end
- Importa dati (CSV) e fai lo split con stratificazione.
- Addestra baseline (testo: CountVectorizer+LR) e salva pesi.
- Valida su test e salva report e matrice di confusione (immagine/CSV).
- Servi il modello via API FastAPI e prova con
curlo Postman. - Interfaccia Streamlit per demo; logga ogni richiesta.
- Itera: migliora preprocessing (stopword dominio-specifiche, n-grammi), confronta F1 e aggiorna versione (
v1.1.0).
🧭 Design dell’autonomia: validazione & fallback
Evenienza reale: la mini-AI deve “sapere dire non so”. Aggiungi un validatore e un fallback:
- Soglia di confidenza: se
confidence < 0.55→ restituisci “richiedi conferma” o inoltra a regola/operatore. - Controlli di sicurezza: blocca input vuoti o troppo lunghi, rimuovi HTML/script.
- Audit: salva i low-confidence per active learning e migliorare il dataset in seguito.
📈 Miglioramenti successivi (opzionali)
- Text: TF-IDF, SVM, o DistilBERT (Hugging Face) con fine-tuning.
- Immagini: CLIP per embedding e nearest neighbor con caption semantiche.
- Decisioni: meta-policy: regole deterministiche + classificatore + spiegazioni (feature importanti) nel payload.









