gigiorancilio.it

Divulgo il digitale a giornalisti, insegnanti, educatori, genitori e nel mondo cattolico

Ecco come ho creato due chatbot (e perché) da una mia conferenza sull’IA

L’intelligenza artificiale sta cambiando anche il modo con il quale ci relazioniamo con i contenuti editoriali. Attraverso i sistemi di ricerca IA cambia il modo col quale li troviamo e come ci vengono restituiti. Ma cambia anche il modo col quale vengono creati.
Sempre più spesso, da giornalista, mi capita di pensare che le formula che abbiamo adottato fino a oggi per fare informazione devono essere affiancate da altre, al passo coi tempi. Ripeto: affiancate, non sostituite.
Per questo ti racconto come ho deciso di creare come esperimento un chatbot che rispondesse a ciò che ho raccontato per più di un’ora in una conferenza.

Ma andiamo con ordine.

Quando, agli inizi di dicembre, sono stato chiamato a tenere una conferenza sul tema Come l’intelligenza artificiale sta cambiando le nostre vite, avevo pensato di filmarla. Non avevo ancora le idee chiare su come avrei utilizzato il video, ma volevo riprenderla anche per studiare meglio i miei eventuali errori.
Purtroppo, per una serie di ragioni anche banali, quella sera non ho potuto filmarla ma solo registrarne l’audio.
Mi sembrava poca cosa mandare un file MP3, tutto sommato anche noioso, visto che dura un’ora, a chi, nei giorni successivi mi chiedeva se esisteva la registrazione di quella serata. Così, per qualche giorno, l’ho lasciato fermo, finché non mi è venuta l’idea di trasformarlo in un testo. Ho pensato, magari potrei farne un piccolo libro in PDF da regalare ai miei amici a Natale.
Così ho chiesto all’intelligenza artificiale di trasformare in testo quel lungo file audio. Nonostante il lavoro eccellente fatto da Gemini, restavano ovviamente quelle frasi non chiuse e non perfette, tipiche di quando si parla in una conferenza rispetto a quando si scrive. Così ho passato il risultato su un’altra, e questa volta su cloud, e gli ho chiesto di metterle a posto utilizzando il mio stile. Per poterlo fare, tempo addietro, avevo insegnato a Claude come scrivo quando tratto temi tecnologici.
Una volta creato il testo, tutto sommato di qualità più che decente, non mi restava che trasformarlo in un piccolo libro PDF.
Eppure non ero soddisfatto. Qualcosa mi diceva di aspettare. Finché mi è venuta un’idea: perché non mettere tutto quel materiale in una sorta di chatbot che potesse essere interrogato dalle persone, così da non dover obbligare amici e colleghi a dovere leggere il libretto dall’inizio alla fine, imbattendosi magari in aree e temi che già conoscevano o non gli interessavano?

A questo punto ho aperto ChatGPT e ho chiesto dei consigli su come fare tecnicamente. Ne è venuta fuori una conversazione piuttosto difficile da comprendere per uno come me, che ha solo delle conoscenze di base di informatica e di linguaggi, e che, se vuoi, puoi trovare qui.

Allora provo NotebookLM

Vista la difficoltà, almeno per me, di fare un sistema simile con ChatGPT ho provato con NotebookLM. Personalmente trovo il sistema di Google davvero utile per chi fa il giornalista. Permette di creare notebook che contengono una o più fonti legate a uno o più argomenti, con la possibilità di fare riassunti, ottenere podcast, infografiche, slide e, ovviamente, poter interrogare tutto il materiale attraverso delle domande.
Così ne ho realizzato uno a partire da due PDF: uno con il testo della mia conferenza, uno con le slide che ho usato (così da rendere più chiaro al sistema la scansione dei temi trattati). Dopo averlo testato, ero davvero soddisfatto e anche la grafica, pur nella sua semplicità, non mi sembrava male. Ti metto un frame qui sotto.

