إدارة الطلبات باستخدام Dotprompt

توفّر منصة Firebase Genkit تنسيق Dotprompt وتنسيق النص لمساعدتك في كتابة الطلبات بالذكاء الاصطناعي التوليدي وتنظيمها.

تم تصميم 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 واستيراد الدالة prompt من مكتبة @genkit-ai/dotprompt:

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. يمكنك استخدام أدوات المساعدة 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}}

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

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: تحميل طلب من عنوان URL
  • 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?`
);