إنشاء برامج تتبُّع صوتية لأجهزة Android باستخدام Dialogflow Essentials مرفرفة

1. قبل البدء

في هذا الدرس التطبيقي حول الترميز، ستتعلّم كيفية دمج روبوت دردشة بسيط يعمل بالنص والصوت من Dialogflow Essentials (ES) في تطبيق Flutter. ‏Dialogflow ES هي حزمة تطوير لإنشاء واجهات مستخدم حوارية. وبالتالي، روبوتات الدردشة والروبوتات الصوتية وبوابات الهاتف. يمكنكم جميعًا إنشاء المحتوى باستخدام الأداة نفسها، ويمكنكم حتى إتاحة قنوات متعددة بأكثر من 20 لغة مختلفة. يتكامل Dialogflow مع العديد من منصات المحادثات الرائجة، مثل "مساعد Google" وSlack وFacebook Messenger. إذا كنت تريد إنشاء وكيل لإحدى هذه المنصات، عليك استخدام أحد خيارات الدمج العديدة. ومع ذلك، لإنشاء روبوت محادثة للأجهزة الجوّالة، عليك إنشاء عملية دمج مخصّصة. يمكنك إنشاء عناصر intent من خلال تحديد عبارات التدريب لتدريب نموذج أساسي لتعلُّم الآلة.

تم ترتيب هذا المختبر ليعكس تجربة شائعة للمطوّرين على السحابة الإلكترونية:

  1. إعداد البيئة
  • ‫Dialogflow: إنشاء وكيل جديد في Dialogflow ES
  • ‫Dialogflow: إعداد Dialogflow
  • ‫Google Cloud: إنشاء حساب خدمة
  1. ‫Flutter: إنشاء تطبيق محادثة
  • إنشاء مشروع Flutter
  • ضبط الإعدادات والأذونات
  • إضافة التبعيات
  • الربط بحساب الخدمة
  • تشغيل التطبيق على جهاز افتراضي أو جهاز حقيقي
  1. ‫Flutter: إنشاء واجهة المحادثة مع إمكانية استخدام ميزة "تحويل الكلام إلى نص"
  • إنشاء واجهة المحادثة
  • ربط واجهة المحادثة
  • دمج حزمة gRPC الخاصة بخدمة Dialogflow في التطبيق
  1. ‫Dialogflow: تصميم وكيل Dialogflow
  • ضبط نية الترحيب والنية الاحتياطية
  • استخدام قاعدة معلومات للأسئلة الشائعة

المتطلبات الأساسية

  • خبرة أساسية في Dart/Flutter
  • تجربة أساسية في Google Cloud Platform
  • تجربة أساسية مع Dialogflow ES

ما ستنشئه

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

أهداف الدورة التعليمية

  • كيفية إنشاء روبوت محادثة باستخدام Dialogflow Essentials
  • كيفية دمج Dialogflow في تطبيق Flutter باستخدام حزمة Dialogflow gRPC
  • كيفية رصد نوايا النص باستخدام Dialogflow
  • كيفية بث صوت عبر الميكروفون إلى Dialogflow
  • كيفية استخدام أداة ربط قاعدة المعلومات لاستيراد الأسئلة الشائعة العامة
  • اختبار روبوت الدردشة من خلال واجهة النص والصوت في جهاز افتراضي أو فعلي

المتطلبات

  • يجب أن يكون لديك Google Identity أو عنوان Gmail لإنشاء وكيل Dialogflow.
  • يجب أن يكون لديك إذن الوصول إلى Google Cloud Platform لتنزيل حساب خدمة.
  • بيئة تطوير Flutter

إعداد بيئة تطوير Flutter

  1. اختَر نظام التشغيل الذي تريد تثبيت Flutter عليه.
  1. يمكنك إنشاء تطبيقات باستخدام Flutter مع أي محرّر نصوص بالإضافة إلى أدوات سطر الأوامر. ومع ذلك، ستستفيد ورشة العمل هذه من استوديو Android. توفّر لك مكوّنات Flutter وDart الإضافية في "استوديو Android" ميزات إكمال الرموز البرمجية، وتمييز بناء الجملة، والمساعدة في تعديل الأدوات، وإمكانية التشغيل وتصحيح الأخطاء، وغير ذلك. اتّبِع الخطوات الواردة في https://flutter.dev/docs/get-started/editor

2. إعداد البيئة

