小布助手閒聊生成式演算法

小布助手閒聊生成式演算法

分享嘉賓:張超 OPPO 高階NLP演算法工程師

編輯整理:王旭 北明軟體

出品平臺:DataFunTalk

導讀:

今天分享的主題是小布助手在生成式聊天方面的探索和實踐。主要內容包括以下幾個方面:

研發背景

業界生成式方案

小布助手業務實踐

總結與展望

01

研究背景

首先和大家介紹下小布助手的研發背景

1. 小布助手業務簡介

① 小布助手是誰

小布助手是OPPO智慧手機和IoT裝置上內建的AI助手,主要包括語音、建議、指令、識屏和掃一掃5大功能模組。截至2021年8月,小布助手覆蓋使用者數達2。5億,月活躍使用者逾1。3億,月互動次數超20億次。

② 小布聊天技能

小布助手閒聊生成式演算法

小布聊天技能作為小布助手數百個技能裡面第一大技能,提供有趣、有溫度、智慧的聊天體驗,具備智趣單輪、技能引導、話題多輪、情緒感知等基礎能力。

智趣單輪

:提供很多有意思的單輪語料,包含了很多緊跟時代潮流的熱梗;

技能引導

:根據使用者的query去判斷他當時所處場景,智慧推薦一些有趣的技能,比如使用者說我好無聊,就會問他,要不要我給你講個笑話,他說好的,然後直接就給他講笑話;

話題多輪

:針對線上比較高頻的一些多輪話題而構建,比如說我想蹦迪,然後我們說你準備好了嗎?他說好了,此時我們就已經知道他是說他已經準備好去蹦迪,接著我們就會告訴他你是整個舞池最靚的仔;

情緒感知

:在與使用者互動的整個過程中,持續感知使用者的情感狀態,透過語料或表情與使用者進行一些情感上的共鳴。比如使用者說我失戀了,我們就會給他一些安慰的話和表情。

2. 小布聊天建設歷程

小布助手閒聊生成式演算法

按照建設的時間順序,我們的聊天演算法演進經歷了:檢索式聊天,規則式聊天,生成式聊天。

檢索式聊天

剛開始採用的是檢索式聊天,主要解決一些頭部query應答問題,解答一些小布人設相關的問題,結果相對安全可控,可以透過語料的增減快速上線。

規則式聊天

規則式聊天主要解決檢索式聊天中一些解決不了的問題,它有一定的規律,但是又不可窮舉,比如說我叫什麼名字這種問題,因為名字不可窮舉,透過寫語料的方式是寫不完的。我們就針對這一類問題去做一些規則,在做規則應答的時候,識別使用者query裡面的槽位並根據槽位生成一些比較定製化的語料。透過這種規則應答也是比較安全可控的。但是當規則的數量大了之後,它的維護成本還是很高的。

生成式聊天

最後我們建設的是生成式聊天,主要解決長尾query的應答。它應答的範圍比較廣,但最大的問題就是生成的內容不可控,容易產生一些安全性的問題,針對這一問題我們也做了一些最佳化。

3. 小布生成式聊天背景

小布助手閒聊生成式演算法

我們為什麼要做生成式聊天?因為小布助手的聊天場景是開放多輪的,傳統的檢索式問答很難滿足這種應用場景。

從開放域來說,使用者會跟我們無話不聊,從感情到蹦迪到動畫片,到節假日到數字貨幣等等。如果透過寫手去寫這種語料,成本是非常高的。

另外,使用者在跟我們聊天過程中期望我們有多輪聊天的能力。如果透過檢索式方案去做,就需要有一些上下文理解能力,我們要去構建一個多輪語料庫,成本相當高,跟單輪相比是一個指數級增長。而且這種上下文理解和指代消解的任務本身也是很難的,在中文領域,這種任務訓練資料又非常的少,所以做起來是非常困難的。

谷歌的Meena和Facebook的Bleeder,這些大規模端到端的神經會話模型讓我們看到了生成式端到端模型的發展空間,在這種開放多輪的場景中將有很好的應用前景。基於此,我們進行了一些探索和實踐。

02

業界生成式方案

接下來介紹我們調研的一些業界常用方案。

1. 生成式建模與挑戰

小布助手閒聊生成式演算法

生成式建模方案基於語言模型來建模,根據context上文以及前面的預測結果持續地預測下一個word的生成結果,直到生成一個答案。

