ELIZA(3)スクリプト ー 応答を作り出す仕掛け

2019/03/19
藤田昭人


間が空いてしまいました。 これも確定申告に忙殺されていたせいです(笑)

さて、クライアント中心療法に関する僕のへっぽこレポートはいかがだったでしょうか? これを書いてみて、僕はクライアント中心療法の要点が次の3つだと理解しました。

  • インタビューでは被験者の内面に焦点を当てる
  • 受容、反復、明確化を用いて信頼を獲得し被験者に内面をより語らせる
  • 語りにより被験者自身の問題解決への気づきを促す

専門家から見れば理解の不足・不十分ではあると思いますが「いわゆる傾聴とはこういうことなのかな?」などと僕はかなり具体的に想像できています。このように要点がまとめられるとELIZA論文に掲載されている対話例について、なおさら驚いてしまいます。ELIZAの被験者が語ったことを思い出すと、最初は「ボーイフレンドに勧められた」から始まったのですが両親のこと、あるいは両親について自分がどのように感じているか?など…見事に彼女の内面に焦点を当てることに成功しているように思えます。正直「あの当時の処理能力の低いコンピュータを使って、このような対話を行うなんて…どういう仕掛けなんだろうか?」と思わず考えちゃいますよね?

ということで…

実際のELIZAのコードを眺めながらその仕掛けを探ってみようというのがこのページのテーマです。

ELIZAのJava版実装を追っかけてみる

と言ったものの…

Weizenbaumの ELIZA 論文ではDOCTORスクリプトの挙動を丁寧に解説しているのですが、肝心のオリジナルのソースコードは(今のところ)見つかっていません。今時の開発環境で動きそうなELIZA実装は?のページでも紹介したように、オリジナルと互換性の高い実装は LISPJava がありますが、ここでは Charles HaydenEliza Test のページの次の文言を信じてJavaの実装を使って追っかけてみることにします。

This rendition of ELIZA is a complete and faithful implementation of the program described by Weizenbaum. The script language has been reformatted for clarity, but is unchanged in its content.

ELIZAのこの版は、Weizenbaumによって記述されたプログラムを忠実かつ完全に再現した実装です。スクリプト言語は明確にするためにフォーマットが変更されていますが、その内容は変わりません。

もっとも、このページには剥き出しの Java ソース(とクラスファイル)が置いてあるだけなので、以降の作業の利便を考えて maven でビルドできる環境を作ってみました。

github.com

macOSの環境であれば、任意のディレクトリで次の手順を実行すれば簡単に ELIZA が実行できます。

$ git clone https://github.com/m04uc513/eliza-java.git
$ cd eliza-java
$ ls
README.md   pom.xml     script      test
bin     run     src
$ mvn package
・・・・
$ bin/ElizaApp script test
>> Hello.
How do you do.  Please state your problem.
>> Men are all alike.
In what way ?
>> They're always bugging us about something or other.
Can you think of a specific example ?
>> Well, my boyfriend made me come here.
Your boyfriend made you come here  ?
>> He says I'm depressed much of the time.
I am sorry to hear that you are depressed.
>> It's true. I am unhappy
Do you think that coming here will help you not to be unhappy ?
>> I need some help, that much seems certain.
What would it mean to you if you got some help  ?
>> Perhaps I could learn to get along with my mother.
Tell me more about your family.
>> My mother takes care of me.
Who else in your family takes care of you  ?
>> My father.
Your father ?
>> You are like my father in some ways.
What resemblence do you see ?
>> You are not very aggressive but I think you don't want me to notice that.
What makes you think I am not very aggressive but you think I don't want you to notice that  ?
>> You don't argue with me.
Why do you think I don't argue with you ?
>> You are afraid of me.
Does it please you to believe I am afraid of you  ?
>> My father is afraid of everybody.
What else comes to mind when you think of your father ?
>> Bullies.
Earlier you said your boyfriend made you come here .
$

bin/ElizaApp は maven でビルドした jar ファイルを使ってCLIベースのELIZAを起動するスクリプトです。 引数の script はELIZAの(Doctor)スクリプト、text はELIZAへの入力を納めたテキストファイルで、Weizenbaumの論文で紹介された実行例の入力が格納されています。

【注】maven の使い方については各種ドキュメントを参考にしてください。

ELIZAとスクリプト

ELIZAは対話相手である人間が直前に入力した文だけを使って返答の文を生成します。 入力文から応答文への書き換えはスクリプトに記述されたルールに従い、概ね次の7つの手順で実行されます。

