解析字符串命令

Parse String command

我正在尝试(这是一个实验)开发一个简单的应用程序 return 数据,给定语音命令(使用 iOs Siri,或 Android 语音识别等) . 我想'parse'了。

我正在使用这种方法,但我很确定它不正确。 假设用户说 "Give me 2015 Revenue of customer Duck"

if InStr(mystring, "Revenue")>0 then
 sql = sql " SELECT revenue FROM mytable "
end if
if InStr(mystring, "Give me Revenue")>0 then
 sql = sql " SELECT revenue FROM mytable "
end if
... 
...
if InStr(mystring, "April")>0 then
 sql = sql " Where month=4 "
end if
if InStr(mystring, "from April")>0 then
 sql = sql " Where month>=4 "
end if
... 
...

这是一个好方法吗? 第二个问题:如何解析客户名称?客户可能有 100 万……最好的方法是什么?

谢谢

如果我没有正确理解你的问题,你想要的是这样的(这只是伪代码,我现在无法测试代码):

Hashtable keywords = new Hashtable();
keywords.add("revenue", 1);
keywords.add("from", 1);
//Add more keywords
...
string[] words = mystring.ToLower().Split(' ');
foreach (string word in words)
{
    if (keywords[word] == 1)
    {
        //Do something based on keywords found
        //E.g. assigning delegates to invoke functions
        //or preparing an SQL string that you can then execute
        //(BEWARE OF SQL-INJECTION IF YOU USE STRINGS)
        //or simply making a big switch-case
    }
}

首先让我们假设一些事情。根据评论 "mystring is the string correctly recognized" 你不是在询问命令的语音识别,只是在询问用户名。

对于用户名,您可能需要计算 VR 机制所理解的内容与您的用户数据库之间的距离。 VR系统"hears"Duck,查找所有用户Duck的距离,取最小的距离。 "Chuck" 比 "Buckingham" 更有可能成为竞争者。 我认为您可能需要调整机制才能根据您的业务规则工作,但您已经可以使用名称之间的 Levensthein distance 创建概念证明。

我将把名字识别扫到地毯下。您需要确定您的要求,而您的问题还不够精确,无法做到这一点。

现在关于语言的解析,我认为更简单的方法是创建一个 Parsing Expression Grammar. It lets you define a grammar that is then turned into code by a generator. The code will then be able to parse the text obeying the grammar you are expecting. There is even a PEG library for C# that you can use to generate the parsing code, peg-sharp

PEG 易于构建且可读性强。您可以使用 PEG.js 在线训练来构建您的第一个语法。您首先需要了解如何将句子翻译成代码。比方说

  • 给我 2015 年 Duck 的收入
  • 2015 年 Fetch Duck 的收入

应该是等效的命令,您会说您的系统应该将其转换为带有参数 customer(Duck)、dataFields(收入)和 timeWindow(2015 年)。这可以翻译成以下语法:

start
  = command

command
= "Give me " year:year " " dataFields:dataFields " for " customer:customer 
{
    return {
        "operation" : "get"
        , "customer": customer
        , "year": year
        , "dataFields": dataFields
    };
}
/ 
"Fetch " customer:customer "'s " dataFields:dataFields " in " year:year
{
    return {
        "operation" : "get"
        , "customer": customer
        , "year": year
        , "dataFields": dataFields
    };
}

dataFields "dataFields"
 = "revenue"

year "year"
 = digits:[0-9]+ { return parseInt(digits.join(""), 10);}

customer "customer"
 = letters:[a-zA-Z]+ {return letters.join("");}

当然这个示例语法非常幼稚;句子结构无法考虑变化,但这是找到句子解析的一般规则的问题:

  • 忽略空格和噪音(例如本例中的所有格 's,或者如果用户感到沮丧则咒骂 :))
  • 创建元素不依赖于顺序但可以从句子中的任何位置选取的规则
  • 扩展可能 dataFields 和命令

如果你在 PEG.js 上尝试它,你会发现它能够将句子翻译成 JSON 对象(使用 peg-sharp 将是一个 C# 对象,你可以通过它控制行为代码)

有了这个以及对句子中的变化进行一些规划,您应该能够创建满足您需要的第一种方法

你描述的是一个比较复杂的自然语言处理问题。如果您可以使用外部 API,请查看 wit.ai(最近由 facebook 购买),这正是您想要的。你给它几个你的应用程序期望的自然语言命令的例子,然后你给它发送一个录音,它 returns 你一个 JSON 它认为语音命令的意图是什么。