将自然语言问题转换为SQL查询

时间:2014-04-10 08:44:34

标签: java desktop-application opennlp

我想使用opennlp Java库将自然语言问题转换为SQL查询,即

  

谁在索契赢得女子花样滑冰?

应转换为

select name from winners where event='skating_woman'

任何人都知道哪些课程会有用以及如何实现这一目标?

还粘贴我尝试的代码。
我已将问题转换为语句,后来转换为标记。

/////////1st part

String paragraph = "Did Matt win the men slalom?";
InputStream is1 = new FileInputStream("bins/en-sent.bin");
SentenceModel model1 = new SentenceModel(is1);
SentenceDetectorME sdetector = new SentenceDetectorME(model1);
String sentences[] = sdetector.sentDetect(paragraph);
System.out.println(sentences[0]);
is1.close();

////////2nd part
InputStream is2 = new FileInputStream("bins/en-token.bin");
TokenizerModel model2 = new TokenizerModel(is2);
Tokenizer tokenizer = new TokenizerME(model2);
String tokens[] = tokenizer.tokenize(sentences[0]);
for (String a : tokens)
    System.out.println(a);
is2.close();

3 个答案:

答案 0 :(得分:4)

对此的简单回答是,你可以"可以"做它 - 但它不切实际,几乎不可能。简单的原因是你可以有许多类似的问题,可以完全相同。使用SQL查询,您必须保留特定的语法才能获取数据...使用标准语言,您可能有100种不同的语法来获取相同的内容。将其映射到SQL语言是非常不切实际的,几乎是不可能的。

是的,你可以强迫用户使用特定的单词或特定的问题格式,这样你的程序就可以将它们解释为SQL查询 - 但这又打破了你想要实现的范式

编辑:

因为你太绝望了;)你可以"潜在地"做这样的事

让我们想象一个非常简单的查询

SELECT * FROM USERS WHERE AGE = '20';

有哪些可能的人类语言问题?

  • 你能告诉我所有20岁的人吗?
  • 展示年龄为20岁的人
  • 这个群体中有多少人的年龄为20岁?
  • 此表中有多少人有20年?
  • 我们有20岁的人吗?
  • 搜索所有年满20岁的人

你可以做的是创建某种Map<key,value>,即ie。

Key = USERS;
Value = people, humans, 

另一张地图

Key = SELECT;
Value = Can you show me, Display, Do we have, Search, How many;

依此类推 - 这将创建一个复杂的地图,其中包含所有可能的短语,这些短语可能意味着相同的东西并且对应于给定的SQL查询语法元素。这可能不是最好的解决方案,但它可能是我可能做的 - 至少这是我将要开始的

答案 1 :(得分:3)

我现在没有时间发布代码,但请查看opennlp句子chunker和文档分类程序。我认为你可以 - 创造性地 - 使用doccat建立你的“关键”和句子chunker来建立名词和动词短语(不是标记,但实际上是多字短语)并结合结果。因此,在查询时,您将对句子进行分类以建立密钥,然后对句子进行分块,然后执行连接到密钥表的查询,然后模糊(可能是全文索引)短语表。只是一个想法,如果有趣,我会将代码发布为编辑。你必须使用样本构建doccat模型。

修改

以下是如何使用opennlp文档分类程序获取一组类别的概率dist,您需要提供一个具有doccat模型路径的属性文件:

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import opennlp.tools.doccat.DoccatModel;
import opennlp.tools.doccat.DocumentCategorizerME;


/**
 *
 * @author Owner
 */
public class SentimentFinder {

  private DoccatModel doccatModel;
  private DocumentCategorizerME documentCategorizerME;
  Properties props =null;

  public void init() {
    try {
      if (doccatModel == null) {
        doccatModel = new DoccatModel(new File(props.getProperty("opennlp.sentiment.model.generic")));
        documentCategorizerME = new DocumentCategorizerME(doccatModel);

      }
    } catch (IOException ex) {
      ex.printStackTrace();
    }
  }

