Wonopを用いた文脈意識型チャットボード


このチュートリアルでは、我々は、車、ホテルやディナーテーブルを予約するための仮想アシスタントとして機能する小さなコンテキスト意識のボットを構築します.私たちはhttps://wonop.com そうする.これらのチュートリアルを通じて、1つずつRockLangの異なる概念に導入されます.チュートリアルの最後までに、独自のコンテキストを意識したボットを構築することができます.最後の結果は次のようになります.

こんにちは世界


慣れるrocklang 伝統を作るHello world 例.移動するAgents GUIでは、既にない場合は、新しいエージェントを作成します.作成したら、コードエディターが表示されます.次のスニペットを入力します
fn main(phrase: String): Int32
{
  // Making the agent say a phrase
  say("You said: "+ phrase)

  // Printing output to the console
  printLn("Debugging: "+ phrase);

  return 0i32;
}
The main 関数は、プログラムを実行したときに呼び出される関数です.この単純なスクリプトは、RockLangを使用して出力を作成する2つの方法を示します.第一の機能say は、エージェントがそのフレーズに応答するように使用されます.第二の機能printLn 画面の下部にあるコンソールにステートメントを出力します.

歓迎コンテキストの作成


前のスクリプトは答えますYou said: ... と異なる意図の間に区別されません.まず最初にすることは、ユーザーの意図を理解しようとすることです.この目的のために、我々はRockLangコンテキスト、パターンとルートの概念を使用します.
私たちは、「Hello World」というフレーズに反応する単純なロボットによって出発します.
context Lobby {
  // Defining the pattern we want to match against
  pattern Hello: "hello" "world";

  // Creating a route for the pattern, meaning
  // that a match on "Hello" will invoke the function
  // "hello".
  route Hello: hello;
}

fn hello(ctx: MatchContext): Bool
{
  // Answers to the matched route
  say("Well, hello there!");

  // Informs the routing system that the route
  // indeed was successful by returning true.
  return true;
}

fn main(phrase: String): Int32
{
  // Getting the current user context. If no context
  // is found, then we default to "Lobby".
  let ctx: UserContext = getUserContext("Lobby");

  // Attempting to route the input phrase within the user
  // context
  if(!routePhrase(ctx, phrase))
  {
    say("I do not understand what you are saying.");
  }

  return 0i32;
}
上の例ではたくさんのことが進行中です.主な機能から始めるならば、我々は最初にユーザーコンテキストを得ます.ユーザーコンテキストがまだ存在しないなら、我々はデフォルトで「ロビー」に行きます.これは、「ロビー」がユーザーの要求にマッチしようとする最初の文脈であることを意味します.次に、コンテキスト内のフレーズをルートにシステムに問い合わせます.我々の場合では、文脈は1つのパターンだけを含みます"hello" "world" これは、“Hello World”に対してのみマッチが見つかることを意味します.ルーティングが失敗するならば、エージェントは質問が理解されないことを知らせます.

文脈情報の抽出


あなたがRegexに精通している場合は、コンテキストパターンは、この概念からインスピレーションを取っていることに注意します.前のエージェントに小さな調整を行うことで、これを説明します.
context Lobby {
  // Defining the pattern we want to match against
  pattern Hello: Exclamation ("world"|"earth"|"planet");

  // ...
}
プログラムへのこの比較的小さな変化は、巨大な影響を与えます:エージェントは、現在、「Hello World」、「Hey惑星」と「歓声地球」のようなフレーズに応じます.我々は、この広い範囲の可能性をカバーするためにどのようにしなければならなかったか注意してください.
我々が作成しているようにLobby 我々は通常、挨拶のいずれかの名前または何も続きます.我々は、ユーザーが名前を右かどうかを確認するためにフレーズから名前を抽出したいと思います.これを行うには、次のようにパターンを更新します.
context Lobby {
  // Defining the pattern we want to match against
  pattern Hello: Exclamation name=AnyWord?;

  // ...
}
そして、helloリクエストに対処するためのロジックを作成します.
fn hello(ctx: MatchContext): Bool
{
  let howCanIHelp : String = "How can I help you?";

  // Checking whether the user used a name
  if(ctx.has("name"))
  {
    // Extracting the name from the context
    let name: String = toString(ctx.get("name"));

    if(name == "lucy")
    {
      // The bot acts happy that you recognised its name
      say("Hi! Good to see you!");
    }
    else
    {
      // Informing the user that he/she got the name wrong
      say("My name is not " + name + ". My name is Lucy");
      howCanIHelp = "Anyway, how can I help you?";
    }
  }
  else
  {
    // In case that the user did not use a name, we give neutral response
    say("Hello there!");
  }

  // Finally, we ask how we can help
  say(howCanIHelp);

  return true;
}

