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

1. قبل البدء

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

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

  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 باستخدام حزمة gRPC الخاصة بـ Dialogflow
  • كيفية رصد أغراض النص باستخدام Dialogflow
  • كيفية بث صوت عبر الميكروفون إلى Dialogflow
  • كيفية استخدام موصّل قاعدة المعرفة لاستيراد الأسئلة الشائعة العامة
  • اختبار روبوت الدردشة من خلال واجهة النص والصوت على جهاز افتراضي أو حقيقي

المتطلبات

  • يجب أن يكون لديك هوية Google أو عنوان 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. لا تختاروا Mega Agent. (باستخدام هذه الميزة، يمكنك إنشاء وكيل شامل يمكنه التنسيق بين الوكلاء "الفرعيين". لا نحتاج إلى ذلك الآن.)
  7. انقر على إنشاء.

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

إعداد Dialogflow

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

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

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

‫Dialogflow Essentials V2Beta1

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

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

بعد إنشاء وكيل في Dialogflow، يجب إنشاء مشروع على Google Cloud في 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 التي سنستخدمها الإصدار 21 من minSdk على الأقل. لذا، لنغيّر ذلك في 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. بعد اختيار جهاز افتراضي جديد، يمكنك النقر عليه مرّتين لبدء تشغيله.

إدارة الأجهزة الافتراضية التي تعمل بنظام التشغيل Android

الجهاز الافتراضي

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

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

تطبيق نموذجي

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

خيارات AVD

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

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

الرمز الأول

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

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

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

  1. أنشئ ملف أداة Flutter جديدًا في مجلد lib. (انقر بزر الماوس الأيمن على مجلد lib، ثم جديد > أداة Flutter > أداة ذات حالة)، وأطلِق على هذا الملف الاسم: 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. عند النقر على زر الميكروفون وإيقافه، سيظهر بث الصوت الذي تم تسجيله في علامة التبويب تشغيل.

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

رائع، نحن الآن جاهزون لدمج التطبيق مع 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 مصرح به لمشروعك على السحابة الإلكترونية باستخدام حساب الخدمة. (تأكَّد من أنّ لديك ملف 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 (مصمّمو نماذج الوكلاء أو اللغويون) أو المطوّرون الأهداف من خلال تحديد عبارات التدريب لتدريب نموذج أساسي لتعلُّم الآلة.

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

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

عندما يكتب المستخدم النهائي شيئًا في برنامج الدردشة الآلي أو يقوله، ويُشار إليه باسم تعبير أو جملة المستخدم، يطابق 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؟