Esistono diverse categorie di informazioni che uno sviluppatore che lavora con un LLM potrebbe gestire contemporaneamente:
- Input: informazioni direttamente pertinenti per guidare la risposta dell'LLM per una determinata chiamata. Un esempio è il testo da riepilogare.
- Contesto di generazione: informazioni pertinenti per l'LLM, ma non specifiche per la chiamata. Un esempio è l'ora corrente o il nome di un utente.
- Contesto di esecuzione:informazioni importanti per il codice che circonda la chiamata all'LLM, ma non per l'LLM stesso. Un esempio è il token di autenticazione corrente di un utente.
Genkit fornisce un oggetto context
coerente che può propagare il contesto di generazione e
esecuzione durante il processo. Questo contesto è reso disponibile per tutte le azioni, inclusi flussi, strumenti e
prompt.
Il contesto viene propagato automaticamente a tutte le azioni chiamate nell'ambito dell'esecuzione: il contesto passato a un flusso viene reso disponibile per i prompt eseguiti all'interno del flusso. Il contesto passato al metodo generate()
è disponibile per gli strumenti chiamati all'interno del ciclo di generazione.
Perché il contesto è importante?
Come best practice, devi fornire all'LLM la quantità minima di informazioni necessarie per completare un'attività. Questo è importante per diversi motivi:
- Meno informazioni estranee ha l'LLM, più è probabile che svolga bene la sua attività.
- Se un modello LLM deve trasmettere informazioni come ID utente o account a strumenti, potrebbe essere indotto a divulgare informazioni.
Il contesto fornisce un canale secondario di informazioni che può essere utilizzato da qualsiasi codice, ma non deve necessariamente essere inviato all'LLM. Ad esempio, può consentirti di limitare le query dello strumento all'ambito disponibile dell'utente corrente.
Struttura del contesto
Il contesto deve essere un oggetto, ma puoi decidere quali proprietà includere. In alcune situazioni, Genkit compila automaticamente il contesto. Ad esempio, quando utilizzi le sessioni permanenti, la proprietà state
viene aggiunta automaticamente al contesto.
Uno degli utilizzi più comuni del contesto è memorizzare informazioni sull'utente corrente. Ti consigliamo di aggiungere il contesto di autenticazione nel seguente formato:
{
auth: {
uid: "...", // the user's unique identifier
token: {...}, // the decoded claims of a user's id token
rawToken: "...", // the user's raw encoded id token
// ...any other fields
}
}
L'oggetto contesto può memorizzare tutte le informazioni che potresti dover conoscere altrove nel flusso di esecuzione.
Utilizzare il contesto in un'azione
Per utilizzare il contesto all'interno di un'azione, puoi accedere all'helper per il contesto fornito automaticamente alla definizione della funzione:
Flusso
const summarizeHistory = ai.defineFlow({
name: 'summarizeMessages',
inputSchema: z.object({friendUid: z.string()}),
outputSchema: z.string();
}, async ({friendUid}, {context}) => {
if (!context.auth?.uid) throw new Error("Must supply auth context.");
const messages = await listMessagesBetween(friendUid, context.auth.uid);
const {text} = await ai.generate({
prompt:
`Summarize the content of these messages: ${JSON.stringify(messages)}`,
});
return text;
});
Strumento
const searchNotes = ai.defineTool({
name: 'searchNotes',
description: "search the current user's notes for info",
inputSchema: z.object({query: z.string()}),
outputSchmea: z.array(NoteSchema);
}, async ({query}, {context}) => {
if (!context.auth?.uid) throw new Error("Must be called by a signed-in user.");
return searchUserNotes(context.auth.uid, query);
});
File dei prompt
Quando utilizzi i modelli Dotprompt, il contesto viene reso disponibile con il prefisso della variabile @
. Ad esempio, è possibile accedere a un oggetto di contesto di {auth: {name: 'Michael'}}
nel modello di prompt nel seguente modo:
---
input:
schema:
pirateStyle?: boolean
---
{{#if pirateStyle}}
Avast, {{@auth.name}}, how be ye today?
{{else}}
Hello, {{@auth.name}}, how are you today?
{{/if}}
Fornire il contesto in fase di esecuzione
Per fornire il contesto a un'azione, devi passare l'oggetto di contesto come opzione quando chiami l'azione.
Flussi
const summarizeHistory = ai.defineFlow(/* ... */);
const summary = await summarizeHistory(friend.uid, {context: {auth: currentUser}});
Generazione
const {text} = await ai.generate({
prompt: "Find references to ocelots in my notes.",
// the context will propagate to tool calls
tools: [searchNotes],
context: {auth: currentUser},
});
Prompt
const helloPrompt = ai.prompt('sayHello');
helloPrompt({pirateStyle: true}, {context: {auth: currentUser}});
Propagazione e sostituzioni del contesto
Per impostazione predefinita, quando fornisci il contesto, questo viene propagato automaticamente a tutte le azioni chiamate a seguito della chiamata originale. Se il flusso chiama altri flussi o la generazione chiama strumenti, viene fornito lo stesso contesto.
Se vuoi eseguire l'override del contesto all'interno di un'azione, puoi passare un oggetto contesto diverso per sostituire quello esistente:
const otherFlow = ai.defineFlow(/* ... */);
const myFlow = ai.defineFlow({
// ...
}, (input, {context}) => {
// override the existing context completely
otherFlow({/*...*/}, {context: {newContext: true}});
// or selectively override
otherFlow({/*...*/}, {context: {...context, updatedContext: true}});
});
Quando il contesto viene sostituito, si propaga nello stesso modo. In questo esempio, tutte le azioni chiamate da otherFlow
durante l'esecuzione erediteranno il contesto sostituito.