دليل المطوِّر حول ميزة "التخصيص على الجهاز"

تم تصميم ميزة "التخصيص على الجهاز فقط" (ODP) لحماية معلومات المستخدمين النهائيين من التطبيقات. تستخدم التطبيقات "معالجة البيانات المحدودة" لتخصيص منتجاتها وخدماتها للمستخدمين النهائيين، ولكن لن تتمكّن من الاطّلاع على عمليات التخصيص الدقيقة التي تم إجراؤها للمستخدم (ما لم تكن هناك تفاعلات مباشرة خارج إطار "معالجة البيانات المحدودة" بين التطبيق والمستخدم النهائي). بالنسبة إلى التطبيقات التي تتضمّن نماذج لتعلُّم الآلة أو تحليلات إحصائية، يوفّر "إطار عمل الخصوصية التفاضلية" مجموعة من الخدمات والخوارزميات لضمان إخفاء هويتها بشكل سليم باستخدام آليات "الخصوصية التفاضلية" المناسبة. لمزيد من التفاصيل، يمكنك الاطّلاع على الشرح حول التخصيص على الجهاز.

تنفّذ "المعالجة على الجهاز فقط" رمز المطوّر في IsolatedProcess لا يمكنه الوصول مباشرةً إلى الشبكة أو الأقراص المحلية أو الخدمات الأخرى التي تعمل على الجهاز، ولكن يمكنه الوصول إلى مصادر البيانات التالية المخزّنة محليًا:

  • RemoteData: بيانات غير قابلة للتغيير على شكل مفتاح وقيمة يتم تنزيلها من الخلفيات البعيدة التي يديرها المطوّرون، إذا كان ذلك منطبقًا
  • LocalData: بيانات قابلة للتغيير على شكل مفتاح وقيمة يحتفظ بها المطوّر محليًا، إذا كان ذلك منطبقًا.
  • UserData: بيانات المستخدم المقدَّمة من المنصّة

يمكن استخدام النواتج التالية:

  • النتائج الثابتة: يمكن استخدام هذه النتائج في عمليات المعالجة المحلية المستقبلية، ما يؤدي إلى إنتاج نتائج معروضة أو تدريب النماذج باستخدام ميزة "التعلّم الاتحادي" أو إجراء تحليل إحصائي على مستوى الأجهزة باستخدام ميزة "التحليل الاتحادي".
    • يمكن للمطوّرين كتابة الطلبات ونتائج معالجتها في جدول REQUESTS المحلي.
    • يمكن للمطوّرين كتابة بيانات إضافية مرتبطة بطلب سابق في جدول EVENTS.
  • الناتج المعروض:
    • يمكن للمطوّرين عرض HTML الذي يعرضه ODP في WebView داخل SurfaceView. ولن يظهر المحتوى المعروض هناك للتطبيق الذي تم استدعاؤه.
    • يمكن للمطوّرين تضمين عناوين URL للأحداث المقدَّمة من ODP في ناتج HTML لتفعيل تسجيل تفاعلات المستخدمين مع HTML المعروض ومعالجتها. تعترض "منصة بيانات Oracle" الطلبات المُرسَلة إلى عناوين URL هذه وتستدعي الرمز البرمجي لإنشاء البيانات التي يتمّ تسجيلها في جدول EVENTS.

يمكن لتطبيقات العميل وحِزم تطوير البرامج (SDK) استدعاء ODP لعرض محتوى HTML في SurfaceView باستخدام واجهات برمجة تطبيقات ODP. لا يظهر المحتوى المعروض في SurfaceView للتطبيق الذي يجري الاتصال. ويمكن أن يكون تطبيق العميل أو حزمة SDK كيانًا مختلفًا عن الكيان الذي يطوّر باستخدام ODP.

تتولّى خدمة ODP إدارة تطبيق العميل الذي يريد استدعاء ODP لعرض محتوى مخصّص ضمن واجهة المستخدم. تنزّل هذه الخدمة المحتوى من نقاط النهاية التي يوفّرها المطوّر وتستدعي منطقًا لمعالجة البيانات التي تم تنزيلها. كما يتوسّط في جميع عمليات التواصل بين IsolatedProcess والخدمات والتطبيقات الأخرى.

