袁志祥,任冬冬,洪旭東,孫國華
(安徽工業大學計算機科學與技術學院,安徽馬鞍山 243000)
互聯網上的許多重要數據都存儲在結構化數據庫中,其具有存儲簡單、數據質量高等特點。但是對于缺少相關SQL 專業知識的用戶而言,很難快速準確地寫出他們所需求的SQL 查詢語句。為解決該問題,研究人員提出NL2SQL(Natural Language to SQL)任務,該任務要求模型根據自然語言問句和數據庫表生成相應的SQL 查詢,而解決該任務的關鍵是充分地理解自然語言問句的語義,并將其映射到SQL 表達式相應的部分(如在表中找到對應的列名,在表內容找到對應的條件值,在SQL 關鍵字中找到對應的聚合函數等)。
由于缺少人工標注的SQL 數據集,使得該任務未被重視。2017 年,ZHOU 等人[1]發布人工標注的大型SQL 數據集——WikiSQL,該數據集含有大量英文問句以及對應的SQL 語句和數據庫表。2019年,追一科技公司在阿里云平臺舉辦的首屆中文NL2SQL 挑戰賽,提供了大型中文SQL 數據集。上述數據集為訓練NL2SQL 神經網絡及解決語義解析提供了訓練條件。
早期將自然語言轉換為SQL 語句的研究是利用中間表達式的方法,結合自定義語法和規則將自然語言問句轉換成SQL 語句。文獻[2]使用斯坦福依存樹解析器[3]解析問句,根據啟發式規則生成SQL候選集,利用語法樹核函數的SVM[4]對候選SQL 進行排序。文獻[5]使用無監督學習的方法生成SQL,利用數據庫模式限制模型的輸出空間以彌補標注數據的不足,同時引入擴展狀態空間的語義依存樹解決語義和語法不匹配的問題。文獻[6]通過與用戶交互來確定問句的詞語與表相應內容的關系,同時自定義規則調整查詢樹的結構,最終將其轉換成SQL。文獻[7]通過自定義一種形式化意義語言實現了中文GIS 自然語言接口。上述方法都是依賴高質量的語法來解析問句,不能處理用戶語法多變的問句,因此具有局限性。
隨著深度學習的發展,人們開始將NL2SQL 的研究轉向訓練神經網絡模型。早期的深度學習模型將NL2SQL 看成序列生成問題,利用sequence-tosequence 模型[8]生成SQL 查詢。文獻[9]運用注意力機制,通過sequence-to-sequence 的解碼層自動生成SQL 序列。為提升SQL 查詢的準確率,結合SQL 語法限制輸出空間的模型被提出。文獻[1]提出Seq2SQL 模型,該模型將SQL 生成分為聚合函數分類、select column 以及where 子句生成三部分,同時利用強化學習解決序列生成引發的“order matters”問題。文獻[10]利用SQL 語句的格式和語法提出sequence-to-set 模型,將SQL 語句任務分成多個子任務,并結合column attention 提升SQL 生成的準確率。文獻[11]結合知識圖譜識別問句中的實體。文獻[12]利用sequence-to-sequence 以及sequence-toset 模型各自的優勢,提出sequence-to-action 模型。該模型使用預定義的action 來填充SQL 查詢草圖的插槽。文獻[13]通過SQL 執行結果修復錯誤的SQL查詢。
近年來,大規模預訓練模型在許多自然語言處理的下游任務中取得優秀的成績,許多基于預訓練的Nl2SQL 模型被提出。研究人員使用Bert[14-15]預訓練模型替代glove[16]作為模型的編碼器,基于Bert 編碼器提出3 種不同的輸出層,超過了人類手動標注。文獻[17]基于MT-DNN 模型[18]提出X_SQL 模型,通過強化上下文信息得到數據庫模式新的表達式,更好地表征其結構信息以用于下游任務。
現有許多深度學習模型都僅局限于數據庫結構對模型的影響,忽略了表內容對NL2SQL 任務的重要性。問句的詞語與表內容不匹配,導致生成的SQL 查詢在數據庫執行錯誤。而結合表內容不僅可以幫助模型更好地識別問句中對應的SQL 語句實體,還可以緩解問句與表內容不一致的問題。本文在SQLova[13]的框架下,提出一個同時結合表結構和內容的NL2SQL 模型。使用字符串匹配的方法篩選出與問句相關的表內容,利用Bert 編碼器對問句、表列名以及相關表內容進行字編碼,value attention 和column attention 將表結構和內容的表示特征加到問句表達式中,幫助模型更好地理解用戶問句的語義,識別問句中的表列名和條件值,并根據多個子模型的分類方法填充SQL 草圖完成SQL 查詢。
本文使用追一公司在阿里云發布的中文數據集作為整篇文章的示例。該中文數據集的任務是在給定問句和數據庫表的情況下生成相應的SQL 查詢。其數據格式如圖1 所示,每條數據對應一個數據庫表和1 條問句以及SQL 查詢。

