0

私は中級の C# プログラマーですが、System.Speech はまったくの初心者です。API がどのように機能するかを理解するために、いくつかの例に取り組んでいますが、最初の例にすでに夢中になっています...ユーザーがこれらの選択肢のいずれかに値を明示的に指定しない場合。(用語が正しくない場合は申し訳ありません...) Visual Studio 2010 (試用版) と .NET 4.0 がインストールされた Windows Vista を使用しています。

次の記事の「ピザの注文」の例から始めました。これは、フォーラムでかなり話題になっているようです。

http://msdn.microsoft.com/en-us/magazine/cc163663.aspx#S5

私が始めたコードは、その記事の図 9 にあります。残念ながら、何らかの理由 (SAPI のあるバージョンから次のバージョンに変更された可能性がありますか?) で、.NET 4.0/SAPI 5.3 では多くの関数呼び出しが実際には有効ではありません。たとえば、GrammarBuilder.AppendChoices() および GrammarBuilder.AppendResultKeyValue() . 後者の呼び出しは、ユーザーがトッピングのみを指定した場合に「サイズ」キーと「クラスト」キーのデフォルトの選択肢を提供することになっています (つまり、「チーズ ピザをお願いします」とサイズ = 大、クラスト = 厚、トッピング = を返します)。チーズ)...だから私はこれを機能させる方法を理解しようとしています。

私のコードの関連セクションは次のとおりです(上記の記事のコードを書き直しただけであるはずです):

// [I'd like] a [< size >] [< crust >] [< topping >] pizza [please]

// build the core set of choices  
GrammarBuilder grbSizes = new GrammarBuilder(new Choices("small", "regular", "large"));  
GrammarBuilder grbCrusts = new GrammarBuilder(new Choices("thin crust", "thick crust"));  
GrammarBuilder grbToppings = new GrammarBuilder(new Choices("vegetarian", "pepperoni", "cheese"));    

// Wrap them in semantic result keys
SemanticResultKey skeySize = new SemanticResultKey("size", grbSizes);  
SemanticResultKey skeyCrust = new SemanticResultKey("crust", grbCrusts);  
SemanticResultKey skeyTopping = new SemanticResultKey("topping", grbToppings);  

// And some default values for later on...    
SemanticResultKey skeyDefaultSize = new SemanticResultKey("size", new GrammarBuilder(new SemanticResultValue("large")));  
SemanticResultKey skeyDefaultCrust = new SemanticResultKey("crust", new GrammarBuilder(new SemanticResultValue("thick crust")));  


// [...snip...]  
// Here's the builder for one of several sub-grammars, the one with two default  
// values... This should allow "cheese" in "A cheese pizza" to be intepreted  
// as large+thick-crust+cheese

//choose topping only, and assume the rest
GrammarBuilder toppingOnly = new GrammarBuilder();
toppingOnly += skeyTopping;
toppingOnly += skeyDefaultSize;
toppingOnly += skeyDefaultCrust;

// [...snip...]
// Later code builds up the full pattern just as in the original article

SemanticResultKey コンストラクターの MSDN ページには、 「 buildersパラメーターで指定された GrammarBuilder オブジェクトには、タグ付けされていない SemanticResultValue インスタンスが 1 つだけ存在する必要があります」という警告が含まれていることを認識しています。そうしないと、例外が発生します。実際、レコグナイザーに「チーズ ピザ」などと言うと、ここで TargetInvocationException が発生します。

私の最初の質問は、誰かがここで何が起こっているのか説明してもらえますか? (a) skeyDefaultSize と skeyDefaultCrust の宣言が実際に SemanticResultValues を SemanticResultKeys に関連付けていると考えたため、この制約がここで適用されるとは必ずしも予想していなかったので、これらの値は「タグなし」と見なされるべきではありません。(b) 問題の 2 つの SemanticResultValues は、実際には異なる SemanticResultKeys の内部にある異なる GrammarBuilders からのものであり、MSDN ページで説明されているシナリオではないようです。

次に、2 番目の質問は、次のコードが機能するのはなぜですか? 唯一の違いは、2 つの「デフォルト」キーが文法に連続して追加されないように、いくつかの行の順序を変更したことです。