تستخدم تطبيقات العميل طرقًا في فئة OnDevicePersonalizationManager للتفاعل مع رمز المطوّر الذي يتم تشغيله في IsolatedProcess. يعمل رمز المطوّر البرمجي في IsolatedProcess على توسيع الفئة IsolatedService وتنفيذ الواجهة IsolatedWorker. يجب أن ينشئ IsolatedService مثيلاً من IsolatedWorker لكل طلب.

يوضّح الرسم البياني التالي العلاقة بين الطرق في OnDevicePersonalizationManager وIsolatedWorker.

مخطّط يوضّح العلاقة بين OnDevicePersonalizationManager وIsolatedWorker.

يطلب تطبيق العميل الوصول إلى ODP باستخدام طريقة execute مع IsolatedService باسم. تعيد خدمة ODP توجيه الطلب إلى الطريقة onExecute في IsolatedWorker. تعرض IsolatedWorker السجلات التي سيتم الاحتفاظ بها والمحتوى الذي سيتم عرضه. تكتب خدمة ODP الناتج الثابت في الجدول REQUESTS أو EVENTS، وتعرض مرجعًا مبهمًا للناتج المعروض في تطبيق العميل. ويمكن لتطبيق العميل استخدام هذا المرجع المبهم في طلب requestSurfacePackage مستقبلي لعرض أي من المحتوى المعروض في واجهة المستخدم.

الناتج الدائم

تحتفظ خدمة ODP بسجلّ في جدول REQUESTS بعد أن تعرض عملية تنفيذ المطوّر للوظيفة onExecute. يحتوي كل سجلّ في جدول REQUESTS على بعض البيانات الشائعة لكل طلب التي تنشئها خدمة ODP، وقائمة Rows تم عرضها. تحتوي كل Row على قائمة بأزواج (key, value). كل قيمة هي عددية أو سلسلة أو كائن ثنائي كبير. يمكن الإبلاغ عن القيم الرقمية بعد تجميعها، ويمكن الإبلاغ عن البيانات التسلسلية أو الثنائية الكبيرة بعد تطبيق الخصوصية التفاضلية المحلية أو المركزية. يمكن للمطوّرين أيضًا كتابة أحداث تفاعل المستخدمين اللاحقة في جدول EVENTS، ويرتبط كل سجلّ في جدول EVENTS بصف في جدول REQUESTS. تسجّل خدمة ODP بشكل شفاف طابعًا زمنيًا واسم حزمة التطبيق الذي يطلب البيانات وحِزمة APK الخاصة بمطوّر ODP مع كل سجلّ.

قبل البدء

قبل البدء في التطوير باستخدام ODP، عليك إعداد بيان الحزمة وتفعيل وضع المطوّر.

إعدادات بيان الحزمة

لاستخدام ODP، يجب استيفاء الشروط التالية:

  1. علامة <property> في AndroidManifest.xml تشير إلى مصدر XML في الحزمة يحتوي على معلومات إعداد ODP.
  2. علامة <service> في AndroidManifest.xml تحدّد الفئة التي توسّع IsolatedService، كما هو موضّح في المثال التالي. يجب أن تتضمّن الخدمة في العلامة <service> السمتَين exported وisolatedProcess مضبوطتَين على true.
  3. علامة <service> في مرجع XML المحدّد في الخطوة 1 تحدّد فئة الخدمة من الخطوة 2. يجب أن تتضمّن علامة <service> أيضًا إعدادات إضافية خاصة بمنصة بيانات العملاء (CDP) داخل العلامة نفسها، كما هو موضّح في المثال الثاني.

ملف AndroidManifest.xml

<!-- Contents of AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.odpsample" >
    <application android:label="OdpSample">
        <!-- XML resource that contains other ODP settings. -->
        <property android:name="android.ondevicepersonalization.ON_DEVICE_PERSONALIZATION_CONFIG"
                  android:resource="@xml/OdpSettings"></property>
        <!-- The service that ODP binds to. -->
        <service android:name="com.example.odpsample.SampleService"
                android:exported="true" android:isolatedProcess="true" />
    </application>
</manifest>

ملف البيان الخاص بمنصة ODP بتنسيق XML

