Xem lại phần 2: Giới thiệu nền tảng Dialogflow và tạo Action đầu tiên
Xem lại phần 3: Thiết kế hội thoại với Dialogflow
Mục tiêu của chuỗi bài hướng dẫn này không chỉ là các đoạn hội thoại đơn giản mà còn hướng đến một ứng dụng Internet of Things hoàn chỉnh với trải nghiệm tương tác hai chiều bằng giọng nói thật tự nhiên; trợ lý ảo phải có khả năng linh hoạt đối đáp với người sử dụng trong nhiều ngữ cảnh khác nhau, có khả năng nhận biết và đưa ra gợi ý đối với những yêu cầu bị sai, thiếu thông tin từ người dùng và cuối cùng là phải liên kết được với hệ thống phần cứng giúp người sử dụng có thể điều khiển, giám sát hệ thống các thiết bị điện. Muốn như vậy, chúng ta phải xây dựng được ứng dụng hội thoại đầy đủ các ngữ cảnh khác nhau thông qua các intents và kết hợp thêm các tính năng nâng cao khác sẽ có trong những phần tiếp theo bao gồm: fulfillmentWebhooks, Slot filling, triển khai fullfilment lên Cloud Functions for Firebase và liên kết để lưu trữ dữ liệu với Firebase Realtime Database.
Phần 5: Xây dựng và triển khai Fulfillment
1. Chức năng exported, restored và imported
Dialogflow hỗ trợ các tính năng khác nhau dành cho agent:
- exported (tạo bản sao lưu của agent dưới dạng file zip)
- Restored (upload agent mới và xóa đi tất cả intent và entity cũ của agent đó)
- Imported (upload agent mới nhưng vẫn giữ lại các intent và entity cũ, các intent và entity cùng tên sẽ bị lưu đè).
Mình đã tạo sẵn một agent với đầy đủ các câu thoại và ngữ cảnh khác nhau, các bạn tải về ở đây sau đó làm theo các bước sau để import vào:
- Chọn icon răng cưa bên cạnh tên agent NodeMcuLed ở thanh menu bên trái.
- Ở tab Export and Import, chọn RESTORE FROM ZIP
- Chọn SELECT FILE và chọn file zip vừa tải về sau đó điền RESTORE vào ô bên dưới, chọn RESTORE để upload và cuối cùng chọn DONE.
Sau khi restore xong, chọn vào phần intent các bạn sẽ thấy các intent mình đã tạo sẵn với 2 intent chính là Control_Devices (xử lý các yêu cầu điều khiển thiết bị) và Get_Status_Devices (xử lý các yêu cầu truy vấn trạng thái thiết bị) cùng các intent phụ trợ khác. Đối với entity thì bao gồm devices (đại diện cho loại thiết bị) và status (đại diện cho trạng thái thiết bị).
2. Chức năng Slot filling
Slot filling là chức năng cho phép chúng ta xây dựng luồng hội thoại yêu cầu thu thập giá trị các tham số khác nhau trong một intent, có nghĩa là action sẽ không hoàn thành cho đến khi nào người dùng cung cấp đầy đủ giá trị các tham số được yêu cầu. Chức năng này rất hữu ích khi chúng ta muốn xây dựng ứng dụng mà trợ lý có khả năng gợi ý hoặc yêu cầu người dùng cung cấp thêm thông tin cần thiết khi phát hiện yêu cầu đó thiếu thông tin.
Ví dụ khi muốn điều khiển một thiết bị luôn cần 2 tham số bắt buộc là device và status theo cấu trúc “turn status the device” (vd: turn on the light, turn off the fan,…). Nếu trợ lý ảo phát hiện bị thiếu 1 trong 2 thông tin sẽ đặt câu hỏi phản hồi lại để người dùng cung cấp thêm cho đến khi đầy đủ thông tin mà không làm gián đoạn hội thoại. Trong agent mẫu đã import phía trên mình đã kích hoạt sẵn chức năng slot filling cho các intent Control_Devices và Get_Status_Devices. Ở cửa sổ Action and Parameters trong intent Control_Devices, để kích hoạt chức năng Slot filling cho một tham số ta phải tick chọn vào cột REQUIRED có ý nghĩa rằng đó là một tham số bắt buộc, sau đó chúng ta có thể cài đặt một câu thoại bất kỳ ở cột PROMTS tức là lời nhắc mà trợ lý ảo sẽ nói để yêu cầu người dùng bổ sung tham số đó.
3.Xây dựng fulfillment
Cùng nhớ lại ở phần 3, để Google Assistant phản hồi nội dung về cho người dùng chúng ta đã tạo sẵn các câu thoại ở cửa sổ Response, hay còn gọi là Static text response, tuy nhiên hầu hết các ứng dụng đều sử dụng fulfillment để xử lý response bởi tính linh hoạt cao và cách này còn được gọi là Webhook response.
Fullfilment là một đoạn code được triển khai dưới dạng webhook cho phép agent có thể gọi đến thông qua một HTTP POST và gửi đến các tham số được trích xuất từ yêu cầu của người dùng dưới định dạng chuỗi JSON, sau đó thực thi các thuật toán logic thực hiện các hành động khác nhau, ví dụ như thực hiện liên kết với cơ sở dữ liệu với mục đích truy vấn hoặc lưu trữ và sau đó gửi phản hồi về agent dữ liệu dưới dạng chuỗi JSON để trả về output cho người dùng như hình trên. Chúng ta có thể xây dựng và sau đó triển khai webhook trên bất kỳ nền tảng hay cloud nào, hoặc đơn giản có thể sử dụng trình inline code editor được Dialogflow hỗ trợ giúp liên kết sẵn với Cloud Functions for Firebase.
Để cấu hình fulfillment cho agent, chọn Fulfillment từ thanh menu bên trái, Dialogflow hỗ trợ 2 phương án để triển khai webhook, đó là:
- Custom webhook: triển khai trên một nền tảng hoặc môi trường bất kỳ tùy nhu cầu của nhà phát triển.
- Inline editor: sử dụng trình chỉnh sửa được Dialogflow cung cấp để triển khai webhook lên dịch vụ Cloud Functions for Firebase của chính tài khoản Google đang sử dụng.
Để đơn giản chúng ta sẽ sử dụng Inline editor để lập trình và triển khai webhook. Đầu tiên, chọn ENABLE ở cửa sổ Inline Editor, giao diện Inline Editor bao gồm 2 cửa sổ:
- Cửa sổ index.js sẽ chứa đoạn mã chính sẽ thực thi khi webhook được gọi thông qua HTTP POST.
- Cửa sổ package.json sẽ chứa các thông tin mô tả về ứng dụng sẽ triển khai như name, description, author,… và đặc biệt là chứa các dependencies có thể hiểu là các gói thư viện cần cài đặt để lập trình ứng dụng. Trong danh sách các dependencies mặc định chứa các thư viện khác nhau có thể dùng để lập trình tương tác với Dialogflow như actions-on-google, dialogflow-fulfillment và cũng bao gồm các thư viện giúp lập trình tương tác với nền tảng Firebase như firebase-admin, firebase-functions. Và một điều vô cùng tiện lợi khi sử dụng inline editor là các dependencies được liệt kê sẽ tự động được cài đặt khi chúng ta triển khai ứng dụng mà không cần phải tốn thời gian cài đặt thủ công bằng công cụ npm.
Copy đoạn chương trình mẫu sau và dán vào cửa sổ index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
'use strict'; //Khai báo thư viện để kết nối triển khai code lên firebase-functions const functions = require('firebase-functions'); // Khai báo các dịch vụ cần dùng được hỗ trợ bởi actions-on-google const { dialogflow, Suggestions, SimpleResponse, } = require('actions-on-google'); //Khai báo các gợi ý dành cho người dùng (tối đa 8 gợi ý) const intentSuggestions = [ 'Control', 'light on', 'light off', 'fan on', 'fan off', ]; // Tạo instance "app" để tương tác với dialogflow. const app = dialogflow(); // Xử lý các Dialogflow intents. app.intent('Input_Welcome', (conv) => { conv.ask(`Welcome, How can I help?`); conv.ask(new Suggestions(intentSuggestions)); }); app.intent('Control_Devices',(conv, { devices, status }) => { conv.ask(`OK, switching ${devices} ${status}. Do you want more?`); conv.ask(new Suggestions(intentSuggestions)); }); exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app); |
Sau đó chọn DEPLOY ở góc phải bên dưới để triển khai fulfillment và đợi vài phút để triển khai thành công. Đoạn chương trình trên được viết bằng ngôn ngữ Node.js sử dụng thư viện Actions on Google Client Library với cấu trúc rất đơn giản bao gồm các thành phần chính sau:
- Khai báo thư viện firebase-functions và actions-on-google với các dịch vụ đi kèm:
1 2 3 4 5 6 7 8 9 10 11 |
const functions = require('firebase-functions'); const { dialogflow, Suggestions, SimpleResponse, } = require('actions-on-google'); |
- intentSuggestions: Danh sách các gợi ý sẽ trả về cho người dùng dưới dạng text button để có thể kick chọn thay vì dùng giọng nói, để tạo gợi ý phản hồi ta sử dụng cú pháp: new Suggestions(intentSuggestions)
Các gợi ý sẽ hiển thị dưới dạng text button
- Tạo thực thể app từ class dialogflow() để tương tác với các intents được yêu cầu từ người dùng
- Xử lý các intent cụ thể:
Để bắt được các intents cụ thể từ agent, sử dụng cấu trúc sau:
1 2 3 |
app.intent(‘intent name’, (conv, { param1, param2,… }) => { ……. }); |
Với intent name là tên của intent muốn xử lý và param1, param2,… là danh sách các tham số được trích xuất từ các intent, chính là tên của các entity.
Để tạo nội dung phản hồi về cho người dùng, có hai trường hợp sử dụng tương ứng với 2 cấu trúc:
- ask(‘response’): phản hồi nội dung response và đợi yêu cầu tiếp theo từ người dùng.
- close(‘response’): phản hồi nội dung response và kết thúc cuộc trò chuyện.
Ngoài ra để chèn nội dung các tham số được trích xuất từ yêu cầu của người dùng vào nội dung phản hồi, sử dụng format: ${param}.
Trong chương trình trên, mình xử lý 2 intent mẫu là Input_Welcome và Control_devices với giá trị tham số được trích xuất là ${devices} và ${status}. Bây giờ chúng ta sẽ sử dụng công cụ simulator của Google Actions và Google Assistant trên điện thoại thông minh để mô phỏng kết quả ứng dụng vừa triển khai (nếu không nhớ cách sử dụng thì xem lại phần 4 nhé).
Kết quả mô phỏng trên simulator và điện thoại thông minh
Chức năng Slot Filling
Các bạn hãy thử chỉnh sửa các câu thoại response và thử viết thêm phần xử lý cho các intent khác để hiểu rõ hơn cách thức hoạt động của webhook response và cách sử dụng thư viện Actions-on-Google Client Library nhé. Trong phần tới chúng ta sẽ hoàn thiện fulfillment, tìm hiểu cách lưu trữ và truy vấn dữ liệu với Firebase Realtime Database từ fulfillment và ESP8266 để hoàn thiện dự án, cùng đón xem nhé.
Phần cuối: Kết nối Firebase Realtime Database
Xem thêm: Tổng hợp hướng dẫn Internet of Things với NodeMCU ESP8266 và ESP32
Nhóm TAPIT IoTs