1. ก่อนเริ่มต้น
ในโค้ดแล็บนี้ คุณจะได้เรียนรู้วิธีผสานรวมบ็อตข้อความและเสียง Dialogflow Essentials (ES) อย่างง่ายเข้ากับแอป Flutter Dialogflow ES เป็นชุดเครื่องมือพัฒนาสำหรับสร้าง UI แบบสนทนา จึงมีแชทบ็อต บ็อตเสียง และเกตเวย์โทรศัพท์ คุณสามารถสร้างแอปทั้งหมดได้ด้วยเครื่องมือเดียวกัน และยังรองรับช่องหลายช่องในกว่า 20 ภาษาอีกด้วย Dialogflow ทำงานร่วมกับแพลตฟอร์มการสนทนายอดนิยมมากมาย เช่น Google Assistant, Slack และ Facebook Messenger หากต้องการสร้าง Agent สำหรับแพลตฟอร์มใดแพลตฟอร์มหนึ่งเหล่านี้ คุณควรใช้ตัวเลือกการผสานรวมที่มีอยู่มากมาย อย่างไรก็ตาม หากต้องการสร้างแชทบอทสำหรับอุปกรณ์เคลื่อนที่ คุณจะต้องสร้างการผสานรวมที่กำหนดเอง คุณจะสร้างความตั้งใจได้โดยการระบุวลีการฝึกเพื่อฝึกโมเดลแมชชีนเลิร์นนิงที่เกี่ยวข้อง
แล็บนี้จัดเรียงเพื่อให้สอดคล้องกับประสบการณ์การใช้งานของผู้พัฒนาบนระบบคลาวด์ทั่วไป
- การตั้งค่าสภาพแวดล้อม
- Dialogflow: สร้าง Agent ของ Dialogflow ES ใหม่
- Dialogflow: กำหนดค่า Dialogflow
- Google Cloud: สร้างบัญชีบริการ
- Flutter: การสร้างแอปพลิเคชันแชท
- การสร้างโปรเจ็กต์ Flutter
- การกำหนดค่าและการตั้งค่าสิทธิ์
- การเพิ่มทรัพยากร Dependency
- การลิงก์กับบัญชีบริการ
- การเรียกใช้แอปพลิเคชันในอุปกรณ์เสมือนหรืออุปกรณ์จริง
- Flutter: สร้างอินเทอร์เฟซแชทที่รองรับการแปลงเสียงเป็นข้อความ
- การสร้างอินเทอร์เฟซแชท
- การลิงก์อินเทอร์เฟซแชท
- การผสานรวมแพ็กเกจ gRPC ของ Dialogflow เข้ากับแอป
- Dialogflow: การสร้างโมเดล Agent ของ Dialogflow
- กำหนดค่าเจตนาต้อนรับและเจตนาสำรอง
- ใช้ประโยชน์จากฐานความรู้ของคำถามที่พบบ่อย
วิชาบังคับก่อน
- ประสบการณ์การใช้งาน Dart/Flutter ขั้นพื้นฐาน
- ประสบการณ์การใช้งาน Google Cloud Platform ขั้นพื้นฐาน
- ประสบการณ์พื้นฐานเกี่ยวกับ Dialogflow ES
สิ่งที่คุณจะสร้าง
โค้ดแล็บนี้จะแสดงวิธีสร้างบ็อตคำถามที่พบบ่อยบนอุปกรณ์เคลื่อนที่ ซึ่งสามารถตอบคำถามที่พบบ่อยที่สุดเกี่ยวกับเครื่องมือ Dialogflow ผู้ใช้ปลายทางสามารถโต้ตอบกับอินเทอร์เฟซข้อความหรือสตรีมเสียงผ่านไมโครโฟนในตัวของอุปกรณ์เคลื่อนที่เพื่อรับคำตอบ |
|
สิ่งที่คุณจะได้เรียนรู้
- วิธีสร้างแชทบอทด้วย Dialogflow Essentials
- วิธีผสานรวม Dialogflow เข้ากับแอป Flutter ด้วยแพ็กเกจ gRPC ของ Dialogflow
- วิธีตรวจหาความตั้งใจที่เป็นข้อความด้วย Dialogflow
- วิธีสตรีมเสียงผ่านไมโครโฟนไปยัง Dialogflow
- วิธีใช้เครื่องมือเชื่อมต่อฐานความรู้เพื่อนำเข้าคำถามที่พบบ่อยแบบสาธารณะ
- ทดสอบแชทบอทผ่านอินเทอร์เฟซข้อความและเสียงในอุปกรณ์เสมือนหรืออุปกรณ์จริง
สิ่งที่คุณต้องมี
- คุณจะต้องมีข้อมูลประจำตัว Google / อีเมล Gmail เพื่อสร้าง Agent ของ Dialogflow
- คุณต้องมีสิทธิ์เข้าถึง Google Cloud Platform เพื่อดาวน์โหลดบัญชีบริการ
- สภาพแวดล้อมการพัฒนา Flutter
ตั้งค่าสภาพแวดล้อมการพัฒนา Flutter
- เลือกระบบปฏิบัติการที่คุณจะติดตั้ง Flutter
- ผู้ใช้ macOS: https://flutter.dev/docs/get-started/install/macos
- Windows: https://flutter.dev/docs/get-started/install/windows
- Linux: https://flutter.dev/docs/get-started/install/linux
- ChromeOS: https://flutter.dev/docs/get-started/install/chromeos
- คุณสร้างแอปด้วย Flutter ได้โดยใช้โปรแกรมแก้ไขข้อความร่วมกับเครื่องมือบรรทัดคำสั่งของเรา อย่างไรก็ตาม เวิร์กช็อปนี้จะใช้ Android Studio ปลั๊กอิน Flutter และ Dart สำหรับ Android Studio จะช่วยให้คุณเขียนโค้ดได้สมบูรณ์ ไฮไลต์ไวยากรณ์ แก้ไขวิดเจ็ตได้ง่าย รองรับการเรียกใช้และการแก้ไขข้อบกพร่อง และอื่นๆ ทำตามขั้นตอนใน https://flutter.dev/docs/get-started/editor
2. การตั้งค่าสภาพแวดล้อม
Dialogflow: สร้าง Agent ของ Dialogflow ES ใหม่
- เปิด
- ในแถบด้านซ้าย ใต้โลโก้ ให้เลือก "สร้างเอเจนต์ใหม่" ในเมนูแบบเลื่อนลง (โปรดทราบว่าอย่าคลิกเมนูแบบเลื่อนลงที่ระบุว่า "ทั่วโลก" เราจะต้องมีอินสแตนซ์ Dialogflow ที่เป็นแบบทั่วโลกเพื่อใช้ฐานความรู้คำถามที่พบบ่อย)
- ระบุชื่อตัวแทน
yourname-dialogflow(ใช้ชื่อของคุณเอง) - เลือกอังกฤษ - en เป็นภาษาเริ่มต้น
- เลือกเขตเวลาที่ใกล้กับคุณมากที่สุดเป็นเขตเวลาเริ่มต้น
- อย่าเลือก Mega Agent (ฟีเจอร์นี้ช่วยให้คุณสร้างเอเจนต์ที่ครอบคลุมได้ ซึ่งสามารถประสานงานระหว่างเอเจนต์ "ย่อย" ได้ เราไม่จำเป็นต้องใช้ตอนนี้)
- คลิกสร้าง

