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

Firebase Genkit, लिखने में आपकी मदद करने के लिए, Dotprompt प्लगिन और टेक्स्ट फ़ॉर्मैट उपलब्ध कराता है और अपने जनरेटिव एआई प्रॉम्प्ट को व्यवस्थित करें.

Dotprompt को इस आधार पर डिज़ाइन किया गया है कि प्रॉम्प्ट, कोड होते हैं. आपने लिखा और अपने प्रॉम्प्ट को विशेष फ़ॉर्मैट वाली फ़ाइलों में बनाए रखें. इन्हें dotprompt फ़ाइलें कहा जाता है, ट्रैक करें, उसी वर्शन कंट्रोल सिस्टम का इस्तेमाल करके उनमें बदलाव किए जा सकते हैं जिसका इस्तेमाल और आप उन्हें उस कोड के साथ डिप्लॉय कर सकते हैं जो आपके जनरेटिव एआई को कॉल करता है मॉडल.

Dotprompt का इस्तेमाल करने के लिए, सबसे पहले अपने प्रोजेक्ट के रूट में prompts डायरेक्ट्री बनाएं और फिर उस डायरेक्ट्री में एक .prompt फ़ाइल बनाएं. यहाँ आपके लिए एक आसान सा उदाहरण दिया गया है, 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}}.

इस प्रॉम्प्ट का इस्तेमाल करने के लिए, dotprompt प्लगिन इंस्टॉल करें:

go get github.com/firebase/genkit/go/plugins/dotprompt

इसके बाद, Open का इस्तेमाल करके प्रॉम्प्ट लोड करें:

import "github.com/firebase/genkit/go/plugins/dotprompt"
dotprompt.SetDirectory("prompts")
prompt, err := dotprompt.Open("greeting")

टेंप्लेट को रेंडर करने और उसे पास करने के लिए, प्रॉम्प्ट के Generate तरीके को कॉल किया जा सकता है करने के लिए एक ही चरण में मॉडल एपीआई पर अपग्रेड करें:

ctx := context.Background()

// Default to the project in GCLOUD_PROJECT and the location "us-central1".
vertexai.Init(ctx, nil)

// The .prompt file specifies vertexai/gemini-1.5-flash, which is
// automatically defined by Init(). However, if it specified a model that
// isn't automatically loaded (such as a specific version), you would need
// to define it here:
// vertexai.DefineModel("gemini-1.0-pro-002", &ai.ModelCapabilities{
// 	Multiturn:  true,
// 	Tools:      true,
// 	SystemRole: true,
// 	Media:      false,
// })

type GreetingPromptInput struct {
	Location string `json:"location"`
	Style    string `json:"style"`
	Name     string `json:"name"`
}
response, err := prompt.Generate(
	ctx,
	&dotprompt.PromptRequest{
		Variables: GreetingPromptInput{
			Location: "the beach",
			Style:    "a fancy pirate",
			Name:     "Ed",
		},
	},
	nil,
)
if err != nil {
	return err
}

fmt.Println(response.Text())

या सिर्फ़ टेंप्लेट को स्ट्रिंग में रेंडर करें:

renderedPrompt, err := prompt.RenderText(map[string]any{
	"location": "a restaurant",
	"style":    "a pirate",
})

डॉटप्रॉम्प्ट का सिंटैक्स हैंडलबार पर आधारित होता है के हिसाब से व्यवस्थित किया जा सकता है. जोड़ने के लिए, 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
  extra?: any, arbitrary extra data
  (*): string, wildcard field

ऊपर दिया गया स्कीमा, इस JSON स्कीमा के बराबर है:

{
  "properties": {
    "metadata": {
      "properties": {
        "updatedAt": {
          "type": "string",
          "description": "ISO timestamp of last update"
        },
        "approvedBy": {
          "type": "integer",
          "description": "id of approver"
        }
      },
      "type": "object"
    },
    "title": {
      "type": "string"
    },
    "subtitle": {
      "type": "string"
    },
    "draft": {
      "type": "boolean",
      "description": "true when in draft state"
    },
    "date": {
      "type": "string",
      "description": "the date of publication e.g. '2024-04-09'"
    },
    "tags": {
      "items": {
        "type": "string"
      },
      "type": "array",
      "description": "relevant tags for article"
    },
    "authors": {
      "items": {
        "properties": {
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string"
          }
        },
        "type": "object",
        "required": ["name"]
      },
      "type": "array"
    }
  },
  "type": "object",
  "required": ["title", "date", "tags", "authors"]
}

Picoschema, स्केलर टाइप string, integer, number, boolean, और any के साथ काम करता है. ऑब्जेक्ट, अरे, और ईनम के लिए, उन्हें फ़ील्ड के नाम के बाद ब्रैकेट में दिखाया जाता है.

Picoschema से तय किए गए ऑब्जेक्ट में सभी ज़रूरी प्रॉपर्टी मौजूद हैं. ऐसा तब तक करना ज़रूरी है, जब तक कि उसे 'ज़रूरी नहीं' के तौर पर दिखाया जाता है ? तक प्रोसेस करें, और अतिरिक्त प्रॉपर्टी को अनुमति न दें. जब किसी प्रॉपर्टी को 'ज़रूरी नहीं' के तौर पर मार्क किया जाता है, यह भी विकल्प नहीं दिखाया जा सकता कि एलएलएम के लिए, शून्य के बजाय कोई वैल्यू न दी जाए फ़ील्ड को छोड़ा जा रहा है.

