音声アシスタントをモバイルアプリケーションに埋め込む方法。Habiticaの例を使って分解します

音声制御があれば、多くのモバイルアプリケーションの方がはるかに便利だと思いませんか?いいえ、これは技術サポートチャットで銀行アシスタントと会話することではありません。基本的には、アプリケーションを介した音声ナビゲーションまたはダイアログモードでのフォーム入力で十分です。



Just AIのソリューションアーキテクトであるVitalyaGorbachevは、Habitica(習慣を修正して目標を達成するためのオープンソースアプリ、Kotlinで作成)の例を使用して、音声インターフェイスを任意のアプリケーションの機能にすばやくシームレスに統合する方法を示します。





しかし、最初に、モバイルアプリケーションの音声制御が便利な理由について説明しましょう。明白なことから始めましょう。



  • 調理、運転、スーツケースの持ち運び、機械的な作業など、手が忙しいときにアプリケーションを使用する必要があることがよくあります。
  • 音声は、視覚障害を持つ人々にとって不可欠なツールです。


ケースはすでに透過的ですが、実際にはすべてがさらに単純です。場合によっては、音声ダイヤルの方が高速です。想像してみてください。長いフォームに記入する代わりに、「明日のチケットを2人でサマラに購入してください」という1つのフレーズで航空券を注文します。同時に、ユーザーに明確な質問をする機能を備えています:夕方または午後?荷物の有無は?

音声は、「フォーム入力」シナリオを実行するときに役立ち、ユーザーからの一定量の情報を必要とするほとんどすべての長いフォームに入力するのに便利です。そして、そのようなフォームはほとんどのモバイルアプリケーションに存在します。






左から右へ:Prigorod RZDアプリ、FatSecret食品日記(ユーザーは数百の製品から選択して、1日に数回フォームに記入する必要があります)、Korzhovベーカリーアプリ。



今日、音声アシスタントはサポートチャットに導入されることが多く、そこから開発されるため、ほとんどの企業はアプリケーションの機能をチャットにプッシュしようとしています。バランスを取り、製品やサービスについて何かを見つけてください...これは必ずしも便利に実装されているわけではなく、音声入力の場合、音声認識が完全に機能しないことが多いという理由だけで、完全に逆効果になります。

正しいアプローチは、アシスタントをアプリケーションの既存の機能にシームレスに統合し、そのインターフェイスでフォームに入力することです。これにより、ユーザーはすべてを正しく言ったことを確認して、[OK]をクリックするだけで済みます。
Habiticaの例を使用してこれを行う方法を示すことにしました。これはほぼ純粋なKotlinで記述されたオープンソースアプリケーションです。 「ハビティカ」は音声アシスタントの場合に最適です。ここでも、新しいタスクを開始するには、かなり膨大なフォームに記入する必要があります。この退屈なプロセスを、主要な質問を含む1つのフレーズに置き換えてみましょう。



チュートリアルを2つの部分に分けました。この記事では、モバイルアプリケーションに音声アシスタントを追加し、基本的なシナリオを実装する方法を理解します(この場合、これは天気と時間の予測を明確にするための既成のシナリオです。これは、世界で最も人気のある音声アシスタントのリクエストの1つです)。 2番目の記事(まもなくリリースされる予定です)では、特定の画面を音声で呼び出し、アプリケーション内に複雑なクエリを実装する方法を学習します。



あなたが働く必要があるもの



SDK。我々はかかったAimyboxをダイアログインターフェースを構築するためのSDKとして。箱から出して、AimyboxはアシスタントSDKと簡潔でカスタマイズ可能なUI(必要に応じて変更可能)を提供します。同時に、既存のモジュールから選択するか認識合成、およびNLPのエンジンとして独自のモジュール作成できます。



基本的に、Aimyboxは音声アシスタントアーキテクチャを実装し、これらすべてのモジュールのインターフェイスを標準化し、それらの相互作用を正しい方法で整理します。したがって、このソリューションを実装することにより、アプリケーション内で音声インターフェイスを開発する時間を大幅に短縮できます。Aimyboxの詳細については、こちらまたはここ



スクリプト作成ツール。スクリプトはJAICF(Just AIから音声アプリケーションを開発するためのオープンソースで完全に無料のフレームワーク)で記述しJAICP(Just AI Conversational Platform)でCaila(NLUサービス)を使用してインテントを認識します。チュートリアルの次のパートで、それらの使用方法について詳しく説明します。スマートフォン。テストには、Habitikaを実行してテストするAndroidスマートフォンが必要です。







手順



まず、「Habitika」(リリースブランチ)をフォークして、私たちにとって最も重要なファイルを検索します。Android Studio IDEを使用しました:MainActivity.kt



を検索します-そこにロジックを埋め込みます。HabiticaBaseApplication.kt-そこでAimyboxを初期化します。Activity_main.xml-そこにインターフェイス要素を埋め込みます。AndroidManifest.xml-アプリケーションの構造全体とそのアクセス許可がそこに保存されます。 Habitikiカブの指示に従って、habitica.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_AUDIOMODIFY_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"/>


それでは、BaseApplicationでAimyboxを初期化しましょう。クラスを初期化するとき



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コンソールからのコードはその後になります。



次に、スニペットをmainActivity.ktに埋め込みます。frameLayoutをactivity_main.xmlの、idbottom_navigationのframeLayoutのすぐ下に事前に挿入します



<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
        }


さらに、AppThemeのスタイル(styles.xml)に追加します



<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コンソールが必要です。



まず、githubアカウントでapp.aimybox.comにアクセスし、新しいプロジェクトを作成し、いくつかのスキルを接続して(テストのためにDateTimeを接続しました)、アシスタントで適切な質問をしてみましょう。ここの設定では、右上隅にあるapiKeyを使用します。これは、KEYの代わりに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>


やったー!



画像



ここにあるリンクコードリポジトリには。



「ハビティカ」のアシスタントに関する次の記事では、あなたの声を使って天気を知るだけでなく、アプリケーションを直接制御する方法を説明します。ページをナビゲートして、習慣やタスクを追加します。



All Articles