يجب أن يعرّف ملف XML الخاص بمصدر البيانات المحدّد في العلامة <property> أيضًا فئة الخدمة في العلامة <service>، ويجب أن يحدّد نقطة نهاية عنوان URL التي سينزّل منها ODP المحتوى لتعبئة الجدول RemoteData، كما هو موضّح في المثال التالي. إذا كنت تستخدم ميزات الحوسبة الاتّحادية، عليك أيضًا تحديد نقطة نهاية عنوان URL لخادم الحوسبة الاتّحادية التي سيتصل بها عميل الحوسبة الاتّحادية.

<!-- Contents of res/xml/OdpSettings.xml -->
<on-device-personalization>
   <!-- Name of the service subclass -->
   <service name="com.example.odpsample.SampleService">
     <!-- If this tag is present, ODP will periodically poll this URL and
          download content to populate REMOTE_DATA. Developers that do not need to
          download content from their servers can skip this tag. -->
     <download-settings url="https://example.com/get" />
     <!-- If you want to use federated compute feature to train a model, you
          need to specify this tag. -->
     <federated-compute-settings url="https://fcpserver.example.com/" />
   </service>
</on-device-personalization>

تفعيل "وضع مطوّر البرامج"

فعِّل وضع المطوّرين باتّباع التعليمات الواردة في قسم تفعيل خيارات المطوّرين ضمن مستندات "استوديو Android".

إعدادات التبديل والإبلاغ

تتضمّن "منصة بيانات Google" مجموعة من مفاتيح التبديل والعلامات التي تُستخدَم للتحكّم في وظائف معيّنة:

  • مفتاح_global_kill: المفتاح العام لجميع ميزات "منصّة بيانات العملاء"، اضبط القيمة على "خطأ" لاستخدام "منصّة بيانات العملاء".
  • ‎_federated_compute_kill_switch: _مفتاح التحكّم في جميع وظائف التدريب (التعلّم الاتحادي) في "منصة تطوير الخصوصية"، ويجب ضبطه على "خطأ" لاستخدام التدريب
  • قائمة _caller_app_allow: تتحكّم هذه القائمة في الجهات المسموح لها باستدعاء ODP، ويمكن إضافة التطبيقات (اسم الحزمة، [اختياري] الشهادة) هنا أو ضبطها على * للسماح للجميع.
  • _isolated_service_allowlist: تتحكّم في الخدمات التي يمكن تشغيلها في عملية Isolated Service.

يمكنك تنفيذ الأوامر التالية لضبط جميع مفاتيح التبديل والعلامات لاستخدام ODP بدون قيود:

# Set flags and killswitches
adb shell device_config set_sync_disabled_for_tests persistent
adb shell device_config put on_device_personalization global_kill_switch false
adb shell device_config put on_device_personalization federated_compute_kill_switch false
adb shell device_config put on_device_personalization caller_app_allow_list \"*\"
adb shell device_config put on_device_personalization isolated_service_allow_list \"*\"

واجهات برمجة التطبيقات على الجهاز

اطّلِع على المستندات المرجعية لواجهة برمجة تطبيقات Android بشأن "البيانات الشخصية المحمية".

التفاعلات مع IsolatedService

فئة IsolatedService هي فئة أساسية مجرّدة يجب أن يوسّعها جميع المطوّرين الذين ينوون التطوير باستخدام ODP، ويجب أن يحدّدوا في ملف بيان الحزمة أنّها تعمل في عملية معزولة. تبدأ خدمة "معالجة البيانات الخاصة" هذه الخدمة في عملية معزولة وتوجّه إليها الطلبات. يتلقّى IsolatedService الطلبات من خدمة ODP وينشئ IsolatedWorker للتعامل مع الطلب.

على المطوّرين تنفيذ الطرق من واجهة IsolatedWorker للتعامل مع طلبات تطبيقات العميل وعمليات التنزيل المكتملة والأحداث التي يتم تشغيلها بواسطة HTML المعروض. تتضمّن جميع هذه الطرق عمليات تنفيذ تلقائية لا تفعل شيئًا، لذا يمكن للمطوّرين تخطّي تنفيذ الطرق التي لا تهمّهم.

يوفّر الصف OnDevicePersonalizationManager واجهة برمجة تطبيقات للتطبيقات وحِزم SDK للتفاعل مع IsolatedService التي ينفّذها المطوّر وتعمل في عملية معزولة. في ما يلي بعض حالات الاستخدام المقصودة:

إنشاء محتوى HTML لعرضه في SurfaceView