Testandolo mi sono accorto che il sistema, da solo, aveva fatto delle sostituzioni gravi. Per esempio, aveva cancellato dalla conferenza Papa Leone XIV. Questo perché l’intelligenza artificiale di Google continua ancora oggi a considerare il Papa regnante, Papa Francesco, e a non vedere l’elezione di Leone XIV.
A questo punto ho caricato un secondo PDF come fonte con tutte le slide che avevo preparato per la conferenza, alcune delle quali erano in maniera specifica incentrate su Papa Leone. Soltanto a questo punto il sistema ha cominciato a dare le risposte giuste sul nuovo Papa.

Dicono che Claude sia meglio. Davvero?

Non sono io a dirlo, ma persone molto più esperte di me: Claude, per quanto riguarda la capacità di creare codici e programmare, al momento è superiore ad altre intelligenze artificiali.
Così ho provato a realizzare il mio sistema usando questa intelligenza artificiale.
Non essendo questo un blog di informatici, non ti metto tutto il ragionamento che mi ha fatto anche Claude. Mi limiterò a raccontarti che, inizialmente, mi ha proposto anche lei una soluzione tecnicamente non facile.

Poi, stimolata da me, è invitata a realizzare qualcosa che potesse essere utilizzata anche da una persona con scarse conoscenze informatiche. È passata a soluzioni più semplici.
Quando dico semplici, però, non voglio dire alla portata di tutti, perché ha realizzato file che andavano caricati via FTP in una certa area del mio sito e poi altri, ai quali dovevano essere fatte delle correzioni nei codici HTML.Insomma, niente di incredibile, ma neanche di così facile per chi non ha alcuna conoscenza di queste cose. Ci ho messo un po’ a farlo funzionare correttamente, ma devo dire che tutte le soluzioni che mi ha dato Claude hanno migliorato sensibilmente il progetto.
L’idea finale è fatta così. Ho creato una versione che funziona 100% offline, completamente client-side, senza bisogno di API esterne.


Andava tutto bene, tranne una cosa. Dopo la prima risposta, il sistema mi dava una sezione rilevante dove cercava, all’interno di tutto il documento, testi che potessero in qualche modo avvicinarsi alla domanda che avevo fatto, in percentuali variabili che andavano dal 10% al 55%. Il risultato era un elenco piuttosto confusionario.Così gli ho chiesto di togliere questa sezione e di mettere al suo posto una serie successiva di domande che potessero aiutare chi interroga il sistema ad approfondire il tema.

Sembrava tutto perfetto. Ma più interrogavo il nuovo chatbot creato con Claude, più trovavo delle imprecisioni. Per cui tornavo a interrogare il sistema che l’avevo creato e gli chiedevo di fare delle correzioni. Il problema della IA è che, se non stai attento a tutto, il suo aiuto non è completo. Mi spiego. Quando facevo domande sulla Chiesa e l’intelligenza artificiale, confondeva il magistero di Papa Francesco con quello di Papa Leone XIV. Quando glielo ho fatto notare con una serie di esempi pratici, ha suddiviso meglio la sezione così da ridurre la possibilità di errore.
Peccato che le altre 22 sezioni, con le quali era stata suddivisa la mia conferenza, non avessero lo stesso trattamento e quindi erano imprecise.
Ho quindi dovuto chiedere espressamente al sistema di fare un’analisi globale di tutto il contenuto e una suddivisione più rigorosa.

Pensavo di avere risolto tutto, ma non avevo fatto i conti con gli errori che mi ero portato dall’inizio. Quindi, anche in questo chatbot, Papa Leone XIV non esisteva più. Ho così ripassato tutto il testo della conferenza e l’ho corretto. Poi ho chiesto al sistema di fare la stessa cosa nel suo database, sperando correggesse l’errore.

Al primo tentativo ha commesso un altro errore: ha sostituito Papa Leone XIV tutte le volte che incontrava le parole Papa Francesco. Ho quindi dovuto rispiegargli che a guidare la Chiesa prima c’era papa Francesco e ora Leone XIV, che entrambi hanno fatto dichiarazioni sull’intelligenza artificiale e che queste dovevano essere attribuite in maniera corretta ai due papi.
Sembrava avesse capito tutto; invece, ha attribuito il documento vaticano sull’intelligenza artificiale del gennaio 2025 a Papa Leone XIV, quando invece c’era ancora Papa Francesco.