1. 入力文をスペースで区切られた単語に分割(いわゆる形態素解析)を行う。
2. 入力文に対し一連の事前の文字列置き換えを行う。
3. 入力文の全ての単語を走査しキーワードリストを作成し、以降はキーワード毎に処理を行う。
4. 与えられたキーワードに対し分解パターン(decomposition pattern)をマッチさせ、最初に一致した要素を選択する。
5. 分解パターンに対応する再構成パターン(reassembly pattern)を選択する。
6. 生成された応答文に対し一連の事後の文字列置き換えを行う。
7. 応答文を出力する。

以下ではロジャー派心理療法士(Rogerian psychotherapist)のインタビューを再現する DOCTER を例に ELIZA スクリプトの記法を解説します。このスクリプトで被験者からの入力文から応答文を生成する書き換えルールを定義します。Weizenbaum のオリジナル・フォーマットを Charles Hayden が変更してくれたおかげで、(僕らの世代には)行指向の読みやすいスクリプトになっていますが ELIZA 論文に掲載されている対話例は完全に再現できます。(まぁ、今時の JSON フォーマットの方が可読性やプログラムからの扱いやすさは格段に上ですけども)

タグ initial, final, quit

タグ initial, final, quit は書き換えルールには関係のない起動・終了・停止時の表示メッセージを定義します。 停止時とは入力文に quit が含まれている場合で、ELIZA は被験者から停止が指示されたと解釈します。

initial: How do you do.  Please tell me your problem.
final: Goodbye.  Thank you for talking to me.
quit: bye
quit: goodbye
quit: quit

quit は複数定義することができますが、実際の停止時には ELIZA が任意のメッセージを選びます。

タグ pre, post

タグ pre は生成処理前に入力文に対する置き換えを行う単語を定義します。左側が置き換え前の単語、右側が置き換え後の単語です。

pre: dont don't
pre: cant can't
pre: wont won't
pre: recollect remember
pre: dreamt dreamed
pre: dreams dream
pre: maybe perhaps
pre: how what
pre: when what
pre: certainly yes
pre: machine computer
pre: computers computer
pre: were was
pre: you're you are
pre: i'm i am
pre: same alike

この処理に続く入力文のパターンマッチングが上手く動くように幾つかの単語の書き直しをしているようです。

タグ post は生成処理後に応答文に対する置き換えを行う単語を定義します。左側が置き換え前の単語、右側が置き換え後の単語です。

post: am are
post: your my
post: me you
post: myself yourself
post: yourself myself
post: i you
post: you I
post: my your
post: i'm you are

これは生成した応答文の書き換え、例えば I → you とか my → your といった人称に関わる書き換えを行なっているようです。

タグ synon

タグ synon はシノニムリスト(同義語・類義語リスト)を定義します。このシノニムリストは入力文に対するパターン・マッチングの際に使用します。左端の単語がリスト名で、例えば @family は mother mom father dad sister brother wife children child の全てとマッチさせ、いずれかの単語が一致すると真となります。

synon: belief feel think believe wish
synon: family mother mom father dad sister brother wife children child
synon: desire want need
synon: sad unhappy depressed sick
synon: happy elated glad better
synon: cannot can't
synon: everyone everybody nobody noone
synon: be am is are was

上記の用例を見ていると、同義語・類義語というよりは会話上の概念(例えば want と need をまとめて desire とする)を定義しているようにみえます。

タグ key, decomp, reasmb

ELIZAでの中核的な応答文を生成する処理は key, decomp, reasmb の3つのタグから構成されるルールを実行します。前述の実行手順3、4、5が該当します。 まずタグ key は1つあるいは2つの引数をとります。1つ目の引数はマッチするキーワード、2つ目の引数はランクと呼ばれる優先度を示す数値です。 ランクは数値が大きくなるほど優先度が高くなります。省略された場合は1と仮定されます。 次にタグ decomp に続く文字列はひとまとまりとして入力文全体を分解するパターンを表します。'*' は1つ以上の単語列を意味します。 最後にタグ reasmb に続く文字列はひとまとまりで応答文あるいはそのテンプレートを表します。 スクリプトでは1つの key 行に対して従属する複数の decomp 行が定義でき、さらに decomp 行各々について従属する複数の reasmb 行ができます。

例として入力文が "hello" だった場合に適用されるルールを示します。