‫Dialogflow: إنشاء وكيل جديد في Dialogflow ES

  1. افتح
  2. في الشريط الأيمن، أسفل الشعار مباشرةً، انقر على إنشاء وكيل جديد في القائمة المنسدلة. (ملاحظة: لا تنقر على القائمة المنسدلة التي تحمل اسم "عام"، بل سنحتاج إلى مثيل Dialogflow عام للاستفادة من قاعدة معلومات الأسئلة الشائعة).
  3. تحديد اسم وكيل yourname-dialogflow (استخدِم اسمك)
  4. اختَر الإنجليزية - en كلغة تلقائية.
  5. اختَر المنطقة الزمنية الأقرب إليك كمنطقة زمنية تلقائية.
  6. لا تختار "وكيل كبير". (باستخدام هذه الميزة، يمكنك إنشاء وكيل شامل يمكنه التنسيق بين الوكلاء "الفرعيين". لا نحتاج إلى ذلك الآن.)
  7. انقر على إنشاء.

شاشة إنشاء مشروع جديد

إعداد Dialogflow

  1. انقر على رمز الترس في القائمة اليمنى بجانب اسم مشروعك.

إنشاء قائمة منسدلة جديدة للمشاريع

  1. أدخِل وصف موظّف الدعم التالي: برنامج الدردشة الآلي للأسئلة الشائعة في Dialogflow
  2. فعِّل ميزات الإصدار التجريبي من خلال النقر على زر التبديل.

Dialogflow Essentials V2Beta1

  1. انقر على علامة التبويب الكلام، وتأكَّد من تفعيل المربّع تكييف الكلام التلقائي.
  2. يمكنك أيضًا قلب مفتاح التبديل الأول، ما سيؤدي إلى تحسين "نموذج الكلام"، ولكن لا يتوفّر هذا الخيار إلا عند ترقية الإصدار التجريبي من Dialogflow.
  3. انقر على حفظ.

‫Google Cloud: الحصول على حساب خدمة

بعد إنشاء وكيل في Dialogflow، يجب إنشاء مشروع على السحابة الإلكترونية في Google Cloud Console.

  1. افتح Google Cloud Console:
  2. تأكَّد من تسجيل الدخول باستخدام حساب Google نفسه المستخدَم في Dialogflow، واختَر المشروع: yourname-dialogflow في الشريط الأزرق العلوي.
  3. بعد ذلك، ابحث عن Dialogflow API في شريط الأدوات العلوي وانقر على نتيجة Dialogflow API في القائمة المنسدلة.

تفعيل واجهة برمجة التطبيقات Dialogflow API

  1. انقر على زر إدارة الأزرق، ثم انقر على بيانات الاعتماد في شريط القائمة الأيمن. (إذا لم يتم تفعيل Dialogflow بعد، انقر على تفعيل أولاً)

بيانات الاعتماد في وحدة تحكّم Google Cloud Platform

  1. انقر على إنشاء بيانات اعتماد (في أعلى الشاشة) واختَر حساب الخدمة.

إنشاء بيانات اعتماد

  1. حدِّد اسم حساب الخدمة: flutter_dialogflow ورقم التعريف والوصف، ثم انقر على إنشاء.

إنشاء حساب خدمة

  1. في الخطوة 2، عليك اختيار الدور: Dialogflow API Admin، ثم النقر على متابعة وتم.
  2. انقر على حساب الخدمة flutter_dialogflow، ثمّ على علامة التبويب المفاتيح، ثمّ على إضافة مفتاح > إنشاء مفتاح جديد.

إنشاء مفتاح

  1. أنشئ مفتاح JSON. أعِد تسميته إلى credentials.json وخزِّنه في مكان آمن على محرك الأقراص الثابتة. سنستخدمه لاحقًا.

مفتاح JSON

ممتاز، تم إعداد جميع الأدوات التي نحتاجها بشكلٍ صحيح. يمكننا الآن البدء بدمج Dialogflow في تطبيقنا.

3- ‫Flutter: إنشاء تطبيق Chat

إنشاء تطبيق Boilerplate

  1. افتح "استوديو Android" وانقر على بدء مشروع Flutter جديد.
  2. اختَر تطبيق Flutter كنوع المشروع. ثم انقر على "التالي".
  3. تأكَّد من أنّ مسار حزمة تطوير البرامج (SDK) في Flutter يحدّد موقع حزمة تطوير البرامج (SDK) (انقر على "تثبيت حزمة تطوير البرامج (SDK)..." إذا كان حقل النص فارغًا).
  4. أدخِل اسم مشروع (على سبيل المثال، flutter_dialogflow_agent). ثم انقر على التالي.
  5. عدِّل اسم الحزمة وانقر على إنهاء.

إنشاء تطبيق Flutter جديد

سيؤدي ذلك إلى إنشاء تطبيق نموذجي باستخدام Material Components.

انتظِر إلى أن يثبِّت "استوديو Android" حزمة SDK وينشئ المشروع.

