Firebase Genkit bietet das Dotprompt-Plug-in und das Textformat, mit denen Sie generative AI-Prompts schreiben und organisieren können.
Dotprompt basiert auf der Prämisse, dass Prompts Code sind. Sie schreiben und verwalten Ihre Prompts in speziell formatierten Dateien, sogenannten Dotprompt-Dateien, verfolgen Änderungen daran mit demselben Versionskontrollsystem, das Sie für Ihren Code verwenden, und stellen sie zusammen mit dem Code bereit, der Ihre generativen KI-Modelle aufruft.
Wenn Sie Dotprompt verwenden möchten, erstellen Sie zuerst ein prompts
-Verzeichnis im Stammverzeichnis Ihres Projekts und dann eine .prompt
-Datei in diesem Verzeichnis. Hier ist ein einfaches Beispiel,
kann greeting.prompt
aufrufen:
---
model: vertexai/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}}.
Installieren Sie das Plug-in dotprompt
, um diesen Prompt zu verwenden:
go get github.com/firebase/genkit/go/plugins/dotprompt
Laden Sie dann den Prompt mit Open
:
import "github.com/firebase/genkit/go/plugins/dotprompt"
dotprompt.SetDirectory("prompts")
prompt, err := dotprompt.Open("greeting")
Sie können die Generate
-Methode des Prompts aufrufen, um die Vorlage zu rendern und in einem Schritt an die Modell-API zu übergeben:
ctx := context.Background()
// Default to the project in GCLOUD_PROJECT and the location "us-central1".
vertexai.Init(ctx, nil)
// The .prompt file specifies vertexai/gemini-1.5-flash, which is
// automatically defined by Init(). However, if it specified a model that
// isn't automatically loaded (such as a specific version), you would need
// to define it here:
// vertexai.DefineModel("gemini-1.0-pro-002", &ai.ModelCapabilities{
// Multiturn: true,
// Tools: true,
// SystemRole: true,
// Media: false,
// })
type GreetingPromptInput struct {
Location string `json:"location"`
Style string `json:"style"`
Name string `json:"name"`
}
response, err := prompt.Generate(
ctx,
&dotprompt.PromptRequest{
Variables: GreetingPromptInput{
Location: "the beach",
Style: "a fancy pirate",
Name: "Ed",
},
},
nil,
)
if err != nil {
return err
}
fmt.Println(response.Text())
Oder Sie rendern die Vorlage einfach in einen String:
renderedPrompt, err := prompt.RenderText(map[string]any{
"location": "a restaurant",
"style": "a pirate",
})
Die Syntax von Dotprompt basiert auf der Handlebars-Templatesprache. Mit den Helfern if
, unless
und each
können Sie Ihrem Prompt bedingte Teile hinzufügen oder strukturierte Inhalte iterieren. Das Dateiformat verwendet YAML-Frontmatter, um Metadaten für einen Prompt inline in der Vorlage bereitzustellen.
Eingabe-/Ausgabeschemas mit Picoschema definieren
Dotprompt enthält ein kompaktes, YAML-basiertes Schemadefinitionsformat namens Picoschema, um die Definition der wichtigsten Attribute eines Schemas zu erleichtern für die LLM-Nutzung. Hier ein Beispiel eines Schemas für einen Artikel:
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 dem folgenden JSON-Schema:
{
"properties": {
"metadata": {
"properties": {
"updatedAt": {
"type": "string",
"description": "ISO timestamp of last update"
},
"approvedBy": {
"type": "integer",
"description": "id of approver"
}
},
"type": "object"
},
"title": {
"type": "string"
},
"subtitle": {
"type": "string"
},
"draft": {
"type": "boolean",
"description": "true when in draft state"
},
"date": {
"type": "string",
"description": "the date of publication e.g. '2024-04-09'"
},
"tags": {
"items": {
"type": "string"
},
"type": "array",
"description": "relevant tags for article"
},
"authors": {
"items": {
"properties": {
"name": {
"type": "string"
},
"email": {
"type": "string"
}
},
"type": "object",
"required": ["name"]
},
"type": "array"
}
},
"type": "object",
"required": ["title", "date", "tags", "authors"]
}
Picoschema unterstützt die skalaren Typen string
, integer
, number
, boolean
und any
.
Bei Objekten, Arrays und Enumerationen werden sie in Klammern nach dem Feldnamen angegeben.
Von Picoschema definierte Objekte haben alle erforderlichen Eigenschaften, sofern nicht als optional gekennzeichnet
von ?
und lassen keine zusätzlichen Eigenschaften zu. Wenn eine Property als optional gekennzeichnet ist, wird sie auch als „nullable“ (null zulässig) festgelegt, damit LLMs flexibler Null zurückgeben können, anstatt ein Feld auszulassen.
In einer Objektdefinition kann der Spezialschlüssel (*)
verwendet werden, um einen „Platzhalter“ zu deklarieren
Felddefinition. Dadurch werden alle zusätzlichen Properties abgeglichen, die nicht über einen expliziten Schlüssel angegeben wurden.
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
Prompt-Metadaten überschreiben
Mit .prompt
-Dateien können Sie Metadaten wie die Modellkonfiguration in
in der Datei selbst können Sie diese Werte auch für jeden Aufruf überschreiben:
// Make sure you set up the model you're using.
vertexai.DefineModel("gemini-1.5-flash", nil)
response, err := prompt.Generate(
context.Background(),
&dotprompt.PromptRequest{
Variables: GreetingPromptInput{
Location: "the beach",
Style: "a fancy pirate",
Name: "Ed",
},
Model: "vertexai/gemini-1.5-flash",
Config: &ai.GenerationCommonConfig{
Temperature: 1.0,
},
},
nil,
)
Prompts für mehrere Nachrichten
Standardmäßig erstellt Dotprompt eine einzelne Nachricht mit der Rolle "user"
. Einige
Prompts lassen sich am besten in einer Kombination aus mehreren Nachrichten wie
Systemaufforderung.
Mit dem Helper {{role}}
können Sie ganz einfach Prompts für mehrere 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 wie Bilder neben Text unterstützen, 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 lauten:
dotprompt.SetDirectory("prompts")
describeImagePrompt, err := dotprompt.Open("describe_image")
if err != nil {
return err
}
imageBytes, err := os.ReadFile("img.jpg")
if err != nil {
return err
}
encodedImage := base64.StdEncoding.EncodeToString(imageBytes)
dataURI := "data:image/jpeg;base64," + encodedImage
type DescribeImagePromptInput struct {
PhotoUrl string `json:"photo_url"`
}
response, err := describeImagePrompt.Generate(
context.Background(),
&dotprompt.PromptRequest{Variables: DescribeImagePromptInput{
PhotoUrl: dataURI,
}},
nil,
)
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 Versionen von Prompts nur vollständig in einer der Produktionsumgebung mit vorhandenen Versionen vergleichen. Dotprompt-Unterstützung Varianten
Wenn Sie eine Variante erstellen möchten, erstellen Sie eine [name].[variant].prompt
-Datei. Wenn beispielsweise
Sie haben Gemini 1.5 Flash in Ihrem Prompt verwendet, wollten aber wissen, ob Gemini 1.5
Pro würde eine bessere Leistung erzielen, wenn Sie zwei Dateien erstellen:
my_prompt.prompt
: die „Baseline“ Aufforderungmy_prompt.geminipro.prompt
: eine Variante namens „geminipro“
Wenn Sie eine Promptvariante verwenden möchten, geben Sie sie beim Laden an:
describeImagePrompt, err := dotprompt.OpenVariant("describe_image", "geminipro")
Der Prompt-Lademechanismus versucht, die Variante dieses Namens zu laden, und greift auf die Baseline zurück, falls keine vorhanden ist. Sie können also bedingtes Laden nutzen, die für Ihre Bewerbung sinnvoll sind:
var myPrompt *dotprompt.Prompt
var err error
if isBetaTester(user) {
myPrompt, err = dotprompt.OpenVariant("describe_image", "geminipro")
} else {
myPrompt, err = dotprompt.Open("describe_image")
}
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-Inspector vergleichen.