2021年了,你還在手寫SQL嗎?

  • 2021 年 4 月 12 日
  • AI

?憶往昔歲月

「你還記得第一份實習,是做什麼嗎?」

我的第一份算法實習工作,是處理數據。準確地說,是每天手敲30句+SQL,從對話數據庫中分析用戶高頻問題、接通率等信息。

手寫SQL是重複性很強的工作,一不小心容易出錯,最初的兩個月每天為此忙得焦頭爛額。

剛剛入門NLP的我天真地想着,「要是模型可以自動生成SQL該多好呀」!

碩士期間,有幸在實驗室從事了半年多Text2SQL的科研工作。2021年,我很高興地看到Text2SQL技術,即通過算法將人的自然語言轉換為數據庫查詢語言SQL,在部分場景中落地應用已經成為了現實。

?談談自動寫SQL的背景

Text2SQL起源於上世紀90年代,是自然語言處理語義解析領域的子任務,核心目標是打破人與結構化數據之間的壁壘,讓普通用戶可以通過自然語言描述完成複雜數據庫的查詢工作。

例如我有一張「歌手」相關的表格,歌迷和狗仔隊們想知道:

Q:「周杰倫和林俊傑最近的演唱會是什麼時候?」

Text2SQL模型自動將問題轉換為SQL語言:

A:「SELECT 近期演唱會 FROM singer WHERE 姓名 = 周杰倫 OR 姓名 = 林俊傑」

再返回查詢結果:「北京-01.08」和「上海-04.28」

簡單的說,以前想從數據庫里拿數據或者分析內容,用戶要純手工實現。有了Text2SQL,相當於我雇了一個不花錢不會累的員工(ai模型),只要發佈命令(Text),它就會幫我寫好SQL。

?聊聊技術實現

明白了背景,我們來聊聊技術實現問題。和分類、匹配等很多NLP任務類似,Text2SQL也經歷了從早期規則匹配,到現在藉助深度學習技術的發展歷程,濃縮了一代又一代科學家們的心血。

具體實現方式有很多,為了節省時間,我幫大家抽出了一些代表性的方法。

模版與規則匹配

早期的SQL生成方法主要通過基於統計的模版與規則匹配方式。

SQL查詢是一種有很強範式的編程語言,典型特徵是可以拆分為「SELECT」和「WHERE」兩個片段。再細分一下,幾乎90%的SQL語句都可以抽象成如下的模版片段:

AGG表示聚合函數,COLUMN表示需要查詢的目標列,WOP表示多個條件之間的關聯規則「與/或」,三元組 [COLUMN, OP, VALUE] 構成了查詢條件,分別代表條件列、條件操作符、從問題中抽取出的文本片段。*表示目標列和查詢條件不止一個!

有了SQL模版,可以先通過統計方法從語料中挖掘出一些高頻實體,如人名、地名等,再根據規則填充到模版相應片段即可。來看一個具體?:

Q:價格低於20W的汽車有哪些品牌

先將問題分詞,方便後續處理:「價格 / 低於 / 20W / 的 / 汽車 / 有 / 哪些 / 品牌 ?」

通過預定義規則,很快可以識別 「低於」代表「<」操作符;「低於20W」代表「< 20W」;通過簡單數據預處理,還原出條件片段「< 20000」。

通過詞性分析和語料統計,識別出「價格」,「20W」,「汽車」是有實際意義的實體。最終通過類似的模版:「$[低於/高於]$的$有哪些?」還原出真實SQL:

A:SELECT 品牌 FROM 汽車 WHERE 價格 < 20000

這裡的條件三元組是 [「價格」, 「<」, 「20000」],目標列為「品牌」,聚合函數為空。

當然通過規則+模版的方式難以窮盡所有自然語言表達,只能處理這種簡單的例子。深度學習技術的出現,讓鹽究員們看到了Text2SQL大放光彩的曙光。

端到端多任務架構

為了充分利用神經網絡的特徵抽取能力和SQL的語法特點,共享編碼器+多任務解碼的Seq2Seq架構是一種有效的解決方法。

共享編碼器一般是用詞向量或預訓練語言模型,對query、table和column進行聯合編碼,捕捉其中隱含的鏈接關係。其中後兩項(表名和列名)統稱為數據庫模式。例如使用BERT等語言模型時,習慣將輸入拼接為 「[CLS] query [SEP] table [SEP] column1 [SEP] column2 [SEP] …. [SEP]」這樣的長序列,經過多層Transformer編碼,不同table和column對於問題query會有不同權重的相關性。

