2017年8月から仕事において、AIMLと言う言語でコーディングする機会を頂いたことから少し調べてみました。この言語に触れるのは勿論初めて、名前も初👂、正式名称を和訳すると「人工知能マークアップ/モデリング言語」で、第一印象は格好良い、頭が良さそうな?名前と言ったとこでしょうか。Wikipediaには下記の様に記載されています。

What’s AIML?

https://ja.wikipedia.org/wiki/Artificial_Intelligence_Markup_Language

Artificial Intelligence Markup Language(アーティフィシャル・インテリジェンス・マークアップ・ランゲージ、AIML、エーアイエムエル)とは、自然言語ソフトウェアエージェント構築のためのXMLを応用したマークアップ言語である。AIMLはRichard Walleceと世界的なフリーソフトウェア・コミュニティにより、1995年から2002年にかけて開発された。当初の目的はELIZA(イライザ:初期の素朴な自然言語処理プログラムの1つ)を高度に拡張した”A.L.I.C.E.”(Artificial Linguistic Internet Computer Entity:自然言語処理を行うおしゃべりボットの1つ)と呼ばれるシステム向けであり、・・・(後略)「Wikipediaより抜粋」

仕事では「音声対話アプリケーションのデータ構築・検証」と言うことで、上記Wikipediaにも「XMLを応用したマークアップ言語」と記載されている様に個人的にはXMLの親戚?の様な認識でしたが、独自に拡張した仕様だったこともあり通常より複雑だったかもしれません。音声対話アプリケーションは所謂、チャットボット(Chatbot = Chat × Bot:会話ロボット)のことです。また、最近良く耳にするAI(Artificial Intelligence:人工知能)とは別に「人工無脳」と言う言葉があります。人工知能は頻繁に聞きますが人工無脳は全くと言っていいほど聞きません。人工知能は「人工的な知能」で知的で賢いニュアンスがありますが、人工無脳は「人工的な無能?」でイメージは言わずもがな・・・。そもそも言葉の定義が根本的に異なります。下記サイトの記事に分かり易い解説がありました。

こちら⇨会話できるコンピューターは人工知能なのか? 人工無脳との違いは?

要するに、

会話の文脈までを理解出来る(思考力有り)なら人工知能で、理解出来なければ人工無脳
自己学習出来る(機械学習有り)なら人工知能で、学習出来なければ人工無脳

とのことです。

例えるなら、ドラえもんは人工知能(ネコ型ロボット)で、のび太くんは人間ですが人工無・・・?

では、本題に入ります。

AIML Tutorial

ネット上の情報量が少なく、「AIML」で検索してもほぼ英文の記事でチュートリアル(学習サイト)も全然無いですが、唯一とも言うべきチュートリアルがありました。翻訳してもいいのですが正確に和訳されない箇所が多々あるので、箇所によっては原文のまま解釈した方が良さそうです。また、こちらのサイト、怪しげな広告が表示されていたりアクセス出来なくなることがあります。下のキャプチャを撮った際もしばらくサイトにアクセス出来ず、広告が全て消えていて不自然なスペースだけが残っています。少し問題有りのサイトなのかもしれません。

http://www.w3ii.com/en-US/aiml/default.html


他にもチュートリアルを探したところ中身は上記サイトと同一の様ですが、こちら⇩は特に問題なさそうです。

https://www.tutorialspoint.com/aiml/

Home/Introduction

Homeの頁ではAIMLはArtificial Intelligence Modelling Languageの略とありますが、Introductionの頁ではArtificial Intelligence Markup Languageの略とあり、どちらが正かは謎です。WikipediaではMarkupでした。そして、AIMLの記述において共通して使用される最も基本的なタグが以下4つで、基本的に1つのAIMLファイルは<aiml>〜</aiml>の開始タグと終了タグが1セット、残り3つのタグが1セット以上の構成から成ります。

