問題の声明
かつて、私が働いている会社のWebbyLabは、米国の保険会社向けのインテリジェントなチャットボットの開発という課題に直面していました。 仕事の開始時には、クライアントはすでにFacebookでチャットするためのユーザーインターフェイスを備えていました。 このインターフェースの背後に「座っている」ボットがユーザーメッセージを理解し、それらに有意義に応答し、フレーズを分析し、入力されたデータから必要な情報を抽出することを確認する必要がありました。 考えられる意図に従ってユーザーのステートメントを分離し、一連のフレーズに基づいてこれらの意図を認識するメカニズムを実装することにしました。 さらに、意図には、チャットボットも認識する必要のあるさまざまなパラメーター(家のエリア、日付、車のモデルなど)を含めることができるという事実を考慮する必要がありました。 ChatScriptは、プロジェクトのプラットフォームとして選択されました。
ChatScript
始めるには、ChatScriptを詳しく見てください。 これは、チャットボットを作成するためのエンジンであり、作成されたプログラムは、レーブナー賞を4回受賞しました。 スーとブルース・ウィルコックスによって開発されました。 CSはルールベースであり、CSでの作業は、インタープリター用の構成ファイルまたは文法の作成に似た宣言型プログラミングのアプローチに似ている場合があります。 ただし、CSでの作業は命令型プログラミングに近くなります。これは、ここでさらに、コマンドを使用して特定のメッセージへの対応方法をエンジンに伝える必要があるためです。 CSはC ++で記述されており、エンジンにはWindows、Linux、およびMacOSプラットフォーム用のバイナリアセンブリがあります。
簡単なボット開発
ソフトウェアツールを習得する最良の方法は、実際に試してみて、シンプルでわかりやすいものを作成することです。 これが私たちが今やろうとしているプロジェクトです。 さらに、この記事を見て、公式のChatScriptチュートリアルを読むことをお勧めします。
まず、便利な職場を準備する価値があります。 これを行うには、CS構文の強調表示をサポートする開発ツールをインストールすることをお勧めします。 Sublime Text 3 、 Visual Studio Code、およびAtomのプラグインは次のとおりです。 Sublimeを使用しました。巨大なファイルを開くことが必要な場合があり、このエディターはこのタスクにすばやく対応しますが、好きなエディターを選択できます。
基本的なことを明確にするために、アクティブチャットボットを開発する段階的な例を検討します。 私の例ではUbuntu 16.04とCS 7.4を使用していますが、サポートされている他のプラットフォームであれば使用できます。
1. GitHubでCSリポジトリを複製します。
git clone https://github.com/bwilcox-1234/ChatScript.git
2.
ChatScript
ディレクトリに
ChatScript
チャットボット用のフォルダーを作成します。このフォルダーには、メイントピックのファイル(以下で説明します)と、アプリケーションに含まれるトピックのリストを含むファイル
filesfood.txt
含まれます。
bash cd ChatScript/RAWDATA mkdir FOOD touch FOOD/food.top touch filesfood.txt
3.
implecontrol.top
ファイルを
RAWDATA/HARRY
から
FOOD
フォルダーに
implecontrol.top
ます。 これは、ボットと対話するために必要なスクリプトです。 ここでは、これは必須ではありませんが、
implecontrol.top
ファイルの9行目の
$botprompt
変数の値を、各ボットメッセージの前に置換される行に
implecontrol.top
できます。 ただし、これはボットの動作に影響を与えないため、すべてをそのままにすることができます(デフォルトでは
HARRY
)。 この例では、この変数に次の設定を使用します:
$botprompt = ^"fastfood>
。
bash cp HARRY/simplecontrol.top FOOD/simplecontrol.top
4.次のコードを
food.top
ファイルに追加します。
topic: ~fastfood keep repeat [] t: Hello in our online fastfood. Please make your order. u: BURGER (I [want need take] _[burger potato ice-cream]) $order = _0 Okay, you want $order . Something else?
5.ボットを構築するときに使用されるファイルのリストを
filesfood.txt
ファイルに追加します。
RAWDATA/FOOD/simplecontrol.top RAWDATA/FOOD/food.top
6.最後に、ボットを収集して起動します。 これを行うには、ChatScriptディレクトリから次のコマンドを実行します。
./BINARIES/ChatScript local
7.この段階で、任意のユーザー名を選択できます。 次に、CSコンソールで、2つのコマンドを実行する必要があります(最初はチャットボットの基本レベルを収集し、2番目は特定のトピック用にセットアップします)。
:build 0 :build food
これらのすべての手順を完了すると、チャットボットが機能します。 現時点では、彼はいくつかのフレーズ(「ハンバーガーが必要です」や「アイスクリームが欲しい」など)しか理解していませんが、新しいルールとトピックを追加することで拡張できます。
food.top
ファイルを変更した後、コマンドを再度実行
food.top
必要があります
:build food
。 以下では、この例で使用されている構文と構成について詳しく説明します。
必須のChatScriptコンストラクト
これでChatScriptを開始できます。 しかし、初心者の方は、公式ドキュメントを読んで基本的なCS設計についてもう少し学ぶことをお勧めします。 ここでは、CSの基本的なメカニズムについて説明します。チャットボットの開発は、この環境での私自身の経験に依存しています。
▍トピック
トピックは、共有されることになっている一連のルールです。 特定のトピックを使用するようにシステムに提案する場合、それらが機能する限り、このトピックのルールのみが機能します。 トピックは、キーワード(
topic:
を使用して宣言され、その後に「
~
」記号(
~fastfood
)で始まる名前と、トピック内のすべてのルールに使用される関数のリスト(
keep
および
repeat
関数が必要です)その中の各ルールを呼び出した後、このトピックに)。 宣言の最後には角括弧-
[]
ます。
topic: ~fastfood keep repeat []
通常、各トピックには多くの関連ルールが含まれます。 トピック間の切り替え、つまり、あるトピックから別のトピックへの呼び出しは、以下で説明する
^respond
メソッドを使用して実行されます。
▍ルール
rule
は、その中のパターンがチャットボットに送信されたデータと一致する場合のアクションの呼び出しです。 ルールは、トピックが宣言された後に投稿する必要があります。
u: BURGER (I want ari-burger) Okay, your order is hamburger
ルールの説明には通常、タイプ(
u:
、ラベル(たとえば、
BURGER
。これはオプションですが、コードのデバッグや自己文書化に役立ちます)、テンプレート(括弧内のすべて)が含まれます。 ルールの説明は、コードの読みやすさを向上させるために、いくつかの行に分割することもできます。 CSはラインフィードに注意を払いません;ルールの終わりの兆候は、新しいルールまたはトピックの発表です。 ルールでは、コマンドを使用して別のトピックに切り替えることができます-関数
^respond
:
u: BURGER (I want ari-burger) ^respond(~answers)
この場合、入力は
^respond
関数に渡されたトピックのルールによって処理されます。 このアプローチにより、CSスクリプトを部分に分割したり、たとえば、フレーズの応答のフォーマットを別々のトピックに入れたりすることができます。
▍変数とメモリ処理
CSの変数は、ユーザー入力を保存するためのメカニズムです。 情報の短期保存用の変数があります-それらの値はテンプレートを終了した後に消去され、ユーザー変数は消去されるまで値を保存する長期情報保存です。 短期変数を使用するルールコードの例を次に示します。
u: ORDER (I want _) $order = _0 Okay, your order is $order
アンダースコアは短期変数を示します(たとえば、すべての単語に対応する
_*2
、または2つの単語に対応する
_*2
の構成を使用して、そのような変数で覚えておく必要のある単語の数を指定できます)。 その結果、上記のコードが機能する場合、「I want」の後に入力されたデータの単語が短期メモリに保存されます。 それにアクセスするために、2行目は
_0
構造を使用します。 テンプレートには、必要なだけ多くの類似変数を含めることができます(通常は20以下ですが、通常はこれで十分です)が、それらからの値の取得は、アンダースコアと一致内のシーケンス番号で構成される名前を使用して行われますテンプレート。 この例では、
$order —
_0
保存されているものを書き込むユーザー変数
_0
。
▍テンプレート
このパターンは、ボットと通信するときにユーザーが入力する内容に現れると予想される順序と一連の単語を記述するために使用されます。 私の意見では、CSテンプレートの非常に注目すべき機能は、テンプレートを記述するときに、各単語のすべての形式を追加する必要がないことです。 システムにはメカニズムのサポートが組み込まれています。その間、単語の1つの形式のみを含むテンプレートでは、この単語のすべての形式を見つけることができます。
たとえば、動詞「be」を使用します。 それをテンプレートに追加すると、この動詞がすべての形式に含まれます:am、is、are、was、were、be ただし、補助動詞(will、have、do)を含むデータを処理するには、それらを明示的に追加する必要があります。CSは、個々の単語に対してのみ異なるフォームを自動的に処理できます。 この目的のために、テンプレートの別の可能性を使用することをお勧めします-中括弧内のオプションの単語:
u: BURGER (I {will} take _burger)
名詞と代名詞にも同じことが言えます-単数形の主格の場合は単語を追加します。その後、CSはその内部メカニズムを使用して、単語のすべてのバリアントの一致を検索します。 テンプレートでは、テンプレートの特定の位置にある単語のセットを使用して、特定の表現に対応するフレーズのオプションを展開することもできます。 この例を拡張して、次を追加できます。
u: BURGER (I {will} [want need take] [_burger hamburger potato ice-cream]) $order = _0 Okay, your order is $order
このルールは、指定された単語の組み合わせ(たとえば、「ハンバーガーが欲しい」、「ジャガイモを食べる」、「アイスクリームが必要」)で、ユーザーが入力したすべての提案に対応します。 メモ化のもう1つの重要な機能は、公式のCSドキュメントでは説明していませんが、短期変数がセットでどのように機能するかです(ドキュメントでこのトピックを見つけた場合はお知らせください)。 実際、短期記憶の同様の状況では、セットからの一致する単語はすべて
_0
変数に格納されます。 いずれの場合でも、ユーザー変数
$order
は、一致が見つかったときに特定の値を受け取ります。
さらに、記号
<
および
>
を使用して、ユーザーが入力したフレーズの開始と終了を制御できます。
u: BURGER (< I {will} [want need take] [_burger hamburger potato ice-cream] >)
実際、テンプレートの内部では、さらに多くの興味深いことができます。 たとえば、いくつかの基準に準拠しているかどうかの値を確認します。 たとえば、特定の範囲内で数値のみに関心がある場合にできることは次のとおりです。
u: OLD_ENOUGH (I be _~number _0>21 _0<120) You are old enough for this. u: TOO_YOUNG (I be _~number _0<21) $missed_age = 21 - _0 You are too young for this, come after $missed_age years.
▍コンセプト
概念とは、単一のキーワード(概念名)に結び付けられた一連の単語または単語の組み合わせです。 概念の発表は、トピックの発表に似ています。 概念に関連する単語のリストは、角括弧で示されています。
concept: ~food_type [burger potato salad ice-cream]
コンセプトが宣言されると、このようなルールのエイリアスとして使用できます(テンプレートは
~food_type
コンセプトで指定された単語のみに一致するようになります)。
u: BURGER (I want _~food_type) $order = _0 Okay, your order is $order
さらに、いくつかの概念を他の概念に投資して、抽象化のレベルを追加し、1つの親概念に異なる単語セットをグループ化できます。
concept: ~dessert [ice-cream sweets cookie] concept: ~burger [burger hamburger cheeseburger vegeterainburger] concept: ~food_type [~burger ~dessert potato salad]
一致が見つかった単語がどの概念に属しているかを調べる必要がある場合は、
pattern
キーワードを使用できます。 次の例では、
$drink
変数に格納されている値が〜alcoholコンセプトに属しているかどうかがチェックされます。 この目的のために、
pattern
キーワードと
?
if
式で、テスト対象と概念のターゲット値から分離します(CSは
if-else
サポートし
if-else
)。
concept: ~drink_type [~alcohol ~non_alcohol] concept: ~alcohol [rum gean wiskey vodka] concept: ~non_alcohol [cola juice milk water] u: DRINK (^want(_~drink_type)) $drink = _0 if (pattern $drink?~alcohol) { ^respond(~age_checker) } else { Ok, take and drink your $drink . }
ユーザー入力の個々の単語だけでなく、単語の組み合わせでも一致を見つける必要がある場合は、それらを概念に追加したり、引用符で囲んだり、1つのフレーズ内の共有単語間でアンダースコアを使用したりすることもできます(このアプローチは、句読点):
concept: ~vegburger ["vegeterian burger" "vegeterian's burger" vegan_burger vegan_'s_burger]
これらのアプローチは似ていますが、コードを読みやすくするため、引用符を使用することを好みます。
CSのもう1つの興味深い機能は、エンジンレベルで定義された標準概念の可用性です。 これらを使用すると、同じまたは類似の意味を持つ自然言語で最も頻繁に使用されるフレーズおよび個々の単語に対して、すでに準備されたセットを使用できます。 その中には、
~yes
および
~yes
という概念があり、自然言語で肯定的および否定的に解釈できるフレーズが含まれます。 たとえば、コンセプト〜yesには、yes、yeah、ok、ok、ok、sure、of_course、alright、および他の多く(合計183)などの単語とフレーズがあります。 〜noコンセプトには、138の対応する単語とフレーズがあります。 以下は、プロジェクトで作業するときに便利な概念です。
-
~number
との一致を検索するのに役立ちます。
-
~yearnumber
-~yearnumber
値のみを含む~yearnumber
サブセットです。
-
~dateinfo
スラッシュを含むレコードの形式を使用して、テキスト内の日付を検索するのに役立ちます。 たとえば、mm_dd_yyまたはmm_dd_yyyyは、文字列「mm / dd / yy」または「mm / dd / yyyy」として認識されます。
-
~timeword
-この概念を使用する場合、たとえば、「2017年7月1日」および「2017年7月1日」の場合、「2017年7月1日」が返されます。 さらに、この概念には、2番目、昨日、すでになど、時間に関連する膨大な単語のセットが含まれます)。
これは、すべての組み込みの概念に関する情報を見つけることができるCS ドキュメントのセクションです。
何らかの理由で既存の標準的な概念を拡張する必要がある場合、
LIVEDATA_ENGLISH_SUBSTITUTES/interjections.txt
ファイルにエントリを追加できます。
<roger_that> ~yes
その後、ChatScriptエンジンを再起動するだけで、「roger that」というフレーズが〜yesコンセプトに追加され
~yes
。 フレーズの最初と最後の山括弧は、これらの2つの単語のみが一致と見なされ、それ以上は見なされないことを意味します。
さらに、既存の概念は別の方法で拡張できます
MORE
キーワードを使用して、新しい値を追加できます。
concept: ~food [burger potato] concept: ~food MORE [ice-cream]
▍マクロ
コードを確実に再利用するために、CSにはマクロがあります。これは、プログラマが開発した関数で、出力データを生成したり、テンプレートで使用したりするために呼び出されます。 私たちのプロジェクトではJSONを使用しているため、出力はJSラッパークラスに渡すことができるように適切にフォーマットする必要があります。 この目的のために、JavaScriptで簡単に解析できる文字列を準備することにしました。 システムが何らかの出力を生成するたびに、JSON文字列に変換します。 ただし、CSにはJSONを操作する方法もあります。
outputmacro
を使用してこれらすべてを使用すると、アプリケーションバックエンドAPIの出力をフォーマットする簡単で便利な方法が得られます。
outputmacro: ^formated_in_json(^param_from_rule) { $_result = ^jsoncreate(object) $_result.first_level_param = ^param_from_rule $_result.nested_object = ^jsoncreate(object) ^jsonwrite($_result) }
ルールでマクロを使用することは、上記の標準の
^respond
関数を適用するように見えます。
u: FOOD (I want _~food_type) ^formated_in_json(_0)
パラメーターに応じて出力のさまざまなフォーマット用にマクロを記述することができるため、
patternmacro
を使用して、多くのルールに対して同様の構造を持つテンプレート用にマクロを作成することもできます。
patternmacro: ^want(^appendix) [i we] * [want need take] ^appendi
マクロによって返されるテンプレートの一部は、他の多くのテンプレートで再利用できるため、スクリプトが簡素化されます。
u: FOOD (^want(_~food_type)) If you want _0, you should get \_0 . u: DRINK (^want(_~drink_type)) Ok, take and drink your _0 .
チャットボットスキーム
次の図は、チャットボットで説明した各CSコンストラクトの場所を示しています。
チャットボットスキーム
ご覧のとおり、トピック、概念、マクロはボットの外側のレイヤーで宣言する必要があります。 ルールはトピックにネストされています。 入力ポイントとしての各ルールには、テンプレートと、レスポンダーのようなもの、または現在のテンプレートが呼び出された場合にのみ実行されるルールの本文があります。 トピックの外部で宣言されたテンプレートの概念とマクロは、応答の形成に必要な値を含むデータの短期保存用の変数とともにルール内で使用されます。 同時に、レスポンダーでマクロを呼び出して出力値を処理できます。 レスポンダーが
^respond(~another_topic)
形式のコマンドを呼び出した場合、長期データストレージの変数は、短期変数から他のトピックにデータを転送するために使用されます。 これは、ユーザーに表示されるデータの処理が別のトピックのルールによって処理されることを意味します。
まとめ
今日、ChatScriptの基本について学びました。つまり、このエンジンを使用して独自のボットを開発したい場合は、プロジェクトの計画を開始できます。 この記事の次のパートでは、CS環境、CSプロジェクトのデバッグ、CSとJavaScriptの統合、およびChatScriptを使用してチャットボットを開発する際に発生する可能性のある問題への対処方法について学習します。
親愛なる読者! チャットボットを作成しますか? その場合、使用するツールについて教えてください。