الإعدادات والأذونات

  1. تتطلّب مكتبة مسجّل الصوت sound_stream التي سنستخدمها minSdk 21 على الأقل. لذا، لنغيّر هذا الإعداد في android/app/build.gradle في قسم defaultConfig. (يُرجى العِلم أنّ هناك ملفَي build.gradle في مجلد Android، ولكن الملف الموجود في مجلد التطبيق هو الملف الصحيح).
defaultConfig {
   applicationId "com.myname.flutter_dialogflow_agent"
   minSdkVersion 21
   targetSdkVersion 30
   versionCode flutterVersionCode.toInteger()
   versionName flutterVersionName
}
  1. لمنح أذونات الوصول إلى الميكروفون والسماح للتطبيق بالتواصل مع وكيل Dialogflow الذي يعمل على السحابة الإلكترونية، علينا إضافة أذونات INTERNET وRECORD_AUDIO إلى ملف app/src/main/AndroidManifest.xml. تتوفّر ملفات AndroidManifest.xml متعددة في مشروع Flutter، ولكنك ستحتاج إلى الملف الموجود في المجلد الرئيسي. يمكنك إضافة الأسطر داخل علامات البيان مباشرةً.
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECORD_AUDIO" />

إضافة التبعيات

سنستخدم حِزم sound_stream وrxdart وdialogflow_grpc.

  1. إضافة اعتمادية sound_stream
$ flutter pub add sound_stream
Resolving dependencies...
  async 2.8.1 (2.8.2 available)
  characters 1.1.0 (1.2.0 available)
  matcher 0.12.10 (0.12.11 available)
+ sound_stream 0.3.0
  test_api 0.4.2 (0.4.5 available)
  vector_math 2.1.0 (2.1.1 available)
Downloading sound_stream 0.3.0...
Changed 1 dependency!
  1. إضافة اعتمادية dialogflow_grpc
flutter pub add dialogflow_grpc
Resolving dependencies...
+ archive 3.1.5
  async 2.8.1 (2.8.2 available)
  characters 1.1.0 (1.2.0 available)
+ crypto 3.0.1
+ dialogflow_grpc 0.2.9
+ fixnum 1.0.0
+ googleapis_auth 1.1.0
+ grpc 3.0.2
+ http 0.13.4
+ http2 2.0.0
+ http_parser 4.0.0
  matcher 0.12.10 (0.12.11 available)
+ protobuf 2.0.0
  test_api 0.4.2 (0.4.5 available)
+ uuid 3.0.4
  vector_math 2.1.0 (2.1.1 available)
Downloading dialogflow_grpc 0.2.9...
Downloading grpc 3.0.2...
Downloading http 0.13.4...
Downloading archive 3.1.5...
Changed 11 dependencies!
  1. إضافة اعتمادية rxdart
$ flutter pub add rxdart
Resolving dependencies...
  async 2.8.1 (2.8.2 available)
  characters 1.1.0 (1.2.0 available)
  matcher 0.12.10 (0.12.11 available)
+ rxdart 0.27.2
  test_api 0.4.2 (0.4.5 available)
  vector_math 2.1.0 (2.1.1 available)
Downloading rxdart 0.27.2...
Changed 1 dependency!

جارٍ تحميل معلومات حساب الخدمة ومشروع Google Cloud

  1. في مشروعك، أنشئ دليل وسمِّه: assets.
  2. انقِل ملف credentials.json الذي نزّلته من "وحدة تحكّم Google Cloud" إلى مجلد assets.
  3. افتح ملف pubspec.yaml وأضِف حساب الخدمة إلى حزمة Flutter.
flutter:
  uses-material-design: true
  assets:
    - assets/credentials.json

تشغيل التطبيق على جهاز فعلي

عندما يكون لديك جهاز Android، يمكنك توصيل هاتفك عبر كابل USB وتصحيح الأخطاء على الجهاز. اتّبِع هذه الخطوات لإعداد هذه الميزة من خلال شاشة خيارات المطوّرين على جهاز Android.

تشغيل التطبيق على جهاز افتراضي

في حال أردت تشغيل التطبيق على جهاز افتراضي، اتّبِع الخطوات التالية:

  1. انقر على الأدوات> أداة إدارة أجهزة Android الافتراضية. (أو اختَر أداة إدارة أجهزة Android الافتراضية من شريط الأدوات العلوي، وهي مميّزة باللون الوردي في الشكل أدناه)

شريط الأدوات العلوي في &quot;استوديو Android&quot;

  1. سننشئ جهاز Android افتراضيًا مستهدفًا، حتى نتمكّن من اختبار تطبيقنا بدون جهاز فعلي. لمزيد من التفاصيل، يُرجى الاطّلاع على إدارة أجهزة AVD. بعد اختيار جهاز افتراضي جديد، يمكنك النقر عليه مرّتين لبدء تشغيله.