1.<aiml>〜</aiml>:所謂、開始タグと終了タグです
2.<category>:知識単位を定義したものとありますが、一先ず次の<pattern>タグと<template>タグを1セットにした単位と捉えた方が分かり易いです
3.<pattern>:ユーザー発話を定義します。実際には文言だけでなくID指定も可能で、タグ名と同じ言い方だと抽象的で分かり難い表現になりますが、タグ名の通りユーザー側の発話の"パターン"を定義します
4.<template>:<pattern>タグとは反対にbot(システム側)の応答を、変数設定、ループ処理、条件分岐、再帰処理、・・・など、ベースはマークアップ言語ながらも一般的なプログミング言語の基本構文も利用可能で、これらを含め様々なロジックと共に処理を定義します

基本形

またインデントは半角スペース2、コメントアウトは下記の通りです。

上記4つの基本的なタグをベースとして、他に<star>タグから<condition>タグの様な種類があることが分かります。これらのタグを使うことで一例として次の様な記述が可能になります。

上記処理概要としては、ユーザーがHELLO ALICEと発話するとシステム側がHello User!と応答します。次に<srai>タグを使うことで再帰処理が可能になり、2番目のカテゴリに処理が遷移します。2番目のカテゴリでは<random>タグによってGOODとBADをランダムに選択します。ランダムに選択されたGOODとBADのいずれかは最初のカテゴリのfeelingにセットされます。そして、その後の<condition>タグで条件判定がなされます。ランダムに選択されたGOODとBADの内、GOODならI’m feeling good.BADならI’m not feeling good.の文がHello User!の後に続きます。そして最後に、もう一つの再帰処理によって3番目のカテゴリに遷移してHave a nice day!が応答(表示)されます。<think>タグはシステム側の処理を制御する為に用います。ここで<think>タグが無いと、再帰処理でランダムに選択されたGOODとBADのいずれかが直接Hello User!の後に続いてしまい、Hello User!GOOD(またはBAD)と言うおかしな応答になります。

環境:macOS Sierra v10.12.6

Environment Setup

環境設定です。Step 1で「Set up Java Development Kit (JDK)」とあるのでJDKが必要な模様です。

Step 1 – Set up Java Development Kit (JDK)

ここではMacなので、ターミナルから下記コマンドでJDKを確認します。

Step 2 – Set up Program AB

次に、program-abと言うzipファイルをdownloadします。下記リンク先より最上部の最新バージョンprogram-ab-0.0.4.3.zipをdownloadします。

https://code.google.com/archive/p/program-ab/downloads

First Application

botsディレクトリ配下にtestディレクトリ、testディレクトリ配下にaiml、aimlif、config、sets、mapsディレクトリを作成します。

ソースファイルを用意します。aimlディレクトリにtest.aiml、aimlifディレクトリにtest.aiml.csvを作成します。

プログラム実行前に、program-ab-0.0.4.3/run.shのbot=superの箇所をbot=testに修正します。

プログラムを実行します。

動確します。HELLO ALICEと入力してEnterでHello Userと応答します。また、byeの場合はI have no answer for that.と返ります。

また、Basic Tagsの頁の<pattern>tagの項目にも記載されている様に大文字、小文字は区別しません。

上記では、program-ab-0.0.4.3/run.shのbot=superの箇所をbot=testに修正したことで、1つのカテゴリしかないテスト用のbotで動確しました。プログラム実行ログの31行目でも「Loaded 1 categories in 0.015 sec」とあるように、1つのカテゴリが0.015秒でロードされたことが確認出来ます。では、今度はbot=superの箇所をbot=testに修正しないでデフォルトの状態でプログラム実行してみます。修正はprogram-ab-0.0.4.3/run.shのbot=testの箇所をbot=superに元に戻します。

同様にプログラム実行します。

今度はファイル数が多いこともあり多くのファイルを読み込んでいますが、94行目で「Loaded 4846 categories in 0.459 sec」とあるように、4846ものカテゴリが予め定義されていて0.459秒でロードされたことが確認出来ます。

そして、今度は多くの発話パターンにも対応出来る様になり、幾つか試してみると4行目の応答が怪しいですが、その他は問題無さそうに見受けられます。