解碼器根據SQL語法特點,設計多個不同的子網絡。例如,針對上一小節的SQL模版,可以設計6個子任務分別預測查詢目標列、目標列的聚合函數等SQL片段,最終拼接出完整SQL。

多任務架構的優點在於針對不同SQL片段,可以設計有效的損失函數;同時在訓練過程中子任務的準確率可以實時監控,便於落地。對此方法感興趣的讀者,可以閱讀國防科大的論文M-SQL[1],它在天池NL2SQL[2]中文公開賽上獲得了第一名。

端到端抽象語法樹解碼

這種方法的編碼器與前一節類似,但是在解碼時將SQL視作一棵抽象語法樹,樹中各個結點是SQL的關鍵字(SELECT、WHERE、AND…)或者表名和列名的候選值。生成SQL的過程相當於從樹的根結點對語法樹做一次深度優先搜索。

以節點「SELECT」為例,「SELECT」節點往下可能包含3個葉子節點:「Column」、「AGG」、「Distinct」,分別代表「選取某一列」、「增加聚合操作」、「對列去重」。從「SELECT」節點向下搜索相當於是3分類任務,根據真實路徑和搜索路徑依次計算各個節點的交叉熵並求和,作為總損失。

抽象語法樹的思想避免了設計各種各樣的子網絡,對於涉及跨表查詢、嵌套查詢的複雜數據集有很好的效果。在領域內權威比賽Spider上取得優異成績的頂會模型IRNet[3]、Rat-SQL[4],都充分借鑒了語法樹思想。

其實語法樹不僅僅可以生成SQL,還可以生成各種各樣好玩的目標序列,例如Python/Java等編程語言,音樂音符等等。CMU的這篇論文[5]從文本生成了Python。

?Text2SQL資源大禮包

筆者在Text2SQL領域踩坑半年有餘,為避免重複性勞動,我將收集到的資料打包成了一個開源項目,主要包含Text2SQL語義解析數據集、解決方案、參考論文等。歡迎小夥伴們前來?

項目地址:
//github.com/yechens/NL2SQL

項目還在持續更新中。對於該領域的部分頂會論文,我加入了自己的解讀(BRIDGE:萬萬沒想到,BERT學會寫SQL了)。

?落地商用的真相

雖然近年該方向在ACL/EMNLP等頂會上出了很多paper,幾個知名比賽各家研究院刷的不亦樂乎,不過在我看來Text2SQL實際商用僅處於初級階段。

究其原因,是準確率還不夠高,無法完全滿足用戶預期。自然語言有很大的熵值,即便同一句話都可以有多種不同理解。同時實際場景中,用戶查詢內容往往涉及多張表格,查詢條件可能非常複雜。語義歧義性、跨表查詢、嵌套查詢等難點給模型生成準確無誤的SQL帶來很大挑戰

所以當前階段,大家看到了Text2SQL應用的曙光,但是還未開始大規模推廣;更多時候是結合人工干預與糾錯,作為對話系統的一個子模塊。

回到標題上來,2021年了,你還在手寫SQL嗎?相信看完本文讀者們心裏已經有了答案。對於WikiSQL、TableQA等簡單的單表數據集,模型已經完全可以cover。但是在現實複雜場景中,還有很長的研究道路要走。

Text2SQL依然是一個很有研究意義的課題,是自然語言處理跨出文本走向多模態的典型代表。相信未來還會有Text2Music、Text2Moive等新技術誕生,更好地服務於人類社會。

推  薦  閱  讀

參  考  資  料

[1] M-SQL://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=9146825

[2] NL2SQL中文挑戰賽://tianchi.aliyun.com/competition/entrance/231716/rankingList

[3] Jiaqi Guo, Zecheng Zhan, et al. Towards complex text-to-SQL in cross-domain database with intermediate representation[C]

[4] Bailin Wang, Richard Shin, et al. RAT-SQL: Relation-aware schema encoding and linking for text-to-SQL parsers[C]

[5] Pengcheng Yin, Graham Neubig. A Syntactic Neural Model for General-Purpose Code Generation[C]

原創不易,有收穫的話請幫忙點擊分享、點贊、在看?