Một đóng góp mang tính thực tiễn của đồ án là áp dụng giải pháp trên vào một hệ thống AI hội thoại cụ thể – SmartDialog. Bằng việc áp dụng các mô hình, kiến trúc, công nghệ tối ưu thì đồ án đã hoàn thiện một công cụ thiết kế luồng hội thoại và sinh kịch bản mới cho SmartDialog và đưa vào triển khai thực tế tại https://bot.smartdialog.vn với người dùng thực tế (ước lượng khoảng hơn 100 người dùng, phục vụ cho các đối tượng khách hàng lớn như Vietcombank, VNPAY, Momo, Mirae Asset…)
Giải pháp cho công cụ thiết kế và sinh kịch bản hội thoại
Phân tích các công cụ đã có
Hiện nay, có khá nhiều các phần mềm Chatbot/Voicebot (một dạng công nghệ AI hội thoại) hoạt động dựa trên kịch bản Có thể kể đến Chatfuel, ManyChat và đến từ thị trường Việt Nam là FPT.AI Chatbot Tất cả các phần mềm kể trên và bản thân SmartDialog (nền tảng
AI hội thoại mà đồ án này đang hướng tới để xây dựng công cụ thiết kế và sinh kịch bản hội thoại) đều đã tự xây dựng riêng cho mình một công cụ để thiết kế luồng hội thoại và sinh kịch bản
Trong khi công cụ thiết kế kịch bản hội thoại của Chatfuel và ManyChat tập trung hỗ trợ và có các thành phần chi tiết dành cho Facebook Messenger thì công cụ này của FPT.AI Chatbot và SmartDialog hiện có mang tính tổng quát, không chỉ tập trung cho một nền tảng là Facebook Messenger Tuy nhiên, công cụ thiết kế và sinh kịch bản hội thoại hiện giờ của SmartDialog (tạm gọi là công cụ version 1 – v1) gặp những lỗi nghiêm trọng về mặt hiển thị, có trải nghiệm người dùng chưa tốt (không dễ sử dụng, không dễ để thiết kế luồng hội thoại), đôi khi sinh kịch bản bị sai, và gặp vấn đề về hiệu năng khi số lượng các nút và đường kết nối trong luồng hội thoại lớn Điều này dẫn tới nhu cầu phát triển một công cụ mới khắc phục được các nhược điểm của công cụ thiết kế và sinh kịch bản hội thoại v1
Các phần tiếp theo trong chương này sẽ tập trung vào việc đưa ra giải pháp cho một công cụ như vậy.
Kiến trúc tổng quan
Hình 4 mô tả kiến trúc tổng quan của giải pháp, thiết kế theo Microservices Về cơ bản, các thành phần chính trong kiến trúc là ứng dụng Frontend, dịch vụ xây dựng bot, dịch vụ sinh kịch bản và dịch vụ sinh kịch bản huấn luyện Ứng dụng Frontend sẽ chỉ tương tác duy nhất
Chương 2 Giải pháp cho công cụ thiết kế và sinh kịch bản hội thoại với dịch vụ xây dựng bot thông qua giao thức HTTP, còn dịch vụ xây dựng bot sẽ tương tác với các dịch vụ còn lại khi cần thiết thông qua một hàng đợi tin nhắn
Có thể thấy với kiến trúc này thì các thành phần chính trong kiến trúc giao tiếp với nhau thông qua giao thức HTTP hoặc một hàng đợi tin nhắn Do đó có thể thay thế hoàn toàn kiến trúc hoặc công nghệ của một thành phần mà không lầm ảnh hưởng đến các thành phần khác, miễn là tất cả đều tuân thủ theo các APIs đã thống nhất Điều này sẽ làm cho quá trình phát triển và bảo trì hệ thống trở nên dễ dàng hơn Thêm vào đó, các thành phần trong kiến trúc này đều mang tính tổng quát, không phụ thuộc hay gắn chặt vào bất cứ một công nghệ cụ thể nào, do đó nó có thể được áp dụng một cách linh hoạt tùy theo nhu cầu sử dụng
Phần mô tả cụ thể cho từng thành phần chính trong kiến trúc này sẽ nằm trong các mục tiếp theo của chương
Hình 4 Kiến trúc tổng quan của giải pháp
Hình 5 mô tả kiến trúc phần Frontend của giải pháp Kiến trúc phần Frontend được chia làm
3 thành phần chính: (1) Frontend Components, (2) thành phần quản lý trạng thái luồng hội thoại, (3) các dịch vụ API Vai trò của từng thành phần và tương tác giữa chúng sẽ được mô tả kĩ lưỡng ở dưới đây
Hình 5 Kiến trúc phần Frontend của giải pháp Đầu tiên, có thể thấy kiến trúc phần Frontend xoay quanh việc xây dựng các Frontend Components độc lập Đây là xu hướng phát triển của hầu hết các ứng dụng (đặc biệt là ứng dụng Web) trong vòng một thập kỷ vừa qua, và hầu hết các công nghệ Frontend hiện nay đều hướng tới việc phát triển các Components, ví dụ như React, Vue, Angular, Svelte… Về cơ bản, các Frontend Components chính là các đại diện cho các thành phần trên giao diện người dùng Khi người dùng tương tác trên giao diện thì bản chất chính là đang tương tác với các Frontend Components này
Tiếp đến, thành phần quản lý trạng thái luồng hội thoại phụ trách việc quản lý trạng thái cho ứng dụng Frontend Mỗi một thao tác của người dùng trên giao diện như kéo thả một nút, tạo thêm đường kết nối, phóng to, thu nhỏ… đều sẽ tạo ra một trạng thái mới, và chính các Frontend Components là các thành phần liên tục cập nhật và làm thay đổi trạng thái này dựa trên các tương tác của người dùng Mặt khác, mỗi khi trạng thái ứng dụng thay đổi thì thành phần quản lý trạng thái này sẽ cập nhật thay đổi cho tất cả các Frontend Components liên quan Điều này đảm bảo rằng thành phần quản lý trạng thái ứng dụng sẽ là nguồn thông tin duy nhất mà các Frontend Components sẽ dựa vào để hiển thị cho đúng trên giao diện người dùng
Thành phần cuối cùng trong kiến trúc là các dịch vụ API Đây là thành phần phụ trách việc tương tác với phía Backend thông qua việc gửi và nhận các HTTP Requests/HTTP Responses Mỗi khi có một tương tác người dùng đòi hỏi phải có sự can thiệp của phía Backend thì Frontend Component tương ứng sẽ gọi tới các dịch vụ API liên quan Như vậy, các dịch vụ API đóng vai trò trung gian trong việc kết nối giữa các Frontend Components và phía Backend
2.3.2 Các thành phần trên giao diện
Hình 6 Các thành phần chính trên giao diện của công cụ thiết kế luồng hội thoại
Mục đích của phần này là dựa vào các thành phần chính trên giao diện có thể thiết kế ra được các Frontend Components tương ứng
Dựa theo Hình 6, giao diện của công cụ thiết kế luồng hội thoại có tất cả 3 thành phần chính: (1) thanh bên lề (Sidebar), (2) thanh công cụ (Toolbar), (3) giao diện chính để thiết kế luồng hội thoại Thanh bên lề là nơi để kéo thả các loại nút vào giao diện thiết kế luồng hồi thoại Thanh công cụ là nơi chứa các chức năng phụ như Undo, Redo, phóng to, thu nhỏ… Giao diện chính để thiết kế luồng hội thoại chứa tất cả các nút và đường kết nối giữa các nút đang được thiết kế
Ngoài ra, có tất cả 5 loại nút khác nhau trong công cụ thiết kế luồng hội thoại này Chi tiết về các loại nút được mô tả ở Bảng 1
Bảng 1 Các loại nút có thể sử dụng trong quá trình thiết kế luồng hội thoại
TT Loại nút Mô tả
1 Bắt đầu Điểm bắt đầu của luồng hội thoại
2 Ý định Một ý định hoặc hành động của người dùng
3 Điều kiện Một điều kiện của tham số trong một ý định
4 Hành động Một hành động của bot
5 Luồng hội thoại con Một luồng hội thoại con
6 Kết thúc cục bộ Điểm mà luồng hội thoại hiện tại kết thúc
7 Kết thúc toàn cục Điểm mà tất cả luồng hội thoại kết thúc
2.3.3 Quản lý trạng thái của các thành phần giao diện
Phần này sẽ mô tả chi tiết về việc quản lý trạng thái của các thành phần giao diện trong công cụ thiết kế luồng hội thoại, từ việc tương tác giữa các Frontend Components với thành phần quản lý trạng thái ứng dụng cho đến cụ thể bên trong thành phần quản lý trạng thái ứng dụng có những gì
Hình 7 Tương tác giữa các Frontend Components và thành phần quản lý trạng thái của công cụ thiết kế luồng hội thoại Đầu tiên, tương tác giữa các Frontend Components và thành phần quản lý trạng thái luồng hội thoại được mô tả ở Hình 7 Có 3 nhóm Frontend Components chính sẽ tương tác với thành phần quản lý trạng thái là: (1) các components nút, (2) các components cạnh, (3) các components khác cần tương tác với thành phần quản lý trạng thái
Các Frontend Components có thể cập nhật trạng thái ứng dụng mỗi khi có tương tác của người dùng (ví dụ như việc di chuyển các nút, các đường kết nối) Khi trạng thái ứng dụng được cập nhật, thành phần quản lý trạng thái sẽ “thông báo” cho tất cả các Frontend Components liên quan để các Components này có thể hiển thị lại cho đúng (ví dụ như khi thay đổi vị trí của một nút thì các đường kết nối đến nút đó cũng phải thay đổi lại vị trí cho chính xác)
Hình 8 Mô hình trạng thái ứng dụng thiết kế luồng hội thoại
Hình 8 là mô hình trạng thái ứng dụng thiết kế luồng hội thoại Cụ thể các thuộc tính cơ bản trong trạng thái của ứng dụng thiết kế luồng hội thoại được mô tả trong Bảng 2
Bảng 2 Các thuộc tính cơ bản trong trạng thái của ứng dụng thiết kế luồng hội thoại
TT Thuộc tính Kiểu dữ liệu
1 width Số Độ rộng của phần giao diện thiết kế luồng hội thoại
2 height Số Chiều cao của phần giao diện thiết kế luồng hội thoại
TT Thuộc tính Kiểu dữ liệu
3 transform Mảng Mảng gồm 3 phần tử số Phần tử thứ nhất là vị trí hiện tại của giao diện thiết kế luồng hội thoại trên trục hoành; phần tử thứ hai là vị trí hiện tại của giao diện thiết kế luồng hội thoại trên trục tung; phần tử thứ ba là độ phóng to thu nhỏ hiện tại
4 minZoom Số Độ thu nhỏ tối thiểu có thể đạt được
5 maxZoom Số Độ thu nhỏ tối đa có thể đạt được
6 nodes Mảng Mảng chứa tất cả các nút hiện có trên giao diện thiết kế luồng hội thoại Cấu trúc dữ liệu của từng nút (mỗi phần tử trong mảng) sẽ được mô tả ở trong Bảng 3
7 edges Mảng Mảng chứa tất cả các đường kết nối hiện có trên giao diện thiết kế luồng hội thoại Cấu trúc dữ liệu của từng đường kết nối (mỗi phần tử trong mảng) sẽ được mô tả ở trong
Bảng 3 Cấu trúc dữ liệu cơ bản của một nút
TT Thuộc tính Kiểu dữ liệu
1 id Xâu ID độc nhất để nhận dạng nút
Giải pháp phần Backend
Hình 12 mô tả kiến trúc phần Backend của giái pháp Có 3 thành phần chính trong kiến trúc phần Backend: (1) dịch vụ xây dựng bot, (2) dịch vụ sinh kịch bản, (3) dịch vụ sinh kịch bản huấn luyện Dịch vụ xây dựng bot và dịch vụ sinh kịch bản sẽ sử dụng chung một cơ sở dữ liệu xây dựng bot Dịch vị sinh kịch bản huấn luyện sẽ sử dụng riêng một cơ sở dữ liệu lưu kịch bản
Hình 12 Kiến trúc phần Backend của giải pháp
2.4.1.1 Dịch vụ xây dựng bot
Dịch vụ xây dựng bot là nơi tiếp nhận và xử lý toàn bộ các HTTP Requests từ phía Frontend Hầu hết mọi logic nghiệp vụ đều sẽ được xử lý tại đây Khi cần sự can thiệp của một dịch vụ khác thì dịch vụ xây dựng bot cũng là nơi sẽ quyết định gọi tới dịch vụ tương ứng nào để xử lý Điều này đảm bảo rằng phía Frontend chỉ cần biết đến duy nhất sự tồn tại của dịch vụ xây dựng bot mà không cần biết đến sự tồn tại của các dịch vụ khác
Cụ thể trong giải pháp cho công cụ thiết kế và sinh kịch bản hội thoại này, dịch vụ xây dựng bot sẽ đảm nhận các nghiệp vụ như tạo, đọc, cập nhật và xóa các luồng hội thoại Còn riêng việc sinh kịch bản hay sinh kịch bản huấn luyện thì dịch vụ xây dựng bot sẽ phải gọi tới dịch vụ sinh kịch bản hoặc dịch vụ sinh kịch bản huấn luyện để xử lý thông qua hàng đợi tin nhắn
2.4.1.2 Dịch vụ sinh kịch bản
Vai trò chính và cũng là duy nhất của dịch vụ sinh kịch bản là xử lý nghiệp vụ sinh kịch bản Khi phía Frontend gửi HTTP Request yêu cầu sinh kịch bản thì phía dịch vụ xây dựng bot sẽ đẩy thông điệp phù hợp vào hàng đợi tin nhắn Phía dịch vụ sinh kịch bản sẽ tiếp nhận thông điệp này và tiếp tục xử lý Dịch vụ sinh kịch bản sẽ tiến hành sinh kịch bản và lưu kịch bản đã sinh vào cơ sở dữ liệu
Về lý thuyết, có thể không cần tới dịch vụ sinh kịch bản này mà để cho dịch vụ xây dựng bot đảm nhiệm luôn việc sinh kịch bản Tuy nhiên nếu làm như vậy thì sẽ sớm gặp phải các vấn đề về hiệu năng khi số lượng các nút và đường kết nối trong luồng hội thoại là lớn và rất lớn Trên thực tế, thuật toán sinh kịch bản (sẽ được mô tả ở các phần sau) là phức tạp và có thời gian chạy tỉ lệ thuận với số lượng kịch bản sẽ được sinh ra Do đó, khi số lượng kịch bản là lớn và rất lớn thì sẽ chiếm nhiều tài nguyên CPU và RAM của máy chủ xử lý, đồng thời sẽ tốn nhiều thời gian khi phải ghi một số lượng lớn bản ghi vào trong cơ sở dữ liệu Trong khi đó, dịch vụ xây dựng bot là nơi xử lý toàn bộ các HTTP Requests từ phía Frontend, nếu CPU và RAM bị chiếm dụng hết bởi việc sinh kịch bản thì sẽ gần như không thể xử lý được các tác vụ khác nữa, và sẽ dẫn tới việc các HTTP Requests bị treo trong trường hợp xấu nhất Chính vì lý do này mà cần phải có riêng một dịch vụ chỉ phụ trách việc sinh kịch bản Khi đó, dù tài nguyên CPU và RAM của máy chủ chạy dịch vụ này có bị chiếm dụng gần hết thì cũng không ảnh hưởng tới dịch vụ xây dựng bot, và mọi HTTP Requests từ phía Frontend vẫn sẽ được xử lý như bình thường mà không bị tắc nghẽn
2.4.1.3 Dịch vụ sinh kịch bản huấn luyện
Vai trò chung của dịch vụ này là sinh kịch bản huấn luyện mà bot có thể hiểu được từ những kịch bản “thô” ban đầu Khi phía Frontend gửi HTTP Request yêu cầu huấn luyện bot thì phía dịch vụ xây dựng bot sẽ đẩy thông điệp yêu cầu sinh kịch bản huấn luyện vào hàng đợi tin nhắn Phía dịch vụ sinh kịch bản huấn luyện sẽ tiếp nhận thông điệp này và tiến hành sinh kịch bản huấn luyện Các kịch bản huấn luyện sẽ được lưu dưới dạng tập tin và được lưu trữ bởi một hệ thống hay dịch vụ lưu trữ tập tin
Một nhiệm vụ quan trọng của dịch vụ sinh kịch bản huấn luyện là sinh kịch bản hoàn chỉnh Theo thiết kế của giải pháp này, các kịch bản sinh ra bởi dịch vụ sinh kịch bản (khi người dùng bấm nút sinh kịch bản trên giao diện của công cụ) không bao gồm các kịch bản được kết hợp với các luồng hội thoại con Thay vào đó, mỗi luồng hội thoại con sẽ chỉ được coi là một nút hội thoại Vì vậy, những kịch bản này được coi là không hoàn chỉnh Kịch bản hoàn chỉnh sẽ được sinh ra bởi dịch vụ sinh kịch bản huấn luyện khi quá trình huấn luyện bắt đầu Trong các kịch bản hoàn chỉnh, những nút luồng hội thoại con (nếu có) sẽ được kết hợp với luồng hội thoại cha
Cụ thể về vai trò và nhiệm vụ của dịch vụ sinh kịch bản huấn luyện này sẽ được trình bày kỹ hơn trong phần “Cách sinh và lưu kịch bản tối ưu” ở Chương 4
2.4.2 Thuật toán sinh kịch bản
Thuật toán sinh kịch bản được chia làm 2 phần: (i) thuật toán sinh kịch bản cơ bản, (ii) thuật toán sinh kịch bản kết hợp luồng hội thoại con
Thuật toán sinh kịch bản cơ bản là thuật toán được dùng để sinh ra các kịch bản mà trong đó luồng hội thoại con sẽ được coi là một nút hội thoại Vì các luồng hội thoại con chỉ được coi là một nút hội thoại nên các kịch bản được sinh ra sẽ không hoàn chỉnh Thuật toán này sẽ được sử dụng bởi dịch vụ sinh kịch bản
Thuật toán sinh kịch bản kết hợp luồng hội thoại con được dùng để sinh ra các kịch bản hoàn chỉnh, trong đó những nút luồng hội thoại con (nếu có) sẽ được kết hợp với luồng hội thoại cha Thuật toán này sẽ được sử dụng bởi dịch vụ sinh kịch bản huấn luyện
2.4.2.1 Thuật toán sinh kịch bản cơ bản
Từ luồng hội thoại đã được thiết kế, các kịch bản tương ứng sẽ được sinh ra để từ đó trải qua huấn luyện trở thành các kịch bản huấn luyện mà Chatbot/Voicebot có thể hiểu được Thuật toán để sinh ra các kịch bản sẽ được mô tả chi tiết dưới đây
Giả sử có một luồng hội thoại như trong Hình 13
Thuật toán sinh kịch bản về bản chất là thuật toán đệ quy duyệt tuần tự tất cả các đường kết nối có trong luồng hội thoại từ nút bắt đầu đến nút kết thúc và ghi nhớ các nút đã đi qua trong quá trình duyệt Thuật toán này được mô tả trong lưu đồ ở Hình 14
Hình 14 Lưu đồ mô tả thuật toán sinh kịch bản
2.4.2.2 Thuật toán sinh kịch bản kết hợp luồng hội thoại con
Một trong các chức năng quan trọng của công cụ thiết kế và sinh kịch bản hội thoại đó là cho phép sự xuất hiện của các luồng hội thoại con Hình 15 là một ví dụ về việc sử luồng hội thoại con trong luồng hội thoại cha
Hình 15 Ví dụ đơn giản về việc sử dụng luồng hội thoại con
Dễ thấy trong ví dụ trên có tất cả 3 kịch bản sẽ được sinh ra là: [1, 2, 1a, 2a, 3a, 3], [1, 2, 1a, 2a, 4a, 3], [1, 2, 1a, 2a, 5a, 3] Thuật toán ở đây chỉ đơn thuần là ghép ba phần kịch bản theo thứ tự như sau: các kịch bản sinh ra từ luồng hội thoại cha trước khi gặp luồng hội thoại con, các kịch bản sinh ra từ luồng hội thoại con, các kịch bản sinh ra từ luồng hội thoại cha sau khi gặp luồng hội thoại con
Tuy nhiên bài toán sẽ trở nên phức tạp hơn khi có các luồng hội thoại con nối tiếp nhau như ví dụ ở Hình 16
Hình 16 Ví dụ sử dụng các luồng hội thoại con nối tiếp nhau
Dễ thấy trong ví dụ trên có tất cả 6 kịch bản được sinh ra Về cơ bản thì cách sinh các kịch bản vẫn là ghép các phần kịch bản theo thứ tự như sau: các kịch bản sinh ra từ luồng hội thoại cha trước khi gặp các luồng hội thoại con, các kịch bản sinh ra từ các luồng hội thoại con nối tiếp nhau, các kịch bản sinh ra từ luồng hội thoại cha sau khi gặp các luồng hội thoại con
Phân tích thiết kế và xây dựng công cụ Workflow trong SmartDialog
Phân tích hiện trạng
Bản thân SmartDialog đã có công cụ thiết kế và sinh kịch bản hội thoại từ trước và đã được đưa vào sử dụng trong một thời gian (tạm gọi là công cụ version 1 – v1) Sau một thời gian sử dụng công cụ thiết kế và sinh kịch bản hội thoại v1, người dùng đã đưa ra những ý kiến đóng góp về cách phát huy những điểm mạnh và khắc phục những điểm yếu của công cụ này
Cụ thể, về cơ bản thì công cụ thiết kế luồng hội thoại và sinh kịch bản v1 đã đáp ứng các yêu cầu tối thiểu về mặt nghiệp vụ, nhưng công cụ này lại có những nhược điểm như: thỉnh thoảng gặp lỗi nghiêm trọng về mặt hiển thị, việc vẽ các đường kết nối không thuận tiện và gây khó khăn cho người dùng, chưa có trải nghiệm người dùng tốt, đôi khi sinh kịch bản bị thừa hoặc thiếu, gặp vấn đề về mặt hiệu năng khi luồng hội thoại lớn, sử dụng một thư viện vẽ biểu đồ đã không còn được phát triển và duy trì nữa… Điều đó đã dẫn tới nhu cầu cấp thiết về việc có một công cụ vẽ luồng hội và sinh kịch bản phiên bản mới có thể kế thừa được những ưu điểm của phiên bản cũ và khắc phục được các nhược điểm kể trên
Vì vậy mà đồ án này được thực hiện để đáp ứng nhu cầu cấp thiết đó: tạo ra công cụ thiết kế và sinh kịch bản hội thoại v2 trực quan, dễ sử dụng, có trải nghiệm người dùng tốt, sinh kịch
Chương 3 Phân tích thiết kế và xây dựng công cụ Workflow trong SmartDialog
Phân tích yêu cầu
Hình 21 Biểu đồ use case tổng quan
Công cụ thiết kế và sinh kịch bản hội thoại v2 cho SmartDialog mà đồ án xây dựng có tác nhân chính là người dùng – bất kì ai sau khi đăng nhập thành công Nhóm chức năng thiết kế luồng hội thoại và chức năng sinh kịch bản là quan trọng nhất Ngoài ra còn có các use cases khác đóng vai trò bổ sung và hỗ trợ cho người dùng trong quá trình sử dụng công cụ Chi tiết về từng use case sẽ được mô tả rõ hơn trong phần “Đặc tả chức năng” bên dưới
3.2.2 Biểu đồ use case phân rã thiết kế luồng hội thoại
Việc thiết kế luồng hội thoại bao gồm các chức năng: tạo nút, sửa thông tin nút, xóa nút, di chuyển nút, tạo cạnh, di chuyển cạnh, xóa cạnh, phóng to, thu nhỏ, vào chế đồ toàn màn hình, kiểm tra trạng thái luồng hội thoại và hoàn toàn, làm lại
Hình 22 Biểu đồ use case phân rã thiết kế luồng hội thoại
Trong phạm vi giới hạn của đồ án, tác giả sẽ chỉ đặc tả một số chức năng điển hình thay vì đặc tả hết toàn bộ các chức năng
3.2.3.1 Đặc tả use case Tạo nút
Bảng 9 Đặc tả use case Tạo nút
Mã Use case UC001 Tên Use case Tạo nút
Tiền điều kiện Người dùng đã đăng nhập
1 Người dùng Chọn một luồng hội thoại và bấm vào nút “Luồng hội thoại”
2 Hệ thống Hiển thị giao diện thiết kế luồng hội thoại
3 Người dùng Thực hiện các thao tác kéo thả từ thanh bên lề để tạo nút
4 Hệ thống Kiểm tra xem việc tạo nút có hợp lệ hay không, nếu hợp lệ thì tiến hành tạo nút
Luồng sự kiện thay thế
4a Hệ thống Nếu việc tạo nút không hợp lệ thì sẽ hiển thị lỗi và không tạo nút
Hậu điều kiện Không có
Bảng 10 liệt kê các loại nút mà người dùng có thể tạo:
Bảng 10 Các loại nút có thể sử dụng trong quá trình thiết kế luồng hội thoại
TT Loại nút Mô tả
1 Bắt đầu Điểm bắt đầu của luồng hội thoại
2 Ý định Một ý định hoặc hành động của người dùng
3 Điều kiện Một điều kiện của tham số trong một ý định
4 Hành động Một hành động của bot
5 Luồng hội thoại con Một luồng hội thoại con
6 Kết thúc cục bộ Điểm mà luồng hội thoại hiện tại kết thúc
7 Kết thúc toàn cục Điểm mà tất cả luồng hội thoại kết thúc
3.2.3.2 Đặc tả use case Tạo cạnh
Bảng 11 Đặc tả use case Tạo cạnh
Mã Use case UC002 Tên Use case Tạo cạnh
Tiền điều kiện Người dùng đã đăng nhập
1 Người dùng Chọn một luồng hội thoại và bấm vào nút “Luồng hội thoại”
2 Hệ thống Hiển thị giao diện thiết kế luồng hội thoại
3 Người dùng Thực hiện thao tác kéo thả cạnh từ một nút nguồn vào một nút đích
4 Hệ thống Kiểm tra xem việc tạo cạnh có hợp lệ hay không, nếu hợp lệ thì tiến hành tạo cạnh
Luồng sự kiện thay thế
4a Hệ thống Nếu việc tạo cạnh không hợp lệ thì sẽ hiển thị lỗi và không tạo cạnh
Hậu điều kiện Không có
Dưới đây là điều kiện tạo cạnh (kết nối) giữa các loại nút (Chú thích: “x” là không kết nối được, còn “v” là có thể kết nối được; còn “một”, “nhiều” mang ý nghĩa là một nút hay nhiều nút):
Bảng 12 Điều kiện tạo cạnh (kết nối) giữa các loại nút Ý định Hành động Điều kiện Bắt đầu Kết thúc cục bộ
Một Nhiều Một Nhiều Một Nhiều Một Nhiều Một Nhiều Một Nhiều Ý định x x v x v v x x x x x x
Kết thúc cục bộ x x x x x x x x x x x x Ý định Hành động Điều kiện Bắt đầu Kết thúc cục bộ
Một Nhiều Một Nhiều Một Nhiều Một Nhiều Một Nhiều Một Nhiều
3.2.3.3 Đặc tả use case Sinh kịch bản
Bảng 13 Đặc tả use case Sinh kịch bản
Mã Use case UC003 Tên Use case Sinh kịch bản
Tiền điều kiện Người dùng đã đăng nhập
1 Người dùng Chọn một luồng hội thoại và bấm vào nút “Luồng hội thoại”
2 Hệ thống Hiển thị giao diện thiết kế luồng hội thoại
3 Người dùng Xác nhận luồng hội thoại đã vẽ là hợp lệ và bấm nút
4 Hệ thống Tiến hành sinh kịch bản
Luồng sự kiện thay thế
3a Người dùng Nếu luồng hội thoại không hợp lệ thì phải chỉnh sửa lại cho hợp lệ, sau đó mới bấm nút “Sinh kịch bản”
Hậu điều kiện Không có
3.2.3.4 Đặc tả use case Xuất luồng hội thoại dưới dạng ảnh
Bảng 14 Đặc tả use case Xuất luồng hội thoại dưới dạng ảnh
Mã Use case UC004 Tên Use case Xuất luồng hội thoại dưới dạng ảnh
Tiền điều kiện Người dùng đã đăng nhập
1 Người dùng Chọn một luồng hội thoại và bấm vào nút “Luồng hội thoại”
2 Hệ thống Hiển thị giao diện thiết kế luồng hội thoại
3 Người dùng Bấm nút “Xuất luồng hội thoại dưới dạng ảnh”
4 Hệ thống Hiển thị giao diện xuất luồng hội thoại dưới dạng ảnh
5 Người dùng Điều chỉnh các tùy chọn phù hợp, sau đó bấm nút xác nhận xuất luồng hội thoại dưới dạng ảnh
6 Hệ thống Xuất luồng hội thoại dưới dạng ảnh cho người dùng
Luồng sự kiện thay thế
Hậu điều kiện Không có
Các tùy chọn khi xuất luồng hội thoại dưới dạng ảnh được mô tả trong Bảng 15:
Bảng 15 Các tùy chọn khi xuất luồng hội thoại dưới dạng ảnh
TT Trường dữ liệu Mô tả Định dạng Ví dụ
1 Lề Khoảng cách lề Số (px) 16
TT Trường dữ liệu Mô tả Định dạng Ví dụ
2 Mức độ chất lượng Mức độ chất lượng có thể nhận giá trị từ 1 đến
10, với 10 là chất lượng cao nhất
3.2.3.5 Đặc tả use case Xuất tệp kiểm thử
Bảng 16 Đặc tả use case Xuất tệp kiểm thử
Mã Use case UC005 Tên Use case Xuất tệp kiểm thử
Tiền điều kiện Người dùng đã đăng nhập
1 Người dùng Chọn một luồng hội thoại và bấm vào nút “Xuất tệp kiểm thử”
2 Hệ thống Hiển thị giao diện xuất tệp kiểm thử
3 Người dùng Điều chỉnh các tùy chọn phù hợp, sau đó bấm nút xác nhận xuất tệp kiểm thử
4 Hệ thống Xuất tệp kiểm thử cho người dùng
Luồng sự kiện thay thế
4a Hệ thống Báo lỗi khi không có tệp kiểm thử phù hợp
Hậu điều kiện Không có
Bảng 17 Các tùy chọn khi xuất tệp kiểm thử
TT Trường dữ liệu Mô tả Định dạng Ví dụ
1 Kết hợp luồng hội thoại con
Trường dữ liệu dưới dạng nút radio
2 Coi luồng hội thoại con là một nút
Trường dữ liệu dưới dạng nút radio
3 Nhóm kịch bản theo end code
Trường dữ liệu dưới dạng checkbox
3.2.3.6 Đặc tả use case Nhân bản luồng hội thoại
Bảng 18 Đặc tả use case Nhân bản luồng hội thoại
Mã Use case UC006 Tên Use case Nhân bản luồng hội thoại
Tiền điều kiện Người dùng đã đăng nhập
1 Người dùng Chọn một luồng hội thoại và bấm vào nút “Nhân bản luồng hội thoại”
2 Hệ thống Nhân bản luồng hội thoại và lựa chọn luồng hội thoại vừa nhân bản cho người dùng
Luồng sự kiện thay thế
Hậu điều kiện Không có
3.2.4 Yêu cầu phi chức năng
Có hai chức năng chính cần phải lưu ý về mặt hiệu năng: (i) Thiết kế luồng hội thoại; (ii) Sinh kịch bản Đối với chức năng thiết kế luồng hội thoại thì khi luồng hội thoại lớn (có rất nhiều nút và đường kết nối) thì phải đảm bảo ứng dụng vẫn không bị đơ hay giật, đặc biệt là khi thực hiện các thao tác kéo thả, di chuyển màn hình, di chuyển nút, chỉnh sửa đường kết nối Đối với chức năng sinh kịch bản, cần phải đảm bảo việc sinh kịch bản chạy đủ nhanh và không làm cho hệ thống bị treo hay trở nên chậm khi sinh kịch bản với số lượng lớn
Giao diện thiết kế luồng hội thoại cần đảm bảo sự tối giản và các thao tác có thể được thực hiện dễ dàng mà người dùng không cần mất thời gian để tìm kiếm Việc thiết kế luồng hội thoại thậm chí có thể trở nên đơn giản và dễ dùng tới mức chỉ cần nhìn vào giao diện là người dùng có thể thực hiện được hết các thao tác mà không cần tới bản hướng dẫn sử dụng chi tiết
Cần phải đảm bảo trong quá trình xây dựng và phát triển sau này thì công cụ thiết kế và sinh kịch bản hội thoại có thể dễ dàng được bổ sung thêm các tính năng mới hoặc nâng cấp, thay đổi các tính năng hiện có tùy theo yêu cầu Hệ thống vẫn sẽ cần phải hoạt động bình thường và ổn định trong quá trình thay đổi, nâng cấp và bảo trì công cụ này.
Công nghệ sử dụng
3.3.1 Các công nghệ sử dụng cho Frontend
ReactJS là một thư viện JavaScript được phát triển bởi Facebook (Meta) với phong cách lập trình khai báo (declarative programming) dùng để xây dựng các UI Components [4] Các đặc điểm chính của ReactJS xoay quanh các từ khóa: Component, JSX và Virtual DOM
ReactJS xoay quanh việc xây dựng các UI Components Mỗi một Component trong ReactJS bản chất là một hàm JavaScript Từng Component có thể quản lý trạng thái của chính nó, và mọi logic trong mỗi Component đều được viết bằng JavaScript, do đó nên có thể truyền các dữ liệu phong phú khắp các Components trong ứng dụng ReactJS sẽ dựa vào các trạng thái
Component được xây dựng sao cho nó có thể được tái sử dụng và khi lắp ghép nhiều Components với nhau một cách có chủ đích thì sẽ hình thành một ứng dụng hoàn chỉnh
Ngoài JavaScript, một ngôn ngữ chính nữa được viết trong mỗi Component của ReactJS là JSX JSX có thể được coi là một ngôn ngữ mở rộng của JavaScript, cho phép viết HTML ở trong JavaScript Đến cuối cùng, JSX sẽ được “thông dịch” sang DOM, hay nói cách khác thì cấu trúc của một đoạn JSX quyết định cấu trúc của các thành phần trên DOM, và cũng chính là những gì sẽ được hiển thị trên giao diện người dùng
JSX thực ra không trực tiếp đại diện cho cấu trúc của DOM mà sẽ đại diện cho cấu trúc của Virtual DOM (DOM ảo) Virtual DOM bản chất là một JavaScript Object đại diện cho cấu trúc của DOM thật Lý do mà ReactJS đưa ra khi sử dụng Virtual DOM là để tránh việc tương tác trực tiếp quá nhiều với DOM, vì quá nhiều tương tác thừa thãi với DOM sẽ tốn rất nhiều chi phí và ảnh hưởng trực tiếp đến hiệu năng của ứng dụng Khi có Virtual DOM thì ReactJS sẽ dựa vào nó để quyết định xem có nên thay đổi DOM thật hay không, và các thao tác trên Virtual DOM thì bản chất chỉ là các thao tác trên một JavaScript Object, và do đó nó tốn ít chi phí và nhanh hơn rất nhiều so với thao tác trên DOM thật
Ngoài ra, một trong những lý do chính mà ReactJS được lựa chọn là vì hệ sinh thái và cộng đồng xoay quanh thư viện này ReactJS hiện tại là một trong những thư viện dùng để phát triển UI Components phổ biến nhất, do đó nó có một hệ sinh thái và cộng đồng phát triển vững mạnh Hầu như các vấn đề và các bài toán gặp phải khi sử dụng ReactJS đều đã được giải quyết bởi cộng đồng Đó đó người phát triển sẽ không phải tốn công “phát minh” ra một lời giải mỗi khi gặp một vấn đề trong quá trình phát triển ứng dụng
SolidJS là một thư viện JavaScript được phát triển bởi Ryan Carniato với phong cách lập trình tương tự như ReactJS dùng để xây dựng các UI Components Cũng như ReactJS, SolidJS cũng xoay quanh các Components, và cũng sử dụng cú pháp JSX Tuy nhiên SolidJS không sử dụng Virtual DOM mà dựa vào “khả năng phản ứng siêu mịn” (fine-grained reactivity) để đáp lại những thay đổi trong một Component [5], và cũng chính nhờ lý do này mà SolidJS tốt hơn rất nhiều so với ReactJS về mặt hiệu năng, và trở thành một trong những thư viện phát triển UI Components có hiệu năng tốt nhất hiện nay
Một nhược điểm lớn của SolidJS đó là thư viện này không được phát triển bởi những công ty hay tập đoàn lớn như ReactJS được phát triển bởi Facebook hay Angular được phát triển bởi Google Thêm vào đó, SolidJS còn khá mới mẻ nên hệ sinh thái và cộng đồng chưa phát triển mạnh
Lý do mà SolidJS được sử dụng trong quá trình xây dựng công cụ thiết kế luồng hội thoại là vì hiệu năng vượt trội của nó Công cụ thiết kế luồng hội thoại đòi hỏi yêu cầu về hiệu năng, đặc biệt là khi luồng hội thoại lớn, có nhiều nút và đường kết nối Đặc điểm của SolidJS là dù cho có bao nhiêu UI Components ở trên giao diện cùng một lúc đi nữa thì việc tương tác với mỗi Component cũng chỉ như khi có duy nhất một Component ở trên giao diện Trong khi đó đối với ReactJS thì việc có càng nhiều Components ở trên giao diện thì hiệu năng sẽ càng giảm đi Do đó SolidJS là lựa chọn tốt nhất về mặt hiệu năng cho công cụ thiết kế luồng hội thoại
Việc phát triển Frontend cho các ứng dụng Web ngày nay hầu như đều đòi hỏi có các công cụ phát triển để hỗ trợ việc biên dịch các đoạn code ra ngôn ngữ mà các trình duyệt có thể hiểu được Ví dụ như JSX là một ngôn ngữ mà các trình duyệt vốn không hiểu, nhưng nhờ việc nó sẽ được biên dịch ra JavaScript thuần túy thông qua các công cụ phát triển nên cuối cùng trình duyệt vẫn hiểu được Ngoài ra, các công cụ phát triển này còn hỗ trợ cho người phát triển các tính năng nhằm đưa trải nghiệm phát triển lên trạng thái tốt nhất Ngày nay có thể kể đến các công cụ phát triển cho Frontend như Webpack, Rollup hay mới nhất là Vite
3.3.2 Các công nghệ sử dụng cho Backend
NodeJS là một nền tảng chạy JavaScript được xây dựng dựa trên V8 JavaScript Engine của Chrome [6] Trước khi NodeJS ra đời, các mã nguồn JavaScript hầu như chỉ có thể chạy được ở trong môi trường trình duyệt Với sự ra đời của NodeJS, JavaScript có thể chạy được cả ở trên môi trường máy chủ, hỗ trợ rất nhiều hệ điều hành khác nhau như Linux, Windows, macOS NodeJS được sử dụng rộng rãi và phổ biến để xây dựng các loại ứng dụng khác nhau, và một trong những loại ứng dụng quan trọng là ứng dụng Web
Ngôn ngữ chính được sử dụng khi viết các ứng dụng bằng NodeJS là JavaScript – vốn là một ngôn ngữ có cộng đồng lớn mạnh Điều này dẫn tới việc khi viết một ứng dụng Web thì phía Frontend vốn đã dùng JavaScript thì khi phát triển ở phía Backend không cần phải học thêm một thứ ngôn ngữ khác nữa nếu đó là NodeJS Ngoài ra, khác với cơ chế chạy đồng bộ như ở một số ngôn ngữ dành cho Backend khác (ví dụ như PHP), JavaScript chạy trong NodeJS có cơ chế bất đồng bộ Điều này làm cải thiện hiệu quả thực thi và khả năng xử lý các yêu cầu đồng thời, giúp cho NodeJS trở thành một ứng cử viên hoàn hảo cho những ứng dụng Web đòi hỏi khả năng xử lý nhiều yêu cầu cùng một lúc
ExpressJS là một framework tối giản và linh hoạt dành cho NodeJS để xây dựng các ứng dụng Web [8] Hầu hết khi nhắc tới phát triển ứng dụng Web trên NodeJS thì người ta sẽ nhắc đến ExpressJS Về bản chất, ExpressJS cung cấp một tầng tính năng chuyên để hỗ trợ xây dựng các ứng dụng Web dựa trên các mô-đun sẵn có mà NodeJS cung cấp
Về bản chất, hoàn toàn có thể chỉ sử dụng NodeJS để xây dựng một ứng dụng Web phía Backend mà không cần tới ExpressJS Nhưng điều này có nghĩa là người phát triển sẽ phải đi xây dựng lại các tính năng gần như ứng dụng Web nào cũng yêu cầu mà ExpressJS đã cung cấp sẵn Vậy nên, để tiết kiệm thời gian phát triển ứng dụng, hầu hết đều sẽ lựa chọn một Web framework như ExpressJS
Khác với các cơ sở dữ liệu quan hệ truyền thống, MongoDB là một cơ sở dữ liệu phi quan hệ Thay vì xoay quanh việc quản lý các bảng và mối quan hệ giữa chúng, MongoDB sẽ xoay quanh việc quản lý các bộ sưu tập (collections) và các tài liệu (documents) bên trong đó (có thể so sánh một bộ sưu tập là một bảng và một tài liệu là một bản ghi trong cơ sở dữ liệu quan hệ) Một điểm khác biệt chính của MongoDB nói riêng hay các cơ sở dữ liệu phi quan hệ nói chung là không cần phải định nghĩa cấu trúc dữ liệu từ trước mà các dữ liệu hoàn toàn là phi cấu trúc, không có tính ràng buộc [9] Đồng thời trong MongoDB không có mối quan hệ giữa các bộ sưu tập với nhau (không có quan hệ giữa các “bảng”) Đối với công cụ thiết kế và sinh kịch bản hội thoại thì cấu trúc dữ liệu khá phức tạp và không hoàn toàn cố định, tuy nhiên mối quan hệ giữa các thực thể thì lại rất đơn giản Đặc biệt các cấu trúc dữ liệu trong JavaScript thường được lưu dưới dạng JSON Object, mà JSON thì hoàn toàn được hỗ trợ bởi MongoDB Với những lý do đó, MongoDB trở thành một lựa chọn hoàn hảo
Thiết kế
3.4.1 Thiết kế kiến trúc tổng quan
Hình 23 Kiến trúc tổng quan của công cụ Workflow trong SmartDialog
Hình 23 mô tả kiến trúc tổng quan của công cụ Workflow trong SmartDialog Các thành phần chính trong kiến trúc là ứng dụng Frontend, dịch vụ xây dựng bot, dịch vụ sinh kịch bản, cổng huấn luyện và một dịch vụ chuyên để sinh kịch bản huấn luyện Ứng dụng Frontend sẽ chỉ tương tác duy nhất với dịch vụ xây dựng bot thông qua giao thức HTTP (cụ thể là sẽ sử dụng REST APIs), còn dịch vụ xây dựng bot sẽ tương tác với dịch vụ sinh kịch bản khi cần thiết thông qua việc sử dụng RabbitMQ Trong khi đó, để bắt đầu quá trình huấn luyện thì dịch vụ xây dựng bot sẽ gửi HTTP Request đến cổng huấn luyện, và khi cần sinh kịch bản huấn luyện thì cổng huấn luyện sẽ gửi yêu cầu đến dịch vụ sinh kịch bản huấn luyện thông qua giao thức HTTP Dịch vụ xây dựng bot và dịch vụ sinh kịch bản đều có quyền truy cập đọc và viết đối với cơ sở dữ liệu lưu các thông tin về công cụ xây dựng bot Ngoài ra, dịch vụ sinh kịch bản huấn luyện sẽ có thể tương tác với cơ sở dữ liệu chuyên biệt để lưu kịch bản
Trong kiến trúc này, dịch vụ xây dựng bot, dịch vụ sinh kịch bản, cổng huấn luyện và dịch vụ sinh kịch bản huấn luyện đều sử dụng NodeJS và ExpressJS Trong khi đó, ứng dụng Frontend sử dụng SolidJS và ReactJS Tất cả cơ sở dữ liệu trong kiến trúc đều sử dụng MongoDB
Lý do tại sao lại có kiến trúc như trên sẽ được đề cập và phân tích cụ thể ở mục “Cách sinh và lưu kịch bản tối ưu” ở Chương 4 Phần mô tả cụ thể cho từng thành phần chính trong kiến trúc này sẽ nằm trong các mục tiếp theo dưới đây của Chương 3
Có 6 thành phần chính trong kiến trúc phần Backend: (1) dịch vụ xây dựng bot, (2) dịch vụ sinh kịch bản, (3) cổng huấn luyện, (4) dịch vụ sinh kịch bản huấn luyện, (5) cơ sở dữ liệu MongoDB lưu các thông tin về công cụ xây dựng bot, (6) cơ sở dữ liệu chuyên lưu các kịch bản
Các thành phần bên trong của máy chủ xây dựng bot, dịch vụ sinh kịch bản, cổng huấn luyện và dịch vụ sinh kịch bản huấn luyện ở trong kiến trúc này là như nhau Trong đó, Routes – sử dụng chức năng định tuyến của ExpressJS – có vai trò tiếp nhận các HTTP Requests và phân bố chúng tới Controller phù hợp để xử lý Tiếp đó Controller gọi tới Service tương ứng để xử lý, và sẽ quyết định trả về HTTP Response dựa theo kết quả xử lý Service sẽ dựa vào logic nghiệp vụ để xử lý Cuối cùng, các Models (sử dụng Mongoose) sẽ được gọi bởi Service khi cần tương tác với cơ sở dữ liệu Các thành phần bên trong mỗi dịch vụ được minh họa ở Hình 24
Hình 24 Các thành phần bên trong của một dịch vụ
Cách mà các thành phần trong kiến trúc Backend tương tác với nhau sẽ được minh họa cụ thể qua các biểu đồ trình tự trong phần tiếp theo
Trong phần này, biểu đồ trình tự minh họa cho luồng hoạt động của các chức năng chính nhất của công cụ thiết kế và sinh kịch bản hội thoại sẽ được trình bày Đầu tiên, Hình 25 mô tả trình tự sinh kịch bản khi người dùng bấm nút lưu luồng hội thoại và sinh kịch bản trên giao diện của công cụ Trong biểu đồ trình tự này, cần lưu ý rằng có thể thay thế RabbitMQ bằng bất kỳ một thành phần nào khác cũng có khả năng tương tự và có thể đóng vai trò là một message broker, ví dụ như Redis
Hình 25 Biểu đồ trình tự quá trình sinh kịch bản
Tiếp đó, Hình 26 mô tả quá trình sinh kịch bản huấn luyện khi người dùng bấm nút để bắt đầu quá trình huấn luyện Ở đây có một điểm quan trọng cần phải lưu ý là kịch bản sinh ra bởi dịch vụ sinh kịch bản (khi người dùng bấm nút lưu luồng hội thoại và sinh kịch bản trên giao diện của công cụ) không phải là kịch bản hoàn chỉnh Cụ thể, kịch bản sinh ra ở dịch vụ sinh kịch bản không bao gồm chi tiết các kịch bản được kết hợp khi có luồng hội thoại con, mà thay vào đó, mỗi luồng hội thoại con sẽ chỉ được coi là một nút hội thoại Sau đó, khi quá trình sinh kịch bản huấn luyện được bắt đầu, dịch vụ sinh kịch bản huấn luyện sẽ đảm nhiệm việc sinh kịch bản hoàn chỉnh, tức là những nút luồng hội thoại con (nếu có) sẽ được kết hợp với luồng hội thoại cha để tạo nên kịch bản hoàn chỉnh Sau đó từ các kịch bản hoàn chỉnh này, dịch vụ sinh kịch bản huấn luyện mới tiến hành sinh kịch bản huấn luyện mà bot có thể sử dụng được
Hình 26 Biểu đồ trình tự quá trình sinh kịch bản huấn luyện
Các bảng dưới đây là danh sách các APIs được thiết kế cho dịch vụ xây dựng bot, cổng huấn luyện và dịch vụ sinh kịch bản huấn luyện
Bảng 20 Thiết kế APIs cho dịch vụ xây dựng bot
Mục đích Phương thức Mô tả
Lấy thông tin về luồng hội thoại
Tạo một luồng hội thoại mới POST /api/v1/workflows
Cập nhật luồng hội thoại PUT /api/v1/workflows/:workflowId
Xóa luồng hội thoại DELETE /api/v1/workflows/:workflowId
Lưu luồng hội thoại và sinh kịch bản
Lấy thông tin về các kịch bản của một luồng hội thoại
GET /api/v2/workflows/:workflowId/scripts
Mục đích Phương thức Mô tả
Tải tệp kiểm thử kịch bản POST /api/v1/test-cases
Bảng 21 Thiết kế APIs cho cổng huấn luyện
Mục đích Phương thức Mô tả
Bắt đầu quá trình huấn luyện hội thoại
POST /api/v1/train-action/:botId/start
Nhận tín hiệu từ các
Bảng 22 Thiết kế APIs cho dịch vụ sinh kịch bản huấn luyện
Mục đích Phương thức Mô tả
Sinh kịch bản huấn luyện POST /api/v1/scripts/generate
Lấy file test cases POST /api/v1/test-cases
Riêng dịch vụ sinh kịch bản không có API nào cả và sẽ giao tiếp thông qua RabbitMQ
Cơ sở dữ liệu được sử dụng là MongoDB Có tất cả 2 cơ sở dữ liệu: (i) Cơ sở dữ liệu lưu các dữ liệu của hệ thống xây dựng bot, (ii) Cơ sở dữ liệu chỉ lưu các kịch bản của các bots
Hình 27 mô tả thiết kế của cơ sở dữ liệu xây dựng bot, chỉ bao gồm các bộ sưu tập liên quan đến công cụ thiết kế và sinh kịch bản hội thoại Có thể thấy, trong phạm vi chỉ xét tới các bộ sưu tập liên quan đến công cụ thiết kế và sinh kịch bản hội thoại thì chỉ có 2 bộ sưu tập là workflows (luồng hội thoại) và scripts (kịch bản)
Hình 27 Thiết kế của cơ sở dữ liệu chính
Dưới đây là các bảng mô tả về các thuộc tính của mỗi tài liệu có trong các bộ sưu tập
Bảng 23 Các thuộc tính của mỗi tài liệu trong bộ sưu tập workflows (luồng hội thoại)
TT Thuộc tính Mô tả
1 _id ID độc nhất để nhận dạng luồng hội thoại
2 name Tên luồng hội thoại
3 displayName Tên hiển thị của luồng hội thoại
4 status Trạng thái của luồng hội thoại
5 agentId ID của Bot mà luồng hội thoại này thuộc về
TT Thuộc tính Mô tả
6 userId ID của người dùng liên quan đến luồng hội thoại này
7 groupId ID của nhóm luồng hội thoại mà luồng hội thoại này thuộc về
8 workflow Mảng chứa tất cả các nút và đường kết nối của luồng hội thoại
Mỗi phần tử có thể là một nút hoặc một đường kết nối Cấu trúc dữ liệu của một nút hoặc một đường kết nối đã được mô tả ở
9 disable Luồng hội thoại có bị vô hiệu hóa hay không
10 hashtag Các thẻ chủ đề được gắn vào luồng hội thoại này
11 createdBy ID của người dùng đã tạo ra luồng hội thoại này
12 createdAt Thời điểm mà luồng hội thoại này được tạo
13 updatedAt Thời điểm mà luồng hội thoại này được cập nhật lần cuối
14 isGeneratedScripts Kiểm tra xem các kịch bản đã được sinh hay chưa
Bảng 24 Các thuộc tính của mỗi tài liệu trong bộ sưu tập scripts (kịch bản)
TT Thuộc tính Mô tả
1 _id ID độc nhất để nhận dạng kịch bản
3 displayName Tên hiển thị của kịch bản
4 status Trạng thái của kịch bản
5 agentId ID của Bot mà kịch bản này thuộc về
6 userId ID của người dùng liên quan đến kịch bản này
TT Thuộc tính Mô tả
7 workflowId ID của luồng hội thoại mà kịch bản này thuộc về
8 mainMessages Danh sách các hội thoại của kịch bản Cấu trúc của từng phần tử trong mảng này sẽ được mô tả ở Hình 28
8 hashtag Các thẻ chủ đề được gắn vào kịch bản này
9 createdBy ID của người dùng đã tạo ra kịch bản này
10 createdAt Thời điểm mà kịch bản này được tạo
11 updatedAt Thời điểm mà kịch bản này được cập nhật lần cuối
12 isInteract Kiểm tra xem kịch bản này có phải là kịch bản tương tác hay không
13 terminate Kiểm tra xem kịch bản này có chứa nút kết thúc toàn cục hay không
Hình 28 Cấu trúc dữ liệu của thuộc tính mainMessages trong một tài liệu ở bộ sưu tập scripts (kịch bản)
Thiết kế của cơ sở dữ liệu lưu các kịch bản của các bots về cơ bản sẽ bao gồm các bộ sưu tập với tên là ID của các bots Số lượng bộ sưu tập cũng sẽ tương ứng với số lượng các bots đã có kịch bản được sinh và lưu trong cơ sở dữ liệu này Còn cấu trúc dữ liệu của mỗi tài liệu trong các bộ sưu tập này đều giống nhau, và giống hoàn toàn với cấu trúc dữ liệu của mỗi tài liệu trong bộ sưu tập scripts (kịch bản) ở trong cơ sở dữ liệu chính đã được đề cập trước đó
Hình 29 Kiến trúc phần Frontend của công cụ Workflow trong SmartDialog
Công nghệ chính được sử dụng ở đây là SolidJS, với sự hỗ trợ của ReactJS Về cơ bản thì kiến trúc phần Frontend tuân theo những gì đã được đề xuất trong giải pháp ở Chương 2 Điểm khác biệt duy nhất là thay vì các SolidJS Components tương tác trực tiếp với các API Services thì giờ phải thông qua ReactJS Components Lý do là vì các Frontend Components có sẵn của SmartDialog đều sử dụng ReactJS từ trước, và ReactJS là công nghệ chính được sử dụng trong SmartDialog Do đó, trong phạm vi phần Frontend của công cụ thiết kế luồng hội thoại này thì sẽ có một ReactJS Component đóng vai trò trung gian để tương tác với các thành phần sẵn có trong Frontend của SmartDialog
Cụ thể, khi người dùng tương tác trên giao diện của công cụ thiết kế luồng hội thoại thì bản chất chính là đang tương tác với các SolidJS Components được biểu diễn thông qua một ReactJS Component ReactJS Component này và các SolidJS Components trao đổi thông tin với nhau qua các SolidJS Signals (một dạng quản lý trạng thái trong các SolidJS dựa theo những tương tác của người dùng đối với các SolidJS Components Khi cần phải tương tác với phía Backend thì các SolidJS Components, thông qua ReactJS Component ở trên, sẽ gọi tới các dịch vụ API cần thiết.
Xây dựng ứng dụng
3.5.1 Thư viện và công cụ sử dụng
Bảng 25 Danh sách thư viện và công cụ sử dụng
Mục đích Công cụ Địa chỉ URL
IDE lập trình Visual Studio Code https://code.visualstudio.com/ Thư viện Frontend 1 ReactJS https://reactjs.org/
Thư viện Frontend 2 SolidJS https://www.solidjs.com/
Backend Framework ExpressJS https://expressjs.com/
Cơ sở dữ liệu MongoDB https://www.mongodb.com/
Message Broker RabbitMQ https://www.rabbitmq.com/
3.5.2 Kết quả đạt được Đồ án đã xây dựng được công cụ thiết kế và sinh kịch bản hội thoại giúp người dùng có thể thông qua việc thiết kế các luồng hội thoại dưới dạng biểu đồ trực quan, cuối cùng sinh ra các kịch bản mà sau đó có thể trở thành kịch bản huấn luyện được sử dụng để huấn luyện cho các Bots trên SmartDialog Ngoài các chức năng chính thì sản phẩm của đồ án cũng cung cấp cho người dùng các chức năng phụ để hỗ trợ cho người dùng trong quá trình sử dụng công cụ thiết kế và sinh kịch bản hội thoại
Hiện tại, công cụ thiết kế và sinh kịch bản hội thoại này đã được triển khai thử nghiệm tại https://dev-bot.iristech.club/ và được triển khai chính thức cho người dùng cuối sử dụng tại https://bot.smartdialog.vn/
3.5.3 Minh họa các chức năng chính
Dưới đây là minh họa cho một số các chức năng của công cụ thiết kế và sinh kịch bản hội thoại
3.5.3.1 Thiết kế luồng hội thoại
Hình 30 Giao diện thiết kế luồng hội thoại
Hình 30 là giao diện thiết kế luồng hội thoại Có tất cả 3 thành phần chính trong giao diện:
(i) thanh bên lề (bên trái), (ii) thanh công cụ (trên cùng bên phải), (iii) giao diện chính để thiết kế luồng hội thoại
Trong đó, thanh bên lề là nơi để kéo thả các nút vào trong giao diện chính để thiết kế luồng hội thoại Mỗi loại nút đều có tên và mô tả chi tiết Ở đây có 2 loại nút cần chú ý nhất là nút kết thúc cục bộ (Local Terminate) và kết thúc toàn cục (Global Terminate): nút kết thúc cục bộ sẽ chỉ dừng ở luồng hội thoại hiện tại (kịch bản sẽ tiếp tục ở luồng hội thoại cha nếu có), còn nút kết thúc toàn cục sẽ dừng đối với toàn bộ luồng hội thoại (kịch bản sẽ không tiếp tục ở luồng hội thoại cha nữa)
Tiếp đó, thanh công cụ là nơi chứa các chức năng như Undo, Redo, thu nhỏ, phóng to, chỉnh tiêu điểm về trung tâm, xuất luồng hội thoại dưới dạng ảnh, chế độ toàn màn hình, biểu tượng hiển thị trạng thái của luồng hội thoại và nút để lưu luồng hội thoại và sinh kịch bản Đối với biểu tượng hiển thị trạng thái của luồng hội thoại thì có tất cả 3 loại trạng thái Trạng thái đầu tiên là trạng thái hợp lệ (màu xanh) Một luồng hội thoại được coi là hợp lệ khi mỗi một nút đều có liên kết (đường nối) với một nút khác (ngoại trừ nút bắt đầu thì không có đường kết nối vào và các nút kết thúc thì không có đường kết nối ra) Ngoài ra các nút điều kiện (nếu có) thì phải đầy đủ cá nhánh TRUE và FALSE và toàn bộ các trường thông tin ở các nút phải được điền đầy đủ Khi trạng thái của luồng hội thoại là hợp lệ thì luồng hội thoại sẽ được tự động lưu Trạng thái thứ hai là trạng thái không hợp lệ (màu đỏ) Một luồng hội thoại được coi là không hợp lệ khi có ít nhất một nút không có đường kết nối vào hoặc ra Khi trạng thái của luồng hội thoại là không hợp lệ thì có thể xem do nút nào trong luồng hội thoại gây ra trạng thái không hợp lệ bằng cách bấm vào biểu tượng trạng thái (minh họa ở
Hình 31) Khi trạng thái của luồng hội thoại là không hợp lệ thì luồng hội thoại sẽ không được tự động lưu
Hình 31 Xem nút nào gây ra trạng thái không hợp lệ của luồng hội thoại
Trạng thái cuối cùng là trạng thái cảnh báo (màu cam) Một luồng hội thoại sẽ có trạng thái cảnh báo khi mỗi một nút đều có đường kết nối với một nút khác (ngoại trừ nút bắt đầu thì không có đường kết nối vào và các nút kết thúc thì không có đường kết nối ra), nhưng một trong những nút điều kiện lại thiếu nhánh TRUE hoặc FALSE Có thể bấm vào biểu tượng trạng thái để xem nút nào đang gây ra trạng thái cảnh báo (minh họa ở Hình 32) Khi trạng thái của luồng hội thoại là cảnh báo thì luồng hội thoại vẫn sẽ được tự động lưu
Hình 32 Xem nút nào gây ra trạng thái không hợp lệ của luồng hội thoại
Ngoài ra có một số các chức năng cần lưu ý trong giao diện chính để thiết kế luồng hội thoại Chức năng đầu tiên là tạo vòng lặp trong luồng hội thoại ở nút điều kiện (với số lần lặp tối đa là 5) Một nút điều kiện bình thường chỉ có 2 nhánh TRUE và FALSE, tuy nhiên khi ở trong vòng lặp thì sẽ có thêm nhánh LOOP END, với tác dụng là khi vượt quá số lần lặp thì kịch bản sẽ chạy vào nhánh này Chức năng này được minh họa ở Hình 33
Hình 33 Giao diện tạo vòng lặp trong luồng hội thoại ở nút điều kiện
Tiếp đó, nút điều kiện có thể chứa nhiều điều kiện và có thể chọn một trong hai toán tử AND/OR cho các điều kiện (minh họa ở Hình 34)
Các nút điều kiện cũng có thể nối liên tiếp với nhau như được minh họa ở Hình 35
Hình 35 Các nút điều kiện nối liên tiếp với nhau
Hình 36 là một ví dụ về một luồng hội thoại chuẩn bị sinh kịch bản
Hình 36 Ví dụ luồng hội thoại chuẩn bị sinh kịch bản
Có tất cả 3 kịch bản sẽ được sinh ra từ luồng hội thoại trên và chúng được minh họa ở các
Hình 37 Ví dụ về kịch bản đầu tiên được sinh ra
Hình 38 Ví dụ về kịch bản thứ hai được sinh ra
Hình 39 Ví dụ về kịch bản thứ ba được sinh ra
Trong ví dụ này, có thể thấy rõ sự hoạt động của nhánh TRUE và FALSE của một nút điều kiện khi có nhiều điều kiện trong một nút điều kiện Toán tử của các điều kiện trong ví dụ này là AND, và do đó nhánh TRUE sẽ ứng với sự kết hợp đồng thời (và) của các điều kiện, còn nhánh FALSE thì sẽ ứng với sự tách biệt (hoặc) của các điều kiện
3.5.3.3 Xuất luồng hội thoại dưới dạng ảnh
Chức năng xuất luồng hội thoại dưới dạng ảnh nằm trong thanh công cụ của giao diện thiết kế luồng hội thoại Có thể xuất dưới dạng ảnh với nhiều mức chất lượng khác nhau Chức năng này được minh họa ở Hình 40
Hình 40 Chức năng xuất luồng hội thoại dưới dạng ảnh
Hình 41 là minh họa cho chức năng xuất tệp kiểm thử (tải tệp kiểm thử) Khi xuất tệp kiểm thử thì có thể lựa chọn các nút luồng hội thoại con nên được khai triển hay coi là một nút, đồng thời có thể nhóm các kịch bản theo end code hoặc không
Hình 41 Chức năng xuất tệp kiểm thử
Tệp kiểm thử sẽ được xuất dưới dạng file Excel như ở Hình 42
Hình 42 Tệp kiểm thử xuất dưới dạng file Excel.
Kiểm thử
Phần kiểm thử này sẽ tiến hành kiểm thử một số chức năng chính của công cụ thiết kế và sinh kịch bản hội thoại dựa theo kĩ thuật kiểm thử hộp đen
3.6.1 Thiết kế luồng hội thoại
Bảng 26 Danh sách các trường hợp kiểm thử cho chức năng thiết kế luồng hội thoại
TT Tên trường hợp kiểm thử Kết quả mong muốn Kết quả thực tế Trạng thái
1 Kiểm tra khả năng kéo thả nút
Có thể kéo thả nút từ thanh bên lề vào giao diện chính
Các nút có thể kéo thả từ thanh bên lề vào giao diện chính Đạt
2 Kiểm tra khả năng tạo đường kết nối giữa các nút
Có thể tạo đường kết nối gấp khúc vuông góc giữa các nút
Có thể tạo đường kết nối gấp khúc vuông góc giữa các nút Đạt
3 Kiểm tra khả năng di chuyển các nút
Khi di chuyển các nút thì đường kết nối cũng di chuyển theo một cách hợp lý
Khi di chuyển các nút thì đường kết nối cũng di chuyển theo một cách hợp lý Đạt
TT Tên trường hợp kiểm thử Kết quả mong muốn Kết quả thực tế Trạng thái
4 Kiểm tra khả năng nhập liệu trong các nút
Có thể nhập liệu vào các trường trong các nút
Có thể nhập liệu vào các trường trong các nút Đạt
5 Kiểm tra điều kiện tạo đường kết nối giữa các nút
Không cho phép tạo đường kết nối không hợp lệ giữa các nút
Không cho phép tạo đường kết nối không hợp lệ giữa các nút Đạt
6 Kiểm tra khả năng tạo nhiều điều kiện trên nút điều kiện
Có thể thêm nhiều điều kiện trong một nút điều kiện
Có thể thêm nhiều điều kiện trong một nút điều kiện Đạt
7 Kiểm tra khả năng tạo nhánh TRUE/FALSE của nút điều kiện
Có thể tạo một nhánh TRUE và một nhánh FALSE từ một nút điều kiện
Có thể tạo một nhánh TRUE và một nhánh FALSE từ một nút điều kiện Đạt
8 Kiểm tra khả năng nối nhiều nút điều kiện với nhau
Có thể nối liên tiếp nhiều nút điều kiện với nhau
Có thể nối liên tiếp nhiều nút điều kiện với nhau Đạt
Có thể Undo/Redo sau khi thực hiện các thao tác
Có thể Undo/Redo sau khi thực hiện các thao tác Đạt
10 Kiểm tra khả năng phóng to, thu nhỏ
Có thể phóng to hoặc thu nhỏ giao diện thiết kế luồng hội thoại
Có thể phóng to hoặc thu nhỏ giao diện thiết kế luồng hội thoại Đạt
Bảng 27 Danh sách các trường hợp kiểm thử cho chức năng sinh kịch bản
TT Tên trường hợp kiểm thử Kết quả mong muốn Kết quả thực tế Trạng thái
1 Kiểm tra sinh kịch bản cơ bản
Sinh đúng số lượng kịch bản đối với luồng hội thoại chỉ có nút ý định và nút hành động
Sinh đúng số lượng kịch bản đối với luồng hội thoại chỉ có nút ý định và nút hành động Đạt
2 Kiểm tra sinh kịch bản với nút điều kiện
Sinh đúng số lượng kịch bản khi luồng hội thoại có nút điều kiện đầy đủ nhánh TRUE và FALSE
Sinh đúng số lượng kịch bản khi luồng hội thoại có nút điều kiện đầy đủ nhánh TRUE và FALSE Đạt
3 Kiểm tra sinh kịch bản với nhiều nút điều kiện nối tiếp nhau
Sinh đúng số lượng kịch bản khi luồng hội thoại có nhiều nút điều kiện nối tiếp nhau
Sinh đúng số lượng kịch bản khi luồng hội thoại có nhiều nút điều kiện nối tiếp nhau Đạt
4 Kiểm tra sinh kịch bản khi có vòng lặp ở nút điều kiện
Sinh đúng số lượng kịch bản khi luồng hội thoại có vòng lặp ở nút điều kiện
Sinh đúng số lượng kịch bản khi luồng hội thoại có vòng lặp ở nút điều kiện Đạt
5 Kiểm tra sinh kịch bản khi có một luồng hội thoại con
Sinh đúng số lượng kịch bản khi luồng hội thoại có chứa một nút luồng hội thoại con
Sinh đúng số lượng kịch bản khi luồng hội thoại có chứa một nút luồng hội thoại con Đạt
6 Kiểm tra sinh kịch bản khi có nhiều nút luồng hội thoại con
Sinh đúng số lượng kịch bản khi luồng hội thoại có chứa
Sinh đúng số lượng kịch bản khi luồng hội thoại có chứa Đạt
TT Tên trường hợp kiểm thử Kết quả mong muốn Kết quả thực tế Trạng thái nhiều nút luồng hội thoại con (không nối tiếp) nhiều nút luồng hội thoại con (không nối tiếp)
7 Kiểm tra sinh kịch bản khi có nhiều nút luồng hội thoại con nối tiếp nhau
Sinh đúng số lượng kịch bản khi luồng hội thoại có chứa nhiều nút luồng hội thoại con nối tiếp nhau
Sinh đúng số lượng kịch bản khi luồng hội thoại có chứa nhiều nút luồng hội thoại con nối tiếp nhau Đạt
Triển khai
Công cụ thiết kế và sinh kịch bản hội thoại đã được triển khai cùng với hệ thống SmartDialog Hiện tại SmartDialog được triển khai trên nhiều môi trường khác nhau như trong Bảng 28
Bảng 28 Các đường dẫn tới các môi trường sản phẩm khác nhau của SmartDialog
TT Môi trường sản phẩm Đường dẫn
1 Môi trường phát triển và kiểm thử
(Development) https://dev-bot.iristech.club/
2 Môi trường kiểm thử chấp nhận người dùng (UAT – User
Acceptance Test) https://uat-bot.iristech.club/
3 Môi trường người dùng cuối
(Production) https://bot.smartdialog.vn/
Chương 4 đề cập đến các đóng góp nổi bật khác trong quá trình phát triển và xây dựng công cụ thiết kế và sinh kịch bản hội thoại cho SmartDialog, bao gồm việc chuyển phiên bản, cách sinh và lưu luồng hội thoại tối ưu và sinh các trường hợp kiểm thử
4.1 Chuyển phiên bản Workflow cũ sang phiên bản mới
Như đã đề cập ở các phần trước, vốn dĩ hệ thống SmartDialog đã có một phiên bản của công cụ thiết kế và sinh kịch bản hội thoại (công cụ v1) Sau khi đã phát triển được phiên bản v2 của công cụ thiết kế và sinh kịch bản hội thoại thì phát sinh ra nhu cầu cần phải chuyển tất cả luồng hội thoại đang sử dụng công cụ v1 sang công cụ v2
4.1.1 Bản chất của việc chuyển phiên bản
Công cụ v2 khác với công cụ v1 ở cả cách hiển thị giao diện thiết kế luồng hội thoại và cấu trúc dữ liệu hiển thị của luồng hội thoại Ngoài ra, thuật toán sinh kịch bản cũng có sự khác biệt Do đó, khi chuyển một luồng hội thoại sử dụng công cụ v1 sang công cụ v2 thì cần phải chuyển cấu trúc dữ liệu hiển thị của luồng hội thoại, sau đó sinh lại kịch bản cho luồng hội thoại đó Trong cơ sở dữ liệu chính của SmartDialog (sử dụng MongoDB) thì thuộc tính workflow của mỗi tài liệu luồng hội thoại có cấu trúc khác biệt giữa hai phiên bản, được mô tả ở Bảng 29
Bảng 29 Cấu trúc của thuộc tính workflow ở 2 phiên bản của công cụ
Phiên bản công cụ Cấu trúc của thuộc tính workflow
Công cụ thiết kế luồng hội thoại và sinh kịch bản v1
Một object có 2 thuộc tính là nodes và links nodes là một mảng các nút, còn links là mảng các đường kết nối
Công cụ thiết kế luồng hội thoại và sinh kịch bản v2
Một mảng chứa tất cả các nút và đường kết nối (đã được mô tả ở Bảng 22).
Các đóng góp nổi bật khác trong quá trình phát triển cho
Chuyển phiên bản Workflow cũ sang phiên bản mới
Như đã đề cập ở các phần trước, vốn dĩ hệ thống SmartDialog đã có một phiên bản của công cụ thiết kế và sinh kịch bản hội thoại (công cụ v1) Sau khi đã phát triển được phiên bản v2 của công cụ thiết kế và sinh kịch bản hội thoại thì phát sinh ra nhu cầu cần phải chuyển tất cả luồng hội thoại đang sử dụng công cụ v1 sang công cụ v2
4.1.1 Bản chất của việc chuyển phiên bản
Công cụ v2 khác với công cụ v1 ở cả cách hiển thị giao diện thiết kế luồng hội thoại và cấu trúc dữ liệu hiển thị của luồng hội thoại Ngoài ra, thuật toán sinh kịch bản cũng có sự khác biệt Do đó, khi chuyển một luồng hội thoại sử dụng công cụ v1 sang công cụ v2 thì cần phải chuyển cấu trúc dữ liệu hiển thị của luồng hội thoại, sau đó sinh lại kịch bản cho luồng hội thoại đó Trong cơ sở dữ liệu chính của SmartDialog (sử dụng MongoDB) thì thuộc tính workflow của mỗi tài liệu luồng hội thoại có cấu trúc khác biệt giữa hai phiên bản, được mô tả ở Bảng 29
Bảng 29 Cấu trúc của thuộc tính workflow ở 2 phiên bản của công cụ
Phiên bản công cụ Cấu trúc của thuộc tính workflow
Công cụ thiết kế luồng hội thoại và sinh kịch bản v1
Một object có 2 thuộc tính là nodes và links nodes là một mảng các nút, còn links là mảng các đường kết nối
Công cụ thiết kế luồng hội thoại và sinh kịch bản v2
Một mảng chứa tất cả các nút và đường kết nối (đã được mô tả ở Bảng 22)
Chương 4 Các đóng góp nổi bật khác trong quá trình phát triển cho SmartDialog
Dựa vào cấu trúc khác biệt của thuộc tính workflow của mỗi tài liệu luồng hội thoại giữa hai phiên bản của công cụ, có thể dễ dàng lấy từ cơ sở dữ liệu ra mọi tài liệu luồng hội thoại mà có thuộc tính workflow có cấu trúc của công cụ v1 Tất cả các luồng hội thoại này chính là các luồng hội thoại đang sử dụng công cụ thiết kế và sinh kịch bản hội thoại v1 Tiếp đó, chỉ việc tiến hành chuyển lần lượt từng luồng hội thoại nói trên sang sử dụng công cụ thiết kế và sinh kịch bản hội thoại v2 Bản chất của việc này chính là thay đổi cấu trúc của thuộc tính workflow trong mỗi tài liệu luồng hội thoại từ công cụ v1 sang công cụ v2, sau đó sinh lại kịch bản cho luồng hội thoại đó
Hình 43 Bản chất của việc chuyển phiên bản
4.1.2 Chiến lược chuyển phiên bản một cách an toàn
Việc chuyển phiên bản nói trên ẩn chứa một số nhược điểm và rủi ro Thứ nhất, bản thân thuật toán hay các dòng mã lệnh dùng để chuyển cấu trúc của thuộc tính workflow trong mỗi tài liệu luồng hội thoại có thể có sai sót Thứ hai là thuật toán sinh kịch bản của hai phiên bản là khác nhau, do đó có thể dẫn tới việc số lượng kịch bản được sinh ra có sự khác biệt giữa hai phiên bản Thứ ba là các nút và các đường kết nối sau khi chuyển sang phiên bản v2 có thể bị lộn xộn, khó nhìn và cần người dùng phải tự tay sắp xếp lại Do đó, cần phải có một cách để khắc phục được những nhược điểm và rủi ro kể trên
Dựa vào các môi trường sản phẩm được đề cập ở phần “Triển khai” trong Chương 3, cách an toàn nhất được đưa ra bao gồm 3 bước Bước thứ nhất là kiểm tra độ chính xác của thuật toán chuyển phiên bản bằng cách xuất một số các bots điển hình từ môi trường Production có chứa các luồng hội thoại sử dụng công cụ v1 và nhập chúng vào môi trường Development, sau đó chạy thuật toán chuyển phiên bản trên các bots này ở môi trường Development Sau đó kiểm tra xem các luồng hội thoại sau khi đã chuyển phiên bản thì chạy có đúng không, số lượng kịch bản mới có trùng khớp với số lượng cũ hay không Khi đã đảm bảo được thuật toán chuyển phiên bản không có sai sót gì thì sẽ tiến hành bước thứ hai Bước thứ hai là xuất tất cả các bots từ môi trường Production có chứa các luồng hội thoại sử dụng công cụ v1 và nhập chúng vào môi trường UAT, sau đó chạy thuật toán chuyển phiên bản cho các bots nói trên ở môi trường UAT Sau đó người dùng sẽ phải vào môi trường UAT và căn chỉnh lại phần giao diện của các luồng hội thoại đã được chuyển phiên bản thành công Bước cuối cùng là sẽ xuất các bots đã được chuyển phiên bản thành công trên môi trường UAT và khôi phục chúng trên môi trường Production
Hình 44 Các bước chuyển phiên bản một cách an toàn
4.1.3 Thuật toán chuyển phiên bản
Hình 45 là lưu đồ mô tả thuật toán để chuyển phiên bản Workflow cũ (v1) sang phiên bản
Workflow mới (v2) đã được sử dụng cho SmartDialog
Hình 45 Lưu đồ thuật toán chuyển phiên bản
Trên thực tế, sau khi tiến hành chuyển phiên bản dựa theo chiến lược chuyển phiên bản một cách an toàn được đề cập ở phần trước thì tất cả các luồng hội thoại sử dụng công cụ thiết kế và sinh kịch bản hội thoại v1 đã được chuyển thành công sang công cụ v2 Sau một thời gian sử dụng thì người dùng cũng không phản ánh lại có vấn đề bất thường gì xảy ra khi sử dụng các luồng hội thoại đã được chuyển phiên bản.
Cách sinh và lưu kịch bản tối ưu
Ban đầu, kiến trúc của công cụ thiết kế và sinh kịch bản hội thoại không có dịch vụ sinh kịch bản huấn luyện Kiến trúc ban đầu này được mô tả ở Hình 46
Hình 46 Kiến trúc ban đầu của công cụ thiết kế và sinh kịch bản hội thoại
Với kiến trúc này, việc sinh và lưu kịch bản vẫn hoàn toàn có thể tiến hành bình thường và không có vấn đề gì nghiêm trọng Tuy nhiên khi áp dụng vào SmartDialog thì cách sinh và lưu kịch bản đó vẫn chưa thực sự tối ưu và vẫn còn tồn đọng một số nhược điểm Nhược điểm đầu tiên là chỉ sử dụng duy nhất một bộ sưu tập để lưu toàn bộ các kịch bản được sinh ra trong toàn bộ các bots có trong SmartDialog, dẫn đến việc bộ sưu tập này dần trở nên rất lớn và có số lượng tài liệu khổng lồ Điều này là không tối ưu vì khi một bộ sưu tập có số lượng tài liệu quá lớn thì các thao tác trên bộ sưu tập này (đặc biệt là khi các thao tác này diễn ra thường xuyên) sẽ trở nên chậm chạp và có thể gây ảnh hưởng đến cả các thao tác khác trên cơ sở dữ liệu đó Nhược điểm tiếp theo là khi có các luồng hội thoại con thì mặc định sẽ sinh ra các kịch bản đã kết hợp với cả các kịch bản của các luồng hội thoại con Điều này dẫn tới việc mỗi khi sử dụng chức năng lưu và sinh kịch bản cho một luồng hội thoại thì sẽ tốn nhiều thời gian và tài nguyên để sinh kịch bản, đặc biệt là khi tần suất sử dụng chức năng này rất lớn Ngoài ra còn một vấn đề nữa là số lượng kịch bản được hiển thị cho người dùng xem trở nên rất lớn, khiến cho việc xem các kịch bản trở nên bất khả thi đối với người dùng Trên thực tế thì có những luồng hội thoại sinh ra tới hàng nghìn, thậm chí là hàng trăm nghìn kịch bản khi sinh kịch bản có sự kết hợp cả các kịch bản của các luồng hội thoại con
Nhược điểm cuối cùng là dịch vụ xây dựng bot sẽ phải đảm đương cả nhiệm vụ sinh kịch bản huấn luyện từ kịch bản mà chưa có một dịch vụ riêng chuyên để sinh kịch bản huấn luyện Để giải quyết các vấn đề trên thì đã có một số các giải pháp được nghiên cứu và đề xuất Đến cuối cùng, giải pháp tối ưu nhất được lựa chọn để sử dụng cho SmartDialog là lưu tất cả kịch bản của mỗi bot ở một bộ sưu tập riêng trong một cơ sở dữ liệu MongoDB riêng Kiến trúc của giải pháp này được mô tả qua sơ đồ ở Hình 47 Có tất cả 4 thành phần chính trong kiến trúc này: (1) dịch vụ xây dựng bot, (2) dịch vụ sinh kịch bản, (3) cổng huấn luyện, (4) dịch vụ sinh kịch bản huấn luyện Có 2 cơ sở dữ liệu được sử dụng: (1) cơ sở dữ liệu MongoDB lưu các thông tin về công cụ xây dựng bot và các kịch bản chưa kết hợp với các kịch bản của các luồng hội thoại con, (2) cơ sở dữ liệu chuyên lưu các kịch bản đầy đủ (đã được kết hợp với các kịch bản của các luồng hội thoại con)
Hình 47 Kiến trúc của giải pháp sinh và lưu kịch bản tối ưu cho SmartDialog
Lúc này, dịch vụ sinh kịch bản sẽ chỉ sinh ra các kịch bản mà chưa kết hợp với các kịch bản của các luồng hội thoại con Điều này khắc phục được nhược điểm thứ hai như sau: Khi sử dụng chức năng sinh kịch bản cho một luồng hội thoại thì sẽ chỉ gọi tới dịch vụ sinh kịch bản để sinh ra các kịch bản mà chưa kết hợp với các kịch bản của các luồng hội thoại con, trong đó coi các luồng hội thoại con chỉ là một nút hội thoại trong kịch bản Khi đó việc sử dụng chức năng lưu và sinh kịch bản cho một luồng hội thoại một cách thường xuyên sẽ không còn tốn quá nhiều thời gian và tài nguyên để sinh kịch bản nữa Đồng thời, số lượng kịch bản hiển thị cho người dùng xem sẽ được giảm đi đáng kể (theo cấp số nhân), và do đó người dùng có thể theo dõi các kịch bản một cách dễ dàng hơn
Kịch bản đầy đủ, tức là kịch bản có cả sự kết hợp với các kịch bản của các luồng hội thoại con, sẽ được sinh ra ở lúc thực hiện huấn luyện Dịch vụ sinh kịch bản huấn luyện sẽ phụ trách việc lấy các kịch bản được sinh ra bởi dịch vụ sinh kịch bản và tiến hành kết hợp các kịch bản này với các kịch bản của các luồng hội thoại con Sau đó các kịch bản đầy đủ này được lưu trong cơ sở dữ liệu riêng, mà cụ thể là các kịch bản của mỗi bots sẽ được lưu trong một bộ sưu tập riêng trong cơ sở dữ liệu Khi đó sẽ khắc phục được nhược điểm thứ nhất đã đề cập và không còn tình trạng một bộ sưu tập chứa quá nhiều số lượng tài liệu nữa Sau khi lưu các kịch bản đầy đủ trong cơ sở dữ liệu thì dịch vụ sinh kịch bản huấn luyện sẽ dựa trên các kịch bản đầy đủ đó để sinh ra các kịch bản huấn luyện Ở đây có thể đặt ra câu hỏi là tại sao dịch vụ sinh kịch bản huấn luyện phải lưu kịch bản đầy đủ ở trong cơ sở dữ liệu trong khi có thể không cần lưu trong cơ sở dữ liệu mà sẽ sinh kịch bản đầy đủ và giữ kịch bản đã sinh ở trong RAM, sau đó trực tiếp tiến hành sinh kịch bản huấn luyện Câu trả lời là việc sinh kịch bản đầy đủ ở trên RAM sau đó sinh kịch bản huấn luyện như vậy rất dễ gây tràn RAM (khi số lượng kịch bản đầy đủ là rất lớn) nếu không cẩn thận Ngoài ra, nếu không lưu kịch bản đầy đủ trong cơ sở dữ liệu thì sẽ không thể dễ dàng thực hiện các chức năng mà cần sử dụng tới kịch bản đầy đủ trong tương lai (ví dụ như chức năng xuất tệp kiểm thử dựa trên các kịch bản đầy đủ)
Cuối cùng, có thể thấy rằng giải pháp này có riêng một dịch vụ sinh kịch bản huấn luyện, tức là nhược điểm thứ ba cũng được khắc phục Như vậy, giải pháp này đã khắc phục được tất cả các nhược điểm của giải pháp ban đầu.
Sinh các trường hợp kiểm thử
Đối với SmartDialog, sau khi các bots đã được huấn luyện dựa theo các kịch bản sinh ra từ các kịch bản thì đội ngũ đảm bảo chất lượng bots sẽ tiến hành kiểm thử các bots xem chúng có chạy theo đúng kịch bản hay không Tuy nhiên để có thể kiểm thử được thì cần phải biết danh sách các kịch bản và các thông tin cụ thể trong đó thì Bản thân danh sách kịch bản huấn luyện không thể được sử dụng để làm điều này vì các kịch bản huấn luyện được biểu diễn dưới dạng cho máy hiểu và không ở dạng ngôn ngữ tự nhiên mà con người có thể hiểu
Do đó sẽ phải sử dụng tới kịch bản Mà cụ thể ở đây cần phải xuất ra một tệp kiểm thử (Excel) chứa danh sách các kịch bản và các thông tin chi tiết xoay quanh mỗi thành phần trong các kịch bản
Do các kịch bản đầy đủ đã được lưu sẵn trong cơ sở dữ liệu riêng nên việc xuất tệp kiểm thử dựa trên các kịch bản là không quá khó khăn Về cơ bản chức năng này sẽ xuất ra một file zip, trong đó chứa các tệp kiểm thử có đuôi xlsx (Excel) Mỗi tệp kiểm thử chính là một nhóm các luồng hội thoại (luồng hội thoại không có nhóm sẽ được nhóm vào một tệp kiểm thử chung) Mỗi một Sheet trong một tệp kiểm thử sẽ chứa tất cả các kịch bản của một luồng hội thoại và các thông tin chi tiết về các thành phần trong kịch bản Cụ thể nội dung các cột xuất hiện trong mỗi Sheet như trong Bảng 30
Bảng 30 Nội dung các cột trong mỗi Sheet ở tệp kiểm thử
TT Tên cột Nội dung
1 End code Tên của hành động cuối cùng xuất hiện trong kịch bản Các kịch bản sẽ được nhóm theo end code nếu người dùng lựa chọn
2 Tên luồng Tên của kịch bản
3 Nút hội thoại Tên của một nút hội thoại trong kịch bản Sắp xếp theo thứ tự từ đầu đến cuối
4 Người gửi Người mà sẽ thực hiện hành động trong nút hội thoại đó Nếu nút hội thoại là một ý định thì người gửi là “User”, còn nếu là một hành động thì người gửi là “Agent” (Bot)
5 Usersay ví dụ Mẫu câu ví dụ mà người dùng sẽ nói ứng với ý định được đề cập trong nút hội thoại này
6 Tiền điều kiện (VÀ) Điều kiện để dẫn tới hành động ở nút hội thoại này Mỗi một điều kiện sẽ được viết trên một dòng và toán tử kết hợp các điều kiện là toán tử và
7 Tham số bắt buộc Các tham số bắt buộc cần phải có đối với ý định ở nút hội thoại này
8 Hành động lặp Mô tả cụ thể về hành động lặp ở nút hội thoại này
TT Tên cột Nội dung
9 Ý định phụ Mô tả cụ thể về ý định phụ xuất hiện ở nút hội thoại này
Khi xuất tệp kiểm thử, người dùng có thể lựa chọn: (i) coi các luồng hội thoại con là một nút (không kết hợp các kịch bản của các luồng hội thoại con) hoặc khai triển luồng hội thoại con (kết hợp các kịch bản của các luồng hội thoại con), (ii) nhóm theo end code hoặc không Như vậy, có thể có tất cả 4 loại tệp kiểm thử có thể được xuất ra Chức năng xuất tệp kiểm thử này đã được minh họa ở trong Chương 3
Chương 5 trình bày về kết luận về kết quả thực hiện đồ án và hướng phát triển trong tương lai
5.1 Kết luận Đóng góp đầu tiên của đồ án là một giải pháp cho công cụ thiết kế và sinh kịch bản hội thoại Đây là một giải pháp đầy đủ để có thể xây dựng công cụ thiết kế và sinh kịch bản hội thoại trong bất cứ hệ thống nào mà không phụ thuộc vào bất kì một công nghệ cụ thể nào Khi sử dụng giải pháp này, người sử dụng sẽ được quyền tự do lựa chọn công nghệ thích hợp cũng như thay đổi lại một phần của giải pháp để phù hợp với nhu cầu sử dụng Giải pháp này sẽ đóng vai trò như khung xương để xây đựng một công cụ thiết kế và sinh kịch bản hội thoại hoàn chỉnh
Một đóng góp mang tính thực tiễn của đồ án là áp dụng giải pháp trên vào một hệ thống AI hội thoại cụ thể – SmartDialog Bằng việc áp dụng các mô hình, kiến trúc, công nghệ tối ưu thì đồ án đã hoàn thiện một công cụ thiết kế luồng hội thoại và sinh kịch bản mới cho SmartDialog và đưa vào triển khai thực tế tại https://bot.smartdialog.vn với người dùng thực tế (ước lượng khoảng hơn 100 người dùng, phục vụ cho các đối tượng khách hàng lớn như Vietcombank, VNPAY, Momo, Mirae Asset…)
Trong quá trình xây dựng công cụ thiết kế và sinh kịch bản hội thoại, tác giả của đồ án đã đối mặt với nhiều thách thức Thách thức đầu tiên là phải đảm bảo hiệu năng tốt và trải nghiệm người dùng mượt mà khi luồng hội thoại lớn Đối với thách thức này, đồ án đã xây dựng được một thư viện thiết kế luồng hội thoại mà ở đó hiệu năng gần như không thay đổi khi số lượng nút và cạnh trong luồng hội thoại tăng lên Thách thức tiếp theo là đảm bảo hiệu năng của hệ thống trong quá trình sinh kịch bản hội thoại với số lượng lớn Đối mặt với thách thức trên, đồ án đã đưa ra một thuật toán sinh kịch bản hiệu quả và lựa chọn một kiến trúc phù hợp là Microservices
Ngoài ra, trong quá trình thực hiện đồ án, tác giả của đồ án đã học hỏi và áp dụng được rất nhiều các kiến thức về thuật toán, cấu trúc dữ liệu, thiết kế và xây dựng hệ thống, quy trình phát triển phần mềm, kĩ năng làm việc nhóm… Đây đều là những kiến thức và kĩ năng vô cùng quý giá và sẽ vẫn còn rất hữu ích trong tương lai lâu dài sau này.