किसी ऑब्जेक्ट की परिभाषा में, "वाइल्डकार्ड" का एलान करने के लिए खास कुंजी (*) का इस्तेमाल किया जा सकता है फ़ील्ड की परिभाषा. यह उन सभी अतिरिक्त प्रॉपर्टी से मेल खाएगा, जिन्हें साफ़ तौर पर बताएं.

Picoschema, पूरी JSON स्कीमा की कई सुविधाओं के साथ काम नहीं करता. अगर आपको ज़्यादा मज़बूत स्कीमा की ज़रूरत होती है, तो इसके बजाय एक JSON स्कीमा दिया जा सकता है:

output:
  schema:
    type: object
    properties:
      field1:
        type: number
        minimum: 20

प्रॉम्प्ट मेटाडेटा बदलना

.prompt फ़ाइलें आपको, मॉडल कॉन्फ़िगरेशन जैसे मेटाडेटा को फ़ाइल में मौजूद है, तो आप प्रति-कॉल आधार पर इन मानों को भी ओवरराइड कर सकते है:

// Make sure you set up the model you're using.
vertexai.DefineModel("gemini-1.5-flash", nil)

response, err := prompt.Generate(
	context.Background(),
	&dotprompt.PromptRequest{
		Variables: GreetingPromptInput{
			Location: "the beach",
			Style:    "a fancy pirate",
			Name:     "Ed",
		},
		Model: "vertexai/gemini-1.5-flash",
		Config: &ai.GenerationCommonConfig{
			Temperature: 1.0,
		},
	},
	nil,
)

एक से ज़्यादा मैसेज वाले प्रॉम्प्ट

डिफ़ॉल्ट रूप से, Dotprompt "user" भूमिका वाला एक मैसेज बनाता है. कुछ सूचनाएं मिल रही हैं प्रॉम्प्ट को कई मैसेज को मिलाकर सबसे अच्छे तरीके से दिखाया जाता है. जैसे सिस्टम प्रॉम्प्ट.

{{role}} हेल्पर, एक से ज़्यादा मैसेज वाले प्रॉम्प्ट बनाने का आसान तरीका है:

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

मल्टी-मोडल प्रॉम्प्ट

टेक्स्ट के साथ इमेज जैसे मल्टीमोडल इनपुट का इस्तेमाल करने वाले मॉडल के लिए, ये काम किए जा सकते हैं {{media}} हेल्पर का इस्तेमाल करें:

---
model: vertexai/gemini-1.5-flash
input:
  schema:
    photoUrl: string
---

Describe this image in a detailed paragraph:

{{media url=photoUrl}}

"इनलाइन" के लिए, यूआरएल https:// या base64 कोड में बदले गए data: यूआरआई हो सकता है इमेज इस्तेमाल. कोड में, यह होगा:

dotprompt.SetDirectory("prompts")
describeImagePrompt, err := dotprompt.Open("describe_image")
if err != nil {
	return err
}

imageBytes, err := os.ReadFile("img.jpg")
if err != nil {
	return err
}
encodedImage := base64.StdEncoding.EncodeToString(imageBytes)
dataURI := "data:image/jpeg;base64," + encodedImage

type DescribeImagePromptInput struct {
	PhotoUrl string `json:"photo_url"`
}
response, err := describeImagePrompt.Generate(
	context.Background(),
	&dotprompt.PromptRequest{Variables: DescribeImagePromptInput{
		PhotoUrl: dataURI,
	}},
	nil,
)

प्रॉम्प्ट के वैरिएंट

प्रॉम्प्ट फ़ाइलें सिर्फ़ टेक्स्ट होती हैं. इसलिए, आपके पास उन्हें अपने वर्शन कंट्रोल सिस्टम का इस्तेमाल कर सकते हैं, जिससे आप समय के साथ होने वाले बदलावों की आसानी से तुलना कर सकते है. अक्सर, प्रॉम्प्ट के बदले हुए वर्शन को सिर्फ़ मौजूदा वर्शन के साथ-साथ प्रोडक्शन एनवायरमेंट को भी शामिल करें. Dotprompt सपोर्ट करता है इसके वैरिएंट सुविधा का इस्तेमाल करें.

वैरिएंट बनाने के लिए, [name].[variant].prompt फ़ाइल बनाएं. उदाहरण के लिए, अगर आपने प्रॉम्प्ट में Gemini 1.5 Flash का इस्तेमाल किया था, लेकिन आपको यह देखना था कि Gemini 1.5 फ़्लैश का इस्तेमाल किया जा रहा है या नहीं Pro की परफ़ॉर्मेंस बेहतर होगी, इसलिए दो फ़ाइलें बनाई जा सकती हैं:

  • my_prompt.prompt: "बेसलाइन" मैसेज
  • my_prompt.geminipro.prompt: "geminipro" नाम का एक वैरिएंट

प्रॉम्प्ट के वैरिएंट का इस्तेमाल करने के लिए, लोड करते समय वैरिएंट की जानकारी दें:

describeImagePrompt, err := dotprompt.OpenVariant("describe_image", "geminipro")

प्रॉम्प्ट लोड करने वाला टूल, उस नाम के वैरिएंट को लोड करने की कोशिश करेगा और वापस आ जाएगा बेसलाइन तक सीमित नहीं है. इसका मतलब है कि आप शर्तों के साथ लोड होने की प्रोसेस का इस्तेमाल कर सकते हैं. जो भी मानदंड आपके ऐप्लिकेशन के लिए मायने रखते हैं:

var myPrompt *dotprompt.Prompt
var err error
if isBetaTester(user) {
	myPrompt, err = dotprompt.OpenVariant("describe_image", "geminipro")
} else {
	myPrompt, err = dotprompt.Open("describe_image")
}

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