กำหนดค่า Dialogflow
- คลิกไอคอนเฟืองในเมนูด้านซ้ายข้างชื่อโปรเจ็กต์

- ป้อนคำอธิบายตัวแทนต่อไปนี้ แชทบอทคำถามที่พบบ่อยของ Dialogflow
- เปิดใช้ฟีเจอร์เบต้าโดยสลับสวิตช์

- คลิกแท็บคำพูด และตรวจสอบว่าช่องการดัดแปลงคำพูดอัตโนมัติเปิดใช้งานอยู่
- นอกจากนี้ คุณยังพลิกสวิตช์แรกได้ด้วย ซึ่งจะช่วยปรับปรุงโมเดลคำพูด แต่จะใช้ได้เมื่ออัปเกรดรุ่นทดลองใช้ Dialogflow เท่านั้น
- คลิกบันทึก
Google Cloud: สร้างบัญชีบริการ
หลังจากสร้าง Agent ใน Dialogflow แล้ว คุณควรสร้างโปรเจ็กต์ Google Cloud ในคอนโซล Google Cloud
- เปิดคอนโซล Google Cloud:
- ตรวจสอบว่าคุณเข้าสู่ระบบด้วยบัญชี Google เดียวกับใน Dialogflow และเลือกโปรเจ็กต์:
yourname-dialogflowในแถบสีน้ำเงินด้านบน - จากนั้นค้นหา
Dialogflow APIในแถบเครื่องมือด้านบน แล้วคลิกผลลัพธ์ Dialogflow API ในเมนูแบบเลื่อนลง

