كيفية تضمين مساعد صوتي في أي تطبيق جوال. نحن نفكك باستخدام مثال Habitica

ألا تعتقد أن العديد من تطبيقات الهاتف المحمول ستكون أكثر ملاءمة إذا كان لديها التحكم الصوتي؟ لا ، لا يتعلق الأمر بإجراء محادثات مع مساعد البنك في دردشة الدعم الفني. في الأساس ، سيكون التنقل الصوتي من خلال التطبيق أو ملء النموذج في وضع الحوار كافياً.



باستخدام مثال Habitica (تطبيق مفتوح المصدر لإصلاح العادات وتحقيق الأهداف ، مكتوب بلغة Kotlin) ، يوضح Vitala Gorbachev ، مهندس الحلول في Just AI ، كيفية دمج واجهة صوتية بسرعة وسهولة في وظائف أي تطبيق.





لكن أولاً ، دعنا نناقش سبب ملاءمة التحكم الصوتي لتطبيق الهاتف المحمول؟ لنبدأ بما هو واضح.



  • نحتاج غالبًا إلى استخدام أحد التطبيقات عندما تكون أيدينا مشغولة: الطهي ، والقيادة ، وحمل الحقائب ، وأثناء الأعمال الميكانيكية ، وما إلى ذلك.
  • الصوت هو أداة أساسية للأشخاص الذين يعانون من إعاقات بصرية.


الحالات شفافة بالفعل ، ولكن في الواقع كل شيء أبسط: في بعض الحالات ، يكون الاتصال الصوتي أسرع ! تخيل - طلب تذكرة طيران بعبارة واحدة "اشتر لي تذكرة غدًا لشخصين إلى سمارا" بدلاً من ملء نموذج طويل. في نفس الوقت مع إمكانية طرح أسئلة توضيحية على المستخدم: في المساء أم بعد الظهر؟ مع أم بدون أمتعة؟

يكون الصوت مفيدًا عندما نمر في سيناريو "ملء النموذج" وهو مناسب لملء أي نماذج طويلة تقريبًا تتطلب قدرًا معينًا من المعلومات من المستخدم. ومثل هذه الأشكال موجودة في معظم تطبيقات الهاتف المحمول.






من اليسار إلى اليمين: تطبيق Prigorod RZD ، مذكرات طعام FatSecret (يتعين على المستخدمين ملء نموذج عدة مرات في اليوم ، والاختيار من بين مئات المنتجات) ، تطبيق Korzhov bakery.



نظرًا لحقيقة أن المساعدين الصوتيين غالبًا ما يتم إدخالهم في دردشة الدعم ويتطورون من هناك ، تحاول معظم الشركات دفع وظائف التطبيق إلى الدردشة. قم بتعبئة الرصيد ، واكتشف شيئًا عن منتج أو خدمة ... لا يتم تنفيذ هذا دائمًا بشكل ملائم ، وفي حالة الإدخال الصوتي ، يكون له نتائج عكسية تمامًا ، فقط لأن التعرف على الكلام غالبًا لا يعمل بشكل مثالي.

تتمثل الطريقة الصحيحة في دمج المساعد بسلاسة في الوظائف الحالية للتطبيق ، في الواجهة التي سيتم ملء النموذج بها ، بحيث يمكن للشخص ببساطة التحقق من أنه قال كل شيء بشكل صحيح والنقر فوق "موافق".
قررنا أن نظهر كيف يمكن القيام بذلك باستخدام مثال Habitica - هذا تطبيق مفتوح المصدر مكتوب بلغة Kotlin الخالصة تقريبًا. "Habitika" مثالي لحالة مع مساعد صوت - هنا أيضًا ، لبدء مهمة جديدة ، تحتاج إلى ملء نموذج ضخم إلى حد ما. دعنا نحاول استبدال هذه العملية الكئيبة بعبارة واحدة بأسئلة إرشادية؟



لقد قسمت البرنامج التعليمي إلى جزأين. في هذه المقالة ، سنكتشف كيفية إضافة مساعد صوتي إلى تطبيق الهاتف المحمول وتنفيذ سيناريو أساسي (في حالتنا ، هذا سيناريو جاهز لتوضيح توقعات الطقس والوقت - أحد أكثر الطلبات شيوعًا للمساعدين الصوتيين في العالم). في المقال الثاني - وسيصدر قريبًا - سنتعلم كيفية استدعاء شاشات معينة بالصوت وتنفيذ استعلامات معقدة داخل التطبيق.



ما تحتاجه للعمل



