Just $ A sandbox

プログラミングと計算機科学とかわいさ

GAEで(Twitter APIを利用した)簡単webアプリ

webアプリとか書いてみたくなったのでGAEでちょっと何か作って見ることにしました。 と言ってもあまり難しいものを作る技術も時間的余裕も無いので、今回は"Twitterにログインし、与えられた文字列をツイートする"ことだけを行います。

もちろん、OAuth認証を利用しますよ!

準備

GAEの登録の仕方やTwitterのコンシューマーキーの取得方法とかは基本的に割愛します。 今回必要となる登録は大体以下のとおりです。

Downloads - Google App Engine — Google Developersからダウンロードできます。今回はPythonで作ったのでGoogle App Engine SDK for Pythonからダウンロードしました。

  • GAEへの登録・Twittter Applicationの登録

(割愛します)

Google App Engine — Google Developers

Twitter Developers

もちろんなんでも構いませんが個人的にはEclipseをオススメします。PyDevというのを入れるとPythonが使えるようになり、さらにGAEのEclipse用プラグインまで用意されているので非常に開発がしやすいです。詳しくは→ Downloading and Installing the Plugin - Google Plugin for Eclipse — Google Developers

  • 必要なライブラリ

PythonからTwitter APIを叩くことになりますが、Tweepyという素晴らしいライブラリが用意されているので今回はこれを使うことにします。TweepyをPythonにインストールするのではなく、今回はこれをGAEのサーバーにのせる必要があるのでソースファイルを用意してください。私はGithubから貰って来ました。

tweepy/tweepy · GitHub (このリポジトリの、tweepyフォルダ以下のみが必要になります)

また、GAE未経験の方は一応ある程度、GAEについて把握されておいたほうが良いと思います。ありがたいことに、全て日本語のチュートリアルが用意されています→ スタート ガイド: Python - Google App Engine — Google Developers

開発

さて、いよいよ実際に作っていくことにします。 今回作ったものは http://prooving-everyday.appspot.com/ にて動いています。 (何やら怪しげなサイトに見えますがやっていることはOAuth認証→つぶやくということだけです)

今回作ったアプリケーションのフォルダ構成は以下のようになっています。

+ src
  + tweepy          -- さっき取ってきたtweepyフォルダ
  - view            -- 静的ファイル
    - stylesheets
      - index.css
    - index.html
    - posted.html
  - cookie.py       -- cookieをあれこれする
  - setting.py      -- cosumer keyとかsecretを持っておく
  - main.py         -- これが今回のメイン
  - app.yaml        -- 設定ファイル

https://github.com/myuon/prooving-everyday

上でソースファイルを公開しています。

動かすには

実際にこれを動かすには、いくつか必要な設定があります。

  • setting.pyの中にconsumer keyとconsumer secretを記入する。
  • tweepyフォルダの中にtweepyを入れる。

これでおそらく動くようになるはずです。

解説

少しだけ解説をします。

  • viewディレクトリ

ここには静的ファイルが入れてあります。cssは普通のcssファイルで、index.html, posted.htmlはどちらもこのファイルを参照しています。また、htmlファイルはDjangoと呼ばれるPython用のwebアプリケーションフレームワークに基づいて書かれています。例えばindex.htmlの中で、

<a href="{{ url }}">{{ url_linktext }}</a> -- このファイルを表示する際に渡された変数url, url_linktextの文字列を展開する
    
{% if login %}
    hogehoge... -- 変数loginが真ならばhogehogeを実行
{% endif %}

のような表記が見られます。これはDjango特有のもので、詳しくはDjango documentation | Django documentation | Djangoなどを読めば分かる気がします(丸投げ){{GAE SDKは内部にDjangoを含んでいるため、GAE SDKが導入されていればDjangoは別に導入しなくても今回のプログラムは動きます}}。

  • main.py

基本的な構造は以下のとおりです。

class MainPage(webapp.RequestHandler):
    def get(self):
        # MainPageを表示するときの処理
        hogehoge ...

        # 以下の部分で、HTMLファイルに変数を渡す
        self.response.out.write(template.render(path, {'url': url,
                                                       'url_linktext': url_linktext,
                                                       'login': url == u'logout',
                                                       'message': message
                                                       }))

def main():
    application = webapp.WSGIApplication([
                                          # "~~~/"というURLがコールされたらMainPageに飛ばす
                                          ('/', MainPage),
                                          hogehoge ...
                                          ],debug=True)
    run_wsgi_app(application)

