LoginSignup

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 1 year has passed since last update.

非タスク指向型対話システムを実装してみる

Last updated at Posted at 2022-12-25

はじめに

この記事は、SLP KBIT AdventCalendar2022 25日目の記事です。
いよいよこれで最後の記事ですね。12月があっという間に感じられたのではないでしょうか?
当初はクリスマスなのでいっそネタに振り切ろうかと考えていましたが(没案:クリぼっちの流儀 ~ブッシュ・ド・ノエルを作ろう~)、流石に最終日は技術的な記事が良いのではと思い普通に書きました。

さて、本題に移りますが今回は「Pythonでつくる対話システム」を参考に非タスク指向型対話システムを解説していきます。

非タスク指向型対話システムとは

簡単に言ってしまうと雑談システムのことです。
タスク指向型対話システムは対話によって特定のタスクを遂行する対話システムでした。一方、非タスク指向型対話システムはユーザとシステムが目的無く雑談したりする対話システムです。
一見雑談システムにどんな利点があるかわかりにくいかと思われますが、ユーザとシステムの心理的な距離を縮めて円滑な対話を構築するという利点があります。(興味があったらこういうのも→ 雑談対話システムにおける心理的近接発話の戦略が対話の評価に及ぼす影響 )
今回はこの非タスク指向型対話システムを採用した2種類の対話システム作成方法を紹介します。

ルールベース方式

ルールベース方式とはシステムの返答が事前に人が決めたルールや過去の対話例に従って行われる基本的な手法です。こちらの方式ではAIML(Artificial Intelligence Markup Language)というマークアップ言語がよく用いられています。実際にAIMLでルールを書くと下記のようになります。

aiml.xml
<?xml version="1.0" encoding="UTF-8"?>
<aiml version="1.0.1" encoding="UTF-8">
  <category>
    <pattern>_ おはよう</pattern>
    <template>ユーザ、おはよー</template>
  </category>
  <category>
    <pattern>* 元気 *</pattern>
    <template>元気だよー</template>
  </category>
  <category>
      <pattern>私 の 名前 は * です</pattern>
      <template><set name="username"><star/></set>さんですか,よろしくお願いします.</template>
   </category>
</aiml>

軽く説明すると

  • category:ルールの定義(pattern,templateを含む)
  • pattern:ユーザが話した内容
  • template:システムが話す内容

という風になります。具体的には、ユーザの話した内容がpatternと一致した時にtemplateを返すという事になります。ですが、これでは完全に同じ内容でないとtemplateを返せません。そのため、'_'と'*'を用いて判定に必要な部分だけに注目させます。また、get/setを用いることでユーザの話した内容を記憶しておくこともできます。(他にも色々記法がありますが多いので略します)
実際にTelegramというアプリを用いてこの手法を実装してみた結果が以下のようになります。

aiml_sys.py
import aiml
import MeCab
from telegram_bot import TelegramBot

class AimlSystem:
    def __init__(self):
        self.sessiondic = {}
        # 形態素解析器
        self.tagger = MeCab.Tagger('-Owakati')
        
    def initial_message(self, input):
        sessionId = input['sessionId']
        # AIMLを読み込むためのインスタンスを用意
        kernel = aiml.Kernel()
        # aiml.xmlを読み込む
        kernel.learn("aiml.xml")
        # セッションごとに保存する
        self.sessiondic[sessionId] = kernel

        return {'utt':'はじめまして,雑談を始めましょう', 'end':False}

    def reply(self, input):
        sessionId = input['sessionId']
        utt = input['utt']
        utt = self.tagger.parse(utt)
        # 対応するセッションのkernelを取り出し,respondでマッチするルールを探す
        response = self.sessiondic[sessionId].respond(utt)
        print(sessionId, utt, response)
        return {'utt': response, 'end':False}
        
if __name__ == '__main__':
    system = AimlSystem()
    bot = TelegramBot(system)
    bot.run()

このコードを実行すると以下のようになります。無事に対話できていることが確認できますね!
対話1.jpg

用例ベース方式

ルールベース方式ではルールを一つ一つ自分で定めていきました。これはすごく手間がかかって効率よくないですよね。そこで、用例ベース方式ではクラウドソーシングで人の対話データを収集しておき、その中からユーザの話した内容に適切な返答を検索するという方式です。ここではElasticsearchというものを用いてデータを集めます。

.....としたかったのですがなぜか思うようにデータ収集ができなかったので対話が上手くできませんでした(いっそほかの方法でデータを収集しようかと試行錯誤しましたが躓いています...)
すみませんがここからは冬休み中に原因を追究して解決しておきます。解決したらまた続きを書いておくと思うのでこの記事のことを思い返した時にでもぜひ見てあげてください。
まあイメージ的にはアレクサとかのようなものです。(たぶん...

おわりに

アドベントカレンダーを通して対話システムを実際にいくつか実装することができました。今回は対話システムの基本となる構成について学び、実装を行いましたが、個人的にはもっと自然言語処理と言えるようなモデルに触ってみたり、理論についての理解を深めたいと感じました。(と言いつつ対話システムの概要についてなんとなく理解することができたので今回の実装経験は個人的に大成功と思っております)
皆さんも関心のある分野などがありましたらその分野の概要をつかむ意味もかねて何か作ってみるのも良いと思います。

ではよいお年を!!!

参考文献

・『Pythonで作る対話システム』(オーム社)

0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up