- คลิกปุ่มจัดการสีน้ำเงิน แล้วคลิกข้อมูลเข้าสู่ระบบในแถบเมนูด้านซ้าย (หากยังไม่ได้เปิดใช้ Dialogflow ให้แตะเปิดใช้ก่อน)

- คลิกสร้างข้อมูลเข้าสู่ระบบ (ที่ด้านบนของหน้าจอ) แล้วเลือกบัญชีบริการ

- ระบุชื่อ รหัส และคำอธิบายของบัญชีบริการ แล้วกดสร้าง
flutter_dialogflow

- ในขั้นตอนที่ 2 คุณจะต้องเลือกบทบาท:
Dialogflow API Adminคลิกต่อไป และเสร็จสิ้น - คลิก
flutter_dialogflowบัญชีบริการ คลิกแท็บคีย์ แล้วคลิกเพิ่มคีย์ > สร้างคีย์ใหม่

- สร้างคีย์ JSON เปลี่ยนชื่อเป็น
credentials.jsonแล้วจัดเก็บไว้ในตำแหน่งที่ปลอดภัยในฮาร์ดไดรฟ์ เราจะใช้ในภายหลัง

เยี่ยมเลย เราตั้งค่าเครื่องมือทั้งหมดที่จำเป็นอย่างถูกต้องแล้ว ตอนนี้เราก็เริ่มผสานรวม Dialogflow ในแอปได้แล้ว
3. Flutter: สร้างแอปพลิเคชันแชท
สร้างแอป Boilerplate
- เปิด Android Studio แล้วเลือกเริ่มโปรเจ็กต์ Flutter ใหม่
- เลือกประเภทโปรเจ็กต์เป็นแอปพลิเคชัน Flutter แล้วคลิกถัดไป
- ตรวจสอบว่าเส้นทาง Flutter SDK ระบุตำแหน่งของ SDK (เลือก "ติดตั้ง SDK..." หากช่องข้อความว่างเปล่า)
- ป้อนชื่อโปรเจ็กต์ (เช่น
flutter_dialogflow_agent) แล้วคลิกถัดไป - แก้ไขชื่อแพ็กเกจ แล้วคลิกเสร็จสิ้น

