Rekayasa perintah adalah cara utama yang dapat Anda gunakan untuk memengaruhi output model AI generatif sebagai developer aplikasi. Misalnya, saat menggunakan LLM, Anda dapat membuat prompt yang memengaruhi nada, format, panjang, dan karakteristik lainnya dari respons model.
Cara Anda menulis prompt ini akan bergantung pada model yang Anda gunakan. Prompt yang ditulis untuk satu model mungkin tidak memiliki performa yang baik saat digunakan dengan model lain. Demikian pula, parameter model yang Anda tetapkan (temperature, top-k, dan sebagainya) juga akan memengaruhi output secara berbeda bergantung pada model.
Membuat ketiga faktor ini—model, parameter model, dan prompt—bekerja sama untuk menghasilkan output yang Anda inginkan bukanlah proses yang mudah dan sering kali melibatkan iterasi dan eksperimen yang substansial. Genkit menyediakan library dan format file yang disebut Dotprompt, yang bertujuan untuk membuat iterasi ini lebih cepat dan lebih praktis.
Dotprompt dirancang berdasarkan premis bahwa prompt adalah kode. Anda menentukan prompt beserta model dan parameter model yang dimaksudkan secara terpisah dari kode aplikasi Anda. Kemudian, Anda (atau, mungkin seseorang yang bahkan tidak terlibat dalam penulisan kode aplikasi) dapat melakukan iterasi dengan cepat pada prompt dan parameter model menggunakan UI Developer Genkit. Setelah prompt berfungsi seperti yang diinginkan, Anda dapat mengimpornya ke aplikasi dan menjalankannya menggunakan Genkit.
Setiap definisi prompt akan ditempatkan dalam file dengan ekstensi .prompt
. Berikut
contoh tampilan file ini:
---
model: googleai/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}}.
Bagian dalam tiga tanda pisah adalah frontmatter YAML, mirip dengan format frontmatter
yang digunakan oleh GitHub Markdown dan Jekyll. Bagian lain dari file adalah
prompt, yang dapat menggunakan template
Handlebars secara opsional. Bagian
berikut akan membahas lebih detail setiap bagian dalam pembuatan
file .prompt
beserta cara menggunakannya.
Sebelum memulai
Sebelum membaca halaman ini, Anda harus memahami konten yang dibahas di halaman Membuat konten dengan model AI.
Jika Anda ingin menjalankan contoh kode di halaman ini, selesaikan langkah-langkah dalam panduan Memulai terlebih dahulu. Semua contoh mengasumsikan bahwa Anda telah menginstal Genkit sebagai dependensi dalam project.
Membuat file prompt
Meskipun Dotprompt menyediakan beberapa cara yang berbeda untuk membuat
dan memuat prompt, Dotprompt dioptimalkan untuk project yang mengatur prompt sebagai
file .prompt
dalam satu direktori (atau subdirektorinya). Bagian
ini menunjukkan cara membuat dan memuat prompt menggunakan penyiapan yang direkomendasikan.
Membuat direktori prompt
Library Dotprompt diharapkan menemukan prompt Anda pada direktori di
root project dan otomatis memuat prompt apa pun yang ditemukan di sana. Secara default,
direktori ini diberi nama prompts
. Misalnya, menggunakan nama direktori
default, struktur project Anda mungkin terlihat seperti ini:
your-project/
├── prompts/
│ └── hello.prompt
├── main.go
├── go.mod
└── go.sum
Jika ingin menggunakan direktori lain, Anda dapat menentukannya saat mengonfigurasi Genkit:
g, err := genkit.Init(ctx.Background(), ai.WithPromptDir("./llm_prompts"))
Membuat satu file prompt
Ada dua cara untuk membuat satu file .prompt
: menggunakan editor teks, atau dengan
UI developer.
Menggunakan editor teks
Jika Anda ingin membuat file prompt menggunakan editor teks, buat file teks dengan
ekstensi .prompt
di direktori prompt: misalnya,
prompts/hello.prompt
.
Berikut adalah contoh sederhana file prompt:
---
model: vertexai/gemini-1.5-flash
---
You are the world's most welcoming AI assistant. Greet the user and offer your
assistance.
Bagian dalam tanda pisah adalah frontmatter YAML, mirip dengan format frontmatter yang digunakan oleh Markdown GitHub dan Jekyll. Bagian lain dari file adalah prompt, yang secara opsional dapat menggunakan template Handlebars. Bagian frontmatter bersifat opsional, tetapi sebagian besar file prompt setidaknya akan berisi metadata yang menentukan model. Bagian lain dari halaman ini menunjukkan cara melakukan tindakan lainnya, dan menggunakan fitur Dotprompt dalam file prompt Anda.
Menggunakan UI developer
Anda juga dapat membuat file prompt menggunakan runner model di UI developer. Mulailah dengan kode aplikasi yang mengimpor library Genkit dan mengonfigurasinya untuk menggunakan plugin model yang Anda inginkan. Contoh:
import (
"context"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai"
)
func main() {
g, err := genkit.Init(context.Background(), ai.WithPlugins(&googlegenai.GoogleAI{}))
if err != nil {
log.Fatal(err)
}
// Blocks end of program execution to use the developer UI.
select {}
}
Muat UI developer di project yang sama:
genkit start -- go run .
Pada bagian Model, pilih model yang ingin Anda gunakan dari daftar model yang disediakan oleh plugin.
Kemudian, bereksperimenlah dengan prompt dan konfigurasi hingga Anda mendapatkan hasil yang memuaskan. Jika sudah siap, tekan tombol Export dan simpan file ke direktori prompt Anda.
Menjalankan prompt
Setelah membuat file prompt, Anda dapat menjalankannya dari kode aplikasi, atau menggunakan alat yang disediakan oleh Genkit. Terlepas dari cara Anda ingin menjalankan prompt, mulailah dengan kode aplikasi yang mengimpor library Genkit dan plugin model yang Anda inginkan. Contoh:
import (
"context"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
"github.com/firebase/genkit/go/plugins/googlegenai"
)
func main() {
g, err := genkit.Init(context.Background(), ai.WithPlugins(&googlegenai.GoogleAI{}))
if err != nil {
log.Fatal(err)
}
// Blocks end of program execution to use the developer UI.
select {}
}
Jika Anda menyimpan prompt di direktori selain direktori default, pastikan untuk menentukannya saat mengonfigurasi Genkit.
Menjalankan prompt dari kode
Untuk menggunakan prompt, muat prompt terlebih dahulu menggunakan fungsi genkit.LookupPrompt()
:
helloPrompt := genkit.LookupPrompt(g, "hello")
Prompt yang dapat dieksekusi memiliki opsi yang mirip dengan genkit.Generate()
dan banyak
di antaranya dapat diganti pada waktu eksekusi, termasuk hal-hal seperti input (lihat
bagian tentang menentukan skema input), konfigurasi, dan sebagainya:
resp, err := helloPrompt.Execute(context.Background(),
ai.WithModelName("googleai/gemini-2.0-flash"),
ai.WithInput(map[string]any{"name": "John"}),
ai.WithConfig(&googlegenai.GeminiConfig{Temperature: 0.5})
)
Setiap parameter yang diteruskan ke panggilan prompt akan mengganti parameter yang sama dengan yang ditentukan dalam file prompt.
Baca Membuat konten dengan model AI untuk deskripsi opsi yang tersedia.
Menggunakan UI developer
Saat meningkatkan kualitas prompt aplikasi, Anda dapat menjalankannya di UI developer Genkit untuk melakukan iterasi pada prompt dan konfigurasi model dengan cepat, secara independen dari kode aplikasi Anda.
Muat UI developer dari direktori project Anda:
genkit start -- go run .
Setelah memuat prompt ke UI developer, Anda dapat menjalankannya dengan nilai input yang berbeda, dan bereksperimen untuk mengetahui pengaruh perubahan pada kata-kata prompt atau parameter konfigurasi terhadap output model. Jika sudah puas dengan hasilnya, Anda dapat mengklik tombol Export prompt untuk menyimpan prompt yang diubah kembali ke direktori project.
Konfigurasi model
Di blok frontmatter pada file prompt, Anda dapat menentukan nilai konfigurasi model untuk prompt secara opsional:
---
model: googleai/gemini-2.0-flash
config:
temperature: 1.4
topK: 50
topP: 0.4
maxOutputTokens: 400
stopSequences:
- "<end>"
- "<fin>"
---
Nilai ini dipetakan secara langsung ke opsi WithConfig()
yang diterima oleh
prompt yang dapat dieksekusi:
resp, err := helloPrompt.Execute(context.Background(),
ai.WithConfig(&googlegenai.GeminiConfig{
Temperature: 1.4,
TopK: 50,
TopP: 0.4,
MaxOutputTokens: 400,
StopSequences: []string{"<end>", "<fin>"},
}))
Baca Membuat konten dengan model AI untuk deskripsi opsi yang tersedia.
Skema input dan output
Anda dapat menentukan skema input dan output prompt dengan menentukan skema tersebut di
bagian frontmatter. Skema ini digunakan dengan cara yang sama seperti yang diteruskan ke
permintaan genkit.Generate()
atau definisi flow:
---
model: googleai/gemini-2.0-flash
input:
schema:
theme?: string
default:
theme: "pirate"
output:
schema:
dishname: string
description: string
calories: integer
allergens(array): string
---
Invent a menu item for a {{theme}} themed
restaurant.
Kode ini menghasilkan output terstruktur berikut:
menuPrompt = genkit.LookupPrompt(g, "menu")
if menuPrompt == nil {
log.Fatal("no prompt named 'menu' found")
}
resp, err := menuPrompt.Execute(context.Background(),
ai.WithInput(map[string]any{"theme": "medieval"}),
)
if err != nil {
log.Fatal(err)
}
var output map[string]any
if err := resp.Output(&output); err != nil {
log.Fatal(err)
}
log.Println(output["dishname"])
log.Println(output["description"])
Anda memiliki beberapa opsi untuk menentukan skema dalam file .prompt
: format definisi skema
Dotprompt-nya sendiri, Picoschema; Skema JSON standar; atau, sebagai
referensi ke skema yang ditentukan dalam kode aplikasi Anda. Bagian berikut
menjelaskan setiap opsi ini secara lebih mendetail.
Picoschema
Skema pada contoh di atas ditentukan dalam format yang disebut Picoschema. Picoschema adalah format definisi skema ringkas yang dioptimalkan untuk YAML yang menyederhanakan penentuan atribut skema paling penting untuk penggunaan LLM. Berikut adalah contoh skema yang lebih panjang, yang menentukan informasi yang mungkin disimpan oleh aplikasi tentang sebuah 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 jenis Go berikut:
type Article struct {
Title string `json:"title"`
Subtitle string `json:"subtitle,omitempty" jsonschema:"required=false"`
Draft bool `json:"draft,omitempty"` // True when in draft state
Status string `json:"status,omitempty" jsonschema:"enum=PENDING,enum=APPROVED"` // Approval status
Date string `json:"date"` // The date of publication e.g. '2025-04-07'
Tags []string `json:"tags"` // Relevant tags for article
Authors []struct {
Name string `json:"name"`
Email string `json:"email,omitempty"`
} `json:"authors"`
Metadata struct {
UpdatedAt string `json:"updatedAt,omitempty"` // ISO timestamp of last update
ApprovedBy int `json:"approvedBy,omitempty"` // ID of approver
} `json:"metadata,omitempty"`
Extra any `json:"extra"` // Arbitrary extra data
}
Picoschema mendukung jenis skalar string
, integer
, number
, boolean
, dan
any
. Objek, array, dan enum dilambangkan dengan tanda kurung setelah nama
kolom.
Objek yang didefinisikan oleh Picoschema memiliki semua properti yang disyaratkan, kecuali jika dilambangkan sebagai properti opsional
dengan ?
, dan tidak mengizinkan properti tambahan. Ketika sebuah properti ditandai
sebagai opsional, properti tersebut juga dibuat nullable, sehingga 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.
Skema JSON
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
Template prompt
Bagian file .prompt
yang mengikuti frontmatter (jika ada) adalah
prompt itu sendiri, yang akan diteruskan ke model. Meskipun prompt ini dapat berupa
string teks sederhana, Anda sering kali ingin menyertakan input pengguna ke dalam
prompt. Untuk melakukannya, Anda dapat menentukan prompt menggunakan
bahasa template Handlebars.
Template prompt dapat menyertakan placeholder yang merujuk ke nilai yang ditentukan oleh
skema input prompt Anda.
Anda telah melihat cara kerjanya di bagian skema input dan output:
---
model: googleai/gemini-2.0-flash
input:
schema:
theme?: string
default:
theme: "pirate"
output:
schema:
dishname: string
description: string
calories: integer
allergens(array): string
---
Invent a menu item for a {{theme}} themed restaurant.
Dalam contoh ini, ekspresi Handlebars, {{theme}}
, di-resolve ke nilai properti theme
input saat Anda
menjalankan prompt. Untuk meneruskan input ke prompt, panggil prompt seperti dalam contoh
berikut:
menuPrompt = genkit.LookupPrompt(g, "menu")
resp, err := menuPrompt.Execute(context.Background(),
ai.WithInput(map[string]any{"theme": "medieval"}),
)
Perlu diperhatikan, karena skema input mendeklarasikan properti theme
sebagai opsional
dan memberikan nilai default, Anda dapat menghilangkan properti, dan prompt
akan di-resolve menggunakan nilai default.
Template Handlebars juga mendukung beberapa konstruksi logis terbatas. Misalnya,
sebagai alternatif dalam memberikan nilai default, Anda dapat menentukan prompt menggunakan
helper #if
Handlebars:
---
model: googleai/gemini-2.0-flash
input:
schema:
theme?: string
---
Invent a menu item for a {{#if theme}}{{theme}}{else}themed{{/else}} restaurant.
Dalam contoh ini, prompt dirender sebagai "Buat item menu untuk restoran"
saat properti theme
tidak ditentukan.
Lihat dokumentasi Handlebars untuk mengetahui informasi tentang semua helper logis bawaan.
Selain properti yang ditentukan oleh skema input, template Anda juga dapat merujuk ke nilai yang ditentukan secara otomatis oleh Genkit. Beberapa bagian berikutnya menjelaskan nilai yang ditentukan secara otomatis dan cara menggunakannya.
Prompt multi-pesan
Secara default, Dotprompt membuat satu pesan dengan peran "pengguna". Namun, beberapa prompt, seperti prompt sistem, sebaiknya dinyatakan sebagai kombinasi dari beberapa pesan.
Helper {{role}}
menyediakan cara paling mudah untuk
membuat prompt multi-pesan:
---
model: vertexai/gemini-2.0-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}}
Prompt multi-modal
Untuk model yang mendukung input multimodal seperti gambar di samping teks, Anda bisa
menggunakan helper {{media}}
:
---
model: vertexai/gemini-2.0-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:
multimodalPrompt = genkit.LookupPrompt(g, "multimodal")
resp, err := multimodalPrompt.Execute(context.Background(),
ai.WithInput(map[string]any{"photoUrl": "https://example.com/photo.jpg"}),
)
Lihat juga Input multimodal, di halaman
Membuat konten dengan model AI, untuk
contoh pembuatan URL data:
.
Parsial
Parsial adalah template yang dapat digunakan kembali dan dapat disertakan dalam prompt apa pun. Parsial dapat sangat membantu prompt terkait yang memiliki perilaku yang sama.
Saat memuat direktori prompt, setiap file yang diawali dengan garis bawah (_
)
dianggap sebagai parsial. Jadi, file _personality.prompt
mungkin berisi:
You should speak like a {{#if style}}{{style}}{else}helpful assistant.{{/else}}.
Kemudian, hal ini dapat disertakan dalam prompt lain:
---
model: googleai/gemini-2.0-flash
input:
schema:
name: string
style?: string
---
{{ role "system" }}
{{>personality style=style}}
{{ role "user" }}
Give the user a friendly greeting.
User's Name: {{name}}
Parsial disisipkan menggunakan sintaksis {{>NAME_OF_PARTIAL args...}}
. Jika tidak ada argumen yang disediakan ke template parsial, argumen tersebut akan dijalankan
menggunakan konteks yang sama dengan prompt induk.
Parsial menerima argumen bernama atau satu argumen posisional yang mewakili konteks. Hal ini dapat berguna untuk tugas seperti merender anggota daftar.
_destination.prompt
- {{name}} ({{country}})
chooseDestination.prompt
---
model: googleai/gemini-2.0-flash
input:
schema:
destinations(array):
name: string
country: string
---
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 genkit.DefinePartial()
:
genkit.DefinePartial(g, "personality", "Talk like a {{#if style}}{{style}}{{else}}helpful assistant{{/if}}.")
Parsial yang ditentukan oleh kode tersedia di semua prompt.
Menentukan Helper Kustom
Anda dapat menentukan helper kustom untuk memproses dan mengelola data di dalam prompt.
Helper didaftarkan secara global menggunakan genkit.DefineHelper()
:
genkit.DefineHelper(g, "shout", func(input string) string {
return strings.ToUpper(input)
})
Setelah helper ditentukan, Anda dapat menggunakannya di prompt apa pun:
---
model: googleai/gemini-2.0-flash
input:
schema:
name: string
---
HELLO, {{shout name}}!!!
Varian prompt
Karena file prompt berupa teks, Anda bisa (dan harus) melakukan commit ke sistem kontrol versi, yang menyederhanakan proses membandingkan perubahan dari waktu ke waktu. 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 2.0 Flash dalam prompt, tetapi ingin mengetahui apakah Gemini 2.5
Pro akan berperforma lebih baik, Anda dapat membuat dua file:
myPrompt.prompt
: prompt "dasar"myPrompt.gemini25pro.prompt
: varian bernamagemini25pro
Untuk menggunakan varian prompt, tentukan opsi varian saat memuat:
myPrompt := genkit.LookupPrompt(g, "myPrompt.gemini25Pro")
Nama varian disertakan dalam metadata trace pembuatan, sehingga Anda dapat membandingkan dan membedakan performa sebenarnya di antara varian dalam pemeriksa trace Genkit.
Menentukan prompt dalam kode
Semua contoh yang telah dibahas sejauh ini mengasumsikan bahwa prompt Anda ditentukan
di setiap file .prompt
pada satu direktori (atau subdirektorinya),
yang dapat diakses oleh aplikasi Anda saat runtime. Dotprompt dirancang berdasarkan penyiapan ini, dan
penulis menganggapnya sebagai pengalaman developer terbaik secara keseluruhan.
Namun, jika memiliki kasus penggunaan yang tidak didukung dengan baik oleh penyiapan ini, Anda juga dapat menentukan prompt dalam kode menggunakan fungsi genkit.DefinePrompt()
:
type GeoQuery struct {
CountryCount int `json:"countryCount"`
}
type CountryList struct {
Countries []string `json:"countries"`
}
geographyPrompt, err := genkit.DefinePrompt(
g, "GeographyPrompt",
ai.WithSystem("You are a geography teacher. Respond only when the user asks about geography."),
ai.WithPrompt("Give me the {{countryCount}} biggest countries in the world by inhabitants."),
ai.WithConfig(&googlegenai.GeminiConfig{Temperature: 0.5}),
ai.WithInputType(GeoQuery{CountryCount: 10}) // Defaults to 10.
ai.WithOutputType(CountryList{}),
)
if err != nil {
log.Fatal(err)
}
resp, err := geographyPrompt.Execute(context.Background(), ai.WithInput(GeoQuery{CountryCount: 15}))
if err != nil {
log.Fatal(err)
}
var list CountryList
if err := resp.Output(&list); err != nil {
log.Fatal(err)
}
log.Println("Countries: %s", list.Countries)
Prompt juga dapat dirender menjadi GenerateActionOptions
yang kemudian dapat
diproses dan diteruskan ke genkit.GenerateWithRequest()
:
actionOpts, err := geographyPrompt.Render(ctx, ai.WithInput(GeoQuery{CountryCount: 15}))
if err != nil {
log.Fatal(err)
}
// Do something with the value...
actionOpts.Config = &googlegenai.GeminiConfig{Temperature: 0.8}
resp, err := genkit.GenerateWithRequest(ctx, g, actionOpts, nil, nil) // No middleware or streaming
Perhatikan bahwa semua opsi prompt akan diterapkan ke GenerateActionOptions
dengan
pengecualian WithMiddleware()
, yang harus diteruskan secara terpisah jika menggunakan
Prompt.Render()
, bukan Prompt.Execute()
.