Claude mi aveva risposto di aver risolto tutto. Invece, quando mi ha restituito questa domanda correlata Cosa significa che l’IA lavora per probabilità?, quando l’ho cliccata mi ha dato una risposta su papa Leone XIV.

Quando gliel’ho fatto notare, mi ha risposto: Hai fatto benissimo a chiedere! Ho trovato un GROSSO problema: le keywords compound come “papa leone xiv”, “essere umani”, “bene comune” NON matchano correttamente!
Quindi ha promesso di correggere tutto e di rivedere anche l’algoritmo. Te la faccio breve: c’è voluta mezz’ora di lavoro per trovare il problema e correggere l’algoritmo.

Ed ecco il chatbot di Claude sulla mia conferenza

Sistema RAG per esplorare i contenuti della conferenza di Gigio Rancilio con domande in linguaggio naturale

Sotto il chatbot creato con NotebookLM

🤖

Assistente Virtuale della Conferenza

Vuoi approfondire un punto specifico delle slide o del mio intervento? Chiedilo direttamente alla mia base documentale tramite NotebookLM.

  • Risposte basate esclusivamente sui miei PDF
  • Citazioni dirette alle pagine e alle slide
  • Generazione di riassunti personalizzati
Inizia la conversazione →


Le mie considerazioni finali

Dopo avere testato due chatbot per qualche ora, posso dire che quello creato con Notebook LM, pur essendo molto più lento, dà risposte più concrete, più complete e coerenti, pescando anche da parti diverse della conferenza.
Quello creato con Claude, che ha una grafica sicuramente più accattivante e il bonus di fornire dopo ogni risposta, ulteriori domande correlate per approfondire il tema, è molto veloce ma un po’ meno preciso.

Caratteristica Chatbot con Claude NotebookLM
Focus Principale Creatività e ragionamento logico Analisi e grounding sui documenti
Domande Correlate Grafica più bella Suggerimenti contestuali alle fonti
Interfaccia Moderna e rifinita Grafica spartana
Approfondimento Risposte bilanciate Risposte più esaurienti
Velocità Molto veloce ed efficiente Sistema più lento

A questo punto ti chiedo la gentilezza di provarli anche tu e di indicarmi gli eventuali errori e le inesattezze che contengono.

Per chi fosse interessato metto qui sotto la prima conversazione con ChatGPT per creare il chatbot sulla conferenza

La conversazione con ChatGPT per creare il chatbot sulla conferenza

Qui sotto una roadmap concreta per farlo bene, cioè “risponde solo dal libro” + citazioni + controlli.

1) Prepara il testo del libro (digitale)

  • Se è PDF: estrai il testo in modo pulito (attenzione a intestazioni/piedipagina, note, rientri).
  • Se è EPUB: di solito è più semplice ottenere testo “pulito”.
  • Mantieni (o ricostruisci) struttura: capitoli, sezioni, numeri pagina (o “posizioni”) → servono per le citazioni.

Output ideale: una cartella con file tipo:

  • capitolo-01.md, capitolo-02.md… (oppure JSON con campi chapter, text, page_start, page_end).

2) Crea l’indice di ricerca (il cuore del sistema)

  • Spezza in chunk (es. 300–800 parole, con 10–20% di sovrapposizione).
  • Salva metadati per ogni chunk: capitolo, paragrafo, pagina/posizione, eventualmente un ID univoco.
  • Indicizza in un sistema di retrieval:
    • minimo: solo vector search (embeddings)
    • meglio: ibrido (semantico + keyword) per prendere anche nomi propri, date, termini tecnici.

3) Costruisci il chatbot “chiuso” sul libro (RAG con guardrail)

Flusso:

  1. domanda utente
  2. recupero dei chunk migliori (es. top 5–10)
  3. risposta solo usando quei chunk

Guardrail che fanno la differenza:

  • Citazioni obbligatorie: ogni risposta deve riportare “Capitolo X, p. Y” (o sezione/posizione).
  • Soglia di confidenza: se i chunk recuperati non sono abbastanza pertinenti → risposta standard:
    “Nel libro non trovo informazioni sufficienti per rispondere con certezza.”
  • Regola anti-estratti lunghi (importante se lo condividi): limita la verbatim quote a poche righe e preferisci parafrasi + citazioni.