ซึ่งจะสร้างแอปพลิเคชันตัวอย่างที่มี Material Components
รอให้ Android Studio ติดตั้ง SDK และสร้างโปรเจ็กต์
การตั้งค่าและสิทธิ์
- ไลบรารีเครื่องบันทึกเสียง sound_stream ที่เราจะใช้ต้องมี minSdk อย่างน้อย 21 ดังนั้นเรามาเปลี่ยนค่านี้ใน android/app/build.gradle ในบล็อก defaultConfig กัน (โปรดทราบว่ามีไฟล์ build.gradle 2 ไฟล์ในโฟลเดอร์ Android แต่ไฟล์ในโฟลเดอร์แอปคือไฟล์ที่ถูกต้อง)
defaultConfig {
applicationId "com.myname.flutter_dialogflow_agent"
minSdkVersion 21
targetSdkVersion 30
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
- หากต้องการให้สิทธิ์เข้าถึงไมโครโฟนและอนุญาตให้แอปติดต่อเอเจนต์ Dialogflow ที่ทำงานในระบบคลาวด์ เราจะต้องเพิ่มสิทธิ์ INTERNET และ RECORD_AUDIO ลงในไฟล์ app/src/main/AndroidManifest.xml โปรเจ็กต์ Flutter มีไฟล์ AndroidManifest.xml หลายไฟล์ แต่คุณจะต้องใช้ไฟล์ในโฟลเดอร์หลัก คุณเพิ่มบรรทัดได้ในแท็กไฟล์ Manifest
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECORD_AUDIO" />
การเพิ่มทรัพยากร Dependency
เราจะใช้แพ็กเกจ sound_stream, rxdart และ dialogflow_grpc
- เพิ่มการอ้างอิง
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!
- เพิ่มการอ้างอิง
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!
- เพิ่มการอ้างอิง
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
- สร้างไดเรกทอรีในโปรเจ็กต์และตั้งชื่อว่า
assets - ย้ายไฟล์ credentials.json ที่คุณดาวน์โหลดจากคอนโซล Google Cloud ไปยังโฟลเดอร์ assets
- เปิด pubspec.yaml แล้วเพิ่มบัญชีบริการลงในบล็อก Flutter
flutter:
uses-material-design: true
assets:
- assets/credentials.json
การเรียกใช้แอปพลิเคชันในอุปกรณ์จริง
เมื่อมีอุปกรณ์ Android คุณสามารถเสียบโทรศัพท์ผ่านสาย USB และแก้ไขข้อบกพร่องในอุปกรณ์ได้ ทำตามขั้นตอนเหล่านี้เพื่อตั้งค่าผ่านหน้าจอตัวเลือกสำหรับนักพัฒนาแอปในอุปกรณ์ Android
การเรียกใช้แอปพลิเคชันในอุปกรณ์เสมือน
หากต้องการเรียกใช้แอปพลิเคชันในอุปกรณ์เสมือน ให้ทำตามขั้นตอนต่อไปนี้
- คลิกเครื่องมือ> AVD Manager (หรือเลือก AVD Manager จากแถบเครื่องมือด้านบน ในรูปด้านล่างจะไฮไลต์เป็นสีชมพู)

- เราจะสร้างอุปกรณ์เสมือน Android เป้าหมายเพื่อให้ทดสอบแอปพลิเคชันได้โดยไม่ต้องใช้อุปกรณ์จริง โปรดดูรายละเอียดที่หัวข้อการจัดการ AVD เมื่อเลือกอุปกรณ์เสมือนใหม่แล้ว คุณสามารถดับเบิลคลิกเพื่อเริ่มใช้งานได้


- ในแถบเครื่องมือหลักของ Android Studio ให้เลือกอุปกรณ์ Android เป็นเป้าหมายผ่านเมนูแบบเลื่อนลง และตรวจสอบว่าได้เลือก main.dart แล้ว จากนั้นกดปุ่มเรียกใช้ (สามเหลี่ยมสีเขียว)
ที่ด้านล่างของ IDE คุณจะเห็นบันทึกในคอนโซล คุณจะเห็นว่าระบบกำลังติดตั้ง Android และแอป Flutter เริ่มต้น ซึ่งจะใช้เวลา 1 นาที เมื่ออุปกรณ์เสมือนพร้อมแล้ว การเปลี่ยนแปลงจะรวดเร็วมาก เมื่อเสร็จแล้ว ระบบจะเปิดแอป Flutter เริ่มต้น

- มาเปิดใช้ไมโครโฟนสำหรับแอปแชทบอทกัน คลิกปุ่มตัวเลือกของอุปกรณ์เสมือนเพื่อเปิดตัวเลือก ในแท็บไมโครโฟน ให้เปิดสวิตช์ทั้ง 3 รายการ

- มาลองใช้ Hot Reload เพื่อแสดงให้เห็นว่าการเปลี่ยนแปลงทำได้รวดเร็วเพียงใด
ใน lib/main.dart ให้เปลี่ยนชื่อ MyHomePage ในคลาส MyApp เป็น Flutter Dialogflow Agent และเปลี่ยน primarySwatch เป็น Colors.orange

บันทึกไฟล์ หรือคลิกไอคอนสายฟ้าในแถบเครื่องมือของ Android Studio คุณควรเห็นการเปลี่ยนแปลงที่เกิดขึ้นโดยตรงในอุปกรณ์เสมือน
4. Flutter: สร้างอินเทอร์เฟซแชทที่รองรับ STT
การสร้างอินเทอร์เฟซแชท
- สร้างไฟล์ Flutter Widget ใหม่ในโฟลเดอร์ lib (คลิกขวาที่โฟลเดอร์ lib, New > Flutter Widget > Stateful widget) เรียกไฟล์นี้ว่า
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),
),
);
}
}
ค้นหา Widget build ในไฟล์ chat.dart ซึ่งจะสร้างอินเทอร์เฟซแชทบ็อตที่มีองค์ประกอบต่อไปนี้
- ListView ซึ่งมีบอลลูนแชททั้งหมดจากผู้ใช้และแชทบ็อต โดยใช้คลาส ChatMessage ซึ่งสร้างข้อความแชทพร้อมรูปโปรไฟล์และข้อความ
- TextField สำหรับป้อนคำค้นหาที่เป็นข้อความ
- IconButton ที่มีไอคอนส่งสำหรับส่งข้อความค้นหาไปยัง Dialogflow
- IconButton ที่มีไมโครโฟนสำหรับส่งสตรีมเสียงไปยัง Dialogflow ซึ่งจะเปลี่ยนสถานะเมื่อกด
การลิงก์อินเทอร์เฟซแชท
- เปิด 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())
);
}
}
- เรียกใช้แอปพลิเคชัน (หากเคยเปิดแอปมาก่อน หยุดอุปกรณ์เสมือน แล้วเรียกใช้ main.dart อีกครั้ง เมื่อคุณเรียกใช้แอปที่มีอินเทอร์เฟซแชทเป็นครั้งแรก คุณจะได้รับป๊อปอัปสิทธิ์ที่ถามว่าต้องการอนุญาตให้ใช้ไมโครโฟนหรือไม่ คลิกขณะใช้แอป

- ลองใช้พื้นที่ข้อความและปุ่มต่างๆ เมื่อพิมพ์คำค้นหาที่เป็นข้อความแล้วกด Enter หรือแตะปุ่มส่ง คุณจะเห็นคำค้นหาที่เป็นข้อความที่บันทึกไว้ในแท็บเรียกใช้ของ Android Studio เมื่อแตะปุ่มไมโครโฟนและหยุด คุณจะเห็นสตรีมเสียงที่บันทึกไว้ในแท็บเรียกใช้

ยอดเยี่ยม ตอนนี้เราพร้อมที่จะผสานรวมแอปพลิเคชันกับ Dialogflow แล้ว
การผสานรวมแอป Flutter กับ Dialogflow_gRPC
- เปิด chat.dart แล้วเพิ่มการนำเข้าต่อไปนี้
import 'package:dialogflow_grpc/dialogflow_grpc.dart';
import 'package:dialogflow_grpc/generated/google/cloud/dialogflow/v2beta1/session.pb.dart';
- ที่ด้านบนของไฟล์ ใต้
// TODO DialogflowGrpcV2Beta1 class instanceให้เพิ่มบรรทัดต่อไปนี้เพื่อเก็บอินสแตนซ์ของคลาส Dialogflow
DialogflowGrpcV2Beta1 dialogflow;
- ค้นหาวิธี 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)
อีกครั้งว่าการจัดเก็บไฟล์ credentials.json ไว้ในโฟลเดอร์ชิ้นงานนั้นใช้ได้สำหรับการสาธิตวิธีทำงานกับ gRPC ของ Dialogflow แต่สำหรับแอปที่ใช้งานจริง คุณไม่ควรจัดเก็บไฟล์ดังกล่าวไว้ในโฟลเดอร์ชิ้นงาน เนื่องจากไม่ถือว่าปลอดภัย
การโทร detectIntent
- ตอนนี้ให้ค้นหา
handleSubmitted()method ซึ่งเป็นจุดที่เกิดการทำงาน เพิ่มโค้ดต่อไปนี้ใต้ความคิดเห็น TODO โค้ดนี้จะเพิ่มข้อความที่ผู้ใช้พิมพ์ลงใน ListView
ChatMessage message = ChatMessage(
text: text,
name: "You",
type: true,
);
setState(() {
_messages.insert(0, message);
});
- ตอนนี้เราจะเรียกใช้ 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);
});
}
- เริ่มอุปกรณ์เสมือนและทดสอบการเรียกใช้ตรวจหาความตั้งใจ ประเภท:
hiโดยควรแสดงข้อความต้อนรับเริ่มต้น เมื่อคุณพิมพ์คำอื่น ระบบจะแสดงผลสำรองเริ่มต้นให้คุณ
การโทร streamingDetectIntent
- ตอนนี้ให้ค้นหา
handleStream()วิธี ซึ่งเป็นจุดที่การสตรีมเสียงจะทำงาน ก่อนอื่นให้สร้าง InputConfigV2beta1 สำหรับเสียงที่มี biasList เพื่อกำหนดรูปแบบเสียงใต้ TODO แรก เนื่องจากเราใช้โทรศัพท์ (อุปกรณ์เสมือน) 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]
);
- จากนั้นเราจะเรียกใช้เมธอด
streamingDetectIntentในออบเจ็กต์dialogflowซึ่งมีเซสชัน Dialogflow ของเรา
final responseStream = dialogflow.streamingDetectIntent(config, _audioStream);
- เมื่อใช้ 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: การสร้างโมเดล Agent ของ Dialogflow
Dialogflow Essentials เป็นชุดเครื่องมือพัฒนาสำหรับสร้าง UI แบบสนทนา จึงมีแชทบ็อต บ็อตเสียง และเกตเวย์โทรศัพท์ คุณสามารถสร้างแอปทั้งหมดได้ด้วยเครื่องมือเดียวกัน และยังรองรับช่องหลายช่องในกว่า 20 ภาษาอีกด้วย นักออกแบบ UX ของ Dialogflow (ผู้สร้างโมเดล Agent นักภาษาศาสตร์) หรือนักพัฒนาซอฟต์แวร์จะสร้าง Intent โดยการระบุวลีการฝึกเพื่อฝึกโมเดลแมชชีนเลิร์นนิงพื้นฐาน
ความตั้งใจจะจัดหมวดหมู่ความตั้งใจของผู้ใช้ คุณกำหนดเจตนาได้หลายอย่างสำหรับแต่ละเอเจนต์ Dialogflow ES โดยเจตนารวมกันจะจัดการการสนทนาทั้งหมดได้ แต่ละเจตนาจะมีพารามิเตอร์และคำตอบได้
การจับคู่ความตั้งใจเรียกอีกอย่างว่าการจัดประเภทความตั้งใจหรือการจับคู่ความตั้งใจ ซึ่งเป็นแนวคิดหลักใน Dialogflow ES เมื่อระบบจับคู่เจตนาได้แล้ว ระบบจะแสดงคำตอบ รวบรวมพารามิเตอร์ (การแยกเอนทิตี) หรือเรียกใช้โค้ด Webhook (การดำเนินการตามคำสั่ง) ได้ เช่น เพื่อดึงข้อมูลจากฐานข้อมูล
เมื่อผู้ใช้ปลายทางเขียนหรือพูดบางอย่างในแชทบอท ซึ่งเรียกว่าการแสดงออกหรือคำพูดของผู้ใช้ Dialogflow ES จะจับคู่การแสดงออกนั้นกับเจตนาที่ดีที่สุดของตัวแทน Dialogflow โดยอิงตามวลีการฝึก โมเดลแมชชีนเลิร์นนิงของ Dialogflow ES ที่ทำงานเบื้องหลังได้รับการฝึกด้วยวลีการฝึกเหล่านั้น
Dialogflow ES ทำงานร่วมกับแนวคิดที่เรียกว่าบริบท Dialogflow ES สามารถจดจำบริบทในเทิร์นที่ 2 และ 3 ได้เช่นเดียวกับมนุษย์ วิธีนี้จะช่วยให้ติดตามคำพูดของผู้ใช้ก่อนหน้านี้ได้
ดูข้อมูลเพิ่มเติมเกี่ยวกับเจตนาของ Dialogflow
การแก้ไข Intent ต้อนรับเริ่มต้น
เมื่อสร้างเอเจนต์ Dialogflow ใหม่ ระบบจะสร้าง Intent เริ่มต้น 2 รายการโดยอัตโนมัติ เจตนาต้อนรับเริ่มต้นคือโฟลว์แรกที่คุณจะได้รับเมื่อเริ่มการสนทนากับตัวแทน เจตนาสำรองเริ่มต้นคือโฟลว์ที่คุณจะได้รับเมื่อตัวแทนไม่เข้าใจคุณหรือไม่สามารถจับคู่เจตนากับสิ่งที่คุณเพิ่งพูด
นี่คือข้อความต้อนรับสำหรับเจตนาต้อนรับเริ่มต้น
ผู้ใช้ | Agent |
สวัสดี | "สวัสดี ฉันคือบ็อตคำถามที่พบบ่อยของ Dialogflow ฉันตอบคำถามเกี่ยวกับ Dialogflow ได้" |
- คลิกเจตนา > เจตนาต้อนรับเริ่มต้น
- เลื่อนลงไปที่คำตอบ
- ล้างคำตอบที่เป็นข้อความทั้งหมด
- ในแท็บเริ่มต้น ให้สร้างคำตอบ 2 รายการต่อไปนี้
- สวัสดี ฉันคือบ็อตคำถามที่พบบ่อยของ Dialogflow ฉันตอบคำถามเกี่ยวกับ Dialogflow ได้ คุณต้องการทราบเรื่องใด
- สวัสดี ฉันคือบ็อตคำถามที่พบบ่อยของ Dialogflow คุณมีคำถามเกี่ยวกับ Dialogflow ไหม มีอะไรให้ช่วยบ้าง
การกำหนดค่าควรมีลักษณะคล้ายกับภาพหน้าจอนี้