  /**
   * Classifies text via a maxent model. Try to keep chunks of text small, or
   * typically there will be all low scores with little difference.
   *
   * @param text the string to be classified
   * @return
   */
  public Map<String, Double> probDist(String text) {
    Map<String, Double> probDist = new HashMap<String, Double>();
    if (doccatModel == null) {
      init();
    }
    double[] categorize = documentCategorizerME.categorize(text);
    int catSize = documentCategorizerME.getNumberOfCategories();
    for (int i = 0; i < catSize; i++) {
      String category = documentCategorizerME.getCategory(i);
      probDist.put(category, categorize[documentCategorizerME.getIndex(category)]);
    }
    return probDist;

  }
}

这里是如何用一个句子chunker和句子短语

来组织句子
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import opennlp.tools.chunker.ChunkerME;
import opennlp.tools.chunker.ChunkerModel;
import opennlp.tools.postag.POSModel;
import opennlp.tools.postag.POSTaggerME;
import opennlp.tools.tokenize.TokenizerME;
import opennlp.tools.tokenize.TokenizerModel;
import opennlp.tools.util.Span;

/**
 *
 * Extracts noun phrases from a sentence. To create sentences using OpenNLP use
 * the SentenceDetector classes.
 */
public class OpenNLPNounPhraseExtractor {

  static final int N = 2;

  public static void main(String[] args) {

    try {
      HashMap<String, Integer> termFrequencies = new HashMap<>();
      String modelPath = "c:\\temp\\opennlpmodels\\";
      TokenizerModel tm = new TokenizerModel(new FileInputStream(new File(modelPath + "en-token.zip")));
      TokenizerME wordBreaker = new TokenizerME(tm);
      POSModel pm = new POSModel(new FileInputStream(new File(modelPath + "en-pos-maxent.zip")));
      POSTaggerME posme = new POSTaggerME(pm);
      InputStream modelIn = new FileInputStream(modelPath + "en-chunker.zip");
      ChunkerModel chunkerModel = new ChunkerModel(modelIn);
      ChunkerME chunkerME = new ChunkerME(chunkerModel);
      //this is your sentence
      String sentence = "Barack Hussein Obama II  is the 44th awesome President of the United States, and the first African American to hold the office.";
      //words is the tokenized sentence
      String[] words = wordBreaker.tokenize(sentence);
      //posTags are the parts of speech of every word in the sentence (The chunker needs this info of course)
      String[] posTags = posme.tag(words);
      //chunks are the start end "spans" indices to the chunks in the words array
      Span[] chunks = chunkerME.chunkAsSpans(words, posTags);
      //chunkStrings are the actual chunks
      String[] chunkStrings = Span.spansToStrings(chunks, words);
      for (int i = 0; i < chunks.length; i++) {
        String np = chunkStrings[i];
        if (chunks[i].getType().equals("NP")) {
          if (termFrequencies.containsKey(np)) {
            termFrequencies.put(np, termFrequencies.get(np) + 1);
          } else {
            termFrequencies.put(np, 1);
          }
        }
      }
      System.out.println(termFrequencies);

    } catch (IOException e) {
    }
  }

}

所以我想的是对输入文本进行分类,然后提取并存储名词短语,然后在查询时对输入进行分类,得到一个类别,然后在SQL中执行类似的操作

select * from categories a inner join nounphrases b on a.id = b.catid where catname = @thecatIjustgotfromtheclassifier and contains(text,'search term')

或类似的东西

答案 2 :(得分:1)

查看Kueri.me

该产品提供的技术支持将英语转换为SQL的搜索框,它构建用于构建关系数据库的答案引擎。

它可以识别各种过滤器,分组和其他分析元素,因此它可以回答诸如

之类的问题
  • 显示过去4个月内法国的所有订单
  • 显示上周总额的前5个订单
  • 每位客户的平均订单数

    依此类推。

您必须将系统配置为识别您的表格,字段和行话。

注意:我在kueri.me工作