4) Decidi come lo condividi (scelta pratica)

Tre opzioni tipiche:

A) Sito web pubblico

  • Frontend (una pagina chat) + backend (API).
  • Autenticazione opzionale (token/utente) se vuoi controllare accessi.
  • Rate limit per evitare abuso/costi.

B) Chatbot “chiuso” con accesso a invito

  • Login, whitelist email, o link con token.
  • Ideale se vuoi testarlo con lettori selezionati.

C) Widget embed

  • Un widget da incorporare nel tuo sito (stessa logica, UI integrata).

5) Protezioni “da autore” (anti-copia / anti-leak)

Se lo condividi, pensa a questi punti:

  • Non far scaricare i chunk sorgente.
  • Limite di output (es. max 800–1200 caratteri) e limite di citazioni testuali.
  • Blocca richieste tipo: “incollami tutto il capitolo 3” → rispondere con riassunto + rimando.
  • Log e monitoraggio: domande frequenti, tentativi di estrazione massiva.

6) Test e qualità

  • Prepara 50 domande (semplici, difficili, trabocchetto) e verifica:
    • citazioni corrette
    • “non lo so” quando serve
    • coerenza terminologica (nomi, date, concetti ricorrenti)

Se vuoi una “ricetta” super concreta (stack tipico)

  • Ingest & indice: LlamaIndex o LangChain
  • Vector DB: Qdrant / pgvector / Pinecone (scegli in base a dove hosti)
  • Backend: FastAPI / Node
  • Frontend: Next.js (o anche una pagina HTML semplice)
  • Regole: citazioni obbligatorie + soglia + blocco estratti lunghi

Se mi dici in che formato digitale è il libro (PDF o EPUB) e quante pagine circa, ti propongo un setup preciso (anche “tutto su un VPS” o “serverless”), con parametri consigliati: chunk size, top-k, soglia, formato delle citazioni e limiti anti-estrazione.

Spiegami come fare, passo dopo passo, come se lo spiegassi a tua zia di 60 anni

Ragionato per 40s

Certo. Ti spiego un modo semplice e “da zia” per creare un chatbot che risponde solo usando il tuo libro e poi metterlo online.

L’idea è questa: il chatbot non “sa” davvero il libro a memoria. Quando gli fai una domanda, prima cerca nel libro i pezzi giusti e poi risponde usando solo quelli (con citazioni). Questa tecnica si chiama RAG, ma tu puoi pensarla come: “prima cerco nel libro, poi parlo”. OpenAI Platform+1


Strada più facile (consigliata): usare “File search” + una mini web-app

Questa strada ti evita di costruire da zero un motore di ricerca: lo fai con l’API e un sito molto semplice. “File search” supporta proprio l’idea di caricare file in un “contenitore” (vector store) e farli cercare al modello con ricerca semantica + keyword. OpenAI Platform+1

Passo 1 — Metti in ordine il file del libro

  1. Assicurati di avere un PDF (o altro formato supportato) pulito:
  • testo selezionabile (non “immagini di testo”)
  • niente doppie versioni, niente password
  1. Se il PDF è impaginato male (colonne, note strane), può comunque funzionare, ma a volte conviene partire da EPUB o testo se lo hai.

Passo 2 — Crea “la casa” del chatbot

  1. Ti serve un account sulla piattaforma API che userai (es. OpenAI API).
  2. Crea una API key (una “chiave” segreta).
  3. Tieni la chiave solo nel server, mai dentro una pagina web pubblica.

Passo 3 — Carica il libro nel “magazzino di ricerca”

  1. Crei un vector store (immagina uno scaffale dove il sistema mette il libro a pezzetti indicizzati).
  2. Carichi il PDF dentro quello scaffale.
  3. Da quel momento, il chatbot può “cercare nel tuo libro” prima di rispondere. OpenAI Platform+1
    (Nota: esistono anche limiti dimensionali/di token per i file, quindi se il libro è enorme o hai tanti file, va gestito con attenzione.) OpenAI Platform

