基于狀態(tài)機(jī)的聊天機(jī)器人設(shè)計(jì)經(jīng)驗(yàn)總結(jié)
為了更好地了解智能機(jī)器人項(xiàng)目的需求和改進(jìn)方向,我們常常需要研發(fā)一些工具。在我參與的多個(gè)機(jī)器人項(xiàng)目中,大多數(shù)都能夠成功地滿足產(chǎn)品需求。通過(guò)這些實(shí)踐,我們深刻認(rèn)識(shí)到,如果要不斷進(jìn)步和提高,就必須對(duì)現(xiàn)有的機(jī)器人定義語(yǔ)言進(jìn)行重大的改進(jìn)。
- 簡(jiǎn)化需要復(fù)雜對(duì)話流程的機(jī)器人的創(chuàng)建過(guò)程。
- 最大限度地提高可重用性,通過(guò)重用過(guò)去已經(jīng)定義過(guò)的模塊和對(duì)話路徑來(lái)創(chuàng)建機(jī)器人
在傳統(tǒng)的做法中,完成這些并不容易,因?yàn)橐鈭D定義與部分排序約束混合在一起,限制了對(duì)話路徑的自由度。這對(duì)于處理“開(kāi)放式”機(jī)器人(常見(jiàn)于FAQ樣式的機(jī)器人),其中大多數(shù)問(wèn)題是獨(dú)立的且始終可用的,這已經(jīng)足夠了。但對(duì)于更“封閉”的機(jī)器人來(lái)說(shuō),潛在的對(duì)話限制要多得多(比如用于從在線訂票機(jī)器人)。
為了將聊天機(jī)器人定義語(yǔ)言的功能提升到一個(gè)新的水平,在一些項(xiàng)目中我們引進(jìn)了更接近狀態(tài)機(jī)語(yǔ)義的DSL,并完全將意圖定義與控制機(jī)器人執(zhí)行定點(diǎn)可用意圖的轉(zhuǎn)換規(guī)則分離,這么做有以下優(yōu)勢(shì):
- 新機(jī)器人中可以復(fù)用以前的意圖,即使設(shè)置的對(duì)話路徑不同。
- 可以使用狀態(tài)機(jī)定義復(fù)雜的對(duì)話流,讓機(jī)器人保持清晰和精確的語(yǔ)義。
- 可以創(chuàng)建復(fù)雜的狀態(tài)守護(hù)來(lái)控制轉(zhuǎn)換。根據(jù)用戶輸入、即將發(fā)生的事件以及之前的數(shù)據(jù)、對(duì)話參數(shù)等,將機(jī)器人移動(dòng)到新?tīng)顟B(tài)。
- 可以使用狀態(tài)主體來(lái)存儲(chǔ)復(fù)雜的對(duì)話邏輯,以響應(yīng)用戶請(qǐng)求。
- 可以將機(jī)器人模塊化,以便在其他機(jī)器人中重用部分狀態(tài)機(jī)。
- 可以將本地回退定義為狀態(tài)行為的一部分。除了默認(rèn)的全局回退,還可以將本地回退與狀態(tài)相關(guān)聯(lián),以便在狀態(tài)上下文中處理錯(cuò)誤,比如顯示一條消息,幫助用戶回答機(jī)器人在對(duì)話中的特定狀態(tài)下提出的問(wèn)題。
意圖定義語(yǔ)言
意圖定義現(xiàn)在與執(zhí)行部分解耦,但仍然是一個(gè)單獨(dú)的子語(yǔ)言。對(duì)于每個(gè)意圖,我們只需提供一些訓(xùn)練句子,讓機(jī)器人能夠識(shí)別出用戶話語(yǔ)的意圖,并從中提取所需的參數(shù)。
舉個(gè)例子,我們有一個(gè)簡(jiǎn)單的機(jī)器人,它只能理解兩種類型的用戶話語(yǔ):?jiǎn)柡蚝完愂鲂彰N覀兛梢詾槊糠N話語(yǔ)類型提供幾個(gè)示例句子,讓機(jī)器人學(xué)會(huì)如何識(shí)別它們。當(dāng)用戶輸入一個(gè)話語(yǔ)時(shí),機(jī)器人會(huì)根據(jù)它的意圖執(zhí)行相應(yīng)的操作,并從中提取所需的參數(shù)。
我們?yōu)槊糠N意圖提供一些樣本句子,來(lái)訓(xùn)練機(jī)器人如何識(shí)別它們。此外,在某些情況下,我們還會(huì)在上下文中收集一些參數(shù)(例如,用戶的姓名),以便以后能夠更個(gè)性化地回答用戶。
我們還沒(méi)有具體說(shuō)明機(jī)器人應(yīng)該先嘗試匹配哪種意圖,這是執(zhí)行部分語(yǔ)言的內(nèi)容。這種方法使我們能夠重復(fù)利用這些意圖(例如,在另一個(gè)機(jī)器人中,我們可能需要詢問(wèn)用戶的姓名,而不僅僅是在問(wèn)候意圖之后)。
執(zhí)行定義語(yǔ)言
使用執(zhí)行文件來(lái)定義一個(gè)狀態(tài)機(jī),描述機(jī)器人如何響應(yīng)意圖/事件,并且可以進(jìn)行轉(zhuǎn)換。這使得機(jī)器人的設(shè)計(jì)者可以查看執(zhí)行文件,了解整個(gè)對(duì)話流程。
執(zhí)行語(yǔ)言中的每個(gè)狀態(tài)包含 3 個(gè)部分
- Body (可選):機(jī)器人在進(jìn)入狀態(tài)時(shí)執(zhí)行的反應(yīng)。
- Next (必選):定義了出站轉(zhuǎn)換,表示為 condition –> State。 當(dāng)接收到事件/意圖時(shí),會(huì)評(píng)估條件,如果滿足轉(zhuǎn)換,則執(zhí)行引擎會(huì)移動(dòng)到指定的狀態(tài)并執(zhí)行其相應(yīng)的反應(yīng)。需要注意的是,轉(zhuǎn)換條件可以非常復(fù)雜。 它們是真正的守衛(wèi),這意味著如果整個(gè)條件不為真,則轉(zhuǎn)換不可導(dǎo)航,引擎將保持當(dāng)前狀態(tài)。
- Fallback (可選):此部分可以包含任意代碼(就像 Body 部分一樣),如果引擎無(wú)法找到可導(dǎo)航的轉(zhuǎn)換,則會(huì)執(zhí)行這些代碼。
執(zhí)行模型還包含 2 個(gè)特殊狀態(tài):
- Init:是創(chuàng)建用戶會(huì)話時(shí)進(jìn)入的常規(guī)狀態(tài)。它可以包含 Body、_Next_和 Fallback 部分。
- Default_Fallback:它只能包含 Body 部分,并且不能作為轉(zhuǎn)換的目標(biāo)狀態(tài)。該狀態(tài)表示在當(dāng)前狀態(tài)中未定義本地回退時(shí)執(zhí)行的默認(rèn)回退代碼。該狀態(tài)可用于打印通用錯(cuò)誤消息(例如,“抱歉,我沒(méi)明白您的意思”),而本地回退則可以打印針對(duì)當(dāng)前狀態(tài)的定制消息(例如,“請(qǐng)回答是或否”)。
最后,一個(gè)狀態(tài)可以定義一個(gè)單一的通配符轉(zhuǎn)換(使用保留字符___作為轉(zhuǎn)換條件),當(dāng)計(jì)算狀態(tài)主體時(shí)將自動(dòng)導(dǎo)航。這使我們能夠在多個(gè)地方重用相同的代碼并模塊化執(zhí)行邏輯。下面是一個(gè)簡(jiǎn)單的機(jī)器人示例,它只回復(fù)問(wèn)候意圖,詢問(wèn)用戶名并向用戶問(wèn)好。這個(gè)機(jī)器人的回復(fù)可以通過(guò)我們基于 React 的聊天小部件顯示。