Firebase Genkit предоставляет плагин Dotprompt и текстовый формат, которые помогут вам писать и организовывать генеративные подсказки ИИ.
Dotprompt разработан на основе предположения, что подсказки — это код . Вы пишете и поддерживаете свои подсказки в файлах специального формата, называемых файлами dotprompt, отслеживаете изменения в них, используя ту же систему контроля версий, которую вы используете для своего кода, и развертываете их вместе с кодом, который вызывает ваши генеративные модели ИИ.
Чтобы использовать 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
приглашения, чтобы отобразить шаблон и передать его в 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 для предоставления метаданных для подсказки, встроенной в шаблон.
Определение схем ввода/вывода с помощью Picoschema
Dotprompt включает компактный формат определения схемы на основе YAML, называемый Picoschema, который упрощает определение наиболее важных атрибутов схемы для использования 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"
. Некоторые подсказки лучше всего выражать в виде комбинации нескольких сообщений, например системное приглашение.
{% verbatim %}{% endverbatim %}
Помощник {% verbatim %}{% endverbatim %}
предоставляет простой способ создания подсказок с несколькими сообщениями:
---
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}}
Мультимодальные подсказки
Для моделей, поддерживающих мультимодальный ввод, например изображения вместе с текстом, вы можете использовать {% verbatim %}{% endverbatim %}
Помощник {% verbatim %}{% endverbatim %}
:
---
model: vertexai/gemini-1.5-flash
input:
schema:
photoUrl: string
---
Describe this image in a detailed paragraph:
{{media url=photoUrl}}
URL-адрес может быть https://
или 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,
)
Подскажите варианты
Поскольку файлы подсказок представляют собой просто текст, вы можете (и должны!) зафиксировать их в своей системе контроля версий, что позволит вам легко сравнивать изменения с течением времени. Зачастую измененные версии подсказок можно полностью протестировать только в производственной среде параллельно с существующими версиями. Dotprompt поддерживает это через функцию вариантов .
Чтобы создать вариант, создайте файл [name].[variant].prompt
. Например, если вы использовали Gemini 1.5 Flash в своем приглашении, но хотели посмотреть, будет ли Gemini 1.5 Pro работать лучше, вы можете создать два файла:
-
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.