語言模型的建模注重的是上下文是否符合語言邏輯,表述是否通順,但對其他方面可能欠考慮,比如上下文是否一致,生成的答案有沒有安全性問題,對常識的理解,還有一些情感化共鳴等等。

2. 生成式模型介紹

下面介紹一下業界常用的一些生成式模型。

① RNN-based seq2seq

小布助手閒聊生成式演算法

最基礎的端到端生成式模型RNN-based seq2seq模型,發表於2014年。初期,該模型主要應用在翻譯領域,後來在很多文字生成任務中得到了應用,包括生成式聊天。

該模型包含兩個模組:encoder和decoder。encoder對context透過RNN-based模型去做編碼表徵,然後在decoder的時候使用context表徵以及上一個預測結果去預測下一個word結果,是一個持續的過程。在解碼過程中,每一個word所採用的context是一樣的,不會動態變化,這樣生成的效果並不好。

2015年提出了Seq2Seq+Attention的模型結構。這個模型結構除了encoder和decoder部分之外,還增加了attention模組。在當前時刻,該模組會計算上一個時刻的狀態和context狀態,對context裡狀態加權,融合到狀態表徵裡,預測下一個word的機率分佈情況。這種結構更好地利用了context的資訊,也取得了更好的效果。在很長一段的時間內,Seq2Seq+Attention都是業界主流的方案。

② tensor2tensor

小布助手閒聊生成式演算法

直到2017年,谷歌發表文章《Attention is all you need》,提出了tensor2tensor框架。

該框架的不同點在於encoder和decoder不再使用RNN-based模型,而是使用self-attention方式進行建模表徵。

encoder使用雙向語言模型建模,使用全“1”的self-attention mask。decoder使用單向語言模型建模,使用下三角矩陣的self-attention mask。

解碼時,計算decoder與encoder之間cross attention權值,使用encode最後一層表示。

在業務實踐當中,通常encode的層數設定比較少,decode層數設定比較多,decode層數增加效果較好。

Google Menna和Facebook的Blender均基於這種模型的結構來進行最佳化。

③ GPT模型

小布助手閒聊生成式演算法

2018年,OpenAI提出GPT模型。該模型跟前面的tensor2tensor不一樣的是,它只採用了tensor2tensor的decoder部分,使用單向語言模型建模。每次預測時,使用當前詞的表徵去預測下一個word的機率分佈。

GPT最大的改進是採用預訓練任務,透過對模型預訓練,使模型學到很多通用知識,進而大幅度提升生成的效果。

OpenAI也發表了很多GPT系列的模型,比如說GPT2、GPT3,均是基於這種模型去建模最佳化。

④ Unilm模型

小布助手閒聊生成式演算法

2019年,微軟提出Unilm模型,該模型跟GPT一樣採用tensor2tensor的decoder部分,不一樣的地方是它的context部分,採用雙向語言模型建模,使用全“1”mask。response部分採用單向的語言模型,使用下三角mask。同樣也是基於當前詞最終狀態去預測下一個詞。和GPT不同的是,它使用單向或者雙向的預訓練任務,因此訓練效果也比較好。百度的plato系列是基於這種模型結構進行最佳化。

⑤ 模型對比

小布助手閒聊生成式演算法

上圖是對幾種模型的對比。

3. 生成式decode方案介紹

① search

小布助手閒聊生成式演算法

search通常有兩種方案:greedy search和beam search。

greedy search

,這是最簡單的方法。它是區域性最優演算法。每一步search的時候,都是選當前機率最大的值作為最終輸出結果,這樣很容易陷入區域性最優。另一方面,在實踐當中我們發現,它生成的答案往往都是通用無意義的,比如說像“好的”、“沒有”等等這種無意義的答案。還有就是生成的結果很容易前後答案重複,體驗不佳。

beam search

,這是一種近似全域性最優的演算法。它每一步解碼的時候,儲存一個top-k值,即它的beam size,這個值是可設的。到最終也會輸出top結果,可以根據一定的策略去進行優選,或者直接選擇最大的路線。在實踐的過程中,我們發現beam內答案多樣性也不夠,同樣容易生成一些通用無意義和前後重複的答案。當然業界也有很多最佳化方案,比如beam分組,還有不同維度的懲罰等等。這裡就不展開介紹了。

② sampling

小布助手閒聊生成式演算法

另一種業界常用的是sampling decode方案。sampling就是取樣,常用取樣方法有兩種:top-k取樣和top-p取樣。

top-k取樣