إدارة أجهزة AVD

جهاز افتراضي

  1. في شريط أدوات استوديو Android الرئيسي، اختَر جهاز Android كهدف من خلال القائمة المنسدلة وتأكَّد من اختيار main.dart. بعد ذلك، انقر على الزر تنفيذ (المثلث الأخضر).

في أسفل بيئة التطوير المتكاملة، ستظهر لك السجلات في وحدة التحكّم. ستلاحظ أنّه يتم تثبيت Android وتطبيق Flutter التجريبي. سيستغرق ذلك دقيقة واحدة، وبعد أن يصبح الجهاز الافتراضي جاهزًا، ستكون عملية إجراء التغييرات سريعة جدًا. عند الانتهاء من ذلك، سيتم فتح تطبيق Flutter التجريبي.

تطبيق نموذجي

  1. لنفعّل الميكروفون لتطبيق chatbot. انقر على زر الخيارات للجهاز الافتراضي لفتح الخيارات. في علامة التبويب "الميكروفون"، فعِّل جميع مفاتيح التبديل الثلاثة.

خيارات AVD

  1. لنجرّب ميزة "إعادة التحميل السريع" لتوضيح مدى سرعة إجراء التغييرات.

في lib/main.dart، غيِّر عنوان MyHomePage في فئة MyApp إلى: Flutter Dialogflow Agent. وغَيِّر primarySwatch إلى Colors.orange.

الرمز الأول

احفظ الملف أو انقر على رمز البرق في شريط أدوات Android Studio. من المفترض أن يظهر التغيير الذي أجريته مباشرةً في الجهاز الافتراضي.

4. ‫Flutter: إنشاء واجهة المحادثة مع إمكانية تحويل الصوت إلى نص

إنشاء واجهة المحادثة

  1. أنشئ ملف أداة Flutter جديدًا في المجلد lib. (انقر بزر الماوس الأيمن على مجلد lib، ثم جديد > أداة Flutter > أداة Stateful)، وأطلِق على هذا الملف الاسم: chat.dart

ألصِق الرمز التالي في هذا الملف. ينشئ ملف Dart هذا واجهة المحادثة. لن يعمل Dialogflow بعد، بل سيتم عرض تخطيط جميع المكوّنات ودمج مكوّن الميكروفون للسماح بالبث. ستشير التعليقات في الملف إلى المكان الذي سنُدمج فيه Dialogflow لاحقًا.

// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:rxdart/rxdart.dart';
import 'package:sound_stream/sound_stream.dart';

// TODO import Dialogflow


class Chat extends StatefulWidget {
  Chat({Key key}) : super(key: key);

  @override
  _ChatState createState() => _ChatState();
}

class _ChatState extends State<Chat> {
  final List<ChatMessage> _messages = <ChatMessage>[];
  final TextEditingController _textController = TextEditingController();

  bool _isRecording = false;

  RecorderStream _recorder = RecorderStream();
  StreamSubscription _recorderStatus;
  StreamSubscription<List<int>> _audioStreamSubscription;
  BehaviorSubject<List<int>> _audioStream;

  // TODO DialogflowGrpc class instance

  @override
  void initState() {
    super.initState();
    initPlugin();
  }

  @override
  void dispose() {
    _recorderStatus?.cancel();
    _audioStreamSubscription?.cancel();
    super.dispose();
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlugin() async {
    _recorderStatus = _recorder.status.listen((status) {
      if (mounted)
        setState(() {
          _isRecording = status == SoundStreamStatus.Playing;
        });
    });

    await Future.wait([
      _recorder.initialize()
    ]);



    // TODO Get a Service account

  }

  void stopStream() async {
    await _recorder.stop();
    await _audioStreamSubscription?.cancel();
    await _audioStream?.close();
  }

  void handleSubmitted(text) async {
    print(text);
    _textController.clear();

    //TODO Dialogflow Code

  }

  void handleStream() async {
    _recorder.start();

    _audioStream = BehaviorSubject<List<int>>();
    _audioStreamSubscription = _recorder.audioStream.listen((data) {
      print(data);
      _audioStream.add(data);
    });


    // TODO Create SpeechContexts
    // Create an audio InputConfig

    // TODO Make the streamingDetectIntent call, with the InputConfig and the audioStream
    // TODO Get the transcript and detectedIntent and show on screen

  }

  // The chat interface
  //
  //------------------------------------------------------------------------------------
  @override
  Widget build(BuildContext context) {
    return Column(children: <Widget>[
      Flexible(
          child: ListView.builder(
            padding: EdgeInsets.all(8.0),
            reverse: true,
            itemBuilder: (_, int index) => _messages[index],
            itemCount: _messages.length,
          )),
      Divider(height: 1.0),
      Container(
          decoration: BoxDecoration(color: Theme.of(context).cardColor),
          child: IconTheme(
            data: IconThemeData(color: Theme.of(context).accentColor),
            child: Container(
              margin: const EdgeInsets.symmetric(horizontal: 8.0),
              child: Row(
                children: <Widget>[
                  Flexible(
                    child: TextField(
                      controller: _textController,
                      onSubmitted: handleSubmitted,
                      decoration: InputDecoration.collapsed(hintText: "Send a message"),
                    ),
                  ),
                  Container(
                    margin: EdgeInsets.symmetric(horizontal: 4.0),
                    child: IconButton(
                      icon: Icon(Icons.send),
                      onPressed: () => handleSubmitted(_textController.text),
                    ),
                  ),
                  IconButton(
                    iconSize: 30.0,
                    icon: Icon(_isRecording ? Icons.mic_off : Icons.mic),
                    onPressed: _isRecording ? stopStream : handleStream,
                  ),
                ],
              ),
            ),
          )
      ),
    ]);
  }
}


//------------------------------------------------------------------------------------
// The chat message balloon
//
//------------------------------------------------------------------------------------
class ChatMessage extends StatelessWidget {
  ChatMessage({this.text, this.name, this.type});