やっていることは非常に単純なので説明はいらないと思います。基本的には、

      +---------------------------+
      | トップページ(MainPage)を表示  |
      +---------------------------+
        ↓          ↑ 反映
+-------------------+    +-----------------------------+
| ログインリンクを踏む   | →  | 情報をcookieに書きこんでおく  |
+-------------------+    +-----------------------------+   
   ↓       ↑(コールバック)
+----------------------+
| TwitterからOAuthで認証 |
+----------------------+

のようにしています。ログインしたかどうかの情報をページをまたいで保持していなくてはならないので、それをcookieでブラウザに保存します。

cookieの保存、読み込み、削除を行います。

  • setting.py

Twitter applicationで手に入れたコンシューマーキーやシークレットはここに書いておきます。

書き方はGAEのドキュメントを参照してください。

まとめ

非常に簡単ですがこれだけでTwitterのアカウント認証を行い、フォームに入力された文字列を受け取ってツイートすることが可能になります。 今回はしませんでしたが、TLを表示することももちろん可能なので簡易webクライアントもすぐに作れるようになると思います。 tweepyとDjangoは本当に便利ですね!

参考

※GAE, OAuth, Tweepyで検索を掛けるとそれなりにいくつかのサイトがヒットしますが、どうやらかつてgoogle developer centerがcookieを読み書きするためのpythonコードを公開していたようで(simple_cookieというのがそれ(?))、それとmemcacheを組み合わせて動かしているコードをいくつか見かけました。そしてどうやらsimple_cookieの公式配布場所が移転or閉鎖してしまったようで手に入らなかったため、今回は自作のcookie.pyを利用することにしました。

3.pythonで対話型AI制作[モジュール化]

前回以降の部分で最初に目標として設定していた、最低限の機能を備えた自律学習型AIの中核はほぼ完成しました。

しかしまだコードが読みにくいので*1、モジュール化してみます。
という訳でモジュール化されたコードがコチラ!→https://github.com/myuon/AI/blob/master/Alice_AI.py
(解説はしていませんでしたが、実はモジュール化する前にちょっと単語の選び方を工夫するアルゴリズムを導入しています。気になる方は上のコードのjudgesentense函数をチェックして下さい)

モジュール化されたAliceさんもちゃんと動いてくれていましたので一安心です。*2

さて、今回はコレだけではありません。
モジュール化したのはなぜかというと、これを使ってAIをもうひとつ生成し、互いに喋らせてみようという思惑があるからです!

やってみましょう。モジュール化されているので簡単ですね。

ai2ai.py: https://github.com/myuon/AI/blob/master/ai2ai.py

#! /usr/bin/python
#-*- coding:utf-8 -*-

import random
import sys
import re

import Alice_AI

if __name__ == "__main__":
    AI = []
    AI.append(Alice_AI.AliceEngine("save/alice_2.txt",u"Alice"))
    AI.append(Alice_AI.AliceEngine("save/bob_2.txt",u"Bob"))

    input = u""
    while True:
        input = AI[0].mainloop(input)
        input = AI[1].mainloop(input)

もちろん名前はAliceさんとBobさんですよ!
この人達に文章を与えて喋ってもらったのがコチラ

alice_bob.txt: https://github.com/myuon/AI/blob/master/log/alice_bob.txt

// Alice:吾輩は猫である
// Bob:こころ


Aliceさんがログインしました。
Bobさんがログインしました。
Alice:我は何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している
Bob:でも辺鄙へんぴな方角にあった
Alice:でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している
Bob:だけは保証します奥さんらしい人を常に先生と呼んでいた
Alice:へんぴな方角へ棄てられたのである
Bob:事である
Alice:が迷亭めいていがこの体を捕つかまえて煮にて食うという話である
Bob:体たいが動いていた
Alice:いていた事だけは記憶している
Bob:迷亭めいていがこの体たいが動いていた
Alice:めいていがこの体を捕つかまえて煮にて食うという話である
Bob:捕つらまえようという決心をしてそのまま下宿へ一切いっさいを脱ぬぎ棄すてる事である
Alice:捕つかまえて煮にて食うという話である
Bob:体たいが動いていた
(一部抜粋)


( ゚д゚)ポカーン

日本語でおk\(^o^)/

