使用 Dotprompt 管理提示

Firebase Genkit 提供 Dotprompt 外掛程式和文字格式,可協助您撰寫及管理生成式 AI 提示。

Dotprompt 是根據提示為程式碼的環境設計。您可以在名為 dotprompt 檔案的特殊格式檔案中編寫及維護提示,並使用與程式碼相同的版本管控系統追蹤檔案變更,並以呼叫生成式 AI 模型的程式碼加以部署。

如要使用 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 外掛程式,並從 @genkit-ai/dotprompt 程式庫匯入 prompt 函式:

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 範本語言為基礎。您可以使用 ifunlesseach 輔助工具,在提示中加入條件部分,或疊代所有結構化內容。檔案格式利用 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;
  };
}

Picoschema 支援純量類型 stringintegernumberboolean。如果是物件、陣列和列舉,則在欄位名稱之後會以括號表示。

除非 ? 表示選擇性,否則 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" 角色建構單一訊息。某些提示最好以結合多則訊息的形式呈現,例如系統提示。

{{role}} 輔助程式可讓您輕鬆建構多重訊息提示:

---
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}}

多重模組提示

如果是支援多模態輸入作業 (例如圖片旁) 的模型,則可使用 {{media}} 輔助程式:

---
model: vertexai/gemini-1.0-pro-vision
input:
  schema:
    photoUrl: string
---

Describe this image in a detailed paragraph:

{{media url=photoUrl}}

這個網址可以是 https:// 或 base64 編碼的 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:從網址載入提示。
  • 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?`
);