Passo 4 — Imposta le regole: “rispondi solo dal libro”

Questa è la parte più importante per evitare invenzioni.
Nel messaggio di sistema (le istruzioni fisse del bot) metti regole tipo:

  • “Usa esclusivamente le informazioni trovate nei file.”
  • “Se nel libro non c’è, rispondi: ‘Non è nel libro’.”
  • “Metti sempre le citazioni (capitolo/pagina o riferimento).”
  • “Non copiare lunghi pezzi del testo: fai riassunti brevi.”

Passo 5 — Crea una pagina web “chat” (la vetrina)

Qui ci sono 2 pezzetti:

A) Backend (server): una piccola API che:

  • riceve la domanda dell’utente
  • chiama il modello con lo strumento file search
  • restituisce risposta + citazioni

B) Frontend (sito): una pagina con:

  • una casella dove scrivi
  • un bottone “Invia”
  • area dove leggi la risposta e le citazioni

(Per pubblicarlo, puoi usare servizi tipo Vercel/Render/Fly/Cloudflare, ma la scelta dipende da cosa sai già usare.)

Passo 6 — Metti “cinture di sicurezza” perché sarà pubblico

Se lo condividi, ti conviene aggiungere:

  • limite di domande (rate limit) per evitare abuso e costi a sorpresa
  • moderazione base (blocca spam/insulti)
  • limite lunghezza risposta
  • blocco richieste tipo: “incollami tutto il capitolo 3” → rispondi con riassunto + invito a consultare il libro

Passo 7 — Prova con domande “cattive”

Prima di pubblicare, fai un test tipo:

  • 20 domande facilissime (deve andare liscio)
  • 20 domande trabocchetto su cose non presenti (deve dire “non è nel libro”)
  • 10 domande ambigue (deve chiedere chiarimenti o rispondere con prudenza)

Strada “più controllabile” (se vuoi più libertà): LlamaIndex/LangChain + un tuo database vettoriale

Se vuoi avere più controllo (chunking, metadati, capitoli/pagine perfette, ecc.), usi strumenti tipo LlamaIndex/LangChain per:

È più lavoro, ma permette “fine tuning” del comportamento del retriever.


Se vuoi, ti do una checklist precisa “da seguire e spuntare”

Per farla davvero su misura, dimmi solo:

  1. Il tuo libro è PDF o EPUB?
  2. Quante pagine circa?
  3. Vuoi che sia pubblico per tutti o con accesso (password/link)?

E ti scrivo i passaggi esatti con: struttura cartelle, regole del prompt, formato delle citazioni e impostazioni consigliate (top-k/soglia/limiti) senza farti impazzire.

1 pdf 2 40 3 con password

Ragionato per 2m 8s

Ok: PDF (40 pagine) + accesso con password + chatbot che risponde solo usando il tuo libro. Ti descrivo la strada più semplice, “da zia”, usando:

  • un sito Next.js (la pagina chat)
  • una password (Basic Auth: ti chiede user+password prima di entrare)
  • File Search + Vector Store (OpenAI indicizza il PDF e lo fa “cercare” al bot) OpenAI Platform+2OpenAI Platform+2

Cosa ti serve (ingredienti)

  1. Il tuo file: mio-libro.pdf
  2. Un computer con Terminale (o Prompt)
  3. Account su:
  • OpenAI Platform (per la chiave API)
  • Vercel (per pubblicare il sito)

Regola d’oro: la API key non va mai messa nel browser. Deve stare “dietro”, nel server. OpenAI Help Center+1


Passo 1 — Crea il sito “con password” (pronto in 2 minuti)

Useremo un modello già pronto di Vercel che mette la password davanti a tutto il sito. Vercel

  1. Apri il Terminale e incolla (così com’è):
pnpm create next-app --example https://github.com/vercel/examples/tree/main/edge-middleware/basic-auth-password basic-auth-password
cd basic-auth-password
pnpm dev
  1. Vai nel browser su http://localhost:3000
  2. Ti chiede user+password (per ora sono quelle di demo nel template). Vercel

