NLTKを使用して自然言語クエリーをSQLクエリーに変換

6072 ワード

文書ディレクトリ
次のようにsqlテーブルがあるとします.
City
Country
Population
athens
greece
1368
bangkok
thailand
1178
barcelona
spain
1280
berlin
east_germany
3481
birmingham
united_kingdom
1112
athensがどの国にあるかを検索する場合は、次のsql文を使用します.
SELECT Country FROM city_table WHERE City = 'athens'

ユーザーが自然言語を使用してクエリーを行う場合
What cities are located in China

構文解析により,この自然言語を対応するsql文に変換することができる.まず、ジョムスキーの様式に合致するコンテキストに関係のない文法を書く必要があります.
% start S
S[SEM=(?np + WHERE + ?vp)] -> NP[SEM=?np] VP[SEM=?vp]
VP[SEM=(?v + ?pp)] -> IV[SEM=?v] PP[SEM=?pp]
VP[SEM=(?v + ?ap)] -> IV[SEM=?v] AP[SEM=?ap]
NP[SEM=(?det + ?n)] -> Det[SEM=?det] N[SEM=?n]
PP[SEM=(?p + ?np)] -> P[SEM=?p] NP[SEM=?np]
AP[SEM=?pp] -> A[SEM=?a] PP[SEM=?pp]
NP[SEM='Country="greece"'] -> 'Greece'
NP[SEM='Country="china"'] -> 'China'
Det[SEM='SELECT'] -> 'Which' | 'What'
N[SEM='City FROM city_table'] -> 'cities'
IV[SEM=''] -> 'are'
A[SEM=''] -> 'located'
P[SEM=''] -> 'in'

この文法をファイルsql 0に保存する.fcfgファイルでは,NLTKを用いてこの文法規則に従ってユーザが入力した自然言語を解析する.
from nltk import load_parser
cfg_path='grammars/book_grammars/sql0.fcfg'
cp=load_parser(cfg_path,trace=3)
query = 'What cities are located in China'
trees = list(cp.parse(query.split()))
answer = trees[0].label()['SEM']
answer = [s for s in answer if s]
q = ' '.join(answer)

出力は次のとおりです.
SELECT City FROM city_table WHERE Country="china"
load_parserでパラメータtrace=3が指定されているので、構文ツリーの構築プロセスも印刷されます
Leaf Init Rule:
|[-] . . . . .| [0:1] 'What'
|. [-] . . . .| [1:2] 'cities'
|. . [-] . . .| [2:3] 'are'
|. . . [-] . .| [3:4] 'located'
|. . . . [-] .| [4:5] 'in'
|. . . . . [-]| [5:6] 'China'
Feature Bottom Up Predict Combine Rule:
|[-] . . . . .| [0:1] Det[SEM='SELECT'] -> 'What' *
Feature Bottom Up Predict Combine Rule:
|[-> . . . . .| [0:1] NP[SEM=(?det+?n)] -> Det[SEM=?det] * N[SEM=?n] {?det: 'SELECT'}
Feature Bottom Up Predict Combine Rule:
|. [-] . . . .| [1:2] N[SEM='City FROM city_table'] -> 'cities' *
Feature Single Edge Fundamental Rule:
|[---] . . . .| [0:2] NP[SEM=(SELECT, City FROM city_table)] -> Det[SEM='SELECT'] N[SEM='City FROM city_table'] *
Feature Bottom Up Predict Combine Rule:
|[---> . . . .| [0:2] S[SEM=(?np+WHERE+?vp)] -> NP[SEM=?np] * VP[SEM=?vp] {?np: (SELECT, City FROM city_table)}
Feature Bottom Up Predict Combine Rule:
|. . [-] . . .| [2:3] IV[SEM=''] -> 'are' *
Feature Bottom Up Predict Combine Rule:
|. . [-> . . .| [2:3] VP[SEM=(?v+?pp)] -> IV[SEM=?v] * PP[SEM=?pp] {?v: ''}
|. . [-> . . .| [2:3] VP[SEM=(?v+?ap)] -> IV[SEM=?v] * AP[SEM=?ap] {?v: ''}
Feature Bottom Up Predict Combine Rule:
|. . . [-] . .| [3:4] A[SEM=''] -> 'located' *
Feature Bottom Up Predict Combine Rule:
|. . . [-> . .| [3:4] AP[SEM=?pp] -> A[SEM=?a] * PP[SEM=?pp] {?a: ''}
Feature Bottom Up Predict Combine Rule:
|. . . . [-] .| [4:5] P[SEM=''] -> 'in' *
Feature Bottom Up Predict Combine Rule:
|. . . . [-> .| [4:5] PP[SEM=(?p+?np)] -> P[SEM=?p] * NP[SEM=?np] {?p: ''}
Feature Bottom Up Predict Combine Rule:
|. . . . . [-]| [5:6] NP[SEM='Country="china"'] -> 'China' *
Feature Bottom Up Predict Combine Rule:
|. . . . . [->| [5:6] S[SEM=(?np+WHERE+?vp)] -> NP[SEM=?np] * VP[SEM=?vp] {?np: 'Country="china"'}
Feature Single Edge Fundamental Rule:
|. . . . [---]| [4:6] PP[SEM=(, Country="china")] -> P[SEM=''] NP[SEM='Country="china"'] *
Feature Single Edge Fundamental Rule:
|. . . [-----]| [3:6] AP[SEM=(, Country="china")] -> A[SEM=''] PP[SEM=(, Country="china")] *
Feature Single Edge Fundamental Rule:
|. . [-------]| [2:6] VP[SEM=(, , Country="china")] -> IV[SEM=''] AP[SEM=(, Country="china")] *
Feature Single Edge Fundamental Rule:
|[===========]| [0:6] S[SEM=(SELECT, City FROM city_table, WHERE, , , Country="china")] -> NP[SEM=(SELECT, City FROM city_table)] VP[SEM=(, , Country="china")] *

なお,ここで用いた線図解析器は,文法木全体を底から上へ構築し,(i,j)位置の木構造を生成し,(i,k)と(k,j)の結果を統合することによって,文S S Sが規定されるまで実現する.
この構文ツリーをより明確に見るために、印刷することができます.
print(trees)

出力は以下の通りです(より明確に見えるように出力をインデント処理し、アドレスをダウンロードしました):
[
	Tree(
		S[
			SEM=(SELECT, City FROM city_table, WHERE, , , Country="china")
		], 
		[
			Tree(
				NP[SEM=(SELECT, City FROM city_table)], 
				[
					Tree(
						Det[SEM='SELECT'], 
						['What']
					), 
					Tree(
						N[SEM='City FROM city_table'], 
						['cities']
					)
				]
			), 
			Tree(
				VP[SEM=(, , Country="china")],
				[
					Tree(
						IV[SEM=''], 
						['are']
					), 
					Tree(
						AP[SEM=(, Country="china")], 
						[
							Tree(
								A[SEM=''], 
								['located']
							),
							Tree(
								PP[SEM=(, Country="china")], 
								[
									Tree(
										P[SEM=''], 
										['in']
									), 
									Tree(
										NP[SEM='Country="china"'], 
										['China']
									)
								]
							)
						]
					 )
				]
			)
		]
	)
 ]


完全なコードは私のgithubから参考文献をダウンロードすることができます.
[1] Natural Language Processing with Python(http://www.nltk.org/book/ch10.html)