張曉芳,歐睿,曾鈺城,饒攀軍,陳科,鄭元,張雷,李明艷
(1 太極計(jì)算機(jī)股份有限公司,北京 100102;2 哈爾濱工業(yè)大學(xué),哈爾濱 150001)
在傳統(tǒng)的以業(yè)務(wù)流為基礎(chǔ)的軟件中,用戶會(huì)根據(jù)業(yè)務(wù)類型,調(diào)用業(yè)務(wù)對(duì)應(yīng)的程序接口,完成業(yè)務(wù)需求。但隨著業(yè)務(wù)需求的多樣化,業(yè)務(wù)對(duì)應(yīng)的程序接口也會(huì)變得愈加繁雜,此時(shí)用戶為完成一項(xiàng)業(yè)務(wù)所需的操作步驟就會(huì)增多,導(dǎo)致工作效率下降和增加出錯(cuò)概率。針對(duì)于此,本文研究的指令序列轉(zhuǎn)換,是把用戶用自然語言表述的業(yè)務(wù)需求轉(zhuǎn)換為可供系統(tǒng)執(zhí)行的指令,通過執(zhí)行指令完成用戶所表達(dá)的業(yè)務(wù)需求,可以有效縮短操作步驟,提高工作效率和降低出錯(cuò)概率。
通常情況下,業(yè)務(wù)需求基本上都可以映射為對(duì)數(shù)據(jù)庫的增、刪、改、查。由于指令與SQL 語句類似,則可將其轉(zhuǎn)換成類似于SQL 語句的表達(dá)方式,進(jìn)而用Text2SQL 和NL2SQL 相關(guān)技術(shù)完成自然語言到指令的轉(zhuǎn)換。
自然語言序列到指令序列的轉(zhuǎn)換任務(wù),在自然語言處理領(lǐng)域一直受到研究人員的關(guān)注,通常被稱為NLIDBs(Natural Language Interface to Databases)[1-2]。
早期提出的系統(tǒng)大多都是基于人工編寫的特定轉(zhuǎn)換規(guī)則,只能應(yīng)用到特定的數(shù)據(jù)庫中[3-5]。后來的工作著重于構(gòu)建一個(gè)能夠泛化的轉(zhuǎn)換系統(tǒng),該系統(tǒng)可以用最少的人力即可用于多個(gè)數(shù)據(jù)庫[6-8]。近年來,隨著語義解析技術(shù)的進(jìn)步,以端到端[9-10]模型為代表的方法,以及在此基礎(chǔ)之上構(gòu)建的高級(jí)神經(jīng)網(wǎng)絡(luò)的方法[11-12],在大規(guī)??珙I(lǐng)域Text-to-SQL 數(shù)據(jù)集上。例如,WikiSQL[13]和Spider[14],取得了非常好的效果。
針對(duì)上述問題,結(jié)合近年來有關(guān)Text2SQL 的工作,本文對(duì)以往模型進(jìn)行改進(jìn),提出了混合排序填充網(wǎng)絡(luò)模型(Hybrid Ranking Filling Network,H-Net)。混合排序填充網(wǎng)絡(luò)模型建模過程如下:
(1)利用語言預(yù)訓(xùn)練模型BERT[15]對(duì)一個(gè)列與問句進(jìn)行聯(lián)合編碼,用以獲取列與問句之間的關(guān)系;
(2)根據(jù)選擇的SQL 模板,將生成完整的SQL語句任務(wù),劃分為若干個(gè)生成子SQL 語句任務(wù);
(3)計(jì)算列與問句在不同子SQL 語句中的相似度,并對(duì)計(jì)算的結(jié)果進(jìn)行排序;
(4)針對(duì)不同的子SQL 語句的生成任務(wù),利用排序結(jié)果和其對(duì)應(yīng)的解碼方式進(jìn)行解碼,生成子SQL 語句。
(5)利用子SQL 語句填充SQL 模板,生成完整的SQL 語句。
混合排序填充模型與傳統(tǒng)端到端模型的不同在于,混合排序填充模型不需要額外的編碼器和解碼器,也不需要引入額外的中間表示層,這些特點(diǎn)降低了模型復(fù)雜度,提高了模型泛化能力。為了驗(yàn)證本文提出方法的有效性,構(gòu)建了文本序列到指令序列的數(shù)據(jù)集,在這一數(shù)據(jù)集上的實(shí)驗(yàn)結(jié)果,驗(yàn)證了本文方法的有效性。
近年來,有關(guān)Text2SQL 的工作主要可以分為端到端翻譯、中間語義表示、SQL 子任務(wù)預(yù)測、中間語義表示等方法。下面分別介紹這4 類模型,并且評(píng)價(jià)其優(yōu)缺點(diǎn),最后比較H-Net 與這4 類模型的聯(lián)系和區(qū)別。
端到端翻譯模型主要思想是,通過端到端模型生成具有SQL 語法結(jié)構(gòu)的草圖,然后利用問句中的內(nèi)容填充該草圖[13-16]。方法可以簡單概括為以下步驟:
(1)將輸入問句和數(shù)據(jù)庫表分別進(jìn)行編碼,計(jì)算問句對(duì)數(shù)據(jù)庫表的注意力,生成注意力表示作為模型輸入,然后通過解碼器生成一張粗略的草圖;
(2)通過對(duì)齊問句與草圖,填充草圖中丟失的細(xì)節(jié)。端對(duì)端模型對(duì)語句順序敏感,但SQL 語句對(duì)順序不敏感。例如,條件語句中交換2 個(gè)條件順序,對(duì)SQL 語句并沒有影響,但卻會(huì)影響端對(duì)端模型的生成過程。
中間語義表示模型主要思想是將問句和所有列拼接,進(jìn)行編碼獲取輸入,然后通過基于語法(Grammar Based)的解碼器,生成樹狀結(jié)構(gòu)的中間語義表示,最后基于中間表示再進(jìn)行一次解碼,生成完整的SQL 語句[11-12,17]。方法可以簡單概括為以下步驟:
(1)將問句與數(shù)據(jù)庫進(jìn)行鏈接(Schema Linking),找出問句中的與數(shù)據(jù)庫對(duì)應(yīng)的表、列和值序列,然后將數(shù)據(jù)庫表中所有列與問句各自進(jìn)行編碼并且拼接作為輸入;
(2)利用基于語法的解碼器,通過ApplyRule,GenToken 2 類規(guī)則,生成樹狀結(jié)構(gòu)的中間語義表示;
(3)對(duì)中間語義表示再進(jìn)行一次解碼,生成完整的SQL。
中間語義表示方法需要專門的基于語法的解碼器、引入專門的中間語義表示層,增加模型復(fù)雜度。此外,引入中間語義不能完全表示問句內(nèi)容,會(huì)造成語義損失[18]。
SQL 子任務(wù)預(yù)測模型主要思想,是將SQL 語句拆解成若干個(gè)子SQL 語句,然后分別生成子SQL 語句,最后組合成一個(gè)完整的SQL 語句[19-20]。這類方法可以簡單概括為以下步驟:
(1)將SQL 語句拆分為SELECT-column、SELECTaggregation、WHERE-number、WHERE-column、WHERE-operator、WHERE-value等子SQL 語句;
(2)每個(gè)子SQL 語句都對(duì)應(yīng)著一個(gè)子任務(wù),每個(gè)子任務(wù)相當(dāng)于一個(gè)分類任務(wù)。子任務(wù)之間各自獨(dú)立,各自生成對(duì)應(yīng)的子SQL 語句,最后組合成一條完整的SQL 語句。
SQL 子任務(wù)預(yù)測模型的子任務(wù)劃分,是通過人工定義規(guī)則完成的,無法拓展到復(fù)雜的SQL 語句;SQL 子任務(wù)預(yù)測模型沒有充分利用句與列之間的依賴關(guān)系,沒有充分利用任務(wù)之間的依賴關(guān)系。
模型的主要思想,是用語言預(yù)練習(xí)模型BERT[15]捕捉問句與列之間的關(guān)系,利用問句與列之間的關(guān)系生成SQL 語句[21-23]。方法可以簡單概括為以下步驟:
(1)將問句和所有列拼接[21-22],或者將問題與單個(gè)列進(jìn)行拼接[23]作為輸入,利用語言預(yù)訓(xùn)練模型獲取編碼得到輸出,獲取問句和列之間的關(guān)系;
(2)用類似SQL 子任務(wù)預(yù)測的方法,將完整SQL 分成若干個(gè)子SQL 語句;
(3)對(duì)于每一個(gè)子SQL 語句,通過對(duì)語言預(yù)處理模型的輸出,用線性神經(jīng)網(wǎng)絡(luò)[23]或LSTM(Long Short-Term Memory)[24]進(jìn)行解碼,填充子SQL 語句,最后合并子SQL 語句,得到完整的子SQL 語句。
這類方法的缺點(diǎn)是:SQL 子任務(wù)的劃分是通過人工定義規(guī)則完成;無法拓展到復(fù)雜的SQL 語句;需要額外的LSTM 解碼器完成SQL 語句生成。
本文提出混合排序填充網(wǎng)絡(luò)模型(H-Net)的方法與文獻(xiàn)[19-20,23]方法類似,采用了語言預(yù)訓(xùn)練模型和SQL 語句子任務(wù)劃分。但主要有以下不同:
(1)引入模板生成層,可以根據(jù)訓(xùn)練數(shù)據(jù)中的SQL 語句,抽取出SQL 模板,讓模型可以根據(jù)輸入問句不同,選擇不同的模板,進(jìn)而依據(jù)模板可以劃分出不同的SQL 子任務(wù),在此基礎(chǔ)上生成結(jié)構(gòu)復(fù)雜的SQL 語句;
(2)拓展了填充SQL 子語句的方法,可以生成復(fù)雜的SQL 語句。
在本節(jié)中,將詳細(xì)介紹在混合排序填充模型如何進(jìn)行模板抽取、模板選擇、子任務(wù)劃分和每類子任務(wù)的完成方式,最后介紹了如何進(jìn)行模型訓(xùn)練和SQL 語句預(yù)測。
首先,為SQL 語句定義上下文無關(guān)文法,如圖1所示。
圖1 SQL 語句的上下文無關(guān)文法Fig.1 Context-free grammar for SQL
與Grappa[25]類似,對(duì)于訓(xùn)練集中SQL 語句s,用上下文無關(guān)文法對(duì)其進(jìn)行解析。對(duì)于每一條SQL語句s,都會(huì)得到一個(gè)SQL 語句的語法結(jié)構(gòu)。
例如,對(duì)于SQL 語句:
利用上下文無關(guān)文法進(jìn)行解析后,得到如圖2所示的SQL 語句的語法結(jié)構(gòu),并依據(jù)該語法結(jié)構(gòu)進(jìn)行聚類。對(duì)于聚類結(jié)果中的每一類,取該類覆蓋率最高的SQL 語句的語法結(jié)構(gòu),作為一個(gè)模板Template,將所有模板記為一個(gè)模板集合T。
圖2 SQL 語句的語法結(jié)構(gòu)Fig.2 The syntax structure of an SQL
2.2.1 定義
問句可以表示為:q
數(shù)據(jù)庫中的一列可以表示為:
其中:type表示列的類型,type∈{string,number,date,...};t為表名;c為列名;為注釋;為列注釋;Concat(·)表示連接操作。
將問句q與列ci組合起來,得到輸入對(duì)(ci,q)。輸入對(duì)經(jīng)過分詞后,得到一個(gè)詞序列:
其中:x1,x2,...,xm表示列ci的詞序列;y1,y2,...,yn表示問句q的詞序列;將[CLS],x1,x2,...,xm,[SEP],y1,y2,...,yn,[SEP]作為模型輸入,記為input。
2.2.2 編碼
采用BERT 語言預(yù)訓(xùn)練模型對(duì)輸入進(jìn)行編碼,用于捕捉問句與列之間的關(guān)系,編碼后將獲得一個(gè)隱藏狀態(tài)序列。
H-Net 模型由語言預(yù)訓(xùn)練模型BERT、模板選擇和模板填充3 部分構(gòu)成。模型結(jié)構(gòu)如圖3 所示。
圖3 H-Net 模型總體結(jié)構(gòu)Fig.3 The structure of H-Net
2.3.1 模板選擇
模板選擇可以認(rèn)為是一種分類任務(wù),對(duì)于給定問句q,其對(duì)應(yīng)模板記為τ,則有:
P(ci∈Rc |q)是問句q與列ci在完整SQL 語句中相似度。
2.3.2 子任務(wù)劃分
假設(shè)一個(gè)SQL 語句模板如圖4 所示。
圖4 一個(gè)SQL 語句模板樣例Fig.4 A template of SQL
根據(jù)SQL 語句模板,可以將預(yù)測SQL 語句拆分為3 類子任務(wù):
(1)列獨(dú)立任務(wù):預(yù)測選擇子句所涉及的列Sc,條件子句中所涉及的列Wc,排序子句中所涉及的列Oc和完整SQL 語句中所涉及的列Rc;
(2)列相關(guān)任務(wù):預(yù)測函數(shù)運(yùn)算符aggregation、條件操作符operator、條件對(duì)應(yīng)的值value、條件對(duì)應(yīng)值的個(gè)數(shù)value_num等;
(3)結(jié)構(gòu)相關(guān)任務(wù):預(yù)測集合運(yùn)算符rel,連接運(yùn)算符link等。
2.3.3 列與問句相似度計(jì)算
對(duì)于問句q,記Sc是在選擇子句select_clause中所涉及的列;Wc是在條件子句where_clause中所涉及的列;Oc是在排序子句order_clause中所涉及的列;Rc是在完整的SQL 語句中所涉及的列,Rc=Sc∪Wc∪Oc。
對(duì)于列ci,需要計(jì)算列ci與問句q在不同SQL子句中的相似度,進(jìn)而確定列ci在對(duì)應(yīng)的SQL 子句中是否出現(xiàn)。以下是4 種不同相似度的計(jì)算方式:
在選擇子句select_clause中,列ci與問句q相似度記為P(ci∈Sc |q):
在條件子句where_clause中,列ci與問句q相似度記為P(ci∈Wc |q):
在排序子句order_clause中,列ci與問句q相似度記為P(ci∈Oc |q):
在完整的SQL 語句中,列ci與問句q相似度記為P(ci∈Rc |q):
2.3.4 列獨(dú)立任務(wù)
列無關(guān)任務(wù),是指在預(yù)測不同SQL 子句中所涉及的列。如:Sc、Wc和Oc。2 種預(yù)測方式為:一是設(shè)置一個(gè)閾值,對(duì)于每一類子句,只保留與問句相似度超過閾值的列;二是對(duì)于每一類子句,預(yù)測一個(gè)n值,只保留與問句相似度排名前n的列。對(duì)于第二種方法,n的計(jì)算過程如下:
(1)選擇子句中的列數(shù)量select_num,記為:
其中,P(ns=k |c(diǎn)i,q)相當(dāng)于一個(gè)分類任務(wù)。
(2)條件子句中的列數(shù)量where_num,記為:
其中,P(nw=k |c(diǎn)i,q)相當(dāng)于一個(gè)分類任務(wù)。
(3)排序子句中的列數(shù)量order_num,記為:
其中,P(no=k |c(diǎn)i,q)相當(dāng)于一個(gè)分類任務(wù)。
2.3.5 列相關(guān)任務(wù)
列相關(guān)任務(wù),可以認(rèn)為是一種分類任務(wù),以下是4 種列相關(guān)任務(wù)的計(jì)算方式:
(1)選擇子句中函數(shù)運(yùn)算符aj:
(2)條件子句中的條件操作符oj:
(3)條件子句中的列對(duì)應(yīng)的值value:
首先,需要預(yù)測條件對(duì)應(yīng)值的個(gè)數(shù)value_num記為nv,
對(duì)于條件對(duì)應(yīng)的第k個(gè)值valuek,只需要指出valuek在問句中開始位置和結(jié)束位置:
開始位置:
結(jié)束位置:
(4)排序子句中的運(yùn)算符orj:
2.3.6 結(jié)構(gòu)相關(guān)任務(wù)
(1)對(duì)于集合運(yùn)算符rel:
(2)對(duì)于連接運(yùn)算符link:
其中,P(rel=k |c(diǎn)i,q)、P(link=k |c(diǎn)i,q)均相當(dāng)于一個(gè)分類任務(wù)。
2.4.1 訓(xùn)練階段
輸入(qi,cj)。其中,qi是第i個(gè)問句,UC={c1,c2,...,cL} 是數(shù)據(jù)庫表中所有列,cj∈UC。
標(biāo)簽:與qi對(duì)應(yīng)的SQL 語句。
優(yōu)化目標(biāo):最小化每一類子任務(wù)的交叉熵?fù)p失
2.4.2 預(yù)測階段
(1)通過式(2)選擇模板,進(jìn)行SQL 語句子任務(wù)劃分;
(2)根據(jù)式(4)計(jì)算列與問句在選擇子句中的相似度、排序;通過式(8)預(yù)測選擇子句中的列的數(shù)量,取相似度前的列(cs1,cs2,...,),根據(jù)式(14)計(jì)算每個(gè)列對(duì)應(yīng)的函數(shù)運(yùn)算符,得到選擇子句select_clause:
(3)根據(jù)式(5)計(jì)算列與問句在條件子句中的相似度、排序;通過式(10)預(yù)測條件子句中列的數(shù)量,取相似度前的列(cw1,cw2,...,),根據(jù)式(15)計(jì)算每個(gè)列對(duì)應(yīng)的條件操作符,根據(jù)式(16)~(18)計(jì)算每個(gè)列對(duì)應(yīng)的值,得到條件子句where_clause:
(4)根據(jù)式(6)計(jì)算列與問句在排序子句中的相似度;通過式(12)預(yù)測排序子句中列的數(shù)量,取相似度前的列(co1,co2,...,),根據(jù)式(19)計(jì)算每個(gè)列對(duì)應(yīng)的操作符,得到排序子句order_clause:
(5)通過式(20)和(22)預(yù)測SQL 語句的結(jié)構(gòu)信息,得到;
(6)根據(jù)上述子句所選擇出的列,可知這些列所對(duì)應(yīng)的表。即S是上述子句所對(duì)應(yīng)的表,S=[t1,t2,...,tnt],就可以得到from子句:
(7)根據(jù)表S之間的外鍵和主鍵的關(guān)系,找到表S之間的最短路徑,將最短路徑上表之間的連接條件加入到條件子句中。
經(jīng)過上述步驟,可以得到不同SQL 的子句。根據(jù)SQL 子句類型,將SQL 子句填充到模板中對(duì)應(yīng)的位置,最后得到完整的SQL 語句。
在SQL 語句的預(yù)測階段,部分生成的SQL 語句也可以被執(zhí)行??筛鶕?jù)部分生成的SQL 語句,以及在數(shù)據(jù)庫上執(zhí)行的結(jié)果,調(diào)整SQL 語句的生成,這被稱為執(zhí)行指導(dǎo)(Execution Guided,EG)[26]。執(zhí)行指導(dǎo)的作用相當(dāng)于剪枝,限制模型在解空間中的搜索范圍,去除不滿足要求的搜索路徑。
本文構(gòu)建的文本到指令序列數(shù)據(jù)集為JSON 格式,采用JSON 格式是為了方便表示指令序列。數(shù)據(jù)集包含2 312 條(問句與JSON 語句對(duì))。其中,1 923條數(shù)據(jù)是一個(gè)問句對(duì)應(yīng)一條JSON 語句,389條數(shù)據(jù)是一個(gè)問題對(duì)應(yīng)2 條JSON 語句。問句類型多為基于多條件查詢匹配的答案檢索。
JSON 語句由method、url、params 3 部分構(gòu)成。params 內(nèi)包含多個(gè)參數(shù)(param),每個(gè)參數(shù)param 又由name、option、value 組成。參數(shù)param 的2 種類型如下:
(1)直接參數(shù):value值直接出現(xiàn)在問句中。如圖5 中參數(shù)create_time 和create_org;
(2)間接參數(shù):value值不直接出現(xiàn)在問句中。如圖5 中的參數(shù)columns。
對(duì)于這2 種參數(shù),在指令轉(zhuǎn)換中有各自的處理方式。
問句與JSON 語句對(duì)示例如圖5 所示。
為了使用Text2SQL 技術(shù),需要將JSON 語句轉(zhuǎn)換成SQL 語句。轉(zhuǎn)換過程如下:
3.2.1 構(gòu)建表
構(gòu)建規(guī)則如下:
根據(jù)圖5 中的JSON 語句,可以構(gòu)建出的結(jié)構(gòu)見表1。
圖5 問句與JSON 語句示例Fig.5 (question,JSON)pair
表1 圖5 中JSON 對(duì)應(yīng)的數(shù)據(jù)表Tab.1 The table corresponding to JSON in Fig.5
3.2.2 JSON 語句轉(zhuǎn)換為SQL 語句
轉(zhuǎn)換規(guī)則如下所示:
對(duì)于直接參數(shù),轉(zhuǎn)換后參數(shù)被放置在條件子句where_clause 中;對(duì)于間接參數(shù),轉(zhuǎn)換后的參數(shù)被放置在選擇子句select_clause 中;url 被放置在from 子句中。根據(jù)圖5 中的JSON 語句,可以轉(zhuǎn)換成如圖6所示的SQL 語句。
圖6 圖5 中JSON 對(duì)應(yīng)的SQL 語句Fig.6 The SQL corresponding to JSON in Fig.5
3.2.3 數(shù)據(jù)整合
經(jīng)過從JSON 抽取并構(gòu)建表,可以得到28 個(gè)表組成的數(shù)據(jù)庫表集合;經(jīng)過將JSON 語句轉(zhuǎn)換為SQL 語句,可以得到新的2 312 條(問句與SQL 語句)對(duì);將2 312條(問句,SQL 語句)對(duì)和數(shù)據(jù)庫表集合,作為新數(shù)據(jù)集,用于模型訓(xùn)練、驗(yàn)證和測試。
將2 312 條數(shù)據(jù)中的1 800 個(gè)數(shù)據(jù)對(duì)用于訓(xùn)練集,100 個(gè)數(shù)據(jù)對(duì)用于驗(yàn)證集,412 個(gè)數(shù)據(jù)對(duì)用于測試集。
表2 展示模型使用不同語言預(yù)訓(xùn)練模型[27],以及在使用執(zhí)行指導(dǎo)和不使用執(zhí)行指導(dǎo)的情況下,模型在驗(yàn)證集和測試集上的邏輯準(zhǔn)確率。邏輯準(zhǔn)確率是指預(yù)測的SQL 語句和標(biāo)簽SQL 語句完全一致的比例。
表2 不同模型在數(shù)據(jù)驗(yàn)證集和測試集上的邏輯準(zhǔn)確率Tab.2 Logical form accuracy on dataset
參考WikiSQL 數(shù)據(jù)集[13]和Spider 數(shù)據(jù)集[14]的評(píng)價(jià)方式,將SQL 語句劃分為不同子SQL 語句,分別評(píng)測模型在每類子SQL 語句對(duì)應(yīng)的子任務(wù)上的準(zhǔn)確率。表3 展示模型在每類子任務(wù)上、在使用和不使用執(zhí)行指導(dǎo)的情況下,模型在驗(yàn)證集和測試集上邏輯準(zhǔn)確率。
表3 不同模型在數(shù)據(jù)驗(yàn)證集和測試集上每類子任務(wù)的邏輯準(zhǔn)確率Tab.3 Logical form accuracy of each task on dataset
本文研究利用語言預(yù)訓(xùn)練模型和深度學(xué)習(xí)來進(jìn)行文本到指令序列的翻譯,提出了一種混合排序填充網(wǎng)絡(luò)模型,該模型可以很好地利用語言預(yù)訓(xùn)練模型的特點(diǎn),并且能處理復(fù)雜的SQL 語句。經(jīng)在自構(gòu)建的文本到指令序列數(shù)據(jù)集上測試,取得了很好的實(shí)驗(yàn)結(jié)果,翻譯結(jié)果的邏輯準(zhǔn)確率可以達(dá)到89.1%。