//choose topping only, and assume the rest
GrammarBuilder toppingOnly = new GrammarBuilder();
toppingOnly += skeyDefaultSize;
toppingOnly += skeyTopping;
toppingOnly += skeyDefaultCrust;

これにより、たとえば「チーズ ピザ」と言うと、正確に望ましい結果が得られます。すべてのキー (「サイズ」、「クラスト」、「トッピング」) は、SpeechRecognided ハンドラーでキャッチした SemanticValue に存在し、目的の既定値が設定されています。サイズとクラストの値に加えて、トッピングのユーザー指定の値。

3 番目の最も重要な質問は次のとおりだと思います。これを適切に行う方法はありますか? 明らかに、追加の順序を微調整することは「魔法」であり、常に実行可能な解決策になるとは限りません。

大変な質問で申し訳ありません。ご協力ありがとうございます。

4

1 に答える 1

1

MSDNの記事から学んだ同じ問題に遭遇しました。私の解決策が「最高」かどうかはわかりませんが、これが私がピザの文法を更新し、デフォルトの選択を処理した方法です。

まず、ピザの文法を作成する方法は次のとおりです。

private Grammar CreatePizzaGrammar()
{
    //create the pizza grammar
    GrammarBuilder pizzaRequest = CreatePizzaGrammarBuilder();
    Grammar pizzaGrammar = new Grammar(pizzaRequest);
    return pizzaGrammar;
}

private GrammarBuilder CreatePizzaGrammarBuilder()
{
    // this is adapted from the sample in http://msdn.microsoft.com/en-us/magazine/cc163663.aspx
    // but the API changed before Vista was released so some changes were made.

    //[I'd like] a [<size>] [<crust>] [<topping>] pizza [please]

    //build the core set of choices

    // size
    Choices sizes = new Choices();
    SemanticResultValue sizeSRV;
    sizeSRV = new SemanticResultValue("small", "small");
    sizes.Add(sizeSRV);
    sizeSRV = new SemanticResultValue("regular", "regular");
    sizes.Add(sizeSRV);
    sizeSRV = new SemanticResultValue("medium", "regular");
    sizes.Add(sizeSRV);
    sizeSRV = new SemanticResultValue("large", "large");
    sizes.Add(sizeSRV);
    SemanticResultKey sizeSemKey = new SemanticResultKey("size", sizes);

    // crust
    Choices crusts = new Choices();
    SemanticResultValue crustSRV;
    crustSRV = new SemanticResultValue("thin crust", "thin crust");
    crusts.Add(crustSRV);
    crustSRV = new SemanticResultValue("thin", "thin crust");
    crusts.Add(crustSRV);
    crustSRV = new SemanticResultValue("thick crust", "thick crust");
    crusts.Add(crustSRV);
    crustSRV = new SemanticResultValue("thick", "thick crust");
    crusts.Add(crustSRV);
    SemanticResultKey crustSemKey = new SemanticResultKey("crust", crusts);

    // toppings
    Choices toppings = new Choices();
    SemanticResultValue toppingSRV;
    toppingSRV = new SemanticResultValue("vegetarian", "vegetarian");
    toppings.Add(toppingSRV);
    toppingSRV = new SemanticResultValue("veggie", "vegetarian");
    toppings.Add(toppingSRV);
    toppingSRV = new SemanticResultValue("pepperoni", "pepperoni");
    toppings.Add(toppingSRV);
    toppingSRV = new SemanticResultValue("cheese", "cheese");
    toppings.Add(toppingSRV);
    toppingSRV = new SemanticResultValue("plain", "cheese");
    toppings.Add(toppingSRV);
    SemanticResultKey toppingSemKey = new SemanticResultKey("topping", toppings);

    //build the permutations of choices...

    // 1. choose all three
    GrammarBuilder sizeCrustTopping = new GrammarBuilder();
    sizeCrustTopping.Append(sizeSemKey);
    sizeCrustTopping.Append(crustSemKey);
    sizeCrustTopping.Append(toppingSemKey);

    // 2. choose size and topping
    GrammarBuilder sizeAndTopping = new GrammarBuilder();
    sizeAndTopping.Append(sizeSemKey);
    sizeAndTopping.Append(toppingSemKey);
    // sizeAndTopping.Append(new SemanticResultKey("crust", "thick crust"));
    // sizeAndTopping.AppendResultKeyValue("crust", "thick crust");

    // 3. choose size and crust, and assume cheese
    GrammarBuilder sizeAndCrust = new GrammarBuilder();
    sizeAndCrust.Append(sizeSemKey);
    sizeAndCrust.Append(crustSemKey);

    // 4. choose topping and crust, and assume cheese
    GrammarBuilder toppingAndCrust = new GrammarBuilder();
    toppingAndCrust.Append(crustSemKey);
    toppingAndCrust.Append(toppingSemKey);


    // 5. choose topping only, and assume the rest
    GrammarBuilder toppingOnly = new GrammarBuilder();
    toppingOnly.Append(toppingSemKey);         //, "topping");

    // 6. choose size only, and assume the rest
    GrammarBuilder sizeOnly = new GrammarBuilder();
    sizeOnly.Append(sizeSemKey);

    // 7. choose crust only, and assume the rest
    GrammarBuilder crustOnly = new GrammarBuilder();
    crustOnly.Append(crustSemKey);


    //assemble the permutations             
    Choices permutations = new Choices();
    permutations.Add(sizeCrustTopping);
    permutations.Add(sizeAndTopping);
    permutations.Add(sizeAndCrust);
    permutations.Add(toppingAndCrust);
    permutations.Add(toppingOnly);
    permutations.Add(sizeOnly);
    permutations.Add(crustOnly);

    GrammarBuilder permutationList = new GrammarBuilder();
    permutationList.Append(permutations);

    //now build the complete pattern...
    GrammarBuilder pizzaRequest = new GrammarBuilder();
    //pre-amble "[I'd like] a"
    pizzaRequest.Append(new Choices("I'd like a", "a", "I need a", "I want a"));
    //permutations "[<size>] [<crust>] [<topping>]"
    pizzaRequest.Append(permutationList, 0, 1);
    //post-amble "pizza [please]"
    pizzaRequest.Append(new Choices("pizza", "pizza please", "pie", "pizza pie"));

    return pizzaRequest;
}