لإنشاء محتوى لعرضه باستخدام OnDevicePersonalizationManager#execute، يمكن لتطبيق الاتصال استخدام عنصر SurfacePackageToken الذي تم عرضه في طلب requestSurfacePackage لاحق لطلب عرض النتيجة في SurfaceView .

عند النجاح، يتم استدعاء المستلِم باستخدام SurfacePackage لعرض View الذي تقدّمه خدمة ODP. يجب أن تُدرج تطبيقات العميل SurfacePackage في SurfaceView ضمن بنية العرض.

عندما يرسل تطبيق طلب requestSurfacePackage مع عرض SurfacePackageToken تم إرجاعه من خلال طلب OnDevicePersonalizationManager#execute سابق، تستدعي خدمة ODP الدالة IsolatedWorker#onRender لجلب مقتطف HTML ليتم عرضه في إطار مسوّر. لا يمكن للمطوّر الوصول إلى LocalData أو UserData خلال هذه المرحلة. يمنع ذلك المطوّر من تضمين UserData يُحتمل أن يكون حسّاسًا ضمن عناوين URL لجلب مواد العرض في رمز HTML الذي تم إنشاؤه. يمكن للمطوّرين استخدام IsolatedService#getEventUrlProvider لإنشاء عناوين URL للتتبُّع وتضمينها في رمز HTML الذي تم إنشاؤه. عند عرض HTML، ستعترض خدمة ODP الطلبات الموجّهة إلى عناوين URL هذه وتطلب IsolatedWorker#onEvent. يمكن استدعاء getRemoteData() عند تنفيذ onRender().

تتبُّع الأحداث ضمن محتوى HTML

يوفّر الصف EventUrlProvider واجهات برمجة تطبيقات لإنشاء عناوين URL لتتبُّع الأحداث يمكن للمطوّرين تضمينها في ناتج HTML. عند عرض HTML، ستستدعي ODP IsolatedWorker#onEvent مع حمولة عنوان URL للحدث.

تعترض خدمة ODP الطلبات إلى عناوين URL للأحداث التي تم إنشاؤها في ODP ضمن رمز HTML المعروض، وتطلب IsolatedWorker#onEvent وتسجّل EventLogRecord التي تم إرجاعها في جدول EVENTS.

كتابة نتائج ثابتة

باستخدام OnDevicePersonalizationManager#execute، يمكن للخدمة كتابة البيانات إلى مساحة تخزين ثابتة (جدولَي REQUESTS وEVENTS). في ما يلي الإدخالات التي يمكن كتابتها في هذه الجداول:

  • RequestLogRecord ليتم إضافته إلى جدول REQUESTS
  • قائمة بعناصر EventLogRecord المطلوب إضافتها إلى جدول EVENTS، ويحتوي كل عنصر على مؤشر إلى RequestLogRecord مكتوب سابقًا .

يمكن أن يستخدم التعلّم الموحّد النتائج الثابتة في مساحة التخزين على الجهاز لتدريب النماذج.

إدارة مهام التدريب على الجهاز

تتصل خدمة ODP بالدالة IsolatedWorker#onTrainingExample عندما تبدأ مهمة تدريب الحوسبة الموحّدة وتريد الحصول على أمثلة تدريب يقدّمها المطوّرون الذين يستخدمون ODP. يمكنك استدعاء getRemoteData() وgetLocalData() وgetUserData() وgetLogReader() عند تنفيذ onTrainingExample().

لتحديد موعد لوظائف الحوسبة الاتّحادية أو إلغائها، يمكنك استخدام الفئة FederatedComputeScheduler التي توفّر واجهات برمجة تطبيقات لجميع IsolatedService في ODP. يمكن تحديد كل مهمة حسابية موحّدة من خلال اسم المجموعة.

قبل جدولة مهمة حسابية جديدة موحّدة:

  • يجب أن تكون مهمة بهذا الاسم قد تم إنشاؤها على خادم الحوسبة الاتّحادية البعيد.
  • يجب أن تكون نقطة نهاية عنوان URL لخادم الحوسبة الاتّحادية محدّدة مسبقًا في إعدادات بيان الحزمة باستخدام العلامة federated-compute-settings.

التفاعلات مع الناتج المستمر

يوضّح القسم التالي كيفية التفاعل مع الناتج الثابت في ODP.

قراءة الجداول المحلية