次に、本来なら「What’s your name?」と入力すべきとこを、たまたまスペルミスして「What’s yor name?」と入力すると意外なログが表示されました。29行目までで色々と処理が走った後に30行目で「Sraix ‘WHAT+IS+yor+name’ failed」と表示されてます。<sraix>タグを使うと別のbot(別のAIMLファイル)に処理を遷移させることが出来ますが、その結果、他のbot(他のAIMLファイル)でも「What’s yor name?」と言う文字列に対して一致するpatternが存在せずにfailedになったのでしょう。31行目で「他のロボットにも聞いてみたけど彼も分からなかった」と応答しているのがユニークです。そして続けて32〜33行目は、「what is yor nameを調べてみてみるよ」と言ったとこでしょうか。<search>も記憶に無いタグですが<oob>は初見の為に役割は不明です。最後に、今度は正しく「what is your name?」と問うと正常に応答して「I am SUPER.」と返りました。「私はスーパー(ボット)」と言うのもやはりユニークに思います。

以後、個々のTagについて検証していきます。尚、program-ab-0.0.4.3/run.shのbot=superの箇所は再びbot=testに修正しておきます。First Applicationと同様にそれぞれのTagでAIMLファイル、CSVファイルを作成します。

<star> Tag:<pattern>タグ内のワイルドカードを一致させます

また、<star index = “n”/>と記述することでn番目のワイルドカードを指定出来ます。

下記、29行目でLoaded 3 categoriesとなっていますが、現在、testボットには最初に作成したtest.aimlと今、作成したstar.aimlの2つのファイルが存在し、それぞれの1つのカテゴリと2つのカテゴリの計3つのカテゴリがあるからです。そして、同様にAIMLファイルを追加していく(categoryが増える)ことで、ロードされるカテゴリ数も増えていきます。また、star.aimlファイルの14行目と実行結果の38行目からも、n=1の場合は<star index = “n”/>は<star/>と記述可能です。

<srai> Tag:多目的タグで、同一のテンプレートに対して異なるターゲットの定義を可能にする?

翻訳すると上記の様になりますが意味が良く分かりません。また、Symbolic Reduction、Divide and Conquer、Synonyms resolution、Keywords detectionと言う用語と関連付けられるという説明も良く分かりません。一先ずは再帰処理が可能であると言う認識で良いと思われます。呼び方はスライと読んでいますが何かの略かは気になるとこでした。すると、偶然見つけた記事にその正式名称について記述がありました。プログラマー、エンジニア向けのプログラミング関連情報コミュニティサイトで非常に有名なQiita(キータ)にもAIMLの記事を投稿されている方がいました。やはり本当にQiitaは凄いサイトだと思います。因みに、こちら⇩の記事では<srai>タグは継承のようなものと説明してあります。そして、肝心のsraiの正式名称ですが「Stimulus-Response artificial intelligence」とのことです。和訳すると「刺激応答(反応)人工知能」となり、これまた凄い名前です。

今更ながら、AIML(Artificial Intelligence Markup Language)入門

Symbolic Reduction

Symbolic(象徴的な、記号の) Reduction(減少、修正)なのですが、まだ良く意味が分かりません。解説には「パターンを平易にし単純なパターンで文法的に複雑なパターンを削減するのに役立つ」とあります。

では会話例を考察します。

上記の場合は単純に2つのカテゴリを用意するだけで問題ないでしょう。

では、仮に次の様な質問の場合はどうするか?

先ほどの2つのカテゴリに新たに2つカテゴリを追加するか?回答は同じなのに質問の尋ね方が異なるだけで都度、全てのカテゴリを記述するのは非常に手間で非効率です。

ここで<srai>が有用となります。1つカテゴリを追加していますが上記と比べ1つ少ないですし、何はともあれ上記3つ目と4つ目のカテゴリの処理が下記3つ目のカテゴリで代用出来ることで記述が簡潔になります。Who is Albert Einstein?またはWho is Isaac Newton?の場合は、2つのカテゴリのパターンのいずれかに一致して応答が返ります。ここで、Do you know who Albert Einstein is?またはDo you know who Isaac Newton is?の場合は、2つのカテゴリのいずれのパターンにも一致しない為、3つ目のカテゴリに処理が移ります。3つ目ではワイルドカードを使うことで、Do you know who Albert Einstein is?またはDo you know who Isaac Newton is?のどちらもパターンに一致するので21行目の処理が成されます。<star/>は*(ワイルドカード)を指したので、Do you know who Albert Einstein is?の場合は<srai>Who is Albert Einstein?</srai>となり、Who is Albert Einstein?のパターンと同一の処理を行います。なので、イメージとしては同一パターンのカテゴリに遷移することになります。