key: hello
  decomp: *
    reasmb: How do you do.  Please state your problem.
    reasmb: Hi.  What seems to be your problem ?

この例では分解パターンは任意(なんでもOK)で、このキー(hello)がマッチするたびに、2つの応答文が交互に採用される動作をします。

入力文に含まれる単語が全くマッチしない場合には、次の xnone で定義されているルールが適用されます。

key: xnone
  decomp: *
    reasmb: I'm not sure I understand you fully.
    reasmb: Please go on.
    reasmb: What does that suggest to you ?
    reasmb: Do you feel strongly about discussing such things ?

ここでは4つの応答文が定義されていますが、この場合は4つの応答文が順番に採用される動作をします。

次に入力文の一部を使って応答文を空白を埋める例を見てみましょう。

key: dreamed 4
  decomp: * i dreamed *
    reasmb: Really, (2) ?
    reasmb: Have you ever fantasized (2) while you were awake ?
    reasmb: Have you ever dreamed (2) before ?
    reasmb: goto dream

ここでは " i dreamed " という分解パターンが定義されていますが、入力文の "i dreamed" よりも前の単語列を(1)と、後ろの単語列を(2)として扱います。続く reasmb 行の3つまでは(2)が定義されていますから、入力文の "i dreamed" よりも後ろの単語列が埋められます。4つ目の reasmb 行はルールの省略記法で、goto の後ろの単語が key として扱われます。 この例では次の dream のルールの reasmb 行が応答文として使われることになります。

key: dream 3
  decomp: *
    reasmb: What does that dream suggest to you ?
    reasmb: Do you dream often ?
    reasmb: What persons appear in your dreams ?
    reasmb: Do you believe that dreams have something to do with your problems ?

このように時折、入力文の一部を取り込む、すなわち対話者の発言におうむ返しをすることにより、ELIZAは対話者の話を聴いてる感を演出します。

もうひとつトリックを紹介しておくと、次のような$から始まる分解パターンのルールがあります。

key: my 2
  decomp: $ * my *
    reasmb: Lets discuss further why your (2).
    reasmb: Earlier you said your (2).
    reasmb: But your (2).
    reasmb: Does that have anything to do with the fact that your (2) ?

この場合、reasmb 行で採用された応答文は対話者には返されずに記録されます。 この記録された応答文は、その後の対話で key が見つからない入力文が現れた場合に応答文として返されます。 すなわち、対話者には ELIZA が以前話したトピックに話題を切り替えたような印象を与えることになります。

このように、ELIZA は数々のちょっとした(でも巧みな)トリックを散りばめて、対話者との会話を演出します。それについて Weizenbaum 自身は論文の冒頭で次のように語っています。

It is said that to explain is to explain away. This maxim is nowhere so well fulfilled as in the area of computer programming, especially in what is called heuristic programming and artificial intelligence. For in those realms machines are made to behave in wondrous ways, often sufficient to dazzle even the most experienced observer. But once a particular program is unmasked, once its inner workings are explained in language sufficiently plain to induce understanding, its magic crumbles away; it stands revealed as a mere collection of procedures, each quite comprehensible. The observer says to himself "I could have written that". With that thought he moves the program in question from the shelf marked "intelligent" to that reserved for curios, fit to be discussed only with people less enlightened that he.

説明は釈明することであると言われています。この格言は、コンピュータプログラミングの分野、特にヒューリスティックなプログラミングや人工知能と呼ばれる分野においては、あまり実現されていません。これらの分野では、マシンは驚愕する方法で動作するように作られています。多くの場合、最も経験豊富な観察者でさえも誤魔化されるのに十分です。しかし、いったん特定のプログラムのマスクが外され、十分明白な言葉による説明でその内部の働きが理解を促されると、その魔法は消滅します。それは単なる手順の集まりとして明らかにされており、それぞれ非常にわかりやすいものです。観察者は彼自身に「私にもそれが書けるかもしれない」と呟くのでしょう。その考えから、彼は問題となっているプログラムを「知的」と記された棚から単に珍しいものの棚に移動させることでしょう。

ちょっと皮肉屋とも言える Weizenbaum の口上は彼流の言い回しなんですが、スクリプトエンジンとしての ELIZA でのテクニックは Weizenbaum が仕掛けた魔法の一部でしかないように思います。傾聴を実現するにはスクリプト自体がよくできている必要があります。そのあたりは、やはり DOCTOR そのものを細かく調べてしっかり理解する必要があるのでしょう。

以上