  final String text;
  final String name;
  final bool type;

  List<Widget> otherMessage(context) {
    return <Widget>[
      new Container(
        margin: const EdgeInsets.only(right: 16.0),
        child: CircleAvatar(child: new Text('B')),
      ),
      new Expanded(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(this.name,
                style: TextStyle(fontWeight: FontWeight.bold)),
            Container(
              margin: const EdgeInsets.only(top: 5.0),
              child: Text(text),
            ),
          ],
        ),
      ),
    ];
  }

  List<Widget> myMessage(context) {
    return <Widget>[
      Expanded(
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.end,
          children: <Widget>[
            Text(this.name, style: Theme.of(context).textTheme.subtitle1),
            Container(
              margin: const EdgeInsets.only(top: 5.0),
              child: Text(text),
            ),
          ],
        ),
      ),
      Container(
        margin: const EdgeInsets.only(left: 16.0),
        child: CircleAvatar(
            child: Text(
              this.name[0],
              style: TextStyle(fontWeight: FontWeight.bold),
            )),
      ),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.symmetric(vertical: 10.0),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: this.type ? myMessage(context) : otherMessage(context),
      ),
    );
  }
}

ابحث في ملف chat.dart عن Widget build. يؤدي ذلك إلى إنشاء واجهة برنامج الدردشة الآلي التي تحتوي على ما يلي:

  • ListView الذي يحتوي على جميع بالونات المحادثة من المستخدم وبرنامج المحادثة الآلي يستخدم هذا التطبيق فئة ChatMessage التي تنشئ رسائل محادثة تتضمّن أفاتارًا ونصًا.
  • TextField لإدخال طلبات البحث النصية
  • IconButton مع رمز الإرسال لإرسال طلبات بحث نصية إلى Dialogflow
  • IconButton مع ميكروفون لإرسال بث الصوت إلى Dialogflow، والذي يغيّر الحالة عند الضغط عليه.

ربط واجهة المحادثة

  1. افتح ملف main.dart وغيِّر Widget build، بحيث يتم إنشاء مثيل لواجهة Chat() فقط. ويمكن إزالة جميع الرموز التجريبية الأخرى.
import 'package:flutter/material.dart';
import 'chat.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.orange,
      ),
      home: MyHomePage(title: 'Flutter Dialogflow Agent'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Chat())
    );
  }
}
  1. شغِّل التطبيق. (إذا تم تشغيل التطبيق من قبل أوقِف الجهاز الافتراضي، وأعِد تشغيل main.dart). عند تشغيل تطبيقك مع واجهة الدردشة للمرة الأولى ستظهر نافذة منبثقة تطلب منك منح الإذن باستخدام الميكروفون. انقر على أثناء استخدام التطبيق.

الأذونات

  1. جرِّب منطقة النص والأزرار. عند كتابة طلب بحث نصي والضغط على Enter أو النقر على زر الإرسال، سيظهر طلب البحث النصي مسجّلاً في علامة التبويب تشغيل في Android Studio. عند النقر على زر الميكروفون وإيقافه، سيظهر بث الصوت الذي تم تسجيله في علامة التبويب تشغيل.

سجل البث الصوتي

رائع، نحن الآن جاهزون لدمج التطبيق مع Dialogflow.

دمج تطبيق Flutter مع Dialogflow_gRPC

  1. افتح الملف chat.dart وأضِف عمليات الاستيراد التالية:
