Dotprompt की मदद से प्रॉम्प्ट मैनेज करना

Firebase Genkit में आपको 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 प्लगिन इंस्टॉल करें और @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 का सिंटैक्स हैंडलबार टेंप्लेट की भाषा पर आधारित है. अपने प्रॉम्प्ट में शर्त वाले हिस्से जोड़ने या स्ट्रक्चर्ड कॉन्टेंट की मदद से दोहराने के लिए, if, unless, और each हेल्पर का इस्तेमाल किया जा सकता है. टेंप्लेट के साथ प्रॉम्प्ट इनलाइन के लिए मेटाडेटा उपलब्ध कराने के लिए, फ़ाइल फ़ॉर्मैट में YAML फ़्रंटमैटर का इस्तेमाल किया जाता है.

Picoschema की मदद से इनपुट/आउटपुट स्कीमा तय करना

Dotprompt में एक छोटा और YAML-ऑप्टिमाइज़ किया गया स्कीमा डेफ़िनिशन फ़ॉर्मैट शामिल होता है. इसे Picoschema कहते हैं. इससे एलएलएम के इस्तेमाल के लिए, स्कीमा की सबसे अहम विशेषताओं को तय करने में आसानी होती है. यहां किसी लेख के लिए स्कीमा का उदाहरण दिया गया है:

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, 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" भूमिका वाला एक मैसेज बनाता है. कुछ प्रॉम्प्ट को, एक से ज़्यादा मैसेज को मिलाकर सबसे सही तरीके से दिखाया जा सकता है. जैसे, सिस्टम का अनुरोध.

{{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: यूआरआई हो सकता है. कोड में, यह होगा:

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,
});

जनरेशन ट्रेस के मेटाडेटा में वैरिएंट का नाम शामिल किया जाता है. इससे, जेनकिट ट्रेस जांच करने वाले टूल के वैरिएंट के बीच, असल परफ़ॉर्मेंस की तुलना और उनमें फ़र्क़ किया जा सकता है.

प्रॉम्प्ट को लोड करने और तय करने के दूसरे तरीके

प्रॉम्प्ट डायरेक्ट्री में, 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?`
);