,是對最終機率值做降序排列,從top k結果裡隨機取樣,採到的就是最終使用結果。top-k取樣方法,其隨機性較強,生成的答案多樣性比較好。但有時候也會出現不太好的case。比如說像上圖中top-k部分第二幅圖的情況,前面幾個機率值都特別大,top-k裡面可能會存在一些機率值很低的字,如果取樣採到了這些字,可能生成的結果並不理想,存在不通順等情況。

top-p取樣

,在一定程度上能夠緩解上述問題。top-p演算法與top-k一樣,首先會對每個字生成機率做降序排列,去計算累計機率,設定一個累計機率門線,對在門線內的詞進行隨機取樣,然後把取樣結果當做最終的結果。透過這種演算法,其生成的多樣性比較好,隨機性也強,生成的答案一般也都比較通順。雖然也會存在低機率被取樣到的情況,但相對來說會少一些。

4. 生成式答案選擇方案介紹

前面介紹如何去取樣生成結果,下面介紹對生成的多個結果怎麼排序。

① RCE rank演算法

小布助手閒聊生成式演算法

業界最簡單的排序演算法就是RCE rank的演算法,即response和context的相關性預測。做預測最簡單的方法是去訓練一個分類任務,透過不同的context和response去判斷是否相關。為了提升效果,也可以在response裡面加入MLM任務。訓練的時候透過同時訓練兩個任務提升整個模型效果。前面講到一些取樣不佳的case,透過這種排序可以很有效的把它們過濾掉,從而保證最終取樣到的結果都是比較合理的。

② MMI rank演算法

小布助手閒聊生成式演算法

第二種使用比較多的是MMI rank演算法。生成式的任務是透過一個context去生成一個response,每個response有一個生成機率。MMI演算法是反向來做,訓練的時候用response去生成context,在排序的時候有多個response,context固定之後用多個response去生成context,然後去計算能夠生成的機率。最後排序的時候,使用前項跟後項的這兩個機率做一個連立,作為最終排序的依據。

透過這種方法,可以有效地降低那些通用無意義的query的得分。

5. 生成式聊天評估方案

小布助手閒聊生成式演算法

目前生成式評估分為兩種方案:人工評估和自動化評估。

① 人工評估

迭代效率比較慢,對於模型迭代來說不利,但是它可能跟我們真實的體驗效果比較一致。現在業界對於生成式的評估沒有一個統一的標準,每個公司會提出一些自己的想法。

比如谷歌提的SSA就是回覆的合理性,回覆內容是否是萬能答案,對兩者做平均。facebook也有自己一套方案,都是透過人,一種是讓一個人同時跟兩個chatbot的去聊,判斷哪個更好;第二種是讓兩個chatbot自己聊,人去判斷哪個更好。在中文領域,百度也提了一種評估方案,包含四個方面評估,回答的內容是否跟上下文相關,是否包含一定的資訊量,內容的新穎性,還有回覆內容跟正常人說話是否相似。

在生成式任務裡面有各種各樣的指標,但是這種自動化指標跟我們真實的使用者體驗之間是有一定gap的。所以在自動化指標裡面評估的效果比較好,在真實體驗的時候並不一定就會好。

② 自動化評估

下面來介紹一下小布助手的業務實踐。

03

小布助手閒聊生成式演算法

小布助手業務實踐

當query出現之後,首先我們會去判斷這是否是首輪的query。

如果是首輪的query,我們會優先用檢索去應答。如果檢索沒有生成答案的話,我們就用規則去應答。如果規則沒有答案,我們就會用生成式應答。

如果不是首輪的query,我們就會去判斷它是不是上下文相關的。如果上下文不相關的話,我們認為它還是一個獨立的query,那麼我們還是像首輪的query一樣處理。如果它是上下文相關的,那麼我們優先會用生成式去答,如果生成式有結果,就直接返回,如果沒有結果就進行兜底。這主要是因為生成式在建模的時候是考慮了這種上下文的理解能力的。

1. 整體方案與流程

一個query過來,首先會做一個query的安全檢測,安全檢測透過之後,就會去做生成式模型,然後結合一些解碼策略去生成答案。答案生成後,我們就會去答案做選擇,選擇排序之後對答案做一個QA的安全檢測,確保我們生成的答案是安全可靠的。

① 小布聊天整體應答流程

② 小布生成式聊天流程

小布助手閒聊生成式演算法

模型選型參考的是百度plato two的模型方案,使用了兩階段式的訓練。

2. 模型設計與最佳化

