Es gibt verschiedene Kategorien von Informationen, die ein Entwickler, der mit einem LLM arbeitet, gleichzeitig verarbeiten kann:
- Eingabe: Informationen, die direkt für die Antwort des LLM für einen bestimmten Aufruf relevant sind. Ein Beispiel hierfür ist der Text, der zusammengefasst werden soll.
- Generierungskontext:Informationen, die für das LLM relevant, aber nicht für den Anruf spezifisch sind. Ein Beispiel hierfür ist die aktuelle Uhrzeit oder der Name eines Nutzers.
- Ausführungskontext: Informationen, die für den Code um den LLM-Aufruf herum wichtig sind, aber nicht für den LLM selbst. Ein Beispiel hierfür ist das aktuelle Authentifizierungstoken eines Nutzers.
Genkit bietet ein einheitliches context
-Objekt, mit dem der Generierungs- und Ausführungskontext während des gesamten Prozesses weitergegeben werden kann. Dieser Kontext ist für alle Aktionen verfügbar, einschließlich Abläufen, Tools und Prompts.
Der Kontext wird automatisch an alle Aktionen weitergegeben, die im Rahmen der Ausführung aufgerufen werden: Der an einen Ablauf übergebene Kontext wird für Prompts verfügbar gemacht, die im Ablauf ausgeführt werden. Der an die generate()
-Methode übergebene Kontext ist für Tools verfügbar, die innerhalb des Generierungs-Loops aufgerufen werden.
Warum ist Kontext wichtig?
Es empfiehlt sich, dem LLM nur die Mindestmenge an Informationen zur Verfügung zu stellen, die er für die Ausführung einer Aufgabe benötigt. Das ist aus mehreren Gründen wichtig:
- Je weniger irrelevante Informationen das LLM hat, desto wahrscheinlicher ist es, dass es seine Aufgabe gut erledigt.
- Wenn ein LLM Informationen wie Nutzer- oder Konto-IDs an Tools weitergeben muss, kann er dazu gebracht werden, Informationen zu preisgeben.
Kontext bietet einen Informations-Sidechannel, der von Ihrem Code verwendet werden kann, aber nicht unbedingt an den LLM gesendet werden muss. So können Sie beispielsweise Toolabfragen auf den verfügbaren Bereich des aktuellen Nutzers beschränken.
Kontextstruktur
Der Kontext muss ein Objekt sein, aber Sie können seine Properties selbst festlegen. In einigen Fällen wird der Kontext von Genkit automatisch ausgefüllt. Wenn Sie beispielsweise persistente Sitzungen verwenden, wird die Property state
automatisch dem Kontext hinzugefügt.
Eine der häufigsten Verwendungen von Kontext besteht darin, Informationen zum aktuellen Nutzer zu speichern. Wir empfehlen, den Auth-Kontext im folgenden Format hinzuzufügen:
{
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
}
}
Im Kontextobjekt können alle Informationen gespeichert werden, die Sie an anderer Stelle im Ablauf benötigen.
Kontext in einer Aktion verwenden
Wenn Sie den Kontext in einer Aktion verwenden möchten, können Sie auf den Kontext-Hilfs-Assistenten zugreifen, der automatisch in Ihre Funktionsdefinition eingefügt wird:
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;
});
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);
});
Bei Verwendung von Dotprompt-Vorlagen wird der Kontext mit dem Variablenpräfix @
verfügbar gemacht. So könnte beispielsweise in der Promptvorlage auf ein Kontextobjekt von {auth: {name: 'Michael'}}
zugegriffen werden:
---
input:
schema:
pirateStyle?: boolean
---
{{#if pirateStyle}}
Avast, {{@auth.name}}, how be ye today?
{{else}}
Hello, {{@auth.name}}, how are you today?
{{/if}}
Kontext während der Laufzeit angeben
Wenn Sie einer Aktion Kontext geben möchten, übergeben Sie das Kontextobjekt beim Aufrufen der Aktion als Option.
const summarizeHistory = ai.defineFlow(/* ... */);
const summary = await summarizeHistory(friend.uid, {context: {auth: currentUser}});
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},
});
const helloPrompt = ai.prompt('sayHello');
helloPrompt({pirateStyle: true}, {context: {auth: currentUser}});
Kontextweitergabe und ‑überschreibungen
Wenn Sie Kontext angeben, wird dieser standardmäßig automatisch an alle Aktionen weitergegeben, die aufgrund Ihres ursprünglichen Aufrufs aufgerufen werden. Wenn Ihr Ablauf andere Abläufe aufruft oder Ihre Generierung Tools aufruft, wird derselbe Kontext bereitgestellt.
Wenn Sie den Kontext innerhalb einer Aktion überschreiben möchten, können Sie ein anderes Kontextobjekt übergeben, um das vorhandene zu ersetzen:
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}});
});
Wenn der Kontext ersetzt wird, wird er auf die gleiche Weise weitergegeben. In diesem Beispiel würde der überschriebene Kontext von allen Aktionen übernommen, die otherFlow
während der Ausführung aufgerufen hat.