- คลิกบันทึก
- มาทดสอบเจตนานี้กัน ก่อนอื่น เราจะทดสอบในโปรแกรมจำลอง Dialogflow โดยพิมพ์ว่า Hello โดยควรแสดงข้อความอย่างใดอย่างหนึ่งต่อไปนี้
- สวัสดี ฉันคือบ็อตคำถามที่พบบ่อยของ Dialogflow ฉันตอบคำถามเกี่ยวกับ Dialogflow ได้ คุณต้องการทราบเรื่องใด
- สวัสดี ฉันคือบ็อตคำถามที่พบบ่อยของ Dialogflow คุณมีคำถามเกี่ยวกับ Dialogflow ไหม มีอะไรให้ช่วยบ้าง
การแก้ไขเจตนาสำรองเริ่มต้น
- คลิก Intent > Fallback Intent เริ่มต้น
- เลื่อนลงไปที่คำตอบ
- ล้างคำตอบที่เป็นข้อความทั้งหมด
- ในแท็บเริ่มต้น ให้สร้างการตอบกลับต่อไปนี้
- ขออภัย เราไม่ทราบคำตอบของคำถามนี้ คุณได้ตรวจสอบเว็บไซต์ของเราแล้วหรือยัง http://www.dialogflow.com
- คลิกบันทึก
การเชื่อมต่อกับฐานความรู้ออนไลน์
เครื่องมือค้นหาความรู้จะช่วยเสริมเจตนาที่กำหนดไว้ โดยจะแยกวิเคราะห์เอกสารความรู้เพื่อค้นหาคำตอบอัตโนมัติ (เช่น คำถามที่พบบ่อยหรือบทความจากไฟล์ CSV, เว็บไซต์ออนไลน์ หรือแม้แต่ไฟล์ PDF) หากต้องการกำหนดค่า คุณต้องกำหนดฐานความรู้อย่างน้อย 1 รายการ ซึ่งเป็นคอลเล็กชันของเอกสารความรู้
อ่านเพิ่มเติมเกี่ยวกับ Knowledge Connectors
มาลองกันเลย
- เลือกความรู้ (เบต้า) ในเมนู

