Firebase Genkit предоставляет плагин Dotprompt и текстовый формат, которые помогут вам писать и организовывать генеративные подсказки ИИ.
Dotprompt разработан на основе предположения, что подсказки — это код . Вы пишете и поддерживаете свои подсказки в файлах специального формата, называемых файлами dotprompt, отслеживаете изменения в них, используя ту же систему контроля версий, которую вы используете для своего кода, и развертываете их вместе с кодом, который вызывает ваши генеративные модели ИИ.
Чтобы использовать Dotprompt, сначала создайте каталог prompts
в корне вашего проекта, а затем создайте в этом каталоге файл .prompt
. Вот простой пример, который вы можете назвать greeting.prompt
:
---
model: vertexai/gemini-1.0-pro
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
и импортируйте функцию prompt
из библиотеки @genkit-ai/dotprompt
:
import { dotprompt, prompt } from '@genkit-ai/dotprompt';
configureGenkit({ plugins: [dotprompt()] });
Затем загрузите приглашение, используя prompt('file_name')
:
const greetingPrompt = await prompt('greeting');
const result = await greetingPrompt.generate({
input: {
location: 'the beach',
style: 'a fancy pirate',
},
});
console.log(result.text());
Синтаксис 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
Приведенная выше схема эквивалентна следующему интерфейсу TypeScript:
interface Article {
title: string;
subtitle?: string;
/** true when in draft state */
draft?: boolean;
/** approval status */
status?: 'PENDING' | 'APPROVED';
/** the date of publication e.g. '2024-04-09' */
date: string;
/** relevant tags for article */
tags: string[];
authors: {
name: string;
email?: string;
}[];
metadata?: {
/** ISO timestamp of last update */
updatedAt?: string;
/** id of approver */
approvedBy?: number;
};
}
Пикосхема поддерживает скалярные типы: string
, integer
, number
и boolean
. Для объектов, массивов и перечислений они обозначаются круглыми скобками после имени поля.
Объекты, определенные Picoschema, имеют все требуемые свойства, если не указано иное как ?
и не разрешать дополнительные свойства.
Picoschema не поддерживает многие возможности полной схемы JSON. Если вам нужны более надежные схемы, вы можете вместо этого предоставить схему JSON:
output:
schema:
type: object
properties:
field1:
type: number
minimum: 20
Переопределение метаданных подсказки
Хотя файлы .prompt
позволяют встраивать метаданные, такие как конфигурация модели, в сам файл, вы также можете переопределить эти значения для каждого вызова:
const result = await greetingPrompt.generate({
model: 'google-genai/gemini-pro',
config: {
temperature: 1.0,
},
input: {
location: 'the beach',
style: 'a fancy pirate',
},
});
Структурированный вывод
Вы можете установить формат и схему вывода приглашения для преобразования в JSON:
---
model: vertexai/gemini-1.0-pro
input:
schema:
theme: string
output:
format: json
schema:
name: string
price: integer
ingredients(array): string
---
Generate a menu item that could be found at a {{theme}} themed restaurant.
При создании приглашения со структурированным выводом используйте помощник output()
для его получения и проверки:
const createMenuPrompt = await prompt('create_menu');
const menu = await createMenuPrompt.generate({
input: {
theme: 'banana',
},
});
console.log(menu.output());
Подсказки с несколькими сообщениями
По умолчанию Dotprompt создает одно сообщение с ролью "user"
. Некоторые подсказки лучше всего выражать в виде комбинации нескольких сообщений, например системное приглашение.
Помощник {% verbatim %}{% endverbatim %}
предоставляет простой способ создания подсказок с несколькими сообщениями:
---
model: vertexai/gemini-1.0-pro
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 %}
:
---
model: vertexai/gemini-1.0-pro-vision
input:
schema:
photoUrl: string
---
Describe this image in a detailed paragraph:
{{media url=photoUrl}}
URL-адрес может быть https://
или data:
URI для «встроенного» использования изображений. В коде это будет:
const describeImagePrompt = await prompt('describe_image');
const result = await describeImagePrompt.generate({
input: {
photoUrl: 'https://example.com/image.png',
},
});
console.log(result.text());
Подскажите варианты
Поскольку файлы подсказок представляют собой просто текст, вы можете (и должны!) зафиксировать их в своей системе контроля версий, что позволит вам легко сравнивать изменения с течением времени. Зачастую измененные версии подсказок можно полностью протестировать только в производственной среде параллельно с существующими версиями. Dotprompt поддерживает это через функцию вариантов .
Чтобы создать вариант, создайте файл [name].[variant].prompt
. Например, если вы использовали Gemini 1.0 Pro в своем приглашении, но хотели посмотреть, будет ли Gemini 1.5 Pro работать лучше, вы можете создать два файла:
-
my_prompt.prompt
: «базовое» приглашение -
my_prompt.gemini15.prompt
: вариант под названием «gemini».
Чтобы использовать вариант подсказки, укажите вариант variant
при загрузке:
const myPrompt = await prompt('my_prompt', { variant: 'gemini15' });
Загрузчик приглашений попытается загрузить вариант с этим именем и вернется к базовому состоянию, если такового не существует. Это означает, что вы можете использовать условную загрузку на основе любых критериев, имеющих смысл для вашего приложения:
const myPrompt = await prompt('my_prompt', {
variant: isBetaTester(user) ? 'gemini15' : null,
});
Имя варианта включается в метаданные трассировки генерации, поэтому вы можете сравнивать и сопоставлять фактическую производительность между вариантами в инспекторе трассировки Genkit.
Альтернативные способы загрузки и определения подсказок
Dotprompt оптимизирован для организации в каталоге подсказок. Однако существует несколько других способов загрузки и определения подсказок:
-
loadPromptFile
: загрузить приглашение из файла в каталоге приглашений. -
loadPromptUrl
: загрузить приглашение по URL-адресу. -
defineDotprompt
: Определите подсказку в коде.
Примеры:
import {
loadPromptFile,
loadPromptUrl,
defineDotprompt,
} from '@genkit-ai/dotprompt';
import path from 'path';
import { z } from 'zod';
// Load a prompt from a file
const myPrompt = await loadPromptFile(
path.resolve(__dirname, './path/to/my_prompt.prompt')
);
// Load a prompt from a URL
const myPrompt = await loadPromptUrl('https://example.com/my_prompt.prompt');
// Define a prompt in code
const myPrompt = defineDotprompt(
{
model: 'vertexai/gemini-1.0-pro',
input: {
schema: z.object({
name: z.string(),
}),
},
},
`Hello {{name}}, how are you today?`
);