← blog
JavaScript Gemini API Firebase AI

Gemini API: conversazione multi-turn e system prompt dinamico

Come accodare i messaggi nell'array contents per simulare una conversazione con Gemini API, e costruire un system prompt che serializza dati Firebase live ad ogni chiamata senza query aggiuntive.

Chiamata base

Una chiamata singola a Gemini richiede un system_instruction e un array contents con il messaggio dell'utente.

gemini.js — chiamata base
async function askGemini(userMessage, systemPrompt) {
  const GEMINI_KEY = '[GEMINI_API_KEY]';
  const MODEL     = 'gemini-2.5-flash-lite';
  const ENDPOINT  = `https://generativelanguage.googleapis.com/v1beta/models/${MODEL}:generateContent?key=${GEMINI_KEY}`;

  const response = await fetch(ENDPOINT, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      system_instruction: { parts: [{ text: systemPrompt }] },
      contents: [{ parts: [{ text: userMessage }] }]
    })
  });

  const data = await response.json();
  if (!response.ok) throw new Error(data?.error?.message || 'Errore API');

  return data.candidates[0].content.parts[0].text;
}

Attenzione: non mettere mai la API key direttamente nel frontend di un'app pubblica. Per un gestionale interno ad accesso limitato è un tradeoff accettabile; in alternativa, salvala come variabile d'ambiente su Netlify e fai le chiamate tramite una Netlify Function proxy.

System prompt dinamico da stato Firebase

La chiave è costruire il system prompt al volo, serializzando lo stato corrente già presente in memoria (sincronizzato da Firebase), senza fare query aggiuntive ad ogni messaggio.

gemini.js — system prompt dinamico
function buildSystemPrompt() {
  const mese   = getCurrentMonthLabel();   // es. "Giugno 2026"
  const utente = sessionStorage.getItem('panelUser') || 'Sconosciuto';

  // Classifica operatori con totali per categoria — già in memoria, no query
  const rankingText = Object.entries(state.operatori)
    .map(([nome, dati]) =>
      `${nome}: ${dati.totale} ordini (Cat-A: ${dati.catA}, Cat-B: ${dati.catB})`
    ).join('\n');

  return `Sei un assistente interno. Rispondi sempre in italiano, in modo diretto e professionale.

=== CONTESTO ATTUALE ===
Utente connesso: ${utente}
Mese di riferimento: ${mese}

=== OPERATORI E RISULTATI ===
${rankingText}

=== CONOSCENZA AZIENDALE ===
[Blocco statico — procedure, prodotti, glossario]
`;
}

Conoscenza statica vs live: nel blocco statico vanno le cose che cambiano raramente (struttura prodotti, procedure core, glossario) — scritte direttamente come stringa nel sorgente. Nel blocco dinamico va tutto ciò che cambia quotidianamente (chi ha venduto cosa, lead del mese), letto da Firebase al volo.

Conversazione multi-turn: accodare i messaggi

Gemini API non ha memoria propria. Per simulare una conversazione con più scambi, ogni chiamata successiva deve includere nell'array contents tutti i messaggi precedenti — alternando role: "user" e role: "model".

gemini.js — multi-turn
let conversationHistory = []; // resettata all'apertura del pannello

async function sendAiMessage(userText) {
  // Aggiunge il turno utente alla storia
  conversationHistory.push({
    role: 'user',
    parts: [{ text: userText }]
  });

  const response = await fetch(ENDPOINT, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      system_instruction: { parts: [{ text: buildSystemPrompt() }] },
      contents: conversationHistory  // intera storia ad ogni chiamata
    })
  });

  const data   = await response.json();
  const aiText = data.candidates[0].content.parts[0].text;

  // Aggiunge la risposta del modello alla storia
  conversationHistory.push({
    role: 'model',
    parts: [{ text: aiText }]
  });

  return aiText;
}

Versioning modelli: Gemini deprecca i modelli rapidamente per i nuovi account. Verifica sempre la disponibilità del modello scelto prima di metterlo in produzione — un nome modello valido oggi può restituire 404 tra qualche settimana.

Articolo correlato
Assistente AI nel gestionale con Gemini API — system prompt dinamico da Firebase