import 'package:dialogflow_grpc/dialogflow_grpc.dart';
import 'package:dialogflow_grpc/generated/google/cloud/dialogflow/v2beta1/session.pb.dart';
  1. في أعلى الملف، مباشرةً تحت // TODO DialogflowGrpcV2Beta1 class instance، أضِف السطر التالي للاحتفاظ بنسخة من فئة Dialogflow:
DialogflowGrpcV2Beta1 dialogflow;
  1. ابحث عن طريقة initPlugin() وأضِف الرمز التالي أسفل تعليق TODO مباشرةً:
    // Get a Service account
    final serviceAccount = ServiceAccount.fromString(
        '${(await rootBundle.loadString('assets/credentials.json'))}');
    // Create a DialogflowGrpc Instance
    dialogflow = DialogflowGrpcV2Beta1.viaServiceAccount(serviceAccount);

سيؤدي ذلك إلى إنشاء مثيل Dialogflow مصرح به لمشروعك على Google Cloud باستخدام حساب الخدمة. (تأكَّد من توفّر ملف credentials.json في مجلد assets).

مرة أخرى، لأغراض العرض التوضيحي لطريقة استخدام Dialogflow gRPC، لا بأس في ذلك، ولكن بالنسبة إلى تطبيقات الإنتاج، لا يُنصح بتخزين ملف credentials.json في مجلد مواد العرض، لأنّ ذلك لا يُعدّ آمنًا.

إجراء مكالمة detectIntent

  1. ابحث الآن عن الطريقة handleSubmitted()، حيث تبدأ العملية. أضِف الرمز التالي أسفل تعليق TODO مباشرةً.سيؤدي هذا الرمز إلى إضافة الرسالة التي كتبها المستخدم إلى ListView:
ChatMessage message = ChatMessage(
 text: text,
 name: "You",
 type: true,
);

setState(() {
 _messages.insert(0, message);
});
  1. الآن، أسفل الرمز السابق مباشرةً، سنُجري طلب detectIntent، وسنمرّر النص من الإدخال وlanguageCode. - ستتم طباعة النتيجة (ضمن data.queryResult.fulfillment) في ListView:
DetectIntentResponse data = await dialogflow.detectIntent(text, 'en-US');
String fulfillmentText = data.queryResult.fulfillmentText;
if(fulfillmentText.isNotEmpty) {
  ChatMessage botMessage = ChatMessage(
    text: fulfillmentText,
    name: "Bot",
    type: false,
  );

  setState(() {
    _messages.insert(0, botMessage);
  });
}
  1. ابدأ تشغيل الجهاز الافتراضي واختبِر طلب detect intent. النوع: hi يجب أن تظهر لك رسالة الترحيب التلقائية. عند كتابة شيء آخر، سيتم عرض العنصر الاحتياطي التلقائي.

