لا داعي للاختيار بين سهولة استخدام الذكاء الاصطناعي الجاهز ومرونة النماذج المخصّصة، إذ يمكنك نشر كليهما في تطبيق واحد بسيط للغاية بدون إضافة ميغابايت من البيانات الثنائية غير الضرورية.
في هذه الجلسة، سنوضّح كيفية إنشاء هذه البنية المزدوجة في تطبيق Android واحد. وسنرى كيفية الاستفادة من حزمة تعلّم الآلة في مهام تعلّم الآلة الكلاسيكية الجاهزة للاستخدام (مثل مسح المستندات ضوئيًا) إلى جانب LiteRT المستقل في "خدمات Google Play" لأعباء عمل الرؤية الحاسوبية أو الصوت المخصّصة. سنستكشف بعمق كيف يتّحد مسارا التنفيذ في الخلفية للاستفادة من بيئة التشغيل الحديثة LiteRT، ما يمنح تطبيقك أداءً سلسًا ومسرَّعًا على مستوى الأجهزة في وحدة المعالجة المركزية ووحدات معالجة الرسومات مع حجم تنزيل يبلغ صفر بايت تقريبًا.
النقاط الرئيسية التي يجب أن يراعيها المطوّرون:
-أداء لا مثيل له: يتم تسريع الأجهزة تلقائيًا لكل من النماذج الجاهزة والمخصّصة باستخدام واجهة برمجة التطبيقات CompiledModel الموحّدة.
-ملفات APK الصغيرة: يمكنك تقليل حجم تنزيل تطبيقك بشكل كبير من خلال تخفيف الحِمل عن وقت تشغيل كل من حزمة تعلّم الآلة وLiteRT إلى خدمات Play.
- الدمج المختلط: تعلَّم كيفية تشغيل عدة مهام تعلُّم آلي جنبًا إلى جنب في بيئة الإنتاج بدون تضارب في الموارد.
play-services-litert، واستدعاء LiteRt.initialize للحصول على بيئة، وتمريرها إلى CompiledModel.create.النص
مساء الخير جميعًا.
نحن على وشك بدء المحادثة.
لذلك، عندما يقول الأشخاص "الذكاء الاصطناعي على الجهاز فقط" اليوم، فإنّهم غالبًا ما يقصدون النماذج اللغوية الكبيرة.
واليوم، شاهدتم عدة جلسات حول Gemini Nano تم تناولها مع حزمة تعلّم الآلة وFirebase والعديد من منتجات Google الأخرى.
تتناول هذه الجلسة النصف الآخر: تعلُّم الآلة الكلاسيكي والنموذج الذي تستخدمه بنفسك.
من المحتمل أنّك استخدمته بضع مرات اليوم بدون أن تدرك ذلك.
فكِّر في استخدام أي من تطبيقاتك التي طمست فيها الخلفية أو استخدمت ماسحًا ضوئيًا للرمز الشريطي أو استخدمت نوعًا من أنواع تعديل الصور.
وقد تم تنفيذ الكثير من ذلك على تعلُّم الآلة الكلاسيكي، وعادةً ما يتم تشغيله على الجهاز فقط.
إذا سبق لك إضافة أي من هذه الميزات إلى تطبيقك أو حزمة APK، فغالبًا ما واجهت هذه المفاضلة: هل أستخدم واجهة برمجة تطبيقات جاهزة للاستخدام، أم أستخدم النموذج الخاص بي؟
ما هو التأثير في حجم تطبيقي؟
اليوم، لن تضطروا إلى الاختيار بين نموذج جاهز أو نموذج خاص بكم.
يمكنك في الواقع تنفيذ كلا الإجراءَين باستخدام وقت تشغيل بسيط واحد.
اسمي "شينتان باريخ".
أنا مدير منتجات LiteRT، ومعي "فيرغوس"، رئيس قسم الهندسة في خدمات تعلُّم الآلة في Android.
مرحبًا.
وفي النهاية، ستتعرّف على كيفية إنشاء تطبيق واحد يشغّل نموذجين على كل لقطة كاميرا بمعدّل 30 لقطة في الثانية تقريبًا.
هناك أربعة أجزاء في هذه المحاضرة.
في الجزء الأول، سنتحدّث عن حلول الذكاء الاصطناعي على الجهاز فقط من Google مع التركيز على تعلُّم الآلة الكلاسيكي، أي حزمة تعلُّم الآلة وLiteRT.
ثانيًا، سنستعرض الميزات الجديدة في LiteRT وخدمات Play أيضًا.
سنتناول أيضًا واجهة برمجة التطبيقات CompiledModel الجديدة من LiteRT والأجهزة المتوافقة معها.
ثالثًا، سنوضّح لك كيفية إنشاء تطبيق جديد.
سيشرح "فيرغوس" كيفية إنشاء تطبيق باستخدام حزمة تعلّم الآلة ونموذج مخصّص في حزمة APK واحدة.
أخيرًا، سنوضّح لك كيفية ترقية تطبيق حالي باستخدام "وضع الوكيل".
ويمكنك أيضًا إنشاء تطبيق جديد باستخدام هذا الوكيل.
حسنًا.
لنبدأ أولاً بتعريف LiteRT.
LiteRT هو وقت تشغيل الاستدلال على الجهاز فقط من Google لنماذجك الخاصة.
ويستخدم تنسيق الملف .tflite نفسه الذي استخدمته من قبل مع TensorFlow Lite.
تمت إعادة تصميمه لتحسين الأداء، كما أنّه يتيح استخدام إطارات عمل متعددة.
وهذا يعني أنّه يمكنك جلب نماذج من PyTorch وTensorFlow وحتى JAX لتقليلها إلى تنسيق مخزن مؤقت مسطّح لـ LiteRT.
منذ عام 2022، أصبح TensorFlow Lite في "خدمات Google Play" هو وقت التشغيل الرسمي على الجهاز فقط على أجهزة Android للنماذج المخصّصة.
واليوم، سيتم إجراء ترقية كبيرة على هذا النموذج، وهذا ما سنتحدث عنه في معظم هذه الجلسة.
ستوفّر الترقية أحدث واجهة برمجة تطبيقات LiteRT CompiledModel، بما في ذلك استنتاج جديد ومحسّن لوحدة معالجة الرسومات سيكون أسرع بمقدار 1.4 مرة، كما ستتيح لك إنشاء تطبيقات أصغر حجمًا في حِزم APK أصغر بكثير.
إذًا، لماذا يتم توفيرها من خلال خدمات Play؟
هناك بعض المزايا، وهذه بالتأكيد مشكلة كبيرة أراها في الكثير من المحادثات التي أسمعها حيث أصبح حجم التطبيق وتضخم حزمة APK يمثلان تحديًا حقيقيًا، أليس كذلك؟
وبالتالي، يمنحك وقت تشغيل صغير.
لا يتوفّر وقت التشغيل في حزمة APK، لذا يمكنك الاعتماد على كمبيوتر تابع جزئيًّا، ما يجعل حزمة APK أصغر حجمًا بمقدار 8 ميغابايت تقريبًا.
الفائدة الثانية هي الكفاءة.
لديك نسخة واحدة من وقت التشغيل، لذا تتم مشاركة وقت التشغيل LiteRT مع جميع التطبيقات.
لذا، يمكنك تخيّل أنّه إذا كان لديك العديد من التطبيقات، يمكن أن يوفّر كل منها 8 ميغابايت.
ويزداد هذا العدد بسرعة كبيرة عندما تحاول توفير مساحة على القرص والحصول على تطبيق أصغر حجمًا.
ثانيًا، تتم صيانته.
توفّر Google إصلاحات الأخطاء، وتعالج المشاكل المتعلّقة ببرامج تشغيل وحدة معالجة الرسومات التي لن تضطر إلى معالجتها، كما أنّ أي تحديثات أمان أخرى يتم إجراؤها من خلال التحديثات التلقائية.
وكما ذكرت، فإنّ وحدة معالجة الرسومات أسرع بمقدار 1.4 مرة، وسنتناول ذلك بمزيد من التفصيل أيضًا.
ومن ناحية التغطية، يمكننا الشحن إلى أجهزة Android القديمة.
تتوفّر LiteRT في "خدمات Play" على جميع الإصدارات السابقة حتى Android 7 من عام 2016.
وكما سيوضّح لكم "فيرغوس" أيضًا، سنعرض في الشرائح التالية الأجهزة الجديدة الأخرى التي سنوفّر عليها هذه الميزة.
هذه هي وسيلة التسليم، ولنتحدّث عن الخطوة التالية، وهي وقت التشغيل.
بالتالي، LiteRT ليس جديدًا وليس تجريبيًا.
يتم حاليًا تشغيل TensorFlow Lite وLiteRT في أكثر من 250,000 تطبيق.
ويعمل أيضًا على أكثر من 3.8 مليار جهاز اليوم.
لذا، فإنّ الكثير من التطبيقات التي قد تستخدمونها، قد لا تعرفون حتى أنّها تعمل كلّها على هذا الأساس.
وهذا يعادل أيضًا أكثر من تريليون استنتاج كل يوم، أليس كذلك؟
بهذا الحجم، واجهنا بالتأكيد كل مشكلة غريبة في شرائح التعريف، وتمكّنا من معالجة مشاكل ذاكرة القراءة فقط (ROM) أو مشاكل برامج تشغيل وحدة معالجة الرسومات (GPU)، ولدينا حل بديل لك فقط.
تستخدم Google أيضًا LiteRT في تطبيقاتها الرئيسية، على مستوى التطبيقات والمنصات وحتى الأجهزة المتعددة.
ومن الأمثلة على ذلك تأثيرات YouTube Shorts، وتقسيم الخلفية في Meet، وميزة "إزالة التمويه"، حيث يتم تشغيل نماذج الفيديو في الوقت الفعلي ونماذج الصور الثقيلة على LiteRT.
هذا أيضًا مهم للغاية لأنّ حالات الاستخدام السريعة والجذابة للمستخدمين تصبح بالغة الأهمية، أليس كذلك؟
هذا هو وقت التشغيل نفسه الذي عزّزنا أمانه لهذه الميزات الرئيسية، وهو ما تحصل عليه من خلال خدمات Play.
لنتحدّث أيضًا عن سبب استخدام الذكاء الاصطناعي على الجهاز فقط.
إذا كان يهمّك وقت الاستجابة أو الخصوصية أو العمل بلا إنترنت أو التكاليف المنخفضة، يمكنك تشغيل النموذج بلا إنترنت.
قد تكون هناك أسباب أخرى، ولكن هذه بعض الأسباب الأكثر وضوحًا التي سمعناها لتشغيل النماذج على الجهاز فقط.
لا يكون تشغيل النماذج على الجهاز مجانيًا دائمًا.
هناك بعض الفروق الدقيقة وبعض التحديات.
لذا، سنستعرض أيضًا بعض هذه التحديات وسنقدّم لك مسارًا للمضي قدمًا أيضًا.
لنتحدّث الآن عن الأداء: كما رأيتم في بعض الأمثلة من التطبيقات السابقة، تكون ميزانيات وقت الاستجابة والذاكرة محدودة دائمًا، أليس كذلك؟
يتطلّب الفيديو والصوت في الوقت الفعلي كفاءة فائقة.
حتى الميزات التفاعلية البسيطة يجب أن تكون سريعة.
وإلا، فستفقد تفاعل المستخدمين.
تنوّع الأجهزة: هناك مئات المنظومات على الرقاقة (SoC) التي تتضمّن إعدادات مختلفة لوحدات المعالجة المركزية (CPU) ووحدات معالجة الرسومات (GPU).
لا يمكنك كتابة رمز برمجي لكل هذه الحالات، أليس كذلك؟
كيف يمكنك حلّ أي من هذه المشاكل؟
حجم ملف APK: يؤدي تجميع بيئة تشغيل أصلية أيضًا إلى زيادة حجم كل عملية تنزيل، ما قد يؤثر في معدلات الإحالات الناجحة.
التخصيص: تدريب النموذج وجودته وحجمه، كل هذه الأمور ستكون بالغة الأهمية قبل النشر.
لذا، قد يكون إنشاء تطبيق رائع يعمل على الجهاز أمرًا صعبًا.
ولكن في كل من هذه الحالات، نريد أن تؤدي المنصة العمل نيابةً عنك وليس العكس، أليس كذلك؟
وتتوفّر مجموعة منتجات Google على الجهاز فقط لمواجهة هذه التحديات، وسنتناول ذلك بعد قليل.
لذا، سنركّز على حلَّين بسيطَين اليوم.
هناك طريقتان سهلتان لإضافة الذكاء الاصطناعي على الجهاز فقط من خلال "خدمات Play".
المسار الأول هو المسار الجاهز للاستخدام الذي يعتمد على "حزمة تعلّم الآلة"، أليس كذلك؟
وهي واجهات برمجة تطبيقات جاهزة للاستخدام في مجال الرؤية واللغة، وتتطلّب خبرة محدودة في تعلُّم الآلة، وتتوفّر العديد من النماذج ويتم تقديمها جميعًا من خلال "خدمات Play".
وسنستعرض بعض الأمثلة على ذلك في الشرائح التالية.
المسار المخصّص، ويتم من خلال LiteRT.
تتيح لك LiteRT استخدام نموذجك الخاص وتشغيله على وحدة المعالجة المركزية (CPU) ووحدة معالجة الرسومات (GPU).
وتأتي بيئة التشغيل من خدمات Play أيضًا.
لذلك، لا يتم تجميعها في حزمة APK.
هذه ليست إما أو.
ويمكن أن يكونا أفضل معًا أيضًا.
وهذا بالضبط ما سننشئه اليوم في الدقائق القليلة القادمة.
لنتحدّث أولاً عن الميزات التي توفّرها "حزمة تعلّم الآلة".
في ما يلي ما تغطّيه "حزمة تعلّم الآلة" بشكل تلقائي.
لذا، إذا كنت تعتقد أنّ بعض هذه الإمكانات تلبي احتياجاتك، فهذه نقطة بداية رائعة، وستكون لديك ميزة إضافية.
لدينا تغطية للرؤية، والرموز الشريطية، والمستندات، والنصوص، والوضعيات، والعديد من هذه الإمكانات، وواجهات برمجة التطبيقات اللغوية مثل الترجمة، والردود الذكية، وحتى استخراج الكيانات، أليس كذلك؟
النقطة الأساسية هي أنّ العديد من واجهات برمجة التطبيقات هذه الخاصة بالرؤية واللغة تعمل جميعها مع LiteRT بشكل غير مرئي.
لذا، إذا كانت "حزمة تعلّم الآلة" تلبّي احتياجاتك، يمكنك البدء من هنا.
وإذا لم يكن الأمر كذلك، يمكنك استخدام نموذجك الخاص.
وهنا تكمن النقطة الأساسية: لن تكون حزمة تعلّم الآلة ونموذجك المخصّص بيئتَي تشغيل، كما ذكرتُ.
يمكنك اعتبارهما كبابَين أماميَين يؤديان إلى LiteRT نفسه الذي سيتم تشغيله في الخلفية.
لذا، سيكون LiteRT هو بيئة التشغيل التي ستنسّق بين هاتين الإمكانيتين.
لذا، إذا كان تطبيقك يستخدم "متجر Google Play"، يمكنك استخدام "حزمة تعلّم الآلة".
بخلاف ذلك، سنراجع مسار LiteRT أيضًا.
لنتعرّف أيضًا على الميزات الجديدة في LiteRT.
كما ذكرت، LiteRT هو تطوّر لـ TensorFlow Lite، أليس كذلك؟
لذا، فإنّ أكبر التحسينات هي أنّ لدينا وحدة معالجة رسومات أسرع.
تدعم وحدة معالجة الرسومات الأسرع OpenCL وOpenGL، كما أنّها متوافقة مع عدّة منصات حتى مع الخلفيات المعدنية.
لذا، يمكنك بالتأكيد استخدام هذا لعدة منصات حسب الحاجة.
وهي أيضًا أبسط.
لدينا سير عمل موحّد لتسريع وحدة المعالجة المركزية (CPU) ووحدة معالجة الرسومات (GPU) ووحدة المعالجة العصبية (NPU).
تتوفّر حاليًا وحدة المعالجة المركزية (CPU) ووحدة معالجة الرسومات (GPU) في خدمات Play، بينما يتم تجميع وحدة المعالجة العصبية (NPU) من خلال LiteRT حاليًا، وهذا العمل قيد التطوير.
في السابق، كان كل مسرِّع يتطلب إعدادًا مختلفًا للمفوَّض، أليس كذلك؟
ما عليك سوى إجراء ذلك مرة واحدة الآن.
وبالتالي، هناك واجهة برمجة تطبيقات واحدة تعود تلقائيًا إلى وحدة المعالجة المركزية، ولن تحتاج إلى إجراء عمليات إعداد مخصّصة ومفوَّضة.
ويمكنك فقط إجراء مكالمات تسريع يمكنها إدارة هذا الأمر ببساطة أكبر وبكود أقل.
وهو أيضًا نموذج فعّال، إذ يعمل على منصات متعددة، كما ذكرتُ.
سيكون هذا أمرًا بالغ الأهمية، وهو جزء المرونة منه.
وبالتالي، يبقى تنسيق .tflite كما هو.
إذا كان لديك تطبيق حالي، سيظل بإمكانك استخدام هذا التنسيق.
إذا كنت بصدد إنشاء تطبيق جديد، يمكنك استخدام تنسيق الملف هذا مرة أخرى.
من المثير للاهتمام أيضًا أنّنا نتيح استخدام Interpreter API التي كانت متوفّرة في TensorFlow Lite.
لذا، إذا أردت نقل البيانات على مراحل، يمكنك استخدام Interpreter API المضمّنة في LiteRT الجديد، ما يسهّل عليك عملية النقل.
هذا هو وقت التشغيل.
لنتحدّث عمّا يمكنك إنشاؤه باستخدام هذه الميزة.
إليك ما يتم إنشاؤه اليوم في تطبيقات Android.
كل شيء بدءًا من تأثيرات الكاميرا وتعديل الصور والكتابة الذكية والألعاب والصور الرمزية، أليس كذلك؟
ستحتاج الكثير من هذه التطبيقات إلى إمكانات في الوقت الفعلي.
ترسل وحدة معالجة الرسومات اللقطات مباشرةً من الكاميرا، لذا من المهم أن تكون الاستجابة سريعة وفي الوقت الفعلي.
أصبحت بعض نماذج تعديل الصور هذه أكبر حجمًا أيضًا.
وينطبق الأمر نفسه على إمكانات الواقع المعزّز والواقع الافتراضي التي رأيتموها أيضًا في بعض العروض التوضيحية مع النظارات، فالكثير منها يشغّل LiteRT في الخلفية.
وهي بيئة التشغيل نفسها التي تستند إليها الآن ميزات Google الرئيسية، وتتوفّر أيضًا في خدمات Play، ما يتيح لك الاستفادة من كل هذه المزايا بدون الحاجة إلى تجميع أي شيء في حزمة APK.
والآن، لِمَ لا ننشئ تطبيقًا؟ سيشرح لنا "فيرغوس" كيفية إجراء ذلك.
لنقم بذلك.
شكرًا لك، شينتان.
سأتحدث قليلاً عن الميزات الجديدة في LiteRT في "خدمات Google Play".
قبل أن نبدأ عملية الإنشاء، لدينا خبر آخر، وهو أنّ كل ما رأيتموه للتو يعمل الآن على أجهزة أخرى غير الهاتف، فإطار عمل LiteRT في خدمات Play متاح أيضًا على نظامَي التشغيل Wear OS ونظام التشغيل Android Automotive.
وبالتالي، يمكنك تشغيل النماذج على ساعتك أو أي جهاز آخر قابل للارتداء أو في السيارة نفسها.
في السابق، كان من الممكن استخدام تطبيق على هاتفك ليكون تطبيقًا مصاحبًا لنظام Wear، ولكن يمكنك الآن تشغيله فعليًا على الجهاز القابل للارتداء نفسه، وكذلك مع Android Automotive.
وبالتالي، يمكنك استخدام واجهة برمجة التطبيقات نفسها ونموذج .tflite نفسه، ولكن على مساحات عرض أكثر.
ولست بحاجة إلى تنفيذ منفصل لكل شكل جهاز، بل يمكنك استخدام التنفيذ نفسه لجميع هذه الأجهزة المختلفة.
ويكمن جمال نموذج توزيع "خدمات Play" في أنّه يمكننا نقل هذه الميزة لتعمل على الأجهزة القديمة.
بالنسبة إلى نظام التشغيل Android Automotive، نتيح الإصدارات القديمة حتى Android 11 الذي تم إطلاقه في عام 2020، وبالنسبة إلى Wear OS، نتيح الإصدار Wear OS 4 والإصدارات الأحدث.
حسنًا
سأتحدث الآن عن مسارَين مختلفَين، وهما إنشاء تطبيق جديد وترقية تطبيق حالي.
هذا ما سنغطيه في بقية الحديث.
لذا، سأبدأ بمثال لتطبيق يجمع بين استخدام "حزمة تعلّم الآلة" ونموذج GPU مخصّص يعمل على LiteRT.
ولترقية تطبيق حالي، سيكون هناك ثلاثة تغييرات صغيرة، وهي تغيير في Gradle لتحديث التبعيات، وتغيير في init لتفعيل LiteRT في خدمات Play، ثم التبديل من Interpreter API إلى واجهة برمجة التطبيقات CompiledModel.
لكننا سنقوم بذلك في التطبيق الجديد أولاً، لأن الترقية تكون أكثر منطقية بمجرد أن ترى ما تقوم بالترقية إليه.
لذا، فإن إنشاء تطبيق جديد.
إليك التطبيق الذي سننشئه.
ستظهر صورة واضحة لك من الكاميرا المباشرة، وستحصل الخلفية على نمط فني.
لذا، سنأخذ إطار الكاميرا.
سنعرض الصور من إطار الكاميرا من خلال ميزة "تقسيم صور السيلفي" في "حزمة تعلّم الآلة".
وهي إحدى واجهات برمجة التطبيقات الجاهزة للاستخدام في حزمة تعلّم الآلة.
وسيؤدي ذلك إلى إنشاء قناع للمقدمة يحدد بشكل أساسي وحدات البكسل في الصورة التي تتوافق مع الشخص في الصورة.
بعد ذلك، سنستخدم نموذجنا المخصّص، وهو نموذج من نوع نقل النمط، لتطبيق نمط على صورة.
وسنطبّق ذلك على إطار الكاميرا بالكامل، ولكنّنا نهتمّ فقط بجزء الخلفية، لأنّنا في النهاية سنأخذ إطار الكاميرا الأصلي والقناع والخلفية ذات النمط، وسنجمعها معًا باستخدام منطق بسيط، لنحصل على إطار مركّب نحتفظ فيه بالموضوع، وتكون الخلفية ذات النمط.
لذلك، نريد أن نستخدم واجهات برمجة التطبيقات الجاهزة حيثما توجد، وواجهات برمجة التطبيقات المخصصة حيثما تميز تطبيقنا.
هذا هو الجزء الأول الذي نستدعي فيه واجهة برمجة التطبيقات الخاصة بتقسيم صور السيلفي في حزمة تعلّم الآلة.
// 1. Configure and create segmenter client
val segmenter = Segmentation.getClient(
SelfieSegmenterOptions.Builder()
.setDetectorMode(
SelfieSegmenterOptions.STREAM_MODE)
.build())
// 2. Prepare image & run inference
fun processFrame(mediaImage: Image) {
val image = InputImage.fromMediaImage(
mediaImage, /* rotationDegrees= */ 0)
segmenter.process(image)
.addOnSuccessListener { mask -> … }
}إذًا، هذا يشبه واجهة برمجة التطبيقات العادية، أليس كذلك؟
هذا يشبه تمامًا الخبز والزبدة لمطوّري برامج Android.
يمكنك الاطّلاع على مستندات واجهة برمجة التطبيقات أو الطلب من Gemini إنشاء التطبيق نيابةً عنك.
لكنّ الأمر بسيط إلى حدّ ما.
يمكنك إنشاء عميل وتمرير بعض الخيارات عند إنشاء العميل.
في هذه الحالة، نحدّد وضع البث لنتمكّن من معالجة سلسلة من إطارات الفيديو.
بعد ذلك، هناك طريقة استدعاء لهذه العملية، وسيؤدي رد الاتصال من ذلك إلى الحصول على القناع الذي يتم عرضه، والذي يتم حسابه من خلال تقسيم صور السيلفي.
والإدخال هو الصورة من الكاميرا.
وجميع واجهات برمجة التطبيقات هذه تستخدم أنواعًا على مستوى التطبيق، وليس موترات أولية، لذا فأنت تبرمج حقًا على مستوى عالٍ جدًا وهذا واضح ومباشر حقًا.
لذلك، في الجزء الثاني، وهو النموذج المخصّص، سنستخدم نموذج PyTorch.
أعتقد أنّ "شينتان" حصل على هذا النموذج من Kaggle أو Hugging Face…
صحيح؟
نعم، أو يمكنك تحويل ملفاتك الخاصة.
يمكنك إنشاء نموذجك الخاص.
عُذْرًا، سَأَعُودْ إِلَى الْخَلْفْ.
نعم، هذا هو شكل هذه المجموعة.
يمكنك أخذ نموذج PyTorch وتحويله وتكميمه، ثم الحصول على نموذج LiteRT.
بعد ذلك، يمكنك توزيع هذا الملف مع تطبيقك كيفما تشاء.
ويمكن تجميعها كجزء من التطبيق كمادة عرض أو يمكن تنزيلها بشكل منفصل.
كلا الطريقتين تعملان.
ويتم بعد ذلك تثبيت هذه الحزمة فوق وقت تشغيل LiteRT في خدمات Play.
بعد ذلك، هناك نواة وحدة المعالجة المركزية (CPU) للتحسين على وحدة المعالجة المركزية (CPU)، وML Drift هو اسم مسرِّع وحدة معالجة الرسومات (GPU).
نعم، كما قلت، يمكنك الحصول على نموذج TFLite، ويمكنك إما تدريب النموذج بنفسك، أو العثور على نموذج موجود، في كلتا الحالتين يعمل.
يتطلب التحويل من PyTorch بضعة أسطر فقط من Python.
import litert_torch
model = my_models.Stylizer().eval()
# Convert with torch.export under the hood
edge_model = litert_torch.convert(
model, sample_inputs)
edge_model.export("stylizer_f32.tflite")لذا، يمكنك تثبيت LiteRT-Torch باستخدام pip، واستدعاء litert_torch.convert، وتمرير بعض sample_inputs التي يمكن أن تكون مدخلات عشوائية، وتصدير ملف TFLite.
بالمناسبة، LiteRT-Torch هو الاسم الجديد لـ ai-edge-torch، إذا كنت على دراية به.
بعد ذلك، تكون عملية التكميم واضحة جدًا.
# Python
# previously ai_edge_quantizer
from litert_quantizer import quantizer, recipe
qt = quantizer.Quantizer("stylizer_f32.tflite")
# int8 weights, float activations
qt.load_quantization_recipe(
recipe.dynamic_wi8_afp32())
qt.quantize().export_model("stylizer_int8.tflite")يمكنك استيراد أداة القياس الكمّي والوصفة من LiteRT Quantizer.
عند إنشاء أداة القياس، يتم تمرير نموذج النقطة العائمة الأصلي، وتمرير وصفة، وهي الوصفة العادية التي نستخدمها وننصح بها لوحدة معالجة الرسومات، والتي تستخدم أوزان أعداد صحيحة بحجم 8 بت، ولكنها تحتفظ بالتنشيطات كنقطة عائمة بحجم 32 بت.
بعد ذلك، ما عليك سوى استدعاء quantize ثم export_model لحفظ نموذج الناتج.
وسيكون هذا نموذجًا مكمّمًا يمكنك تشغيله بعد ذلك، وسيكون له أوزان أصغر بكثير، وسيتم تنفيذه بكفاءة أكبر.
حسنًا، واجهة برمجة التطبيقات CompiledModel ووحدة معالجة الرسومات هما ما يميّز هذا الجهاز.
كما ذكر "شينتان"، هناك زيادة كبيرة في السرعة مقارنةً بوحدة معالجة الرسومات القديمة في TFLite.
ستختلف الأرقام الدقيقة قليلاً من نموذج إلى آخر، ولكن 1.4 مرة هو ما يمكنك توقّعه بشكل معقول.
أسرع بما يصل إلى 10 مرات من الاستنتاج لدى وحدة المعالجة المركزية، وهذا هو الإنجاز الكبير، أليس كذلك؟
إذا كنتم تستخدمون النماذج اليوم، فمن المحتمل أنّكم تشغّلونها على وحدة المعالجة المركزية، وتفوتكم فرصة تحسين الأداء بمقدار 10 أضعاف تقريبًا من خلال وحدة معالجة الرسومات.
لذا، هذا حافز حقيقي.
ما الذي يجعله سريعًا؟
حسنًا، هناك مجموعة من الميزات التي نتيحها، على سبيل المثال، التنفيذ غير المتزامن، بحيث يمكنك أخذ AHardwareBuffer وتمريره مباشرةً أو مخزن OpenGL المؤقت من مسار عرض الكاميرا، وتمريره مباشرةً إلى مخزن Tensor المؤقت.
نحن نتيح ميزة "التحسين بدون نسخ"، لذا يمكنك استخدامها عند محاولة معالجة البيانات، مثلاً، في حال استخدام ميزانية ذات وقت استجابة منخفض، مثل معالجة كل لقطة في غضون بضع عشرات من الملّي ثانية، فقد يكون مجرد نسخ مخزن مؤقت للذاكرة عبئًا كبيرًا.
لذلك، بالنسبة إلى التطبيقات التي تتطلّب معالجة البيانات في الوقت الفعلي بسرعة كبيرة، يمكنك استخدام ميزة "التحسين بدون نسخ" التي نتيحها.
وكما ذكر "شينتان"، إنّها تعمل على عدّة منصات وتتوافق مع OpenGL وOpenCL وMetal كواجهات خلفية لوحدة معالجة الرسومات.
أخيرًا وليس آخرًا، إنّ أداة ML Drift Optimizer مفتوحة المصدر.
وهي متاحة بموجب ترخيص Apache.
وقد أتاحته Google مؤخرًا كمصدر مفتوح.
حسنًا، إليكم رمز التطبيق.
// Kotlin
// Build once, off the main thread.
private val model: CompiledModel =
CompiledModel.create(
context.assets,
"stylizer_int8.tflite",
// Simple GPU setup!
CompiledModel.Options(Accelerator.GPU),
environment
)
// Reuse buffers across frames.
private val inputBuffers = model.createInputBuffers()
private val outputBuffers = model.createOutputBuffers()
fun stylize(input: FloatArray): FloatArray {
inputBuffers[0].writeFloat(input)
model.run(inputBuffers, outputBuffers) // sync
return outputBuffers[0].readFloat()
}كما ترون، إنّه صغير وبسيط جدًا.
وبالتالي، يمكنك إنشاء النموذج مرة واحدة، ثم إعادة استخدامه في كل لقطة.
لذلك، يتم تمرير CompiledModel.create في ملف .tflite.
ما عليك سوى تحديد أنّك تريد تشغيل النموذج على وحدة معالجة الرسومات، ثم إنشاء الإدخال وoutputBuffers.
بعد ذلك، في الحلقة الرئيسية، حيث تتم معالجة كل لقطة، يمكنك استدعاء model.run هذا لتمرير الإدخال والإخراج.
بعد الكتابة إلى inputBuffers، يمكنك الاتصال بـ model.run، ثم القراءة من outputBuffers.
حسنًا
نعم، وبعد ذلك، إذا حدّدت وحدة معالجة الرسومات هناك، سيتم تشغيلها على وحدة معالجة الرسومات.
إذا حدّدت أيضًا وحدة المعالجة المركزية ووحدة معالجة الرسومات هناك، فسيحاول تشغيل وحدة معالجة الرسومات.
إذا لم تكن وحدة معالجة الرسومات متاحة لأي سبب، سيتم استخدام وحدة المعالجة المركزية.
لذلك، في بعض الحالات، قد لا يكون استخدام وحدة المعالجة المركزية كبديل فعّالاً بما يكفي لتطبيقك، وعندها يمكنك تحديد وحدة معالجة الرسومات فقط كما هو موضّح.
في أغلب الأحيان، ستحتاج إلى استخدام وحدة المعالجة المركزية (CPU) كخيار احتياطي.
حسنًا
لذلك، أنشأنا هذه الميزة باستخدام حزمة LiteRT، والتي لا تستخدم خدمات Play بعد.
لذا، دعونا نوضّح لكم كيفية استخدام LiteRT في خدمات Play.
لذا، هناك ثلاثة تغييرات: الأول هو تغيير التبعية.
// Easier with CompiledModel API: 3 steps
// 1. app/build.gradle: replace litert with play-services-litert
- implementation 'com.google.ai.edge.litert:litert:...'
+ implementation 'com.google.android.gms:play-services-litert:17.0.0' // also pulls in litert-apiما عليك سوى استبدال تبعيات حزمة Maven في ملف Gradle أو في أي مكان آخر، أيًا كان نظام الإصدار الذي تستخدمه، وأيًا كان المكان الذي تحدد فيه تبعيات حزمة Maven، هذا ما ستغيّره.
وإزالة تبعية litert أو أي من تبعيات حزمة TensorFlow Lite Maven القديمة، واستبدالها بـ play-services-litert.
يؤدي ذلك أيضًا إلى سحب حزمة litert-api.
الآن، إذا كنت تكتب طبقة وسيطة تريد الاعتماد على LiteRT فقط، ولكن لا يهمّك حقًا ما إذا كان وقت التشغيل يأتي من التطبيق أو من خدمات Play، يمكنك الاعتماد على LiteRT API فقط، واستخدام بيئة كمَعلمة إدخال.
لذا، الخطوة الثانية هي مَعلمة البيئة.
هنا يمكنك توفير حقن التبعية، لتحديد أنك تستخدم، أو تريد استخدام، LiteRT في خدمات Play.
لذا، عليك استيراد gms.litert.LiteRt واستدعاء دالة الإعداد، مع تمرير السياق، وهو نشاط Android.
// 2. Initialize the LiteRT Environment from Play services (context = your Activity)
- val environment = Environment.create(...)
+ import com.google.android.gms.litert.LiteRt
+ val environment = LiteRt.initialize(context).await()
// 3. Pass environment whenever you call CompiledModel.create
// That's it! The rest of your app uses the normal CompiledModel APIs from litert-api.وهذا أمر غير متزامن، لذا عليك استدعاء .await أو أن يكون الباقي مستندًا إلى معاودة الاتصال.
وأخيرًا، بعد الحصول على هذه البيئة، ما عليك سوى تمريرها عند استدعاء CompiledModel.create.
وهذا ما سيجعله يستخدم وقت تشغيل LiteRT من "خدمات Play".
هذا كل ما في الأمر.
وهذا يعني أنّ بقية تطبيقك يستخدم واجهات برمجة التطبيقات LiteRT CompiledModel نفسها من واجهة برمجة التطبيقات LiteRT.
لا يتغيّر باقي رمز الاستدلال لاستخدام خدمات Play.
ويمكنك إجراء عملية النقل هذه بشكل تدريجي.
ليس عليك نقل كل شيء دفعة واحدة، بل يمكنك نقل مكوّن واحد في كل مرة.
إذا كان لديك تطبيق كبير، من المنطقي نقل كل مكوّن يستخدم LiteRT، ثم يمكنك نقل مكوّن واحد في كل مرة واختبار مكوّن واحد في كل مرة.
التحذير الوحيد هو أنّك ستحصل على ميزة تقليل الحجم فقط، ولن تتمكّن من توفير المساحة إلا عند إزالة آخر تبعية في وقت التشغيل المجمّع.
وإذا كنت تستخدمه، يجب عدم الخلط بين العناصر في LiteRT في "خدمات Play" وLiteRT المجمّع.
لذا، إذا كنت تحصل على متّجهات متعدّدة الأبعاد أو نماذج مجمّعة أو مترجمات من LiteRT في "خدمات Play"، يجب عدم تمريرها إلى LiteRT المجمّع أو العكس.
ولكن بخلاف ذلك، فإن المزج بين هذه الأشياء يعمل بشكل جيد.
حسنًا
كان ذلك إنشاء تطبيق جديد.
سأتحدّث الآن عن كيفية ترقية تطبيق حالي.
لذا، قد يكون لديك تطبيق حالي يستخدم Interpreter API.
هذا ما نسميه واجهة برمجة تطبيقات TFLite القديمة التي تستخدم المترجم كفئة رئيسية.
هذا هو الرمز البرمجي على اليمين الذي يستخدم Interpreter API، وعلى اليسار، يظهر رمز CompiledModel API الجديد.
// Dependencies (Gradle):
// play-services-tflite-java and/or litert (bundled)
// Init
TfLite.initialize(context).await()
// Load
val interpreterOptions =
InterpreterApi.Options().apply {
runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
}
val interpreter =
InterpreterApi.create(modelFile, interpreterOptions)
// Prepare inputs/outputs
val inputs = …
val outputs = …
// Execute
interpreter.run(inputs, outputs)// Dependencies (Gradle):
// play-services-litert
// Init
val environment =
LiteRt.initialize(context).await()
// Load
val modelOptions = CompiledModel.Options(Accelerator.CPU)
val model =
CompiledModel.create(modelPath, modelOptions, environment)
// Prepare inputs/outputs
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()
// Execute
model.run(inputBuffers, outputBuffersلذا، ما عليك سوى تغيير TfLite.initialize إلى LiteRt.initialize، وسيؤدي ذلك الآن إلى عرض بيئة.
بعد ذلك، يمكنك تمرير البيئة إلى CompiledModel.create.
هذا تغيير بسيط، ولا يؤدي إلى زيادة حجم حزمة APK.
في الشريحة التالية، سنوضّح لك كيفية إجراء ذلك باستخدام وحدة معالجة الرسومات، وهو خيار إضافي.
هذا هو الرمز الإضافي الذي تحتاج إليه لتفعيل وحدة معالجة الرسومات.
// Dependencies (Gradle):
// play-services-tflite-java and/or litert (bundled)
// Init
val initOptions = TfLiteInitializationOptions.builder()
.setEnableGpuDelegateSupport(true).build()
TfLite.initialize(context, initOptions).await()
val useGpu =
TfLiteGpu.isGpuDelegateAvailable(context).await()
// Load
val interpreterOptions =
InterpreterApi.Options().apply {
runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
}
if (useGpu) {
interpreterOptions.addDelegateFactory(
GpuDelegateFactory());
}
val interpreter =
InterpreterApi.create(modelFile, interpreterOptions)
// Prepare inputs/outputs
val inputs = …
val outputs = …
// Execute
interpreter.run(inputs, outputs)// Dependencies (Gradle):
// play-services-litert
// Init
val initOptions = LiteRtInitializationOptions.builder()
.setEnableGpu(true).build()
val environment = LiteRt.initialize(context, initOptions).await()
// Load
val modelOptions =
CompiledModel.Options(Accelerator.CPU, Accelerator.GPU)
val model =
CompiledModel.create(modelPath, modelOptions, environment)
// Prepare inputs/outputs
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()
// Execute
model.run(inputBuffers, outputBuffers)كما ترون، الرمز البرمجي في واجهة برمجة التطبيقات الجديدة لتفعيل وحدة معالجة الرسومات هو أبسط قليلاً من الرمز البرمجي السابق.
لذا، فإنّ أول استدعاء لـ setEnableGpu في خيارات إعداد LiteRT التي يتم تمريرها بعد ذلك إلى LiteRt.initialize سيؤدي إلى تحميل رمز مسرِّع وحدة معالجة الرسومات في تطبيقك.
بعد ذلك، عند إنشاء modelOptions وتمريرها إلى CompiledModel.create، يمكنك تحديد المسرِّع الذي سيتم استخدامه لنموذج معيّن، سواء كنت تريد تشغيل نموذج آخر على وحدة معالجة الرسومات فقط، أو على وحدة معالجة الرسومات مع وحدة المعالجة المركزية كخيار احتياطي، أو على وحدة المعالجة المركزية فقط.
حسنًا.
نعم، كما ترون، أصبح تفعيل وحدة معالجة الرسومات أسهل بكثير باستخدام واجهة برمجة التطبيقات الجديدة.
إذًا، ما الذي ستحصل عليه فعليًا؟
سيخبرك "شينتان" بذلك.
حسنًا.
حسنًا، شكرًا لك يا "فيرغوس".
لنتحدّث الآن عن الفوائد التي نحصل عليها من كل ذلك.
تذكّروا أنّنا قلنا إنّنا سننشئ تطبيقًا، لذا لنرَ ما أنشأناه بالفعل.
هذا أنا، على أي حال، وما فعلناه هنا هو أن ما يحدث الآن هو أننا استخدمنا حزمة تعلّم الآلة للعثور عليّ، لذا يتم إجراء التقسيم بواسطة واجهة برمجة تطبيقات جاهزة للاستخدام مثل حزمة تعلّم الآلة.
لذا، هذا مجرد العثور على رأسي هناك.
بعد ذلك، يستخدم LiteRT نموذجًا آخر مشابهًا لنموذج نقل النمط لتلوين الخلفية.
ومن المزايا الأخرى التي ذكرناها هي توفير مساحة تبلغ 8 ميغابايت تقريبًا، واستخدام بيئة تشغيل واحدة الآن بين جميع تطبيقاتك، أو على الأقل مثل تلك التي تتم مشاركتها هنا، والحصول على تحديثات تلقائية، بالإضافة إلى وحدة معالجة رسومات أسرع تتيح لك الحصول على ما يقرب من 30 لقطة في الثانية في ما يتعلّق بتوفير تجربة مستخدم غنية في الوقت الفعلي.
من الجيد أيضًا أنك لست مضطرًا للقيام بكل هذا يدويًا.
هناك أيضًا مهارة جديدة أطلقناها للتو في Android، وهي في الأساس مهارة Android LiteRT التي تعمل على ترقية تعلُّم الآلة على الجهاز فقط في دقائق، أليس كذلك؟
لذا، يمكنك إجراء بعض الأمور باستخدام هذه الميزة: يمكنك ترقية تطبيق حالي، أو إنشاء تطبيق جديد، أو ترقية تطبيقك لاستخدام هذا الدمج الجديد مع "خدمات Play".
إذًا، كل هذه الميزات متاحة.
يتوفّر الرابط في الشريحة، وهو متاح أيضًا على GitHub، وسيظهر في مستنداتنا ومدوّنتنا أيضًا.
وهذا مفيد أيضًا لأي شخص يتطلّع إلى إجراء التغيير قريبًا.
سيخبرنا "فيرغوس" بعد ذلك عن الخطوات التالية.
لذلك، نحن ملتزمون بتوفير الذكاء الاصطناعي على الجهاز فقط باستخدام LiteRT.
نواصل الاستثمار بشكل كبير في تحسين تسريع وحدة معالجة الرسومات وتغطية النماذج، ونواصل تقديم تحديثات منتظمة لـ LiteRT 2.x، سواء لحزمة LiteRT المفتوحة المصدر أو لحزمة LiteRT Maven في "خدمات Google Play".
وسنواصل أيضًا توفير التوافق مع الأنظمة القديمة.
ستواصل بيئة التشغيل في "خدمات Play" إتاحة التطبيقات التي تم إنشاؤها باستخدام حِزم تطوير البرامج (SDK) القديمة.
أجل
هذا الأمر مهم جدًا لمستخدمينا ولنا أيضًا.
بالنسبة إلى حِزم تطوير البرامج (SDK) من LiteRT 1.x، فهي في وضع الصيانة الآن، لذا يتم إجراء إصلاحات الأمان المُلحّة فقط.
أما واجهة NNAPI، التي أوقفناها في عام 2024، فستتم إزالتها نهائيًا اعتبارًا من عام 2027.
لذا، إذا كنت تستخدم NNAPI، يُرجى التبديل إلى استخدام تسريع وحدة معالجة الرسومات أو تسريع وحدة NPU مع LiteRT المجمّعة.
حسنًا
أجل
لذلك، كلما انتقلت إلى الإصدار 2.x وCompiledModel في وقت أقرب، قلّت المهام التي عليك تنفيذها لاحقًا.
إذًا، هناك ثلاث نقاط يجب تذكّرها.
لذا، ابدأوا بإنشاء المحتوى.
ابدأ باستخدام حزمة تعلّم الآلة، وإذا كانت تلبّي احتياجاتك، فهذا رائع.
وإذا لم يكن الأمر كذلك، استخدِم LiteRT لنماذجك المخصّصة.
يمكنك الترقية إلى LiteRT في "خدمات Google Play" للاستفادة من توفير مساحة في حِزم APK ووقت التشغيل المشترَك.
ننصحك أيضًا باستخدام واجهة برمجة التطبيقات CompiledModel للاستدلال بشكل أسرع وأبسط من خلال وحدة معالجة الرسومات.
أجل
يمكنك الاطّلاع على كل التفاصيل في موقع مستندات LiteRT على AI Edge على عنوان URL الظاهر على الشاشة.
هذا صحيح.
شكرًا لانضمامكم إلينا، ونحن متحمّسون لرؤية ما ستبتكرونه.
// 1. Configure and create segmenter client
val segmenter = Segmentation.getClient(
SelfieSegmenterOptions.Builder()
.setDetectorMode(
SelfieSegmenterOptions.STREAM_MODE)
.build())
// 2. Prepare image & run inference
fun processFrame(mediaImage: Image) {
val image = InputImage.fromMediaImage(
mediaImage, /* rotationDegrees= */ 0)
segmenter.process(image)
.addOnSuccessListener { mask -> … }
}import litert_torch
model = my_models.Stylizer().eval()
# Convert with torch.export under the hood
edge_model = litert_torch.convert(
model, sample_inputs)
edge_model.export("stylizer_f32.tflite")# Python
# previously ai_edge_quantizer
from litert_quantizer import quantizer, recipe
qt = quantizer.Quantizer("stylizer_f32.tflite")
# int8 weights, float activations
qt.load_quantization_recipe(
recipe.dynamic_wi8_afp32())
qt.quantize().export_model("stylizer_int8.tflite")// Kotlin
// Build once, off the main thread.
private val model: CompiledModel =
CompiledModel.create(
context.assets,
"stylizer_int8.tflite",
// Simple GPU setup!
CompiledModel.Options(Accelerator.GPU),
environment
)
// Reuse buffers across frames.
private val inputBuffers = model.createInputBuffers()
private val outputBuffers = model.createOutputBuffers()
fun stylize(input: FloatArray): FloatArray {
inputBuffers[0].writeFloat(input)
model.run(inputBuffers, outputBuffers) // sync
return outputBuffers[0].readFloat()
}// Easier with CompiledModel API: 3 steps
// 1. app/build.gradle: replace litert with play-services-litert
- implementation 'com.google.ai.edge.litert:litert:...'
+ implementation 'com.google.android.gms:play-services-litert:17.0.0' // also pulls in litert-api// 2. Initialize the LiteRT Environment from Play services (context = your Activity)
- val environment = Environment.create(...)
+ import com.google.android.gms.litert.LiteRt
+ val environment = LiteRt.initialize(context).await()
// 3. Pass environment whenever you call CompiledModel.create
// That's it! The rest of your app uses the normal CompiledModel APIs from litert-api.// Dependencies (Gradle):
// play-services-tflite-java and/or litert (bundled)
// Init
TfLite.initialize(context).await()
// Load
val interpreterOptions =
InterpreterApi.Options().apply {
runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
}
val interpreter =
InterpreterApi.create(modelFile, interpreterOptions)
// Prepare inputs/outputs
val inputs = …
val outputs = …
// Execute
interpreter.run(inputs, outputs)// Dependencies (Gradle):
// play-services-litert
// Init
val environment =
LiteRt.initialize(context).await()
// Load
val modelOptions = CompiledModel.Options(Accelerator.CPU)
val model =
CompiledModel.create(modelPath, modelOptions, environment)
// Prepare inputs/outputs
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()
// Execute
model.run(inputBuffers, outputBuffers// Dependencies (Gradle):
// play-services-tflite-java and/or litert (bundled)
// Init
val initOptions = TfLiteInitializationOptions.builder()
.setEnableGpuDelegateSupport(true).build()
TfLite.initialize(context, initOptions).await()
val useGpu =
TfLiteGpu.isGpuDelegateAvailable(context).await()
// Load
val interpreterOptions =
InterpreterApi.Options().apply {
runtime = TfLiteRuntime.FROM_SYSTEM_ONLY
}
if (useGpu) {
interpreterOptions.addDelegateFactory(
GpuDelegateFactory());
}
val interpreter =
InterpreterApi.create(modelFile, interpreterOptions)
// Prepare inputs/outputs
val inputs = …
val outputs = …
// Execute
interpreter.run(inputs, outputs)// Dependencies (Gradle):
// play-services-litert
// Init
val initOptions = LiteRtInitializationOptions.builder()
.setEnableGpu(true).build()
val environment = LiteRt.initialize(context, initOptions).await()
// Load
val modelOptions =
CompiledModel.Options(Accelerator.CPU, Accelerator.GPU)
val model =
CompiledModel.create(modelPath, modelOptions, environment)
// Prepare inputs/outputs
val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()
// Execute
model.run(inputBuffers, outputBuffers)