とっ、とにかく、AIとAIで互いに喋らせる、なんてことも出来るようになりましたよ!
まだまだ完成度が低いとはいえ夢が膨らみますね!

*1:折角、保守性の高いPythonなんて高級言語を用いているのにこれはあまりよくないことです!

*2:そういえばAIの名前をアルファベットにしたのは後でもう一人登場させるという理由からです

2.pythonで対話型AI制作[形態素解析]

形態素解析とは

形態素解析とはなんでしょうか?ちょっと調べてみましょう。

形態素解析(けいたいそかいせき、Morphological Analysis)とは、コンピュータ等の計算機を用いた自然言語処理の基礎技術のひとつ。かな漢字変換等にも応用されている。

対象言語の文法の知識(文法のルールの集まり)や辞書(品詞等の情報付きの単語リスト)を情報源として用い、自然言語で書かれた文を形態素(Morpheme, おおまかにいえば、言語で意味を持つ最小単位)の列に分割し、それぞれの品詞を判別する作業を指す。
(from Wikipwdia:形態素解析 - Wikipedia)

というわけで、要は品詞分解をさせましょう、ということです。ですが、品詞分解を日本語文法に則って行うためには日本語の単語を覚えさせなくてはいけません。
これは私の個人的な意見なのですが、いろいろAIに教えて自然にしゃべれるようにするよりも、何も教えていないところからできる限りいろいろ自分で学べるようになってほしいので、今回は辞書(単語リスト)を与えることはしないでおきましょう。

形態素解析させると?

以下の文章を例に挙げます。
「今日の天気は晴れです。明日は雨かもしれません。」
これを、文字の種類によって形態素解析にかけるとこうなります。
今日/の/天気/は/晴/れです/。/明日/は/雨/かもしれません/。
つまりカタカナ、ひらがな、漢字、句読点などが切り替わるところで別の形態素(擬似的な品詞のようなものです)に切り替わるように解析することにします。

あとはこれを、前回のマルコフ連鎖にかけてやって、
明日→は→晴→れです→。
明日→は→雨→かもしれません→。
のように文章を構成します。単純なn-gramマルコフ連鎖とは違い、前後の形態素の組は自然なものになるのでかなりマシになると思われます。

ソース

実際に上のようにして実装したソースは以下にあります。ご覧ください。
AI2.py/github

実行例

#「私の名前はアリーチェです」のみを初期文章として与え、話しかけてみた場合の会話ログ

アリーチェ:いらっしゃいませ〜。メッセージをどうぞ〜
あなた:こんばんわ〜
アリーチェ:の名前はアリーチェです
あなた:あなたの名前の話でしょうか?
アリーチェ:あなたの名前はアリーチェです
あなた:いいえ、私はみょんです、。みょんみょんと呼んでくださいなのです!
アリーチェ:いいえ、私の名前はアリーチェです
あなた:あ、はい、そうですね。すみませんです。
アリーチェ:。こんばんわあなたの名前はアリーチェです
あなた:いいえ!私の名前はみょんです!
アリーチェ:!あ、私の名前はアリーチェです
あなた:はい、そうですね。知ってますよ〜
アリーチェ:、私の名前はアリーチェです
あなた:いい加減話を変えませんかw今日も雨でしたね。
アリーチェ:変えませんか今日も雨でしたね
あなた:はい、でも昨日はもっと降ってましたね?
アリーチェ:?いいえ、私の名前はアリーチェです
あなた:名前の話はもう結構です。分かりましたから天気の話をしましょうよ。
アリーチェ:。こんばんわあなたの名前はアリーチェです
あなた:いいえ!私の名前を忘れましたか?
アリーチェ:忘れましたか
あなた:訊いているのは私の方ですよ?
アリーチェ:私の名前はアリーチェです
あなた:はい、そのとおり。早く梅雨が明けるといいですね〜
アリーチェ:そのとおり
あなた:雨は私は嫌いです。明日は晴れて欲しいですね。。
アリーチェ:しいですね
あなた:しいですか?
アリーチェ:しいですか
あなた:まぁ暑いのはしんどいですけどね

これは最初に「私の名前はアリーチェです」しか与えてないので知識はほとんど0のところから会話が始まっているのですが、ちゃんと学習して私の言葉をうまく使って話せるようになっていますね!

前回に比べてかなり状況は改善したと思います。では次回はもう少し単語を選択する精度を上げる、ということについて考えてみましょう♪