إجراء مكالمة streamingDetectIntent

  1. ابحث الآن عن طريقة handleStream()، فهنا يكمن سحر بث الصوت. أولاً، أنشئ InputConfigV2beta1 صوتيًا أسفل قائمة المهام الأولى مباشرةً مع biasList لتحسين النموذج الصوتي. بما أنّنا نستخدم هاتفًا (جهازًا افتراضيًا)، سيكون sampleHertz هو 16000 وسيكون الترميز Linear 16. يعتمد ذلك على أجهزة الكمبيوتر / الميكروفون الذي تستخدمه. بالنسبة إلى ميكروفون جهاز Macbook الداخلي، كان الرقم 16000 مناسبًا. (راجِع معلومات حزمة https://pub.dev/packages/sound_stream)
var biasList = SpeechContextV2Beta1(
    phrases: [
      'Dialogflow CX',
      'Dialogflow Essentials',
      'Action Builder',
      'HIPAA'
    ],
    boost: 20.0
);

    // See: https://cloud.google.com/dialogflow/es/docs/reference/rpc/google.cloud.dialogflow.v2#google.cloud.dialogflow.v2.InputAudioConfig
var config = InputConfigV2beta1(
    encoding: 'AUDIO_ENCODING_LINEAR_16',
    languageCode: 'en-US',
    sampleRateHertz: 16000,
    singleUtterance: false,
    speechContexts: [biasList]
);
  1. بعد ذلك، سنستدعي الطريقة streamingDetectIntent على الكائن dialogflow الذي يتضمّن جلسة Dialogflow:
final responseStream = dialogflow.streamingDetectIntent(config, _audioStream);
  1. باستخدام responseStream، يمكننا أخيرًا الاستماع إلى نص المحادثة الوارد وطلب المستخدم الذي تم رصده وردّ النية المطابقة الذي تم رصده. سنطبع هذا في ChatMessage على الشاشة:
// Get the transcript and detectedIntent and show on screen
responseStream.listen((data) {
  //print('----');
  setState(() {
    //print(data);
    String transcript = data.recognitionResult.transcript;
    String queryText = data.queryResult.queryText;
    String fulfillmentText = data.queryResult.fulfillmentText;

    if(fulfillmentText.isNotEmpty) {

      ChatMessage message = new ChatMessage(
        text: queryText,
        name: "You",
        type: true,
      );

      ChatMessage botMessage = new ChatMessage(
        text: fulfillmentText,
        name: "Bot",
        type: false,
      );

      _messages.insert(0, message);
      _textController.clear();
      _messages.insert(0, botMessage);

    }
    if(transcript.isNotEmpty) {
      _textController.text = transcript;
    }

  });
},onError: (e){
  //print(e);
},onDone: () {
  //print('done');
});

هذا كل ما عليك فعله، ابدأ تشغيل تطبيقك واختبِره على الجهاز الافتراضي، ثم انقر على زر الميكروفون وقُل: "مرحبًا".

سيؤدي ذلك إلى تشغيل نية الترحيب التلقائية في Dialogflow. ستتم طباعة النتائج على الشاشة. بعد أن أصبح Flutter يعمل بشكل رائع مع عملية الدمج في Dialogflow، يمكننا البدء في العمل على محادثة برنامج الدردشة الآلي.

5- ‫Dialogflow: تصميم وكيل Dialogflow

‫Dialogflow Essentials هي مجموعة أدوات تطوير لإنشاء واجهات مستخدم حوارية. وبالتالي، روبوتات الدردشة والروبوتات الصوتية وبوابات الهاتف. يمكنكم جميعًا إنشاء المحتوى باستخدام الأداة نفسها، ويمكنكم حتى إتاحة قنوات متعددة بأكثر من 20 لغة مختلفة. ينشئ مصمّمو تجربة المستخدم في Dialogflow (مصمّمو نماذج الوكلاء واللغويون) أو المطوّرون عناصر intent من خلال تحديد عبارات التدريب لتدريب نموذج أساسي لتعلُّم الآلة.

تصنّف النية هدف المستخدم. بالنسبة إلى كل وكيل في Dialogflow ES، يمكنك تحديد العديد من الأهداف، حيث يمكن أن تتعامل أهدافك المجمّعة مع محادثة كاملة. يمكن أن يحتوي كل هدف على مَعلمات وردود.

تُعرف مطابقة الغرض أيضًا باسم تصنيف الغرض أو مطابقة الغرض. هذا هو المفهوم الرئيسي في Dialogflow ES. بعد مطابقة غرض، يمكن أن يعرض ردًا أو يجمع مَعلمات (استخراج الكيانات) أو يشغّل رمز Webhook (التنفيذ)، على سبيل المثال، لاسترجاع البيانات من قاعدة بيانات.

عندما يكتب المستخدم النهائي شيئًا في روبوت محادثة أو يقوله، ويُشار إليه باسم عبارة أو تعبير مستخدم، يطابق Dialogflow ES العبارة مع أفضل هدف لوكيلك على Dialogflow، استنادًا إلى عبارات التدريب. تم تدريب نموذج تعلُّم الآلة في Dialogflow ES على عبارات التدريب هذه.

يعمل Dialogflow ES مع مفهوم يُعرف باسم السياق. مثل الإنسان، يمكن أن يتذكّر Dialogflow ES السياق في الدور الثاني والثالث من تبادل الأدوار. وبهذه الطريقة، يمكنه تتبُّع عبارات المستخدم السابقة.

مزيد من المعلومات حول نوايا Dialogflow

تعديل نية الترحيب التلقائية

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

في ما يلي رسالة الترحيب الخاصة بـ "نية الترحيب التلقائية":

المستخدم

الوكيل

مرحبًا

"مرحبًا، أنا برنامج تتبّع الأسئلة الشائعة في Dialogflow، ويمكنني الإجابة عن الأسئلة المتعلقة بـ Dialogflow".

"ما الذي تريد معرفته؟"

  1. انقر على طلبات > طلب الترحيب التلقائي
  2. انتقِل للأسفل إلى الردود.
  3. محو جميع الردود النصية
  4. في علامة التبويب التلقائية، أنشئ الردّين التاليين:
  • مرحبًا، أنا برنامج الدردشة الآلي الخاص بالأسئلة الشائعة في Dialogflow، ويمكنني الإجابة عن الأسئلة المتعلقة بـ Dialogflow. ما الذي تريد معرفته؟
  • مرحبًا، أنا روبوت الأسئلة الشائعة في Dialogflow. هل لديك أسئلة حول Dialogflow؟ كيف يمكنني مساعدتك؟

يجب أن يكون الإعداد مشابهًا للقطة الشاشة هذه.

تعديل نية الترحيب التلقائية

  1. انقر على حفظ.
  2. لنجرّب هذه النية. أولاً، يمكننا اختبارها في محاكي Dialogflow.اكتب: Hello. من المفترض أن يتم عرض إحدى الرسائل التالية:
  • مرحبًا، أنا برنامج الدردشة الآلي الخاص بالأسئلة الشائعة في Dialogflow، ويمكنني الإجابة عن الأسئلة المتعلقة بـ Dialogflow. ما الذي تريد معرفته؟
  • مرحبًا، أنا روبوت الأسئلة الشائعة في Dialogflow. هل لديك أسئلة حول Dialogflow؟ كيف يمكنني مساعدتك؟

تعديل Intent الاحتياطي التلقائي

  1. انقر على الطلبات > طلب احتياطي تلقائي
  2. انتقِل للأسفل إلى الردود.
  3. محو جميع الردود النصية
  4. في علامة التبويب التلقائية، أنشئ الردّ التالي:
  • لا أعرف الإجابة عن هذا السؤال. هل اطّلعت على موقعنا الإلكتروني؟ http://www.dialogflow.com؟
  1. انقر على حفظ.

الربط بقاعدة معرفة على الإنترنت

تكمّل موصّلات المعرفة النوايا المحدّدة. وهي تحلّل مستندات المعلومات للعثور على الردود المبرمَجة. (على سبيل المثال، الأسئلة الشائعة أو المقالات من ملفات CSV أو المواقع الإلكترونية أو حتى ملفات PDF) لضبطها، عليك تحديد قاعدة معلومات واحدة أو أكثر، وهي عبارة عن مجموعات من مستندات المعلومات.

مزيد من المعلومات عن "موصِّلات المعرفة"

لنجرّب هذا.

  1. انقر على المعرفة (إصدار تجريبي) في القائمة.

قاعدة المعلومات

  1. انقر على الزر الأزرق الأيمن: إنشاء قاعدة معلومات
  2. اكتب اسمًا لقاعدة المعرفة، مثل أسئلة وأجوبة في Dialogflow، ثم انقر على حفظ.
  3. انقر على الرابط إنشاء أول رابط.

Knowledge Base first one

  1. سيؤدي ذلك إلى فتح نافذة.

استخدِم الإعداد التالي:

اسم المستند: DialogflowFAQ نوع المعرفة: FAQ نوع MIME: text/html

  1. عنوان URL الذي نحمّل البيانات منه هو:

https://www.leeboonstra.dev/faqs/

  1. انقر على إنشاء

تم إنشاء قاعدة معلومات:

تم إنشاء قاعدة المعلومات

  1. انتقِل للأسفل إلى قسم "الردود" وانقر على إضافة ردّ.

أنشئ الإجابات التالية وانقر على حفظ.

$Knowledge.Answer[1]
  1. انقر على عرض التفاصيل.

عرض التفاصيل

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

سيؤدي ذلك إلى عرض جميع الأسئلة الشائعة التي نفّذتها في Dialogflow.

اعلم أنّه يمكنك أيضًا الإشارة إلى موقع إلكتروني بتنسيق HTML على الإنترنت يتضمّن أسئلة شائعة لاستيرادها إلى برنامجك الآلي. يمكنك حتى تحميل ملف PDF يتضمّن مجموعة من النصوص، وسيقترح Dialogflow الأسئلة بنفسه.

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

  1. اختبِر الأسئلة في المحاكي على يسار الصفحة.
  2. عندما يعمل كل شيء بشكل صحيح، ارجع إلى تطبيق Flutter واختبِر برنامج الدردشة وبرنامج التتبُّع الصوتي باستخدام هذا المحتوى الجديد. اطرح الأسئلة التي حمّلتها إلى Dialogflow.

النتيجة

6. تهانينا

تهانينا، لقد أنشأت تطبيق Flutter الأول بنجاح من خلال دمج برنامج الدردشة الآلي من Dialogflow.

المواضيع التي تناولناها

  • كيفية إنشاء روبوت محادثة باستخدام Dialogflow Essentials
  • كيفية دمج Dialogflow في تطبيق Flutter
  • كيفية رصد نوايا النص باستخدام Dialogflow
  • كيفية بث صوت عبر الميكروفون إلى Dialogflow
  • كيفية الاستفادة من أداة ربط قاعدة المعرفة

ما هي الخطوات التالية؟

هل أعجبك هذا الدرس العملي؟ ننصحك بالاطّلاع على هذه المعامل الرائعة في Dialogflow.

هل يهمّك معرفة كيف أنشأت حزمة Dialogflow gRPC للغة Dart/إطار عمل Flutter؟