توفر الفئة LogReader واجهات برمجة تطبيقات لقراءة الجدولَين REQUESTS وEVENTS. تحتوي هذه الجداول على بيانات كتبها IsolatedService أثناء مكالمات onExecute() أو onEvent(). يمكن استخدام البيانات في هذه الجداول لتدريب النماذج باستخدام التعلّم الاتحادي، أو لإجراء تحليل إحصائي على مستوى الأجهزة باستخدام "التحليلات الموحّدة".

التفاعلات مع المحتوى الذي تم تنزيله

يوضّح القسم التالي كيفية التفاعل مع المحتوى الذي تم تنزيله في ODP.

تنزيل المحتوى من الخوادم

تنزّل خدمة ODP المحتوى بشكل دوري من عنوان URL المحدّد في بيان الحزمة IsolatedService، وتطلب onDownloadCompleted بعد انتهاء عملية التنزيل. التنزيل هو ملف JSON يحتوي على أزواج المفاتيح والقيم.

يمكن للمطوّرين الذين يستخدمون ODP اختيار المجموعة الفرعية من المحتوى الذي تم تنزيله والتي يجب إضافتها إلى جدول RemoteData والمجموعة التي يجب حذفها. لا يمكن للمطوّرين تعديل المحتوى الذي تم تنزيله، ما يضمن عدم احتواء جدول RemoteData على أي بيانات للمستخدمين. بالإضافة إلى ذلك، يمكن للمطوّرين ملء جدول LocalData بالطريقة التي يختارونها، على سبيل المثال، يمكنهم تخزين بعض النتائج المحسوبة مسبقًا مؤقتًا.

تنسيق طلب التنزيل

يطلب ODP بشكل دوري نقطة نهاية عنوان URL المحدّدة في بيان الحزمة الخاص بالمطوّر لجلب المحتوى لتعبئة جدول RemoteData.

من المتوقّع أن تعرض نقطة النهاية استجابة JSON كما هو موضّح لاحقًا. يجب أن تتضمّن استجابة JSON syncToken تحدّد إصدار البيانات التي يتم إرسالها، بالإضافة إلى قائمة بأزواج المفاتيح والقيم التي سيتم ملؤها. يجب أن تكون قيمة syncToken طابعًا زمنيًا بالثواني، ويجب أن تكون ضمن حدود ساعة بالتوقيت العالمي المتفق عليه. في إطار طلب التنزيل، يوفّر ODP syncToken لعملية التنزيل المكتملة سابقًا وبلد الجهاز كمَعلمتَي syncToken وcountry في عنوان URL الخاص بالتنزيل. يمكن للخادم استخدام syncToken السابق لتنفيذ عمليات التنزيل التزايدي.

تنسيق ملف التنزيل

الملف الذي يتم تنزيله هو ملف JSON بالبنية التالية. من المتوقّع أن يحتوي ملف JSON على syncToken لتحديد إصدار البيانات الذي يتم تنزيله. يجب أن يكون syncToken عبارة عن طابع زمني بالتوقيت العالمي المتفق عليه (UTC) ومثبّت على حدود الساعة، ويجب أن يتجاوز syncToken عملية التنزيل السابقة. إذا لم يستوفِ الرمز المميز للمزامنة كلا الشرطَين، يتم تجاهل المحتوى الذي تم تنزيله بدون معالجته.

حقل "المحتويات" هو قائمة من مجموعات (مفتاح، بيانات، ترميز). من المتوقّع أن تكون key سلسلة UTF-8. الحقل encoding هو مَعلمة اختيارية تحدّد طريقة ترميز الحقل data. ويمكن ضبطه على "utf8" أو "base64"، ويُفترض أن يكون "utf8" تلقائيًا. يتم تحويل الحقل key إلى عنصر String ويتم تحويل الحقل data إلى مصفوفة بايت قبل استدعاء onDownloadCompleted().

{
  // syncToken must be a UTC timestamp clamped to an hour boundary, and must be
  // greater than the syncToken of the previously completed download.
  "syncToken": <timeStampInSecRoundedToUtcHour>,
  "contents": [
    // List of { key, data } pairs.
    { "key": "key1",
      "data": "data1"
    },
    { "key": "key2",
      "data": "data2",
      "encoding": "base64"
    },
    // ...
  ]
}

واجهات برمجة التطبيقات من جهة الخادم

يوضّح هذا القسم كيفية التفاعل مع واجهات برمجة التطبيقات لخادم الحوسبة الاتّحادية.