- คลิกปุ่มสีน้ำเงินทางด้านขวา: สร้างฐานความรู้
- พิมพ์ชื่อเป็นฐานความรู้ FAQ ของ Dialogflow แล้วกดบันทึก
- คลิกลิงก์สร้างรายการแรก

- ซึ่งจะเป็นการเปิดหน้าต่าง
ใช้การกำหนดค่าต่อไปนี้
ชื่อเอกสาร: DialogflowFAQ ประเภทความรู้: FAQ ประเภท MIME: text/html
- URL ที่เราโหลดข้อมูลคือ
https://www.leeboonstra.dev/faqs/
- คลิกสร้าง
สร้างฐานความรู้แล้ว

- เลื่อนลงไปที่ส่วนคำตอบ แล้วคลิกเพิ่มคำตอบ
สร้างคำตอบต่อไปนี้ แล้วกดบันทึก
$Knowledge.Answer[1]
- คลิกดูรายละเอียด

- เลือกเปิดใช้การโหลดซ้ำอัตโนมัติเพื่อดึงข้อมูลการเปลี่ยนแปลงโดยอัตโนมัติเมื่อมีการอัปเดตหน้าเว็บคำถามที่พบบ่อย แล้วแตะบันทึก
ซึ่งจะแสดงคำถามที่พบบ่อยทั้งหมดที่คุณใช้ใน Dialogflow ง่ายๆ แค่นี้เอง
โปรดทราบว่าคุณยังชี้ไปยังเว็บไซต์ HTML ออนไลน์ที่มีคำถามที่พบบ่อยเพื่อนำเข้าคำถามที่พบบ่อยไปยังเอเจนต์ได้ด้วย คุณยังอัปโหลด PDF ที่มีบล็อกข้อความได้ด้วย แล้ว Dialogflow จะสร้างคำถามขึ้นมาเอง
ตอนนี้ควรมองว่าคำถามที่พบบ่อยเป็น "ส่วนเสริม" ที่จะเพิ่มให้กับเอเจนต์ของคุณข้างโฟลว์ความตั้งใจ คำถามที่พบบ่อยในฐานความรู้จะฝึกโมเดลไม่ได้ ดังนั้นการถามคำถามในรูปแบบที่แตกต่างไปจากเดิมอย่างสิ้นเชิงอาจไม่ได้รับการจับคู่เนื่องจากไม่ได้ใช้ความเข้าใจภาษาธรรมชาติ (โมเดลแมชชีนเลิร์นนิง) ด้วยเหตุนี้บางครั้งจึงคุ้มค่าที่จะแปลงคำถามที่พบบ่อยเป็นเจตนา
- ทดสอบคำถามในโปรแกรมจำลองทางด้านขวา
- เมื่อทุกอย่างทำงานได้แล้ว ให้กลับไปที่แอป Flutter แล้วทดสอบแชทบ็อตและวอยซ์บ็อตด้วยเนื้อหาใหม่นี้ ถามคำถามที่คุณโหลดลงใน Dialogflow