SDK. أخذنا Aimybox كحزمة SDK لبناء واجهات الحوار. من خارج الصندوق ، يوفر Aimybox مساعد SDK وواجهة مستخدم مقتضبة وقابلة للتخصيص (يمكن تغييرها إذا رغبت في ذلك). في نفس الوقت ، يمكنك الاختيار من بين تلك الموجودة أو إنشاء الوحدة النمطية الخاصة بك كمحركات للتعرف والتوليف ومعالجة اللغات الطبيعية .



بشكل أساسي ، يقوم Aimybox بتنفيذ هندسة المساعد الصوتي ، وتوحيد واجهات كل هذه الوحدات وتنظيم تفاعلها بالطريقة الصحيحة. وبالتالي ، من خلال تنفيذ هذا الحل ، يمكنك تقليل الوقت بشكل كبير لتطوير واجهة صوتية داخل التطبيق الخاص بك. يمكنك قراءة المزيد عن Aimybox هنا أوهنا .



أداة إنشاء النص. سنكتب البرنامج النصي في JAICF (هذا إطار مفتوح المصدر ومجاني تمامًا لتطوير التطبيقات الصوتية من Just AI) ، وسنتعرف على النوايا باستخدام Caila (خدمة NLU) في JAICP (مجرد منصة محادثة AI). سأخبرك بالمزيد عنها في الجزء التالي من البرنامج التعليمي - عندما نبدأ في استخدامها.



هاتف ذكي. لإجراء الاختبارات ، نحتاج إلى هاتف ذكي يعمل بنظام Android ، وسنعمل عليه ونختبر Habitika.



إجراء



أولاً ، نقوم بتفكيك "Habitika" (فرع الإصدار) ونبحث عن الملفات الأكثر أهمية بالنسبة لنا. لقد استخدمت Android Studio IDE:



Find MainActivity .kt - سنقوم بتضمين المنطق هناك.



HabiticaBaseApplication .kt - هناك سنقوم بتهيئة Aimybox.



Activity_main .xml - قم بتضمين عنصر الواجهة هناك.



AndroidManifest .xml - يتم تخزين بنية التطبيق بالكامل وأذوناته هناك.



وفقًا للتعليمات الواردة في اللفت "Habitiki" ، نعيد تسمية Habitiki.properties.example و Habitica.resources.example ، مع إزالة المثال منها ، وبدء المشروع في Firebase للتطبيق ونسخ ملف google-services.json إلى الجذر.



نقوم بتشغيل التطبيق للتحقق من عمل التجميع. هاهو!



صورة



أولاً ، دعنا نضيف تبعيات Aimybox.



implementation 'com.justai.aimybox:core:0.11.0'
    implementation("com.justai.aimybox:components:0.1.8")


في التبعيات و



    maven { url 'https://dl.bintray.com/aimybox/aimybox-android-sdk/' }
    maven { url "https://dl.bintray.com/aimybox/aimybox-android-assistant/" }
 


في المستودعات.



وأضف السطر التالي مباشرة بعد compileOptions حتى يعمل كل شيء بشكل صحيح



    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8.toString()
    }


أذونات الآن.



إزالة الأعلام من RECORD_AUDIO و أذونات MODIFY_AUDIO_SETTINGS في AndroidManifest . XML بحيث الخيارات تبدو مثل هذه.




    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="com.android.vending.BILLING" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>


لنبدأ الآن في تهيئة Aimybox في BaseApplication.



أضف AimyboxProvider عند تهيئة الفصل.



صورة



ونقوم بالتهيئة الفعلية.



private fun createAimybox (context: Context): Aimybox {
        
        val unitId = UUID.randomUUID().toString()

        val textToSpeech = GooglePlatformTextToSpeech(context, Locale("Ru"))
        val speechToText = GooglePlatformSpeechToText(context, Locale("Ru"))
        val dialogApi = AimyboxDialogApi(
                "YOUR KEY", unitId)
        
        return Aimybox(Config.create(speechToText, textToSpeech, dialogApi))
    }


بدلاً من YOUR_KEY ، سيكون الرمز الخاص بك من Aimybox Console لاحقًا.



الآن نقوم بتضمين المقتطف في mainActivity.kt. أدخل مخطط الإطار مسبقًا في activity_main.xml ، أسفل تخطيط الإطار مباشرةً مع المعرف bottom_navigation



<FrameLayout
                                android:id="@+id/assistant_container"
                                android:layout_width="match_parent"
                                android:layout_height="match_parent"/>


في MainActivity نفسها ، قم أولاً بإضافة طلب إذن صريح إلى OnCreate

        ActivityCompat.requestPermissions(this, arrayOf(android.Manifest.permission.RECORD_AUDIO), 1)