Se non hai pnpm, installalo con:

npm i -g pnpm

Passo 2 — Metti la tua password

Nel progetto, crea un file chiamato .env.local (nella cartella del progetto) e mettici:

BASIC_AUTH_USER=tuoUser
BASIC_AUTH_PASSWORD=unaPasswordLungaERobusta

Il template usa l’Edge Middleware per proteggere le pagine con Basic Auth. Vercel+1


Passo 3 — Carica il PDF in un “contenitore” di ricerca (Vector Store)

Qui crei lo “scaffale” dove il PDF viene spezzato e indicizzato automaticamente. Poi il bot ci cerca dentro. OpenAI Platform+2OpenAI Cookbook+2

3A) Prepara la chiave OpenAI

  1. Prendi la tua OPENAI_API_KEY
  2. Aggiungila a .env.local:
OPENAI_API_KEY=la_tua_chiave_openai

3B) Crea vector store + carica PDF (script “una volta sola”)

  1. Metti mio-libro.pdf dentro la cartella del progetto.
  2. Crea un file upload_book.py con questo contenuto:
import os
from openai import OpenAI

client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])

# 1) crea il "magazzino"
vs = client.vector_stores.create(name="Mio libro (chatbot)")
print("VECTOR_STORE_ID =", vs.id)

# 2) carica il PDF come file
f = client.files.create(
    file=open("mio-libro.pdf", "rb"),
    purpose="assistants"
)

# 3) collega il file al vector store
client.vector_stores.files.create(
    vector_store_id=vs.id,
    file_id=f.id
)

print("OK: PDF caricato e indicizzato (potrebbe volerci un po' di tempo).")
  1. Esegui:
pip install openai
python upload_book.py
  1. Copia il valore stampato VECTOR_STORE_ID = ... e mettilo in .env.local:
VECTOR_STORE_ID=vs_xxxxxx

(Questo flusso di upload è esattamente quello usato negli esempi ufficiali.) OpenAI Cookbook+1


Passo 4 — Crea l’API del chatbot (il “cervello” dietro)

Il punto chiave: la tua pagina web chiama il tuo server, e il server chiama OpenAI con file_search puntato al tuo vector store. OpenAI Help Center+2OpenAI Platform+2

  1. Nel progetto, crea questo file:
  • pages/api/chat.js (se usi Pages Router)

Dentro incolla (versione semplice):

import OpenAI from "openai";

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

export default async function handler(req, res) {
  if (req.method !== "POST") return res.status(405).json({ error: "Use POST" });

  const { question } = req.body || {};
  if (!question) return res.status(400).json({ error: "Missing question" });

  const systemRules = `
Rispondi ESCLUSIVAMENTE usando il contenuto del libro caricato.
Se nel libro non trovi la risposta, dì: "Non è presente nel libro."
Non inventare.
Alla fine, aggiungi una sezione "Fonti" con i riferimenti ai passaggi trovati.
`;

  const response = await openai.responses.create({
    model: "gpt-4.1",
    input: [
      { role: "system", content: systemRules },
      { role: "user", content: question },
    ],
    tools: [{
      type: "file_search",
      vector_store_ids: [process.env.VECTOR_STORE_ID],
      max_num_results: 5,
    }],
    include: ["file_search_call.results"],
  });

  // risposta testuale “pronta”
  const answer = response.output_text || "";

  res.status(200).json({ answer });
}

Queste opzioni (file_search, vector_store_ids, max_num_results, include) sono documentate nella guida ufficiale di File Search. OpenAI Platform+1


Passo 5 — Crea la pagina chat (la “faccia”)

  1. Apri pages/index.js (o la pagina principale del template)
  2. Metti un form semplice che manda la domanda a /api/chat e stampa answer.

Se vuoi, posso darti un file index.js già pronto “copia-incolla” (molto corto).


Passo 6 — Pubblica su internet (con password)

  1. Carica il progetto su GitHub (anche privato va bene)
  2. Su Vercel: “New Project” → collega il repo → Deploy
  3. Su Vercel → Settings → Environment Variables: inserisci
  • OPENAI_API_KEY
  • VECTOR_STORE_ID
  • BASIC_AUTH_USER
  • BASIC_AUTH_PASSWORD

