Prompt-Engineering ist die primäre Möglichkeit, wie Sie als App-Entwickler die Ausgabe von Modellen mit generativer KI beeinflussen. Wenn Sie beispielsweise LLMs verwenden, können Sie Prompts erstellen, die den Ton, das Format, die Länge und andere Merkmale der Antworten der Modelle beeinflussen.
Wie Sie diese Prompts formulieren, hängt vom verwendeten Modell ab. Ein Prompt, der für ein Modell geschrieben wurde, funktioniert möglicherweise nicht gut, wenn er mit einem anderen Modell verwendet wird. Ebenso wirken sich die von Ihnen festgelegten Modellparameter (Temperatur, Top-K usw.) je nach Modell unterschiedlich auf die Ausgabe aus.
Es ist selten ein einfacher Prozess, alle drei Faktoren – das Modell, die Modellparameter und den Prompt – so zu kombinieren, dass die gewünschte Ausgabe erzielt wird. Oft sind umfangreiche Iterationen und Tests erforderlich. Genkit bietet eine Bibliothek und ein Dateiformat namens Dotprompt, mit dem diese Iteration schneller und einfacher werden soll.
Dotprompt basiert auf der Prämisse, dass Prompts Code sind. Sie definieren Ihre Prompts zusammen mit den Modellen und Modellparametern, für die sie bestimmt sind, getrennt von Ihrem Anwendungscode. Anschließend können Sie (oder vielleicht jemand, der nicht einmal am Schreiben von Anwendungscode beteiligt ist) mithilfe der Genkit-Entwickler-Benutzeroberfläche schnell an den Prompts und Modellparametern iterieren. Sobald Ihre Prompts wie gewünscht funktionieren, können Sie sie in Ihre Anwendung importieren und mit Genkit ausführen.
Ihre Promptdefinitionen müssen jeweils in einer Datei mit der Erweiterung .prompt
gespeichert werden. Hier ein Beispiel für diese Dateien:
---
model: googleai/gemini-1.5-flash
config:
temperature: 0.9
input:
schema:
location: string
style?: string
name?: string
default:
location: a restaurant
---
You are the world's most welcoming AI assistant and are currently working at {{location}}.
Greet a guest{{#if name}} named {{name}}{{/if}}{{#if style}} in the style of {{style}}{{/if}}.
Der Teil zwischen den drei Bindestriche ist YAML-Frontmatter, ähnlich dem Frontmatter-Format, das von GitHub Markdown und Jekyll verwendet wird. Der Rest der Datei ist der Prompt, für den optional Handlebars-Vorlagen verwendet werden können. In den folgenden Abschnitten werden die einzelnen Teile einer .prompt
-Datei und ihre Verwendung genauer beschrieben.
Hinweis
Bevor Sie diese Seite lesen, sollten Sie sich mit den Inhalten auf der Seite Inhalte mit KI-Modellen generieren vertraut gemacht haben.
Wenn Sie die Codebeispiele auf dieser Seite ausführen möchten, führen Sie zuerst die Schritte in der Anleitung Erste Schritte aus. Bei allen Beispielen wird davon ausgegangen, dass Sie Genkit bereits als Abhängigkeit in Ihrem Projekt installiert haben.
Promptdateien erstellen
Dotprompt bietet zwar verschiedene Möglichkeiten zum Erstellen und Laden von Prompts, ist aber für Projekte optimiert, bei denen die Prompts als .prompt
-Dateien in einem einzigen Verzeichnis (oder Unterverzeichnissen davon) organisiert werden. In diesem Abschnitt erfahren Sie, wie Sie mit dieser empfohlenen Einrichtung Prompts erstellen und laden.
Prompt-Verzeichnis erstellen
Die Dotprompt-Bibliothek erwartet, dass Ihre Prompts in einem Verzeichnis im Projektstamm gefunden werden, und lädt alle dort gefundenen Prompts automatisch. Standardmäßig heißt dieses Verzeichnis prompts
. Wenn Sie beispielsweise den Standardverzeichnisnamen verwenden, könnte Ihre Projektstruktur so aussehen:
your-project/
├── lib/
├── node_modules/
├── prompts/
│ └── hello.prompt
├── src/
├── package-lock.json
├── package.json
└── tsconfig.json
Wenn Sie ein anderes Verzeichnis verwenden möchten, können Sie dies bei der Konfiguration von Genkit angeben:
const ai = genkit({
promptDir: './llm_prompts',
// (Other settings...)
});
Promptdatei erstellen
Es gibt zwei Möglichkeiten, eine .prompt
-Datei zu erstellen: mit einem Texteditor oder über die Entwickleroberfläche.
Texteditor verwenden
Wenn Sie eine Promptdatei mit einem Texteditor erstellen möchten, erstellen Sie eine Textdatei mit der Erweiterung .prompt
im Prompts-Verzeichnis, z. B. prompts/hello.prompt
.
Hier ist ein minimales Beispiel für eine Promptdatei:
---
model: vertexai/gemini-1.5-flash
---
You are the world's most welcoming AI assistant. Greet the user and offer your assistance.
Der Teil zwischen den Bindestriche ist YAML-Frontmatter, ähnlich dem Frontmatter-Format, das von GitHub Markdown und Jekyll verwendet wird. Der Rest der Datei ist der Prompt, für den optional Handlebars-Vorlagen verwendet werden können. Der Abschnitt mit den Vorinformationen ist optional, aber die meisten Promptdateien enthalten mindestens Metadaten, die ein Modell angeben. Im Rest dieser Seite erfahren Sie, wie Sie noch mehr herausholen und die Funktionen von Dotprompt in Ihren Promptdateien nutzen.
Entwickler-UI verwenden
Sie können eine Promptdatei auch mit dem Modellausführer in der Entwickler-Benutzeroberfläche erstellen. Beginnen Sie mit Anwendungscode, der die Genkit-Bibliothek importiert und so konfiguriert, dass das gewünschte Modell-Plug-in verwendet wird. Beispiel:
import { genkit } from 'genkit';
// Import the model plugins you want to use.
import { googleAI } from '@genkit-ai/googleai';
const ai = genkit({
// Initialize and configure the model plugins.
plugins: [
googleAI({
apiKey: 'your-api-key', // Or (preferred): export GOOGLE_GENAI_API_KEY=...
}),
],
});
Es ist in Ordnung, wenn die Datei anderen Code enthält, aber der oben genannte Code ist alles, was erforderlich ist.
Laden Sie die Entwickler-Benutzeroberfläche im selben Projekt:
genkit start -- tsx --watch src/your-code.ts
Wählen Sie im Bereich „Modelle“ das gewünschte Modell aus der Liste der vom Plug-in bereitgestellten Modelle aus.
Experimentieren Sie dann mit dem Prompt und der Konfiguration, bis Sie mit den Ergebnissen zufrieden sind. Wenn Sie fertig sind, klicken Sie auf die Schaltfläche „Exportieren“ und speichern Sie die Datei im Prompts-Verzeichnis.
Prompts ausführen
Nachdem Sie Promptdateien erstellt haben, können Sie sie über Ihren Anwendungscode oder mit den von Genkit bereitgestellten Tools ausführen. Unabhängig davon, wie Sie Ihre Prompts ausführen möchten, beginnen Sie zuerst mit dem Anwendungscode, der die Genkit-Bibliothek und die gewünschten Modell-Plug-ins importiert. Beispiel:
import { genkit } from 'genkit';
// Import the model plugins you want to use.
import { googleAI } from '@genkit-ai/googleai';
const ai = genkit({
// Initialize and configure the model plugins.
plugins: [
googleAI({
apiKey: 'your-api-key', // Or (preferred): export GOOGLE_GENAI_API_KEY=...
}),
],
});
Es ist in Ordnung, wenn die Datei anderen Code enthält, aber der oben genannte Code ist alles, was erforderlich ist. Wenn Sie Ihre Prompts in einem anderen Verzeichnis als dem Standardverzeichnis speichern, müssen Sie dies bei der Konfiguration von Genkit angeben.
Prompts über Code ausführen
Wenn Sie einen Prompt verwenden möchten, laden Sie ihn zuerst mit der Methode prompt('file_name')
herunter:
const helloPrompt = ai.prompt('hello');
Nach dem Laden können Sie den Prompt wie eine Funktion aufrufen:
const response = await helloPrompt();
// Alternatively, use destructuring assignments to get only the properties
// you're interested in:
const { text } = await helloPrompt();
Ein aufrufbarer Prompt nimmt zwei optionale Parameter an: die Eingabe für den Prompt (siehe Abschnitt unten zum Angeben von Eingabeschemata) und ein Konfigurationsobjekt, ähnlich wie bei der Methode generate()
. Beispiel:
const response2 = await helloPrompt(
// Prompt input:
{ name: 'Ted' },
// Generation options:
{
config: {
temperature: 0.4,
},
}
);
Alle Parameter, die Sie an den Prompt-Aufruf übergeben, überschreiben die in der Promptdatei angegebenen Parameter.
Beschreibungen der verfügbaren Optionen finden Sie unter Inhalte mit KI-Modellen generieren.
Entwickler-UI verwenden
Während Sie die Prompts Ihrer App optimieren, können Sie sie in der Genkit-Entwickler-UI ausführen, um Prompts und Modellkonfigurationen unabhängig von Ihrem App-Code schnell zu iterieren.
Laden Sie die Entwickler-UI aus Ihrem Projektverzeichnis:
genkit start -- tsx --watch src/your-code.ts
Nachdem Sie Prompts in die Entwickler-UI geladen haben, können Sie sie mit verschiedenen Eingabewerten ausführen und testen, wie sich Änderungen an der Formulierung des Prompts oder an den Konfigurationsparametern auf die Modellausgabe auswirken. Wenn Sie mit dem Ergebnis zufrieden sind, können Sie auf die Schaltfläche Prompt exportieren klicken, um den geänderten Prompt wieder in Ihrem Projektverzeichnis zu speichern.
Modellkonfiguration
Im Block mit den Vorinformationen Ihrer Promptdateien können Sie optional Modellkonfigurationswerte für den Prompt angeben:
---
model: googleai/gemini-1.5-flash
config:
temperature: 1.4
topK: 50
topP: 0.4
maxOutputTokens: 400
stopSequences:
- "<end>"
- "<fin>"
---
Diese Werte werden direkt dem Parameter config
zugeordnet, der vom aufrufbaren Prompt akzeptiert wird:
const response3 = await helloPrompt(
{},
{
config: {
temperature: 1.4,
topK: 50,
topP: 0.4,
maxOutputTokens: 400,
stopSequences: ['<end>', '<fin>'],
},
}
);
Beschreibungen der verfügbaren Optionen finden Sie unter Inhalte mit KI-Modellen generieren.
Eingabe- und Ausgabeschemas
Sie können Eingabe- und Ausgabeschemata für Ihren Prompt angeben, indem Sie sie im Abschnitt „Vorwort“ definieren:
---
model: googleai/gemini-1.5-flash
input:
schema:
theme?: string
default:
theme: "pirate"
output:
schema:
dishname: string
description: string
calories: integer
allergens(array): string
---
Invent a menu item for a {{theme}} themed restaurant.
Diese Schemas werden in etwa so verwendet wie die, die an eine generate()
-Anfrage oder eine Ablaufdefinition übergeben werden. Der oben definierte Prompt liefert beispielsweise folgende strukturierte Ausgabe:
const menuPrompt = ai.prompt('menu');
const { data } = await menuPrompt({ theme: 'medieval' });
const dishName = data['dishname'];
const description = data['description'];
Sie haben mehrere Möglichkeiten, Schemas in einer .prompt
-Datei zu definieren: das eigene Schemadefinitionformat von Dotprompt, Picoschema, das Standard-JSON-Schema oder Verweise auf Schemas, die in Ihrem Anwendungscode definiert sind. In den folgenden Abschnitten werden diese Optionen ausführlicher beschrieben.
Picoschema
Die Schemas im obigen Beispiel sind in einem Format namens Picoschema definiert. Picoschema ist ein kompaktes, für YAML optimiertes Schemadefinitionformat, mit dem sich die wichtigsten Attribute eines Schemas für die Verwendung in der lokalen Verschlüsselung leicht definieren lassen. Hier ein längeres Beispiel für ein Schema, in dem die Informationen angegeben sind, die eine App zu einem Artikel speichern könnte:
schema:
title: string # string, number, and boolean types are defined like this
subtitle?: string # optional fields are marked with a `?`
draft?: boolean, true when in draft state
status?(enum, approval status): [PENDING, APPROVED]
date: string, the date of publication e.g. '2024-04-09' # descriptions follow a comma
tags(array, relevant tags for article): string # arrays are denoted via parentheses
authors(array):
name: string
email?: string
metadata?(object): # objects are also denoted via parentheses
updatedAt?: string, ISO timestamp of last update
approvedBy?: integer, id of approver
extra?: any, arbitrary extra data
(*): string, wildcard field
Das obige Schema entspricht der folgenden TypeScript-Schnittstelle:
interface Article {
title: string;
subtitle?: string | null;
/** true when in draft state */
draft?: boolean | null;
/** approval status */
status?: 'PENDING' | 'APPROVED' | null;
/** the date of publication e.g. '2024-04-09' */
date: string;
/** relevant tags for article */
tags: string[];
authors: {
name: string;
email?: string | null;
}[];
metadata?: {
/** ISO timestamp of last update */
updatedAt?: string | null;
/** id of approver */
approvedBy?: number | null;
} | null;
/** arbitrary extra data */
extra?: any;
/** wildcard field */
}
Picoschema unterstützt die Skalartypen string
, integer
, number
, boolean
und any
. Objekte, Arrays und enums werden nach dem Feldnamen in Klammern angegeben.
Von Picoschema definierte Objekte haben alle erforderlichen Eigenschaften, sofern sie nicht durch ?
als optional gekennzeichnet sind. Zusätzliche Eigenschaften sind nicht zulässig. Wenn eine Property als optional gekennzeichnet ist, wird sie auch als nullable festgelegt, damit LLMs flexibler Null zurückgeben können, anstatt ein Feld auszulassen.
In einer Objektdefinition kann der spezielle Schlüssel (*)
verwendet werden, um eine Platzhalterfelddefinition zu deklarieren. Dadurch werden alle zusätzlichen Properties abgeglichen, die nicht über einen expliziten Schlüssel angegeben wurden.
JSON-Schema
Picoschema unterstützt viele der Funktionen des vollständigen JSON-Schemas nicht. Wenn Sie robustere Schemas benötigen, können Sie stattdessen ein JSON-Schema angeben:
output:
schema:
type: object
properties:
field1:
type: number
minimum: 20
Im Code definierte Zod-Schemas
Sie können Schemas nicht nur direkt in der .prompt
-Datei definieren, sondern auch per Name auf ein bei defineSchema()
registriertes Schema verweisen. Wenn Sie TypeScript verwenden, können Sie mit diesem Ansatz die Funktionen zur statischen Typprüfung der Sprache nutzen, wenn Sie mit Prompts arbeiten.
So registrieren Sie ein Schema:
import { z } from 'genkit';
const MenuItemSchema = ai.defineSchema(
'MenuItemSchema',
z.object({
dishname: z.string(),
description: z.string(),
calories: z.coerce.number(),
allergens: z.array(z.string()),
})
);
Geben Sie in Ihrem Prompt den Namen des registrierten Schemas an:
---
model: googleai/gemini-1.5-flash-latest
output:
schema: MenuItemSchema
---
Die Dotprompt-Bibliothek löst den Namen automatisch in das zugrunde liegende registrierte Zod-Schema auf. Sie können das Schema dann verwenden, um die Ausgabe eines Dotprompts stark zu typisieren:
const menuPrompt = ai.prompt<
z.ZodTypeAny, // Input schema
typeof MenuItemSchema, // Output schema
z.ZodTypeAny // Custom options schema
>('menu');
const { data } = await menuPrompt({ theme: 'medieval' });
// Now data is strongly typed as MenuItemSchema:
const dishName = data?.dishname;
const description = data?.description;
Prompt-Vorlagen
Der Teil einer .prompt
-Datei, der auf den Vorspann (falls vorhanden) folgt, ist der Prompt selbst, der an das Modell übergeben wird. Dieser Prompt kann ein einfacher Textstring sein, aber oft sollten Sie die Nutzereingaben in den Prompt einbinden. Dazu können Sie den Prompt mit der Handlebars-Template-Sprache angeben.
Promptvorlagen können Platzhalter enthalten, die sich auf die Werte beziehen, die im Eingabeschema Ihres Prompts definiert sind.
Sie haben das bereits im Abschnitt zu Eingabe- und Ausgabeschemata gesehen:
---
model: googleai/gemini-1.5-flash
config:
temperature: 1.4
topK: 50
topP: 0.4
maxOutputTokens: 400
stopSequences:
- "<end>"
- "<fin>"
---
In diesem Beispiel wird der Handlebars-Ausdruck {{theme}}
beim Ausführen des Prompts in den Wert der Eigenschaft theme
der Eingabe aufgelöst. Wenn Sie Eingaben an den Prompt übergeben möchten, rufen Sie ihn wie im folgenden Beispiel auf:
const menuPrompt = ai.prompt('menu');
const { data } = await menuPrompt({ theme: 'medieval' });
Da die Eigenschaft theme
im Eingabeschema als optional deklariert und ein Standardwert angegeben wurde, hätten Sie die Eigenschaft auch weglassen können. Der Prompt wäre dann mit dem Standardwert aufgelöst worden.
Handlebars-Vorlagen unterstützen auch einige eingeschränkte logische Konstrukte. Anstatt einen Standardwert anzugeben, können Sie den Prompt beispielsweise mit dem #if
-Helfer von Handlebars definieren:
---
model: googleai/gemini-1.5-flash
input:
schema:
theme?: string
---
Invent a menu item for a {{#if theme}}{{theme}} themed{{/if}} restaurant.
In diesem Beispiel wird der Prompt als „Erfinde einen Menüpunkt für ein Restaurant“ angezeigt, wenn die Property theme
nicht angegeben ist.
Informationen zu allen integrierten logischen Helfern finden Sie in der Handlebars-Dokumentation.
Neben den vom Eingabeschema definierten Properties können Ihre Vorlagen auch auf Werte verweisen, die automatisch von Genkit definiert werden. In den folgenden Abschnitten werden diese automatisch definierten Werte und ihre Verwendung beschrieben.
Prompts für mehrere Nachrichten
Standardmäßig erstellt Dotprompt eine einzelne Nachricht mit der Rolle „Nutzer“. Einige Prompts lassen sich jedoch am besten als Kombination aus mehreren Nachrichten ausdrücken, z. B. ein Systemprompt.
Mit dem {{role}}
-Hilfsprogramm können Sie ganz einfach Prompts mit mehreren Nachrichten erstellen:
---
model: vertexai/gemini-1.5-flash
input:
schema:
userQuestion: string
---
{{role "system"}}
You are a helpful AI assistant that really loves to talk about food. Try to work
food items into all of your conversations.
{{role "user"}}
{{userQuestion}}
Multimodale Prompts
Für Modelle, die multimodale Eingaben unterstützen, z. B. Bilder neben Text, können Sie den Helfer {{media}}
verwenden:
---
model: vertexai/gemini-1.5-flash
input:
schema:
photoUrl: string
---
Describe this image in a detailed paragraph:
{{media url=photoUrl}}
Die URL kann ein https:
- oder ein Base64-codierter data:
-URI für die „Inline“-Bildnutzung sein.
Im Code würde das so aussehen:
const multimodalPrompt = ai.prompt('multimodal');
const { text } = await multimodalPrompt({
photoUrl: 'https://example.com/photo.jpg',
});
Ein Beispiel für die Erstellung einer data:
-URL finden Sie unter Multimodale Eingabe auf der Seite „Modelle“.
Teilrechnungen
Teilvorlagen sind wiederverwendbare Vorlagen, die in jeden Prompt eingefügt werden können. Sie können besonders hilfreich sein, wenn es um ähnliche Prompts mit ähnlichem Verhalten geht.
Beim Laden eines Promptverzeichnisses wird jede Datei, die mit einem Unterstrich (_
) beginnt, als unvollständig betrachtet. Eine Datei _personality.prompt
könnte also Folgendes enthalten:
You should speak like a {{#if style}}{{style}}{{else}}helpful assistant.{{/else}}.
Diese können dann in andere Prompts eingefügt werden:
---
model: googleai/gemini-1.5-flash
input:
schema:
name: string
style?: string
---
{{ role "system" }}
{{>personality style=style}}
{{ role "user" }}
Give the user a friendly greeting.
User's Name: {{name}}
Teilelemente werden mit der {{>NAME_OF_PARTIAL args...}}
-Syntax eingefügt. Wenn für den Teilprompt keine Argumente angegeben werden, wird er mit demselben Kontext wie der übergeordnete Prompt ausgeführt.
Für partielle Vorlagen können sowohl benannte Argumente wie oben als auch ein einzelnes Positionsargument für den Kontext verwendet werden. Das kann für Aufgaben wie das Rendern von Listenelementen hilfreich sein.
_destination.prompt
- {{name}} ({{country}})
chooseDestination.prompt
---
model: googleai/gemini-1.5-flash-latest
input:
schema:
destinations(array):
name: string
country: string
---
Help the user decide between these vacation destinations:
{{#each destinations}}
{{>destination this}}
{{/each}}
Teilseiten im Code definieren
Sie können Teilansichten auch im Code mit definePartial
definieren:
ai.definePartial(
'personality',
'Talk like a {{#if style}}{{style}}{{else}}helpful assistant{{/if}}.'
);
Codedefinierte Teilelemente sind in allen Prompts verfügbar.
Benutzerdefinierte Helpers definieren
Sie können benutzerdefinierte Helfer definieren, um Daten in einem Prompt zu verarbeiten und zu verwalten.
Helfer werden weltweit mit defineHelper
registriert:
ai.defineHelper('shout', (text: string) => text.toUpperCase());
Nachdem Sie einen Helfer definiert haben, können Sie ihn in jedem Prompt verwenden:
---
model: googleai/gemini-1.5-flash
input:
schema:
name: string
---
HELLO, {{shout name}}!!!
Prompt-Varianten
Da Promptdateien nur Text enthalten, können und sollten Sie sie in Ihrem Versionskontrollsystem festschreiben, damit Sie Änderungen im Zeitverlauf ganz einfach vergleichen können. Oft können optimierte Prompt-Versionen nur in einer Produktionsumgebung neben vorhandenen Versionen vollständig getestet werden. Dotprompt unterstützt dies über die Variantefunktion.
Wenn Sie eine Variante erstellen möchten, erstellen Sie eine [name].[variant].prompt
-Datei. Wenn Sie beispielsweise Gemini 1.5 Flash in Ihrem Prompt verwendet haben, aber wissen möchten, ob Gemini 1.5 Pro eine bessere Leistung erzielt, können Sie zwei Dateien erstellen:
my_prompt.prompt
: „baseline“my_prompt.gemini15pro.prompt
: eine Variante mit dem Namengemini15pro
Wenn Sie eine Promptvariante verwenden möchten, geben Sie beim Laden die Variante an:
const myPrompt = ai.prompt('my_prompt', { variant: 'gemini15pro' });
Der Name der Variante ist in den Metadaten der generierten Traces enthalten. So können Sie die tatsächliche Leistung der Varianten im Genkit-Trace-Inspektor vergleichen.
Prompts im Code definieren
Bei allen bisher besprochenen Beispielen wurde davon ausgegangen, dass Ihre Prompts in einzelnen .prompt
-Dateien in einem einzigen Verzeichnis (oder Unterverzeichnissen davon) definiert sind, auf die Ihre App zur Laufzeit zugreifen kann. Dotprompt wurde für diese Konfiguration entwickelt und die Autoren betrachten es als die beste Entwicklungsumgebung insgesamt.
Wenn Sie jedoch Anwendungsfälle haben, die mit dieser Einrichtung nicht gut unterstützt werden, können Sie Prompts auch im Code mithilfe der Funktion definePrompt()
definieren:
Der erste Parameter dieser Funktion entspricht dem Block „Vorwort“ einer .prompt
-Datei. Der zweite Parameter kann entweder ein Handlebars-Vorlagestring wie in einer Promptdatei oder eine Funktion sein, die eine GenerateRequest
zurückgibt:
const myPrompt = ai.definePrompt(
{
name: 'myPrompt',
model: 'googleai/gemini-1.5-flash',
input: {
schema: z.object({
name: z.string(),
}),
},
},
'Hello, {{name}}. How are you today?'
);
const myPrompt = ai.definePrompt(
{
name: 'myPrompt',
model: 'googleai/gemini-1.5-flash',
input: {
schema: z.object({
name: z.string(),
}),
},
},
async (input): Promise<GenerateRequest> => {
return {
messages: [
{
role: 'user',
content: [{ text: `Hello, ${input.name}. How are you today?` }],
},
],
};
}
);