次に、SpeechRecognized イベントのイベント ハンドラーを次のように設定します。

void recognizer_SpeechRecognizedPizza(object sender, SpeechRecognizedEventArgs e)
{

    // set the default semantic key values if the result does not include these
    string size = "regular";
    string crust = "thick crust";
    string topping = "cheese";

    if (e.Result.Semantics != null && e.Result.Semantics.Count != 0)
    {
        if (e.Result.Semantics.ContainsKey("size"))
        {
            size = e.Result.Semantics["size"].Value.ToString();
            AppendTextOuput(String.Format("\r\n  Size = {0}.", size));
        }

        if (e.Result.Semantics.ContainsKey("crust"))
        {
            crust = e.Result.Semantics["crust"].Value.ToString();
            AppendTextOuput(String.Format("\r\n  Crust = {0}.", crust));
        }

        if (e.Result.Semantics.ContainsKey("topping"))
        {
            topping = e.Result.Semantics["topping"].Value.ToString();
            AppendTextOuput(String.Format("\r\n  Topping = {0}.", topping));
        }
    }
    String sOutput = String.Format("\r\nRecognized: You have orderd a {0}, {1}, {2} pizza.", size, crust, topping);
    AppendTextOuput(sOutput);
}

AppendTextOuput は、私自身の小さな出力文字列メソッドです。

これは、文法内のすべての可能な順列を明示的にレイアウトするのに大変な作業のように思えました。しかし、それは本当にうまく機能します。

ご覧のとおり、最終的に文法にデフォルトを提供させるという問題を回避し、単純にそれをイベント ハンドラーに組み込みました。おそらくもっと良い方法があります。

さらに学習するもう 1 つの手順は、SrgsDocument.WriteSrgs()メソッドを使用して、文法を表す SRGS XML ドキュメントを書き出すことです。ルール タグとセマンティック タグは、XML で視覚化するのがはるかに簡単です。

于 2011-04-18T16:30:37.287 に答える