Firebase Genkit menyediakan plugin Dotprompt dan format teks untuk membantu Anda menulis dan mengatur prompt AI generatif Anda.
Dotprompt dirancang berdasarkan premis bahwa prompt adalah kode. Anda menulis dan mempertahankan prompt Anda dalam file berformat khusus yang disebut file dotprompt, melacak perubahannya menggunakan sistem kontrol versi yang sama dengan yang Anda gunakan untuk kode, dan men-deploy-nya bersama dengan kode yang memanggil model AI generatif.
Untuk menggunakan Dotprompt, buat direktori prompts
terlebih dahulu di root project Anda dan
lalu buat file .prompt
di direktori tersebut. Berikut adalah contoh
sederhana yang mungkin memanggil 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}}.
Untuk menggunakan perintah ini, instal plugin dotprompt
, dan impor fungsi promptRef
dari
library @genkit-ai/dotprompt
:
import { dotprompt, promptRef } from '@genkit-ai/dotprompt';
configureGenkit({ plugins: [dotprompt()] });
Kemudian, muat prompt menggunakan promptRef('file_name')
:
const greetingPrompt = promptRef('greeting');
const result = await greetingPrompt.generate({
input: {
location: 'the beach',
style: 'a fancy pirate',
},
});
console.log(result.text());
Sintaksis titik prompt didasarkan pada bahasa template
Handlebar. Anda dapat menggunakan helper if
, unless
, dan each
untuk menambahkan
bagian kondisional ke prompt Anda atau melakukan iterasi melalui konten terstruktur. Format
file menggunakan frontmatter YAML guna menyediakan metadata untuk prompt yang merupakan bagian dari
template.
Menentukan Skema Input/Output
Dotprompt menyertakan format definisi skema ringkas dan dioptimalkan YAML yang disebut {i>Picoschema<i} untuk memudahkan penentuan atribut terpenting dari suatu skema untuk penggunaan LLM. Berikut contoh skema untuk 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
Skema di atas setara dengan antarmuka TypeScript berikut:
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 mendukung jenis skalar string
, integer
, number
, boolean
, dan any
.
Untuk objek, array, dan enum, semuanya dilambangkan dengan tanda kurung setelah nama kolom.
Objek yang didefinisikan oleh Picoschema memiliki semua properti yang disyaratkan, kecuali dilambangkan sebagai properti opsional
dengan ?
, dan tidak mengizinkan properti tambahan. Ketika sebuah properti ditandai sebagai opsional,
properti tersebut juga dibuat nullable untuk memberikan lebih banyak kemudahan bagi LLM agar menampilkan null daripada
menghilangkan kolom.
Dalam definisi objek, kunci khusus (*)
dapat digunakan untuk mendeklarasikan definisi bidang
"karakter pengganti". Hal ini akan cocok dengan semua properti tambahan yang tidak disediakan oleh
kunci eksplisit.
Picoschema tidak mendukung banyak kemampuan skema JSON lengkap. Jika memerlukan skema yang lebih andal, Anda dapat memberikan Skema JSON:
output:
schema:
type: object
properties:
field1:
type: number
minimum: 20
Memanfaatkan Skema yang Dapat Digunakan Kembali
Selain menentukan skema secara langsung dalam file .prompt
, Anda dapat mereferensikan
skema yang didaftarkan dengan defineSchema
berdasarkan nama. Untuk mendaftarkan skema:
import { defineSchema } from '@genkit-ai/core';
import { z } from 'zod';
const MySchema = defineSchema(
'MySchema',
z.object({
field1: z.string(),
field2: z.number(),
})
);
Dalam prompt, Anda dapat memberikan nama skema terdaftar:
# myPrompt.prompt
---
model: vertexai/gemini-1.5-flash
output:
schema: MySchema
---
Library Dotprompt akan otomatis me-resolve nama ke model skema Zod terdaftar. Anda kemudian dapat memanfaatkan skema tersebut untuk mengetik output Dotprompt:
import { promptRef } from "@genkit-ai/dotprompt";
const myPrompt = promptRef("myPrompt");
const result = await myPrompt.generate<typeof MySchema>({...});
// now strongly typed as MySchema
result.output();
Mengganti Metadata Prompt
Meskipun file .prompt
memungkinkan Anda menyematkan metadata seperti konfigurasi model di
file itu sendiri, Anda juga dapat mengganti nilai-nilai ini per panggilan:
const result = await greetingPrompt.generate({
model: 'vertexai/gemini-1.5-pro',
config: {
temperature: 1.0,
},
input: {
location: 'the beach',
style: 'a fancy pirate',
},
});
Output terstruktur
Anda dapat menetapkan format dan skema output perintah untuk dipaksa masuk ke JSON:
---
model: vertexai/gemini-1.5-flash
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.
Saat membuat perintah dengan output terstruktur, gunakan helper output()
untuk
mengambil dan memvalidasinya:
const createMenuPrompt = promptRef('create_menu');
const menu = await createMenuPrompt.generate({
input: {
theme: 'banana',
},
});
console.log(menu.output());
Kesesuaian output dicapai dengan memasukkan petunjuk tambahan ke dalam
. Secara default, ID ini ditambahkan ke bagian akhir pesan terakhir yang dibuat
oleh prompt. Anda dapat mengubah posisinya secara manual menggunakan {{section "output"}}
.
This is a prompt that manually positions output instructions.
== Output Instructions
{{section "output"}}
== Other Instructions
This will come after the output instructions.
Prompt multi-pesan
Secara default, Dotprompt membuat satu pesan dengan peran "user"
. Beberapa
prompt sebaiknya dinyatakan sebagai kombinasi dari beberapa pesan, seperti
prompt sistem.
Helper {{role}}
menyediakan cara mudah untuk membuat prompt multi-pesan:
---
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}}
Histori dan Perintah Multi Giliran
Dotprompt mendukung perintah multi-giliran dengan meneruskan opsi history
ke
Metode generate
:
const result = await multiTurnPrompt.generate({
history: [
{ role: 'user', content: [{ text: 'Hello.' }] },
{ role: 'model', content: [{ text: 'Hi there!' }] },
],
});
Secara default, histori akan disisipkan sebelum pesan terakhir yang dibuat oleh
prompt tersebut. Namun, Anda dapat memosisikan histori secara manual menggunakan {{history}}
bantuan:
{{role "system"}}
This is the system prompt.
{{history}}
{{role "user"}}
This is a user message.
{{role "model"}}
This is a model message.
{{role "user"}}
This is the final user message.
Prompt multi-modal
Untuk model yang mendukung input multimodal seperti gambar di samping teks, Anda bisa
menggunakan helper {{media}}
:
---
model: vertexai/gemini-1.5-flash
input:
schema:
photoUrl: string
---
Describe this image in a detailed paragraph:
{{media url=photoUrl}}
URL dapat berupa URI https://
atau data:
berenkode base64 untuk penggunaan gambar
"inline". Dalam kode, ini akan menjadi:
const describeImagePrompt = promptRef('describe_image');
const result = await describeImagePrompt.generate({
input: {
photoUrl: 'https://example.com/image.png',
},
});
console.log(result.text());
Parsial
Parsial adalah template yang dapat digunakan kembali dan dapat disertakan dalam perintah apa pun. Parsial dapat sangat membantu untuk prompt terkait yang memiliki perilaku yang sama.
Saat memuat direktori prompt, file apa pun yang diawali dengan _
dianggap
parsial. Jadi file _personality.prompt
mungkin berisi:
You should speak like a {{#if style}}{{style}}{{else}}helpful assistant.{{/else}}.
Tindakan ini dapat disertakan dalam perintah lain:
---
model: vertexai/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}}
Sebagian disisipkan menggunakan sintaksis {{>NAME_OF_PARTIAL args...}}
. Jika tidak
argumen diberikan ke parsial, argumen tersebut dieksekusi dengan konteks yang sama dengan
perintah orang tua.
Parsial menerima argumen yang dinamai seperti di atas atau satu argumen posisi yang mewakili konteks. Ini dapat berguna, misalnya, merender anggota daftar.
# _destination.prompt
- {{name}} ({{country}})
# chooseDestination.prompt
Help the user decide between these vacation destinations:
{{#each destinations}}
{{>destination this}}{{/each}}
Menentukan Parsial dalam Kode
Anda juga dapat menentukan parsial dalam kode menggunakan definePartial
:
import { definePartial } from '@genkit-ai/dotprompt';
definePartial(
'personality',
'Talk like a {{#if style}}{{style}}{{else}}helpful assistant{{/if}}.'
);
Parsial yang ditentukan kode tersedia di semua perintah.
Varian Prompt
Karena file prompt berupa teks, Anda bisa (dan harus) melakukan commit ke sistem kontrol versi, yang memungkinkan Anda untuk membandingkan perubahan dari waktu ke waktu dengan mudah. Sering kali, versi prompt yang sudah diutak-atik hanya bisa diuji sepenuhnya di lingkungan produksi secara berdampingan dengan versi yang sudah ada. Dotprompt mendukung hal ini melalui fitur varian.
Untuk membuat varian, buat file [name].[variant].prompt
. Misalnya, jika
Anda menggunakan Gemini 1.5 Flash di prompt, tetapi ingin mengetahui apakah Gemini 1.5 Pro
akan berperforma lebih baik, Anda dapat membuat dua file:
my_prompt.prompt
: prompt "dasar"my_prompt.gemini15pro.prompt
: varian bernama "gemini15pro"
Untuk menggunakan varian perintah, tentukan opsi variant
saat memuat:
const myPrompt = promptRef('my_prompt', { variant: 'gemini15pro' });
Nama varian disertakan dalam metadata trace pembuatan, sehingga Anda dapat membandingkan dan membedakan performa sebenarnya di antara varian dalam pemeriksa trace Genkit.
Menentukan Bantuan Kustom
Anda dapat menentukan helper kustom untuk memproses dan mengelola data di dalam perintah. Helper
terdaftar secara global menggunakan defineHelper
:
import { defineHelper } from '@genkit-ai/dotprompt';
defineHelper('shout', (text: string) => text.toUpperCase());
Setelah ditentukan, Anda dapat menggunakannya dalam perintah apa pun:
---
model: vertexai/gemini-1.5-flash
input:
schema:
name: string
---
HELLO, {{shout name}}!!!
Untuk informasi selengkapnya tentang argumen yang diteruskan ke helper, lihat Dokumentasi Handlebar tentang cara membuat helper kustom.
Cara alternatif untuk memuat dan menentukan perintah
Dotprompt dioptimalkan untuk pengaturan di direktori prompt. Namun demikian, ada adalah beberapa cara lain untuk memuat dan menentukan prompt:
loadPromptFile
: Memuat perintah dari file dalam direktori perintah.loadPromptUrl
: Memuat perintah dari URL.defineDotprompt
: Menentukan perintah dalam kode.
Contoh:
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.5-flash',
input: {
schema: z.object({
name: z.string(),
}),
},
},
`Hello {{name}}, how are you today?`
);