E ridistribuisci.


Due accorgimenti importanti (per farlo davvero “solo dal libro”)

  • Mantieni la regola: se non trova nel libro, deve dire “non è presente” (niente supposizioni).
  • Metti un limite: se qualcuno chiede “incollami l’intero capitolo”, rispondi con riassunto e basta (utile anche per evitare estrazioni massicce).

Se mi dici solo che sistema stai usando (Windows/Mac), ti adatto i comandi (Terminale/Prompt) e ti passo anche la pagina chat completa già pronta da incollare.

windows

Ragionato per 3m 45s

Perfetto. Ti spiego come farlo su Windows, passo-passo, in modo “da zia”: copi/incolli comandi, crei 3–4 file, e poi lo pubblichi con password.

L’idea tecnica è: il bot prima cerca nel PDF (con File Search su un vector store) e poi risponde solo usando quello. OpenAI Platform


0) Prima di iniziare (cose da installare su Windows)

  1. Node.js LTS (serve per far girare il sito)
  2. Git (serve per pubblicare su Vercel tramite GitHub)
  3. Visual Studio Code (consigliato, per modificare i file)

Se non sai dove prenderli: cerca su Google “Node.js LTS download”, “Git for Windows”, “VS Code”.


1) Crea il progetto (con la password già pronta)

Apri PowerShell (Start → cerca “PowerShell”) e incolla:

npm install -g pnpm
pnpm create next-app --example https://github.com/vercel/examples/tree/main/edge-middleware/basic-auth-password libro-chatbot
cd libro-chatbot
pnpm dev

Poi apri il browser su http://localhost:3000 → vedrai che chiede user/password. Questo template è fatto apposta per proteggere con password usando Middleware. Vercel+1


2) Metti la tua password (davvero tua)

Nel progetto, crea un file chiamato .env.local (nella cartella libro-chatbot) con questo contenuto:

BASIC_AUTH_USER=Gigio
BASIC_AUTH_PASSWORD=UnaPasswordLunga123!

Ora crea (o sostituisci) il file middleware.ts nella cartella principale del progetto (stesso livello di package.json) con questo codice:

import { NextResponse } from "next/server";

export const config = {
  matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
};

export function middleware(req: Request) {
  const user = process.env.BASIC_AUTH_USER ?? "";
  const pass = process.env.BASIC_AUTH_PASSWORD ?? "";

  const auth = req.headers.get("authorization");
  const valid =
    auth &&
    auth.startsWith("Basic ") &&
    (() => {
      const b64 = auth.slice("Basic ".length);
      const [u, p] = Buffer.from(b64, "base64").toString().split(":");
      return u === user && p === pass;
    })();

  if (valid) return NextResponse.next();

  return new Response("Auth required", {
    status: 401,
    headers: { "WWW-Authenticate": 'Basic realm="Protected"' },
  });
}

Questa è la “porta con la chiave” davanti a tutto il sito. Middleware in Next.js/Vercel funziona proprio così. Vercel+1

Riavvia il server (nel terminale: CTRL+C, poi):

pnpm dev

3) Metti il PDF nel progetto

Copia il tuo libro (40 pagine) dentro la cartella libro-chatbot e chiamalo libro.pdf.


4) Crea il “magazzino” dove il bot cercherà nel PDF (Vector Store)

4A) Metti la chiave OpenAI

Nel file .env.local aggiungi anche:

OPENAI_API_KEY=la_tua_chiave_openai

4B) Installa la libreria OpenAI

In PowerShell (dentro libro-chatbot):

pnpm add openai

4C) Crea lo script che carica il PDF

Crea la cartella scripts e dentro un file upload.mjs:

scripts/upload.mjs

import fs from "node:fs";
import OpenAI from "openai";

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

async function sleep(ms) {
  return new Promise((r) => setTimeout(r, ms));
}