圖1 中文數據集數據格式Fig.1 Chinese dataset data format
對于問句的詞語與表內容不完全匹配的問題,如圖1 中的“死侍2”與表內容的“死侍2:我愛我家”不一致的情況,會導致SQL 查詢結果為空。模型結合表內容通過字符串匹配的方法來替換模型從問句中生成的詞語,即將“死侍2:我愛我家”替換成“死侍2”,緩解表內容與問句詞語不一致的問題。在WikiSQL 測試集上比SQLova 準確率高出1.4%,實驗結果表明,結合數據庫結構和內容特征可以幫助模型更好地理解問句語義,提升SQL 查詢的準確率。
本文將序列生成任務轉化為多個分類任務,通過填充SQL 草圖生成SQL 查詢。該中文數據集的SQL 查詢對應的SQL 草圖如圖2 所示,草圖的每個槽對應不同子任務。以$開頭的標記表示槽標記,$后面的名稱表示需要預測的類型。其中:$AGG 表示模型預測SQL 查詢的聚合函數,取值集合包括{‘ ’,‘MAX’,‘MIN’,‘COUNT’,‘SUM’,‘AVG’};$SELECT_COL 和$WHERE_COL 表示模型需要預測的數據庫表列名;$WHERE_RELA 表示where 子句的關系,包括{‘ ’,‘and’,‘or’};$WHERE_OP 表示SQL 查詢的操作符,包括{‘=’,‘>’,‘<’};$WHERE_VAL 表示從問句中生成的SQL 查詢條件值;(…)*表示子句的數量是零個或多個。

圖2 SQL 草圖Fig.2 SQL sketch
在SQLova 框架下,將模型分成Encoder 層、Attention 層以及Ouput 層三部分,具體結構如圖3 所示。在Encoder 層,SQLova 將問句和表列名作為Bert 預訓練模型的輸入,在SQLova 模型的基礎上將相關表內容作為Bert 的輸入;在Attention 層,SQLova 通過Column Attention 得到問句表達式,利用Value Attention 將表內容的信息融入問句的表達式中;在Output 層,為了更好地預測Where Column和Where Value 子任務,將基于表內容的問句表達式作為額外輸入。

圖3 模型整體結構Fig.3 Model overall structure
在解析問句語義時,相對于結合數據庫結構,表內容對于生成SQL 查詢有著重要作用。結合表內容可以幫助模型更好地找到SQL 查詢的條件值,如圖1中的示例,模型根據表內容“大黃蜂”更好地找到問句中的“大黃蜂”。同時結合表內容還可以幫助模型預測問句中表列名,比如“北京”這個條件值使模型更傾向于預測“城市”列名。但將表內容所有的信息作為Bert 編碼器的輸入,給模型帶來過多的干擾因素,同時會使得模型的輸入過長,所以本文篩選出與問句有關的表內容作為模型的輸入。
為得到與問句相關的表內容,模型將問句進行分詞處理,枚舉長度為1~4 的所有n-garms,使用Jaccrad公式計算組合的詞語與表內容的相似度。若問句中出現單引號或者雙引號以及書名號時,直接使用該詞語與表內容進行相似度計算。計算公式如下:

如果相似度超過一定的閾值,則將表內容加到模型的輸入中。本文利用得到的相關表內容、問句和表列名共同構成Bert 編碼器的輸入。
基于語境的動態詞表達式ELMO[19-20]和Bert[14]預訓練模型,在處理許多自然語言處理任務方面表現突出。SQLova[13]的實驗結果也表明利用Bert 模型得出的基于上下文和表的詞表達式,可以有效提高NL2SQL 任務的準確率。模型使用Bert 模型對其進行字編碼,同時將問句、數據庫列名以及相關表內容作為Bert 的整體輸入。Bert 中的self-attention 機制使得模型更注重問句中列名和條件值,獲得更準確的表達式。具體如圖3 所示,其中[CLS]和[SEP]是用于分類和上下文分離的特殊標記。本文使用[SEP]來分隔問句、列名以及表內容,與位置向量共同構成bert 編碼器的輸入,得到對應的問句、列名以及表內容的特征表達式Hq、Hcol和Hval。
將Hq、Hcol、Hval通過3 個Bi-LSTM,選擇最后的隱藏狀態得到對應的表達式Eq、Ecol、Eval。在預測Select Column 與Where Column 子任務時,為表示不同列名在自然語言問句的重要程度,本文引用SQLNet 的Column Attention[9]表示問句的表達式,具體如下:

其中,Wcol是d×d的參數矩陣,softmax 函數對輸入矩陣的每行做歸一操作,wq|col表示列名對問句的注意力權重,Eq|col是結合表內容的問句表達式。
為更好地理解問句中的條件值,本文提出Value Attention,使問句的表達式可以在預測SQL 查詢的條件值時更好地反映出表內容在問句的重要信息。本文首先利用問句和表內容的表達式計算問句對應表內容的權重,其中,Wval是參數矩陣。根據得到的每個問句的權重wq|val,然后與問句的特征表達式Eq進行加權乘積求和得到基于表內容問句的新表達式,具體公式如下:

模型利用Attention 層得到的輸出來預測SQL 草圖不同的槽,其中槽分別對應8 個子任務,分別是Select Number、Select Column、Select Agg、Where Relation、Where Number、Where Column、Where Operator、Where Value。Output 層的子任務以及之間詳細的依存關系如圖4 所示。由于Select Number 子任務與Where Number 以及Where Relation 模型結構相同,在圖中只顯示出Select Number 子模型的結構。

圖4 輸出層子模型之間的關系Fig.4 Relationship between output layer submodels
子任務分別介紹如下:
1)Select Number。該任務是確定Select 子句中表列名的數量,模型把該任務當成一個4 分類任務,具體公式如下:

其中,Eq|q表示基于self-attention 的問句表達式,Vsnum和Wsnum分別對應4×d、d×d的參數矩陣。
2)Select Column。該任務根據概率的大小從表中k個列名作為SQL 語句的Select 查詢字段,其中,k是Select Number 預測的個數,具體公式如下:

3)Select Agg。該任務是預測SQL 查詢的聚合函數,利用Select 子句的列名和問句進行分類任務,具體公式如下:

4)Where Number:該任務是利用問句的表達式預測Where 子句的個數,具體公式如下:

5)Where Relation。該子模型是預測Where 子句之間的關系。若Where 子句的數量為1 時,默認Where Relation 為空;當Where 子句的數量大于1 時,將問句表達式作為輸入對Where 子句的關系進行二分類(and,or),具體公式如下:

6)Where Column。該任務是確定Where 子句的表列名,利用列名、基于表結構和表內容的問句表達式進行分類任務。根據SQL 語法,Select Column 與Where Column 不能同時對應數據庫表的同一個列名,因此把Select 子句生成的列名也作為該任務的輸入,公式具體如下:

7)Where op。該子任務是確定Where 子句的操作符,需要根據Where 子句的表列名與問句表達式來進行分類,具體公式如下:

8)Where Value。該任務通過序列標注從問句中找到每一個Where Column 對應的條件值。除了基于列名問句表達式與Where Column 預測的Column表達式作為Where Value 任務的輸入外,基于Value attention 的問句表達式也可以幫助模型預測Where Column,具體公式如下:

若該任務生成的條件值與表內容存在不匹配的問題,模型結合表內容利用字符串匹配的方法替換生成的條件值。
在訓練階段,由于模型被分成多個分類子任務,因此目標函數可以被看成多個子模型的交叉熵損失函數的和。針對表列名的預測,模型通過交叉熵損失函數計算標注數據出現的表列名與預測列名概率的損失;針對Where Value 子任務的預測,通過預測問句中的條件值的開始位置和結束位置與真值的損失。交叉熵損失函數的具體公式如下:

其中,x表示訓練數據,y表示真值,N表示樣本的數量。本文通過最小化目標函數的方式來更新模型參數。
本文分別在追一公司發布的中文數據集和WikiSQL 數據集進行測試。WikiSQL 數據集是ZHONG 等人[1]發布的手工數據集,被廣泛應用于NL2SQL 深度學習模型,該數據集擁有80 000 多條訓練數據以及對應的20 000 多張數據庫表。中文數據集共有50 000 多條數據,與WikiSQL 不同的是,中文數據集的SQL 查詢中Select 子句的表列名可以是多個,另外,Where 子句之間的關系不是默認的“and”關系,其條件數量以多個為主。本文使用Logic Form Accuracy(Logic)和Execution Accuracy(Exe)兩個指標評估模型性能,其中,Logic Form Accuracy 是指生成的SQL 查詢與數據集的SQL 真值比對的準確率,Execution Accuracy 是指生成的SQL 語句與數據庫的SQL 語句在數據庫執行完查詢結果后進行比對的準確率。
在實驗中,本文使用768 維的Bert 作為模型的編碼器,其最大長度設置為222,在訓練階段微調Bert 預訓練模型的參數;設置模型使用的Bi-LSTM隱藏層的維度是100,丟失率為0.3,不同子任務之間的Bi-LSTM 的參數不共享;設置迭代次數為100,批訓練次數為8,每次迭代打亂訓練數據的順序,學習率設置為0.003,使用Adam 方法優化參數模型。
表1 給出本文模型和不使用表內容的模型在中文數據驗證集上的實驗結果,其中,“-表內容”表示不使用表內容的模型。可以觀察到在S_col 任務上,原模型比不使用表內容的模型準確率高出0.021,在W_col 任務上,比不使用表內容的模型高出0.007,結果表明,結合表內容可以在一定程度上幫助模型預測與表內容相關的表列名;原模型在W_val 上高出0.01,這是因為原模型可以通過表內容更好地理解問句中的SQL 查詢條件值。例如問句“愛情的呼喚這部電影是哪家單位引進的”,對應正確的Where 子句是“Where 劇名=愛情呼叫轉移and 類別=電影”,結合表內容可以幫助模型預測“電影”應該作為SQL查詢的條件值,而不是表列名。不使用表內容的模型比原模型在Execution 低0.19,在Logic Form 低1.8%,說明模型利用Attention 層的Value Attention 注意力機制,獲得更加準確的問句表達式,可以更好地幫助下游任務分類。

表1 不同模型在中文數據集上的實驗結果Table 1 Experimental results of different models on the Chinese dataset
表2 給出不同模型在WikiSQL 驗證集和測試集上的實驗結果。從表2 可以看出,本文模型的準確率明顯高于表中前5 個模型。針對SQLova 的模型,本文獲取到SQLova 源碼得到的模型由于不知道SQLova 具體的參數,實驗結果比原文給出的準確率低。本文模型在驗證集上的Logic Form 比SQLova高出0.18,在測試集高出0.15;在驗證集上的Execution Accuracy 比SQLova 模型高出0.14,在測試集高出0.14。該結果表明結合表內容和表結構可以有效地提高SQL 生成的準確率。

表2 不同模型在WikiSQL 數據集上的實驗結果Table 2 Experimental results of different models on the WikiSQL dataset%
本文在SQLova 框架下,提出一個基于表結構及其表內容的NL2SQL 模型,利用Column Attention和Value Attention 來更好地理解用戶問句的語義。將序列生成任務轉變成多個分類任務,通過填充SQL 草圖生成SQL 查詢。實驗結果表明,結合表結構和內容可以提升模型生成單表的SQL 語句的準確率。但該模型暫不能處理結合生活常識解決的問題,同時在實際情況中,用戶提出的問題往往需要多張數據庫表來解決,而多表對應的SQL 查詢會涉及表名、多張表的連接方式、嵌套查詢以及增加Group、Order 等SQL 關鍵字的情況。下一步研究方向是處理涉及多表查詢的Spider 數據集,利用人們的生活常識生成SQL 查詢,以更符合實際應用場景。