Al centro dell'IA generativa ci sono i modelli di IA. Attualmente, i due esempi più importanti di modelli generativi sono i modelli linguistici di grandi dimensioni (LLM) e i modelli di generazione di immagini. Questi modelli accettano un input, chiamato prompt (in genere testo, un'immagine o una combinazione di entrambi), e producono come output testo, un'immagine o persino audio o video.
L'output di questi modelli può essere sorprendentemente convincente: gli LLM generano testo che sembra essere stato scritto da un essere umano e i modelli di generazione di immagini possono produrre immagini molto simili a fotografie reali o artwork creati da persone.
Inoltre, gli LLM si sono dimostrati in grado di svolgere attività oltre la semplice generazione di testo:
- Scrittura di programmi per computer.
- Pianificare le attività secondarie necessarie per completare un'attività più grande.
- Organizzazione di dati non organizzati.
- Comprendere ed estrarre dati informativi da un corpus di testo.
- Seguire ed eseguire attività automatiche in base a una descrizione testuale dell'attività.
Sono disponibili molti modelli di diversi fornitori. Ogni modello ha i suoi punti di forza e di debolezza e un modello potrebbe eccellere in un compito ma avere un rendimento inferiore in altri. Le app che utilizzano l'IA generativa possono spesso beneficiare dell'utilizzo di più modelli diversi a seconda dell'attività da svolgere.
In qualità di sviluppatore di app, in genere non interagisci direttamente con i modelli di AI generativa, ma tramite servizi disponibili come API web. Sebbene questi servizi spesso abbiano funzionalità simili, le forniscono tutte tramite API diverse e incompatibili. Se vuoi utilizzare più servizi di modelli, devi utilizzare ciascuno dei relativi SDK proprietari, potenzialmente incompatibili tra loro. Inoltre, se vuoi eseguire l'upgrade da un modello all'altro, quello più recente e più capace, potresti dover creare di nuovo l'integrazione.
Genkit risolve questo problema fornendo un'unica interfaccia che astrae i dettagli di accesso a qualsiasi servizio di modelli di IA generativa, con diverse implementazioni predefinite già disponibili. La creazione di un'app basata sull'IA con Genkit semplifica il processo di esecuzione della prima chiamata di IA generativa e rende altrettanto facile combinare più modelli o sostituirne uno con un altro man mano che vengono sviluppati nuovi modelli.
Prima di iniziare
Se vuoi eseguire gli esempi di codice in questa pagina, completa prima i passaggi descritti nella guida Inizia. Tutti gli esempi presuppongono che tu abbia già installato Genkit come dipendenza nel tuo progetto.
Modelli supportati da Genkit
Genkit è progettato per essere abbastanza flessibile da utilizzare potenzialmente qualsiasi servizio di modelli di IA generativa. Le librerie di base definiscono l'interfaccia comune per lavorare con i modelli, mentre i plug-in dei modelli definiscono i dettagli di implementazione per lavorare con un modello specifico e la relativa API.
Il team di Genkit gestisce i plug-in per lavorare con i modelli forniti da Vertex AI, Google Generative AI e Ollama:
- La famiglia di LLM Gemini, tramite il plug-in Vertex AI di Google Cloud.
- La famiglia di LLM di Gemini, tramite il plug-in di IA di Google.
- Gemma 3, Llama 4 e molti altri modelli aperti tramite il plug-in Ollama (devi ospitare autonomamente il server Ollama).
Caricamento e configurazione dei plug-in dei modelli
Prima di poter utilizzare Genkit per iniziare a generare contenuti, devi caricare e configurare un plug-in del modello. Se proveni dalla guida Inizia, hai già eseguito questa operazione. In caso contrario, consulta la guida Inizia o la documentazione del singolo plug-in e segui i passaggi indicati prima di continuare.
La funzione genkit.Generate()
In Genkit, l'interfaccia principale tramite la quale interagisci con i modelli di IA generativa è la funzione genkit.Generate()
.
La chiamata genkit.Generate()
più semplice specifica il modello che vuoi utilizzare e un prompt di testo:
import (
"context"
"log"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai"
)
func main() {
ctx := context.Background()
g, err := genkit.Init(ctx,
genkit.WithPlugins(&googlegenai.GoogleAI{}),
genkit.WithDefaultModel("googleai/gemini-2.0-flash"),
)
if err != nil {
log.Fatal(err)
}
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("Invent a menu item for a pirate themed restaurant."),
)
if err != nil {
log.Fatal(err)
}
log.Println(resp.Text())
}
Quando esegui questo breve esempio, vengono stampate alcune informazioni di debug followed by the output of the genkit.Generate()
call, which will usually be
Markdown text as in the following example:
## The Blackheart's Bounty
**A hearty stew of slow-cooked beef, spiced with rum and molasses, served in a
hollowed-out cannonball with a side of crusty bread and a dollop of tangy
pineapple salsa.**
**Description:** This dish is a tribute to the hearty meals enjoyed by pirates
on the high seas. The beef is tender and flavorful, infused with the warm spices
of rum and molasses. The pineapple salsa adds a touch of sweetness and acidity,
balancing the richness of the stew. The cannonball serving vessel adds a fun and
thematic touch, making this dish a perfect choice for any pirate-themed
adventure.
Esegui di nuovo lo script e otterrai un output diverso.
Il precedente esempio di codice ha inviato la richiesta di generazione al modello predefinito, che hai specificato durante la configurazione dell'istanza Genkit.
Puoi anche specificare un modello per una singola chiamata genkit.Generate()
:
resp, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-2.5-pro"),
ai.WithPrompt("Invent a menu item for a pirate themed restaurant."),
)
Un identificatore di stringa del modello ha il seguente aspetto: providerid/modelid
, dove l'ID fornitore (in questo caso googleai
) identifica il plug-in e l'ID modello è un identificatore di stringa specifico del plug-in per una versione specifica di un modello.
Questi esempi illustrano anche un punto importante: quando utilizzi genkit.Generate()
per effettuare chiamate ai modelli di IA generativa, cambiare il modello che vuoi utilizzare è semplicemente una questione di passaggio di un valore diverso al parametro del modello. Se utilizzi genkit.Generate()
anziché gli SDK dei modelli nativi, hai la flessibilità di utilizzare più facilmente diversi modelli nella tua app e di cambiarli in futuro.
Finora hai visto solo esempi delle chiamate genkit.Generate()
più semplici.
Tuttavia, genkit.Generate()
fornisce anche un'interfaccia per interazioni più avanzate con i modelli generativi, che vedrai nelle sezioni che seguono.
Prompt di sistema
Alcuni modelli supportano la fornitura di un prompt di sistema, che fornisce al modello le istruzioni su come vuoi che risponda ai messaggi dell'utente. Puoi utilizzare il prompt di sistema per specificare una persona che vuoi che il modello adotti, il tono delle sue risposte, il formato delle sue risposte e così via.
Se il modello in uso supporta i prompt di sistema, puoi fornirne uno con l'opzione WithSystem()
:
resp, err := genkit.Generate(ctx, g,
ai.WithSystem("You are a food industry marketing consultant."),
ai.WithPrompt("Invent a menu item for a pirate themed restaurant."),
)
Per i modelli che non supportano i prompt di sistema, WithSystem()
li simula modificando la richiesta in modo che assomigli a un prompt di sistema.
Parametri del modello
La funzione genkit.Generate()
accetta un'opzione WithConfig()
, tramite la quale puoi specificare impostazioni facoltative che controllano il modo in cui il modello genera i contenuti:
resp, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-2.0-flash"),
ai.WithPrompt("Invent a menu item for a pirate themed restaurant."),
ai.WithConfig(&googlegenai.GeminiConfig{
MaxOutputTokens: 500,
StopSequences: ["<end>", "<fin>"],
Temperature: 0.5,
TopP: 0.4,
TopK: 50,
}),
)
I parametri esatti supportati dipendono dal singolo modello e dall'API del modello. Tuttavia, i parametri nell'esempio precedente sono comuni a quasi tutti i modelli. Di seguito è riportata una spiegazione di questi parametri:
Parametri che controllano la lunghezza dell'output
MaxOutputTokens
Gli LLM operano su unità chiamate token. Un token in genere, ma non necessariamente, viene mappato a una sequenza specifica di caratteri. Quando passi un prompt a un modello, uno dei primi passaggi consiste nel tokenizzare la stringa del prompt in una sequenza di token. L'LLM genera quindi una sequenza di token dall'input tokenizzato. Infine, la sequenza di token viene convertita di nuovo in testo, che è l'output.
Il parametro Token di output massimi imposta semplicemente un limite al numero di token da generare utilizzando l'LLM. Ogni modello utilizza potenzialmente un tokenizzatore diverso, ma una buona regola empirica è considerare una singola parola inglese composta da 2-4 token.
Come affermato in precedenza, alcuni token potrebbero non essere mappati a sequenze di caratteri. Un esempio di questo tipo è che spesso esiste un token che indica la fine della sequenza: quando un LLM genera questo token, smette di generarne altri. Pertanto, è possibile e spesso accade che un LLM generi meno token rispetto al massimo perché ha generato il token "stop".
StopSequences
Puoi utilizzare questo parametro per impostare i token o le sequenze di token che, se generati, indicano la fine dell'output dell'LLM. I valori corretti da utilizzare qui in genere dipendono da come è stato addestrato il modello e di solito vengono impostati dal plug-in del modello. Tuttavia, se hai chiesto al modello di generare un'altra sequenza di fermate, puoi specificarla qui.
Tieni presente che stai specificando sequenze di caratteri e non token in sé. Nella maggior parte dei casi, specificherai una sequenza di caratteri che lo tokenizer del modello mappa a un singolo token.
Parametri che controllano "creativity"
I parametri temperature, top-p e top-k controllano insieme il livello di "creatività" del modello. Di seguito sono riportate spiegazioni molto brevi del significato di questi parametri, ma il punto più importante da ricordare è che questi parametri vengono utilizzati per regolare il carattere dell'output di un modello LLM. I valori ottimali dipendono dai tuoi obiettivi e dalle tue preferenze e probabilmente possono essere trovati solo tramite la sperimentazione.
Temperatura
Gli LLM sono essenzialmente macchine di previsione dei token. Per una determinata sequenza di token (come il prompt), un LLM prevede, per ogni token nel suo vocabolario, la probabilità che il token sia successivo nella sequenza. La temperatura è un coefficiente di scala per cui queste previsioni vengono divise prima di essere normalizzate a una probabilità compresa tra 0 e 1.
I valori di temperatura bassi, compresi tra 0,0 e 1,0, amplificano la differenza di probabilità tra i token, con il risultato che il modello avrà meno probabilità di produrre un token che ha già valutato come improbabile. Ciò viene spesso percepito come un output meno creativo. Anche se tecnicamente 0, 0 non è un valore valido, molti modelli lo considerano come un'indicazione del fatto che il modello deve comportarsi in modo deterministico e considerare solo il token più probabile.
I valori di temperatura elevati, ovvero quelli maggiori di 1, comprimono le differenze di probabilità tra i token, con il risultato che il modello diventa più propenso a produrre token che in precedenza aveva valutato come improbabili. Ciò viene spesso percepito come un risultato più creativo. Alcune API di modelli impongono una temperatura massima, spesso 2.0.
TopP
Top-p è un valore compreso tra 0,0 e 1,0 che controlla il numero di possibili token che vuoi che il modello prenda in considerazione, specificando la probabilità cumulativa dei token. Ad esempio, un valore pari a 1,0 significa prendere in considerazione ogni possibile token (tenendo comunque conto della probabilità di ciascun token). Un valore di 0,4 significa considerare solo i token più probabili, le cui probabilità si sommano a 0,4, ed escludere i token rimanenti.
TopK
Top-K è un valore intero che controlla anche il numero di token possibili che vuoi che il modello prenda in considerazione, ma questa volta specificando esplicitamente il numero massimo di token. Se specifichi un valore pari a 1, il modello deve comportarsi in modo deterministico.
Sperimenta con i parametri del modello
Puoi sperimentare l'effetto di questi parametri sull'output generato
da diverse combinazioni di modelli e prompt utilizzando l'interfaccia utente per gli sviluppatori. Avvia l'interfaccia utente per gli sviluppatori con il comando genkit start
e verranno caricati automaticamente tutti i modelli definiti dai plug-in configurati nel progetto. Puoi provare rapidamente diversi prompt e valori di configurazione senza dover apportare ripetutamente queste modifiche al codice.
Accoppia il modello con la relativa configurazione
Poiché ogni provider o anche un modello specifico può avere il proprio schema di configurazione o garantire determinate impostazioni, potrebbe essere soggetto a errori impostare opzioni separate utilizzando WithModelName()
e WithConfig()
, poiché quest'ultimo non è fortemente tipizzato per il primo.
Per accoppiare un modello con la relativa configurazione, puoi creare un riferimento al modello da passare alla chiamata generate:
model := googlegenai.GoogleAIModelRef("gemini-2.0-flash", &googlegenai.GeminiConfig{
MaxOutputTokens: 500,
StopSequences: ["<end>", "<fin>"],
Temperature: 0.5,
TopP: 0.4,
TopK: 50,
})
resp, err := genkit.Generate(ctx, g,
ai.WithModel(model),
ai.WithPrompt("Invent a menu item for a pirate themed restaurant."),
)
if err != nil {
log.Fatal(err)
}
Il costruttore del riferimento del modello imporrà che venga fornito il tipo di configurazione corretto, il che potrebbe ridurre le mancate corrispondenze.
Output strutturato
Quando utilizzi l'IA generativa come componente della tua applicazione, spesso vuoi un output in un formato diverso dal testo normale. Anche se stai solo generando contenuti da mostrare all'utente, puoi trarre vantaggio dall'output strutturato semplicemente per presentarli in modo più accattivante. Tuttavia, per applicazioni più avanzate dell'IA generativa, come l'utilizzo programmatico dell'output del modello o l'alimentazione dell'output di un modello in un altro, l'output strutturato è un must.
In Genkit, puoi richiedere un output strutturato da un modello specificando un tipo di output quando chiami genkit.Generate()
:
type MenuItem struct {
Name string `json:"name"`
Description string `json:"description"`
Calories int `json:"calories"`
Allergens []string `json:"allergens"`
}
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("Invent a menu item for a pirate themed restaurant."),
ai.WithOutputType(MenuItem{}),
)
if err != nil {
log.Fatal(err) // One possible error is that the response does not conform to the type.
}
I tipi di output del modello sono specificati come schema JSON utilizzando il pacchetto
invopop/jsonschema
. Questo
fornisce il controllo dei tipi di runtime, che colma il divario tra i tipi Go statici
e l'output imprevedibile dei modelli di IA generativa. Questo sistema ti consente di scrivere codice che può fare affidamento sul fatto che una chiamata generate andata a buon fine restituirà sempre un output conforme ai tuoi tipi Go.
Quando specifichi un tipo di output in genkit.Generate()
, Genkit esegue diverse operazioni dietro le quinte:
- Amplia il prompt con ulteriori indicazioni sul formato di output preferito. Questo ha anche l'effetto collaterale di specificare al modello esattamente quali contenuti vuoi generare (ad esempio, non solo suggerire un elemento del menu, ma anche generare una descrizione, un elenco di allergeni e così via).
- Verifica che l'output sia conforme allo schema.
- Esegue il marshalling dell'output del modello in un tipo Go.
Per ottenere un output strutturato da una chiamata generate andata a buon fine, chiama Output()
sulla risposta del modello con un valore vuoto del tipo:
var item MenuItem
if err := resp.Output(&item); err != nil {
log.Fatalf(err)
}
log.Printf("%s (%d calories, %d allergens): %s\n",
item.Name, item.Calories, len(item.Allergens), item.Description)
In alternativa, puoi utilizzare genkit.GenerateData()
per una chiamata più concisa:
item, resp, err := genkit.GenerateData[MenuItem](ctx, g,
ai.WithPrompt("Invent a menu item for a pirate themed restaurant."),
)
if err != nil {
log.Fatal(err)
}
log.Printf("%s (%d calories, %d allergens): %s\n",
item.Name, item.Calories, len(item.Allergens), item.Description)
Questa funzione richiede il parametro di tipo di output, ma imposta automaticamente l'opzione WithOutputType()
e chiama resp.Output()
prima di restituire il valore.
Gestione degli errori
Nell'esempio precedente, tieni presente che la chiamata genkit.Generate()
può generare un
errore. Un possibile errore può verificarsi quando il modello non riesce a generare un output conforme allo schema. La strategia migliore per gestire questi errori dipende dal caso d'uso specifico, ma di seguito sono riportati alcuni suggerimenti generali:
Prova un altro modello. Affinché l'output strutturato vada a buon fine, il modello deve essere in grado di generare output in JSON. I modelli LLM più potenti come Gemini sono abbastanza versatili per farlo; tuttavia, i modelli più piccoli, come alcuni dei modelli locali che utilizzeresti con Ollama, potrebbero non essere in grado di generare un'uscita strutturata in modo affidabile, a meno che non siano stati addestrati specificamente per farlo.
Semplifica lo schema. Gli LLM potrebbero avere difficoltà a generare tipi complessi o nidificati in modo approfondito. Prova a utilizzare nomi chiari, meno campi o una struttura appiattita se non riesci a generare dati strutturati in modo affidabile.
Riprova a chiamare
genkit.Generate()
. Se il modello che hai scelto raramente non riesce a generare un output conforme, puoi trattare l'errore come faresti con un errore di rete e riprovare semplicemente la richiesta utilizzando una sorta di strategia di back-off incrementale.
Streaming
Quando generi grandi quantità di testo, puoi migliorare l'esperienza degli utenti presentando l'output man mano che viene generato, ovvero in streaming. Un esempio familiare di streaming in azione può essere visto nella maggior parte delle app di chat LLM: gli utenti possono leggere la risposta del modello al loro messaggio durante la generazione, il che migliora la reattività percepita dell'applicazione e migliora la illusione di chattare con una controparte intelligente.
In Genkit, puoi trasmettere in streaming l'output utilizzando l'opzione WithStreaming()
:
resp, err := genkit.Generate(ctx, g,
ai.WithPrompt("Suggest a complete menu for a pirate themed restaurant."),
ai.WithStreaming(func(ctx context.Context, chunk *ai.ModelResponseChunk) error {
// Do something with the chunk...
log.Println(chunk.Text())
return nil
}),
)
if err != nil {
log.Fatal(err)
}
log.Println(resp.Text())
Input multimodale
Gli esempi che hai visto finora hanno utilizzato stringhe di testo come prompt del modello. Anche se rimane il modo più comune per fornire prompt ai modelli di IA generativa, molti modelli possono anche accettare altri contenuti multimediali come prompt. I prompt multimediali vengono utilizzati più spesso in combinazione con prompt di testo che chiedono al modello di eseguire alcune operazioni sui contenuti multimediali, ad esempio aggiungere una didascalia a un'immagine o trascrivere una registrazione audio.
La possibilità di accettare input multimediali e i tipi di contenuti multimediali che puoi utilizzare dipendono completamente dal modello e dalla relativa API. Ad esempio, la serie di modelli Gemini 2.0 può accettare immagini, video e audio come prompt.
Per fornire un prompt multimediale a un modello che lo supporta, anziché passare un semplice prompt di testo a genkit.Generate()
, passa un array costituito da una parte multimediale e una parte di testo:
resp, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-2.0-flash"),
ai.WithMessages(
NewUserMessage(
NewMediaPart("image/jpeg", "https://example.com/photo.jpg"),
NewTextPart("Compose a poem about this image."),
),
),
)
Nell'esempio precedente, hai specificato un'immagine utilizzando un URL HTTPS accessibile pubblicamente. Puoi anche passare i dati multimediali direttamente codificandoli come URL di dati. Ad esempio:
image, err := ioutil.ReadFile("photo.jpg")
if err != nil {
log.Fatal(err)
}
resp, err := genkit.Generate(ctx, g,
ai.WithModelName("googleai/gemini-2.0-flash"),
ai.WithMessages(
NewUserMessage(
NewMediaPart("image/jpeg", "data:image/jpeg;base64," + base64.StdEncoding.EncodeToString(image)),
NewTextPart("Compose a poem about this image."),
),
),
)
Tutti i modelli che supportano l'input di contenuti multimediali supportano sia gli URL di dati sia gli URL HTTPS. Alcuni plug-in dei modelli aggiungono il supporto di altre origini multimediali. Ad esempio, il plug-in Vertex AI consente anche di utilizzare gli URL di Cloud Storage (gs://
).
Passaggi successivi
Scopri di più su Genkit
- In qualità di sviluppatore di app, il modo principale per influenzare l'output dei modelli di IA generativa è tramite i prompt. Leggi Gestire i prompt con Dotprompt per scoprire come Genkit ti aiuta a sviluppare prompt efficaci e a gestirli nel tuo codebase.
- Sebbene
genkit.Generate()
sia il nucleo di ogni applicazione basata sull'IA generativa, le applicazioni reali di solito richiedono un lavoro aggiuntivo prima e dopo l'invocazione di un modello di IA generativa. Per riflettere questo aspetto, Genkit introduce il concetto di flussi, che sono definiti come funzioni, ma aggiungono funzionalità aggiuntive come l'osservabilità e il deployment semplificato. Per scoprire di più, consulta Definire i flussi di lavoro di IA.
Utilizzo avanzato di LLM
- Un modo per migliorare le funzionalità degli LLM è fornire loro un elenco di modi in cui possono chiederti maggiori informazioni o chiederti di eseguire un'azione. Questa operazione è nota come chiamata di strumenti o chiamata di funzioni. I modelli addestrati per supportare questa funzionalità possono rispondere a un prompt con una risposta formattata in modo speciale, che indica all'applicazione chiamante di eseguire un'azione e inviare il risultato all'LLM insieme al prompt originale. Genkit ha funzioni di libreria che automatizzano sia la generazione di prompt sia gli elementi del loop di chiamata e risposta dell'implementazione di una chiamata dello strumento. Per saperne di più, consulta Chiamate di strumenti.
- La generazione basata sul recupero (RAG) è una tecnica utilizzata per introdurre informazioni specifiche del dominio nell'output di un modello. Questo viene ottenuto inserendo informazioni pertinenti in un prompt prima di trasmetterle al modello linguistico. Un'implementazione completa di RAG richiede l'unione di diverse tecnologie: modelli di generazione di embedding di testo, database vettoriali e modelli linguistici di grandi dimensioni. Consulta la sezione Retrieval-Augmented Generation (RAG) per scoprire come Genkit semplifica il processo di coordinamento di questi vari elementi.