6. ขอแสดงความยินดี
ขอแสดงความยินดี คุณสร้างแอป Flutter แรกด้วยการผสานรวมแชทบอท Dialogflow ได้สำเร็จแล้ว ยอดเยี่ยมมาก
สิ่งที่เราได้พูดถึงไปแล้ว
- วิธีสร้างแชทบอทด้วย Dialogflow Essentials
- วิธีผสานรวม Dialogflow เข้ากับแอป Flutter
- วิธีตรวจหาความตั้งใจที่เป็นข้อความด้วย Dialogflow
- วิธีสตรีมเสียงผ่านไมโครโฟนไปยัง Dialogflow
- วิธีใช้ตัวเชื่อมต่อฐานความรู้
ขั้นตอนต่อไปคืออะไร
คุณชอบโค้ดแล็บนี้ไหม ลองดูแล็บ Dialogflow ที่ยอดเยี่ยมเหล่านี้
- การผสานรวม Dialogflow กับ Google Assistant
- การผสานรวม Dialogflow กับ Google Chat
- สร้างการทำงานสำหรับ Google Assistant ด้วย Dialogflow (ระดับ 1)
- ทำความเข้าใจการดำเนินการตามคำสั่งโดยการผสานรวม Dialogflow กับ Google ปฏิทิน + สร้างแอป Flutter แรก
หากสนใจวิธีที่เราสร้างแพ็กเกจ gRPC ของ Dialogflow สำหรับ Dart/Flutter
- ดูบทความในบล็อกของฉันเรื่องคู่มือที่ซ่อนไว้สำหรับการทำงานกับ Google Cloud gRPC API