在訓練生成式任務的時候,相同的context會有多個response。因為同樣說一句話,別人去答的時候可能有多種多樣的回答方法。但是對於模型來說,我們給一個context然後生成多個不一樣的response,模型學習起來是困難的。就相當於一個query有多個標籤。為了降低學習的複雜度,我們首先1V1訓練,對相同context的多個答案進行隨機抽取,抽取出一個答案來進行訓練,這樣的話就降低了整個學習的難度。整個模型的選型用的是Unilm的模型結構,使用bert-base對這個模型來進行初始化,並且引入了一些預訓練的知識。

① 模型選型

使用全量的語料來進行訓練。針對前面一對多的情況做了一個處理,首先會把context、response和隱狀態同時輸入到雙向的語言模型裡面來,然後利用這個隱狀態來做一個分類,相當於去判斷response跟context它們到底屬於哪個類別的回覆。在預測的時候使用不同的latent,根據context去生成,在相同的context的情況下,就可以合理地去生成不同的response。這樣做還有一個好處,就是在預測的時候,隱狀態是可以人為輸入的,不同的輸入可以生成更多種答案,可以很好地提高生成的多樣性。Latent的狀態個數也可以根據我們語料的情況去設定。

第一階段1V1訓練

小布助手閒聊生成式演算法

模型輸入除了普通的token embedding之外,我們加了一個context mask,主要去提示哪一部分是單向的語言模型,哪一部分是雙向的語言模型。還有一個role embedding去提示當前query是哪個人物說的。目前支援兩個角色的對話。Context支援的最大長度是128,支援的最大的對話輪數是10輪。

第二階段1VN訓練

小布助手閒聊生成式演算法

上圖是我們模型訓練的一些配置。

② 模型輸入

小布助手閒聊生成式演算法

在decode方面,我們使用的是sampling rank的方法,取樣的方法用的是top-p的演算法。

beam search中,一個query可以search出多個answer。取樣的時候,都是一個query能取樣一個結果。為了同時生成多個結果,我們會把相同的query組裝成一個batch,同時輸入進去做預測。query batch越大,生成的答案可能就越多,多樣性就越好。

但是batch大了之後整體效能就會有很大問題,所以我們設定batch size為10,最大生成長度15。

取樣的時候,在隨機性放的比較大的時候,可能會採到一些不太好的結果,因此我們可以將一些query的隨機性設少一點,一些隨機性設大一點,這樣哪怕取樣採到一些不太好的結果,仍有隨機性小的那些答案來保底,確保有一個合適的結果,兼顧生成結果的多樣性與可靠性。

③ 訓練配置

小布助手閒聊生成式演算法

在答案選擇方面,我們使用的是RCE演算法,bert-base的模型。第一階段生成式模型來對模型做初始化,訓練時使用MLM任務。正樣本基本上都使用的是生成式的訓練語料,負樣本有的是隨機取樣,有的是一些規則生成的。

在答案選擇方面,除了純模型的打分,我們還引入了很多別的變數進來。比如本來query生成不同的response,會有一個生成的機率,這也是我們一個參考因素。我們還會做一些規則去做衝突檢測,如果當前query跟上文有明確的衝突,我們就把它的分值給降低。我們也會去對判斷query是不是有意義的,如果無意義也會把它分值降低。除此之外,我們還會去做對query本身以及跟上下文的重複檢測,把這個結果也納入到我們最終的排序裡面來。這就是我們最終的排序的結果分數的計算方法。

④ decode方案

小布助手閒聊生成式演算法

我們在安全方面也做了很多的工作。一個query要進入到生成式模型,會經過三個漏斗的步驟,第一步會做一個系統級的安全檢測,然後閒聊業務會對query再做一個安全檢測,包括一些關鍵詞、長度或者一些特殊字元等等。最後還設定了一個安全模型,來提高敏感query的召回率。

我們做了一個線上的統計,線上query從源頭到能夠過生成式模型,透過率大概是85%。

query的安全檢測模型,最開始是用我們的線上的日誌去訓練了一個bert-base的模型。為了提升效率,我們又用bert-base去蒸餾了一個四層的bert,在線上用T4卡一次預測大概是三毫秒。使用query檢測模型,相對於從策略去檢測的話,識別準確率提升了7%,召回率也有12%的明顯提升。

⑤ 答案選擇方案

小布助手閒聊生成式演算法

有的query本身是不敏感的,但query和answer組合起來不太好。針對這種情況,我們基於bert-base來建模。這個模型相對於前面純query檢測來說難度更大一些,為了保證效果,這裡我們就用了一個bert-base的模型,沒有再去做蒸餾。

