إدارة الطلبات باستخدام 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",
})

تستند بنية Dotprompt إلى Handlebars. لغة النماذج. يمكنك استخدام مساعدي 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}}

عنوان URL يمكن أن يكون https:// أو بترميز base64 data: معرف موارد منتظم (URI) "مضمّن". مصوّر الاستخدام. في التعليمات البرمجية، سيكون هذا كالتالي:

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 الجديد.