Firebase Genkit には、生成 AI プロンプトの作成と整理に役立つ Dotprompt プラグインとテキスト形式が用意されています。
Dotprompt は、「プロンプトはコードである」という考え方で設計されています。プロンプトは、dotprompt ファイルと呼ばれる特別な形式のファイルで作成、管理します。そして、コードに使用するのと同じバージョン管理システムを使用してプロンプトの変更を追跡し、生成 AI モデルを呼び出すコードとともにデプロイします。
Dotprompt を使用するには、まずプロジェクトのルートに prompts
ディレクトリを作成し、そのディレクトリに .prompt
ファイルを作成します。greeting.prompt
を呼び出す簡単な例を次に示します。
---
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}}.
このプロンプトを使用するには、dotprompt
プラグインをインストールします。
go get github.com/firebase/genkit/go/plugins/dotprompt
次に、Open
を使用してプロンプトを読み込みます。
import "github.com/firebase/genkit/go/plugins/dotprompt"
dotprompt.SetDirectory("prompts")
prompt, err := dotprompt.Open("greeting")
プロンプトの Generate
メソッドを呼び出すと、1 つのステップで、テンプレートからの生成を行い、結果をモデル API に渡すことができます。
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())
または、テンプレートから文字列を生成します。
renderedPrompt, err := prompt.RenderText(map[string]any{
"location": "a restaurant",
"style": "a pirate",
})
Dotprompt の構文は、Handlebars テンプレート言語をベースにしています。if
、unless
、each
の各ヘルパーを使用すると、条件付きの部分をプロンプトに追加したり、構造化された内容について反復処理したりできます。このファイル形式では、YAML frontmatter を使用して、テンプレートを使いインラインでプロンプトにメタデータを与えます。
Picoschema で入力 / 出力スキーマを定義する
Dotprompt には Picoschema というコンパクトな YAML ベースのスキーマ定義形式が含まれ、これにより、LLM の使用に必要なスキーマの最も重要な属性を簡単に定義できます。記事のスキーマの例を次に示します。
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
上記のスキーマは、次の JSON スキーマと同等です。
{
"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 は、スカラー型の string
、integer
、number
、boolean
、any
をサポートしています。オブジェクト、配列、列挙型については、フィールド名の後に括弧で囲んで記述します。
Picoschema で定義されたオブジェクトは、?
で省略可能と指定されていない限り、すべてのプロパティが必須であり、また追加のプロパティは許可されません。プロパティが省略可能としてマークされている場合、そのプロパティは null 値許容型にもなるため、LLM はフィールドを省略するかわりに null を返すことも可能になります。
オブジェクト定義では、特殊キー (*)
を使用して「ワイルドカード」フィールド定義を宣言できます。これには、明示的なキーで指定されていない任意の追加プロパティがマッチします。
Picoschema は、フルセットの JSON スキーマが持つ多くの機能をサポートしていません。より堅牢なスキーマが必要な場合は、代わりに JSON スキーマで与えることができます。
output:
schema:
type: object
properties:
field1:
type: number
minimum: 20
プロンプト メタデータをオーバーライドする
.prompt
ファイルでは、モデル構成などのメタデータをファイル自体に埋め込むことができますが、これらの値を呼び出しごとにオーバーライドすることもできます。
// 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,
)
複数メッセージのプロンプト
デフォルトでは、Dotprompt は "user"
ロールで単一のメッセージを作成します。システム プロンプトなどのプロンプトは、複数のメッセージを組み合わせて表現するのが最善です。
{{role}}
ヘルパーは、複数のメッセージのプロンプトを作成する簡単な方法を提供します。
---
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}}
マルチモーダル プロンプト
テキストと一緒に画像などのマルチモーダル入力をサポートするモデルでは、{{media}}
ヘルパーを使用できます。
---
model: vertexai/gemini-1.5-flash
input:
schema:
photoUrl: string
---
Describe this image in a detailed paragraph:
{{media url=photoUrl}}
URL には、画像を「インライン」で使用するために、https://
URI または base64 でエンコードされた data:
URI を使用できます。コードでは、次のように記述します。
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,
)
プロンプトのバリアント
プロンプト ファイルはテキストにすぎないため、バージョン管理システムに commit できます(また、そうすべきです)。これにより、変更点を簡単に比較できます。調整されたバージョンのプロンプトは、本番環境で既存のバージョンと同居させた状態でテストする以外に、完全にテストできる方法がない場合がよくあります。Dotprompt は、これを バリアント機能でサポートしています。
バリアントを作成するには、[name].[variant].prompt
ファイルを作成します。たとえば、プロンプトで Gemini 1.5 Flash を使用していて、Gemini 1.5 Pro の方がパフォーマンスが良いかどうかを確認したい場合は、次の 2 つのファイルを作成します。
my_prompt.prompt
: 「ベースライン」のプロンプトmy_prompt.geminipro.prompt
: 「geminipro」という名前のバリアント
プロンプトのバリアントを使用するには、読み込み時にバリアントを指定します。
describeImagePrompt, err := dotprompt.OpenVariant("describe_image", "geminipro")
プロンプト ローダーが、その名前のバリアントを読み込もうとします。存在しない場合は、ベースラインを読み込みます。つまり、アプリに適した条件に基づく条件付き読み込みを使用できます。
var myPrompt *dotprompt.Prompt
var err error
if isBetaTester(user) {
myPrompt, err = dotprompt.OpenVariant("describe_image", "geminipro")
} else {
myPrompt, err = dotprompt.Open("describe_image")
}
バリアント名は生成トレースのメタデータに含まれるため、Genkit トレース インスペクタを使い、バリアント間で実際のパフォーマンスを比較および対比できます。