CSVファイルを用意します。ここで下記CSVには「?」を含めないようにします。理由は謎ですが、例えば「Who is Albert Einstein?」とすると「I have no answer for that.」になってしまいます。2行目も同様で、3行目も「Do you know who * is?」または「<srai>Who is <star/>?</srai>」いずれか、或いは両方に「?」を含めると「I have no answer for that.」となります。

実行結果は下記の通りで<srai>タグの処理も正しく実行されています。46行目の様に「?」はなくても問題ないようです。また余談ですが、48行目の様に「?」だけでは無反応で、入力無しの場合は「I have no answer for that.」となりました。

Divide and Conquer

Divide and Conquer(分割統治)とは、複雑な問題に対して分割して解決する考え方で言葉の起源は古代ローマのようです。プログラミングに限らず全ての物事に通ずる考え方でしょうか。こちらの和訳⇨「完全な返答をする際に副文を再利用するために使用されます。複数のカテゴリの定義を減らすのに役立ちます。」も良く分からないので先に会話例を見ます。

例では、要は単にByeで始まる場合は全てGoodBye!で応答するとのことです。どの様な内容であっても最初にBye(さようなら)で始まるなら一律でGoodBye!としても不自然ではないと言うことでしょう。srai.aimlにカテゴリを追加します。

特に問題ないでしょう。

Synonyms Resolution

似た意味である同義語に対してbotは同様な返答をする必要があります。例えば、「工場」や「産業」と言うキーワードに対して「開発センター」と返答したいとします。この様な場合にも<srai>タグを利用出来ます。

こちらも特に問題はないでしょう。

Keywords Detection

キーワード検出します。特定のキーワードが含まれている場合に一律で同じ応答をしたい場合にも<srai>タグが活用出来ます。会話例だと「学校」と言うキーワードが含まれている場合に全て同一の応答をさせたいとしています。

_(アンダースコア)と*(アスタリスク)のワイルドカードを利用します。文脈に「学校」が含まれていた場合は53行目のカテゴリに全て処理が移ります。まず初めに、単に「学校」と言うキーワードしかない場合は勿論56行目の「School is an important institution in a child’s life.」が応答されます。次に、「I like my school.」の様に「学校」のキーワードの前に任意の文字が1文字以上ある場合は61行目のパターンに一致します。任意の文字がない場合、0の場合は「学校」なので54行目で一致します。「School is 〜」など、後ろに任意の文字が0文字以上ある場合は68行目で一致します。最後に、「I love going to school daily.」の様に前後に文字がある場合が75行目で一致となります。

動作も問題なさそうです。

<random> Tag:ランダムな応答に用います

<li>タグでユーザーへの応答を複数設定可能です。

上記、random.aiml.csvで最後の</li>に「>」を忘れプログラムを実行し、ユーザー入力するとエラーになりました。たまたまのスペルミスなどでこの様なエラーが出ると、これはこれで参考になります。

random.aiml.csvを修正して再度プログラム実行します。Hiと言うユーザー入力に対してちゃんとランダムに応答が返ることが確認出来ます。

<set>、<get> Tags:変数と連携する為に使用されるとありますが、要はsetで値を設定しgetで値を利用します

下記の様な会話例を考えます。

ユーザー入力のパターンで「I am 〜」の場合、〜の箇所をワイルドカードにして7行目でusernameに設定しています。そして、usernameに設定された名前を14行目のgetで取得しています。

usernameに設定された名前は上書きされることも分かります。

<that> Tag:文脈、前後関係に基づいて応答する為に用います

<that>タグで<template>タグ内のシステム応答を指定することで<category>の結び付きが成されます。What about movies?→Do you like comedy movies?の後にYesまたはNoと応答した場合、それぞれのカテゴリは<that>タグで最初のカテゴリと結び付いている為、Nice! I like comedy movies too.またはOk! But I like comedy movies.が返りますが、YesまたはNoで始まる場合は2、3番目のカテゴリの処理は実行されずにI have no answer for that.となります。