論理は比較的まっすぐです:ユーザが名前を使用したかどうか.名前が使用されている場合は、それが正しい名前であることを確認します.されていない場合、我々は、ユーザーが名前が間違っていたし、それ以外の場合、我々は挨拶を通知します.

上級パターン


あなたがより高度なシナリオに一致しようとすると、使用するパターンが長くなり、より関与します.物事をシンプルでテストしやすくするために、パターンをサブパターンに分割することができます.我々は予約のための仮想アシスタントを構築しているとして、我々はユーザーがこの要求を策定することが多くの異なる方法に一致することができる必要があります.我々は、文を部分に壊すことによってこれをします.まず最初に文の序論的な部分を定義し、次に、活字のある部分と最後に、文の修正を行います.
context Lobby {
  // ...

  // Introductory part of the sentence
  pattern IWouldLike: "i" "would" Adverb* ("like" "you"?|"want" "you") "to";
  pattern CouldYou: "could" "you";
  pattern INeed: "i" ("need"|"want") "you"? "to";

  // The active verb
  pattern Booking: (IWouldLike|CouldYou|INeed) ("book"|"reserve"|"get"|"find")?;

  // Phrase modification
  pattern ForWhoOrWhat: "for" forWhoOrWhat=(Determiner (Pronoun|Noun));

  // The full phrase and the route
  pattern ObjectBooking: Booking determiner=Determiner what=(Noun+) ForWhoOrWhat?;
  route ObjectBooking: objectBooking;
}
我々は小さな征服可能な部分に問題を壊すためにパターンを入れ子にしている方法に注意してください.このパターンは、(“私はあなたに本を予約してほしい”という願望を介して)(“私はホテルを予約したい”)(丁寧に要求する)を介して必要なものから様々なフレーズに一致します.

コンテキストのナビゲーション


次に、このパターンで作られたリクエストを処理するロジックを作ります.
fn objectBooking(ctx: MatchContext): Bool
{
  // Defining the variables we will need
  let what: String = toString(ctx.get("what"));
  let determiner: String = toString(ctx.get("determiner"));
  let newContext: String  = what.capitalize() + "Booking";
  let who: String;

  // Checking if the context exists
  if(hasContext(newContext))
  {
    // If the request had a modification, we give a response
    // to reflect that we understood the request
    if(ctx.has("forWhoOrWhat"))
    {
      who = toString(ctx.get("forWhoOrWhat"));
      say("So you want to book " + determiner + " " + what + " for " + who);
    }
    else
    {
      // Otherwise, it's a straight forward request
      say("So you want to book " + determiner + " " + what);
    }

    // Regardless, we inform the user that we can do this
    say("Sure, I can do that!");

    // And then we change context
    pushContext(newContext);
  }
  else
  {
    // We do not have a context to handle this case and we inform the user about this
    say("Unfortunately, I don't know how to get you " + determiner + " " + what);
  }

  return true;
}
上記のロジックのほとんどは、グリーティングセクションのロジックに似ています.しかし、我々は2つの新しい機能を使用しますhasContext and pushContext . 機能hasContext 開発者が特定の名前を持つコンテキストを作成したかどうかを調べ、それを反映するBooleanを返します.機能pushContext 新しいパターンで新しいコンテキストにユーザーをプッシュします.この場合、Lobby は、新しいコンテキストのパターンの利点に取って代わられます.
このチュートリアルの最後のステップは、車やホテルのダミーコンテキストを作成することです.これを行うには、1つのルートで単純なコンテキストを追加します.
context CarBooking
{
  pattern WhatCar: AnyWord*;
  route WhatCar: whatCar;
}

fn whatCar(ctx: MatchContext): Bool
{
  // User feedback
  say("Car booked!");

  // Popping the context to return back to the Lobby
  popContext();

  // Informing the routing system that we were successful
  return true;
}
経路機能の中で、我々は電話しますpopContext 戻るLobby コンテキスト.最後に、ホテルにも同様のコンテキストを追加することで拡張できます.
context HotelBooking
{
  pattern WhatHotel: AnyWord*;
  route WhatHotel: whatHotel;
}

fn whatHotel(ctx: MatchContext): Bool
{
  say("Hotel booked!");
  popContext();
  return true;
}
コードの約140行(コメントを含む)で、私たちは、あなたが何をしたいか、そして、その文脈に操縦する能力を持っている文脈意識のエージェントを作りました.もちろん、これが完全に機能するようにするために行われるより多くの仕事があります、そして、我々は今後のチュートリアルでこれをカバーします.
私は私が開発したこの言語にいくつかのフィードバックを聞くのが大好きだ!最後に、コミュニティに参加できます.
https://wonop.com/
デーヴァトゥ
不和https://discord.gg/YtkWN9fb
Twitter