async function main() {
  // 1) crea un vector store (lo “scaffale”)
  const vectorStore = await openai.vectorStores.create({ name: "Libro PDF" });

  // 2) carica il file su Files API
  const file = await openai.files.create({
    file: fs.createReadStream("libro.pdf"),
    purpose: "assistants",
  });

  // 3) aggancia il file al vector store
  await openai.vectorStores.files.create(vectorStore.id, { file_id: file.id });

  // 4) aspetta finché l’indicizzazione è pronta (status = completed)
  while (true) {
    const list = await openai.vectorStores.files.list({
      vector_store_id: vectorStore.id,
    });
    const status = list.data?.[0]?.status;
    console.log("Stato indicizzazione:", status);

    if (status === "completed") break;
    if (status === "failed") throw new Error("Indicizzazione fallita");
    await sleep(1500);
  }

  console.log("\n✅ Fatto!");
  console.log("VECTOR_STORE_ID =", vectorStore.id);
}

main().catch((e) => {
  console.error(e);
  process.exit(1);
});

E avvialo:

node scripts/upload.mjs

Quando finisce, copia il VECTOR_STORE_ID = vs_... e incollalo in .env.local:

VECTOR_STORE_ID=vs_qualcosa

Questi passaggi (upload file → attach al vector store → status “completed”) sono esattamente quelli descritti nella guida ufficiale di File Search. OpenAI Platform+2OpenAI Platform+2


5) Crea l’API “/api/chat” (il cervello del chatbot)

Qui facciamo una rotta che:

  • riceve una domanda
  • usa file_search sul tuo VECTOR_STORE_ID
  • risponde solo usando il libro (e se non c’è, dice “non è nel libro”) OpenAI Platform

Se nel tuo progetto c’è la cartella app

Crea: app/api/chat/route.js

import OpenAI from "openai";

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

export async function POST(req) {
  const { question } = await req.json();

  const system = `
Rispondi ESCLUSIVAMENTE usando il contenuto del file fornito tramite file_search (il libro).
Se nel libro non trovi la risposta, scrivi: "Non è presente nel libro."
Non inventare. Risposta breve e chiara.
  `.trim();

  const response = await openai.responses.create({
    model: "gpt-4.1",
    input: [
      { role: "system", content: system },
      { role: "user", content: question },
    ],
    tools: [
      {
        type: "file_search",
        vector_store_ids: [process.env.VECTOR_STORE_ID],
        max_num_results: 5,
      },
    ],
  });

  return Response.json({ answer: response.output_text });
}

Se nel tuo progetto c’è la cartella pages

Crea: pages/api/chat.js

import OpenAI from "openai";

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

export default async function handler(req, res) {
  if (req.method !== "POST") return res.status(405).end();

  const { question } = req.body || {};

  const system = `
Rispondi ESCLUSIVAMENTE usando il contenuto del file fornito tramite file_search (il libro).
Se nel libro non trovi la risposta, scrivi: "Non è presente nel libro."
Non inventare. Risposta breve e chiara.
  `.trim();

  const response = await openai.responses.create({
    model: "gpt-4.1",
    input: [
      { role: "system", content: system },
      { role: "user", content: question },
    ],
    tools: [
      {
        type: "file_search",
        vector_store_ids: [process.env.VECTOR_STORE_ID],
        max_num_results: 5,
      },
    ],
  });

  res.status(200).json({ answer: response.output_text });
}

Il modo in cui si usa file_search, vector_store_ids, max_num_results e la Responses API è documentato ufficialmente. OpenAI Platform+1


6) Crea la pagina “chat” (la faccia del bot)

Dimmi solo se nel tuo progetto c’è app/page.* oppure pages/index.* e ti incollo la pagina completa giusta (è un file corto, con una casella di testo + bottone + risposta).


7) Mettilo online con password (Vercel)

Metodo semplice:

  1. Carica il progetto su GitHub (repo privato o pubblico)
  2. Su Vercel: “New Project” → importi il repo → Deploy
  3. In Vercel → Settings → Environment Variables aggiungi:
    • OPENAI_API_KEY
    • VECTOR_STORE_ID
    • BASIC_AUTH_USER
    • BASIC_AUTH_PASSWORD

Così, appena qualcuno apre il sito, vede subito la richiesta password (grazie al middleware).