透過使用這種QA檢測模型,線上敏感query下降了7。8%。

⑥ query安全檢測

小布助手閒聊生成式演算法

除了以上策略和模型方面的工作,我們在安全方面還對訓練資料做了一些處理。首先我們對原始的訓練資料進行安全識別,對於不合理的資料,我們考慮兩種策略,一種是直接移除,另外一種是透過一些萬能回覆或者引導回覆來進行替換,最終讓模型看到的資料都是安全的乾淨的資料,這樣就可以在很大程度上避免模型去生成一些不太合適的query。

⑦ query-answer安全檢測

3. 應答安全方案

小布助手閒聊生成式演算法

基於預訓練的生成式任務,還有一個很大的挑戰,就是效能問題。生成式任務是一個自迴歸任務,需要一個字一個字地去生成,所以它呼叫模型的次數是非常大的。針對性能最佳化,我們也做了一些工作:

4. 效能分析與最佳化

:前面講過為了去使用sample rank的方法,我們會做一個batch去輸入,在一個batch去預測的時候,我們發現有的已經生成完了,再讓它繼續輸入進去做預測,其實已經沒有意義了。所以我們動態地把這些已經生成完了的去掉,在預測的過程中batch size不斷地減少,這樣就能達到效能最佳化的結果。

① 效能最佳化

:首先我們從一個check point固化到Pb,然後轉到onnx,用onnx去做加速。使用onnx進行加速後,單次預測耗時下降了20%。我們還嘗試使用FP16去進行加速,但是生成的結果不太符合預期。

動態batch

小布助手閒聊生成式演算法

生成式為了去提高預測的效能,往往都會去做一個cache機制。在做某一次預測的時候,預測完了之後我們會把這一次預測的一些中間結果儲存起來,而在下一次預測的時候,只需要把上一次預測出來的結果當成輸入去獲得它的一個embedding,然後透過這個embedding和上一步存的中間結果進行互動的計算,直接來計算下一個預測的機率,就可以避免很多重複計算。當然,在第一次預測時沒有cache,這樣預測耗時相對會長一些,後面基本上就比較穩定了。

我們用我們的模型在T4卡上也做了一些測試。batch_size=10,seq_len=10的時候,第一次預測大概是15毫秒,後面每一次預測大概是9毫秒。整個生成式模型全鏈路算下來,也就是query安全檢測 + 第1次預測 + 第N次預測 * (max_len - 1) + QA安全檢測,計算下來大概是152毫秒左右。

用onnx runtime的方式來進行模型的預測

② 效能分析

小布助手閒聊生成式演算法

我們對訓練的模型做了效果評估,包括兩個方面:

5. 效果分析與展示

:使用selfchat的方式來進行評估,就是讓兩個自己去聊,然後我們去採他們的對話資料來進行評估。評估的自動化指標是多樣性。上圖(左)可以看到我們和業界其他一些方案的對比。

① 效果評估

:讓三方評測團隊對我們進行盲評,使用了5000多條線上的query。評估的標準主要包含安全性、相關性、豐富性和通順性。打分的話,不合適是0分,還可以是0。5分,達到預期的是1分。小布助手得分為0的情況遠遠少於標杆產品,得分0。5和1的遠超標杆產品,最後綜合滿意度接近85%。

自動化評估

接下來展示一下我們生成式的效果。

小布助手閒聊生成式演算法

從上圖可以看出,內容生成的相關性是非常好的。結合我們線上的業務,我們也做了一些專門的最佳化,有時候線上的業務可能會存在有一些模糊意圖,像是幫我打,我們針對這種模糊意圖構建了很多的引導澄清的answer,然後透過使用模型來進行最佳化。

小布助手閒聊生成式演算法

上圖是多輪的效果展示,整個聊天體驗還是非常順暢的。

人工評估

② 效果展示

透過我們的實踐,還有業界的一些方案,我們看到了端到端生成式是有一定的可行性的。

當然也會存在有一些不足,從工業界落地的角度看,這種大規模的生成式方案在效能上還存在一定挑戰,耗時還比較高。除此之外,我們的模型與產品人設結合時,也存在一定的困難,我們也仍在不斷地探索當中。

還有一些業界普遍存在的問題,比如安全性、一致性、合理性和情感化存在的一些問題。

除了端到端純文字的生成式方面,我們團隊後續也會在多模態的生成式問答方面進行持續投入,如果大家感興趣的話,也歡迎隨時加入我們,一起交流。

04