Federated Compute Server APIs

لجدولة مهمة حوسبة اتحادية على جهاز العميل، تحتاج إلى مهمة تتضمّن اسم مجموعة تم إنشاؤها على خادم الحوسبة الاتحادية البعيد. في هذا القسم، سنتناول كيفية إنشاء مهمة من هذا النوع على خادم الحوسبة الاتّحادية.

مخطّط طوبولوجيا خادم العميل للحوسبة الموحّدة

عند إنشاء مهمة جديدة في "أداة إنشاء المهام"، على مطوّري ODP تقديم مجموعتَين من الملفات:

  1. نموذج tff.learning.models.FunctionalModel محفوظ من خلال طلب بيانات من واجهة برمجة التطبيقات tff.learning.models.save_functional_model يمكنك العثور على نموذج واحد في مستودع GitHub.
  2. ملف fcp_server_config.json يتضمّن السياسات وإعدادات التعلّم الاتحادي وإعدادات الخصوصية التفاضلية في ما يلي مثال على fcp_server_config.json:
{
  # Task execution mode.
  mode: TRAINING_AND_EVAL
  # Identifies the set of client devices that participate.
  population_name: "mnist_cnn_task"
  policies {
    # Policy for sampling on-device examples. It is checked every
    # time a device is attempting to start a new training.
    min_separation_policy {
      # The minimum separation required between two successful
      # consective task executions. If a client successfully contributes
      # to a task at index `x`, the earliest they can contribute again
      # is at index `(x + minimum_separation)`. This is required by
      # DP.
      minimum_separation: 1
    }
    data_availability_policy {
      # The minimum number of examples on a device to be considered
      # eligible for training.
      min_example_count: 1
    }
    # Policy for releasing training results to developers adopting ODP.
    model_release_policy {
      # The maximum number of training rounds.
      num_max_training_rounds: 512
    }
  }

  # Federated learning setups. They are applied inside Task Builder.
  federated_learning {
    # Use federated averaging to build federated learning process.
    # Options you can choose:
      # * FED_AVG: Federated Averaging algorithm
      #            (https://arxiv.org/abs/2003.00295)
      # * FED_SGD: Federated SGD algorithm
      #            (https://arxiv.org/abs/1602.05629)
    type: FED_AVG
    learning_process {
      # Optimizer used at client side training. Options you can choose:
      # * ADAM
      # * SGD
      client_optimizer: SGD
      # Learning rate used at client side training.
      client_learning_rate: 0.02
      # Optimizer used at server side training. Options you can choose:
      # * ADAM
      # * SGD
      server_optimizer: SGD
      # Learning rate used at server side training.
      server_learning_rate: 1.0
      runtime_config {
        # Number of participating devices for each round of training.
      report_goal: 2
      }
      metrics {
        name: "sparse_categorical_accuracy"
      }
    }
    evaluation {
      # A checkpoint selector controls how checkpoints are chosen for
      # evaluation. One evaluation task typically runs per training
      # task, and on each round of execution, the eval task
      # randomly picks one checkpoint from the past 24 hours that has
      # been selected for evaluation by these rules.
      # Every_k_round and every_k_hour are definitions of quantization
      # buckets which each checkpoint is placed in for selection.
      checkpoint_selector: "every_1_round"
      # The percentage of a populate that should delicate to this
      # evaluation task.
      evaluation_traffic: 0.2
      # Number of participating devices for each round of evaluation.
      report_goal: 2
    }
  }

  # Differential Privacy setups. They are enforced inside the Task
  # Builder.
  differential_privacy {
    # * fixed_gaussian: DP-SGD with fixed clipping norm described in
    #                   "Learning Differentially Private Recurrent
    #                   Language Models"
    #                   (https://arxiv.org/abs/1710.06963).
    type: FIXED_GAUSSIAN
    #   The value of the clipping norm.
    clip_norm: 0.1
    # Noise multiplier for the Gaussian noise.
    noise_multiplier: 0.1
  }
}

يمكنك العثور على المزيد من النماذج في مستودع GitHub.

بعد إعداد هذين المدخلَين، استدعِ "أداة إنشاء المهام" لإنشاء العناصر وإنشاء مهام جديدة. تتوفّر تعليمات أكثر تفصيلاً في مستودع GitHub.