وعندما تستقبلهم ، أضف جزءًا إلى الإطار أعلاه.



    @SuppressLint("MissingPermission")
    override fun onRequestPermissionsResult(
            requestCode: Int,
            permissions: Array<out String>,
            grantResults: IntArray
    ) {
        val fragmentManager = supportFragmentManager
        val fragmentTransaction = fragmentManager.beginTransaction()

        fragmentTransaction.add(R.id.assistant_container, AimyboxAssistantFragment())
        fragmentTransaction.commit()
    }


لا تنس أن تضيف إلى OnBackPressed إمكانية الخروج من المساعد بعد دخوله.



        val assistantFragment = (supportFragmentManager.findFragmentById(R.id.assistant_container)
                as? AimyboxAssistantFragment)
        if (assistantFragment?.onBackPressed() != true) {
            return
        }


بالإضافة إلى ذلك ، أضف إلى الأنماط (styles.xml) في AppTheme



<item name="aimybox_assistantButtonTheme">@style/CustomAssistantButtonTheme</item>
        <item name="aimybox_recognitionTheme">@style/CustomRecognitionWidgetTheme</item>
        <item name="aimybox_responseTheme">@style/CustomResponseWidgetTheme</item>
        <item name="aimybox_imageReplyTheme">@style/CustomImageReplyWidgetTheme</item>
        <item name="aimybox_buttonReplyTheme">@style/CustomButtonReplyWidgetTheme</item>


والأنماط الفردية أدناه:



 <style name="CustomAssistantButtonTheme" parent="DefaultAssistantTheme.AssistantButton">
    </style>

    <style name="CustomRecognitionWidgetTheme" parent="DefaultAssistantTheme.Widget.Recognition">
    </style>

    <style name="CustomResponseWidgetTheme" parent="DefaultAssistantTheme.Widget.Response">
    </style>

    <style name="CustomButtonReplyWidgetTheme" parent="DefaultAssistantTheme.Widget.ButtonReply">
    </style>

    <style name="CustomImageReplyWidgetTheme" parent="DefaultAssistantTheme.Widget.ImageReply">
    </style>


دعنا نتحقق مما إذا تمت إضافة ميكروفون. نطلق التطبيق.



لدينا مجموعة من الأخطاء المتعلقة بالصياغة غير الصحيحة. نقوم بإصلاح كل شيء كما ينصح IDE.



العمل!



صورة



لكن الميكروفون يتسلل إلى أسفل التنقل. دعونا نرفع قليلا. أضف إلى الأنماط أعلاه في CustomAssistantButtonTheme:



        <item name="aimybox_buttonMarginBottom">72dp</item>


أفضل!



صورة



الآن دعنا نربط مساعدًا هناك ونتحقق مما إذا كان يجيب بشكل طبيعي. لهذا نحن بحاجة إلى وحدة التحكم Aimybox.



لنبدأ بالذهاب إلى app.aimybox.com ضمن حساب github الخاص بنا ، وقم بإنشاء مشروع جديد ، وقم بتوصيل اثنين من المهارات (لقد قمت بتوصيل DateTime للاختبار) وحاول طرح الأسئلة المناسبة في المساعد. هنا في الإعدادات ، في الزاوية اليمنى العليا ، نأخذ apiKey ، الذي ندرجه في createAimybox بدلاً من مفتاحك.



private fun createAimybox (context: Context): Aimybox {
        
        val unitId = UUID.randomUUID().toString()

        val textToSpeech = GooglePlatformTextToSpeech(context)
        val speechToText = GooglePlatformSpeechToText(context)
        val dialogApi = AimyboxDialogApi(
                "YOUR KEY", unitId)
        
        return Aimybox(Config.create(speechToText, textToSpeech, dialogApi))
    }


العمل!



صورة



نص باللغة الإنجليزية فقط ، فلنغير رسالة الترحيب في strings.constants.xml.



<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!--  Prefs -->
    <string name="SP_userID" translatable="false">UserID</string>
    <string name="SP_APIToken" translatable="false">APIToken</string>
    <string name="base_url" translatable="false">https://habitica.com</string>
    <string name="initial_phrase">"!   ?</string>


الصيحة!



صورة



هنا رابط لمستودع الكود.



في المقال التالي حول مساعد "Habitika" سأخبرك بكيفية استخدام صوتك ليس فقط لمعرفة الطقس ، ولكن للتحكم في التطبيق مباشرة - تصفح الصفحات وإضافة عادات ومهام.



All Articles