siriproxyを使ってみよう

siriproxyに言及している記事では最も分かりやすく書かれているこちらの情報は既に古くなってしまっているので気をつけてください。

siriproxyってなんなの?という方は前回の記事を読んでください。
あなたのSiriを僕のSiriと分かつものは何もない。Siriproxyがなければ - nekovaの日記

注意事項

  • 基本的にはREADMEを信用してください。
  • rbenvのままやろうとすると面倒なことになるので心を鬼にしてrvmを使ってください。

(僕は心を鬼にすることが出来なかったので、メインではなくサブPCにrvmをインストールしてsiriproxyを動かしています。)

https://github.com/plamoni/SiriProxy

まずはsiriproxyのインストールから
git cloneするほうがメンテナンスが楽かもしれませんが、まずはREADME通りにやります。

$ gem install siriproxy

ディレクトリを作って、.pemファイルを生成するコマンドを打ちます。

$ mkdir ~/.siriproxy
$ siriproxy gencerts

生成された.pemファイルをiPhoneにメール等で送信してください。
添付されたファイルをタップすることでiPhoneに証明書をインストール出来ます

自分のPCのIPアドレスを確認してください

$ ifconfig

XXX.XXX.XXX.XXXには先ほど確認したIPアドレスを入力してください。

$ rvmsudo siriproxy server -d XXX.XXX.XXX.XXX -u nobody

これで、音声の送信先をあなたのPCに設定することが出来ましたが、まだ設定は終わっていません
最後に、iPhonewifiの設定画面を開き、PCと同じネットワークに接続していることを確認してください。
ネットワークの名前をタップすると、DNSというフォームに先ほどのIPアドレスを入力してください。

siriの言語設定を日本語から英語に変更してください。
siriに「test siri proxy」と話しかけるとsiriが返事をしてくれるはずです

あなたのSiriを僕のSiriと分かつものは何もない。Siriproxyがなければ

Siri Proxy from nekova on Vimeo.

Siriに個性は無く、ラボで教わった数少ないパターンでしか、気の利いたフレーズを言うことが出来ません。
さきのフレーズをお手持ちのSiriに話しかけてもらうとわかるのですが、「”なんでも知ってるね”をwebで検索しますか?」という悲しい返事になってしまいます。
そこでSiriproxyを使って、Siriに個性を獲得してもらいましょうというお話です。

Siriproxyって何
SiriproxyはSiriの機能を拡張するためのRubyのライブラリです。
https://github.com/plamoni/SiriProxy

Siriproxyの仕組み
Siriはユーザーからの音声データを受け取るとguzzoni.apple.comにリクエストを送信することであなたとの対話を実現しています。
Siriproxyを使えば、音声の送信先を任意のサーバに設定することが出来るので、Siriがとるべき行動を事前に指定することが可能になります。

Siriproxyでどういう実装をするのか
最初に紹介した返事に必要なのはたった3行

liste_for /Siriはなんでも知ってるね/i do
  say "なんでもは知らないわよ。知ってることだけ。"
end

正規表現やif文を使ってより柔軟に対応させることも出来ます。

さて、言うまでもなくこのような一対一対応の対話は飽きますし、何よりわざわざSiriを使う必要性がありません。
そんなに静的なお喋りがしたいなら、ターミナルでsayコマンドとお喋りすればいい。

$ say "sore, orenimo dekiruyo"


さらに言えば、SiriとSiriproxyには欠点があります。
Siri(iPhone)とSiriproxy(サーバ)は同一のネットワークで繋がれていなければ、カスタマイズしたSiriを使うことはできません。
この欠点はRaspberry piにSiriproxyをインストールすることで軽減され、歩きながら優秀なSiriを呼び出すことも可能にはなりますが、Raspberry piはあまりパワフルではありません。
Raspberry Pi Model B (512MB)本体のみ

最大の欠点は、Siri自身が抱えている問題です。
Siriの音声認識Googleのそれと比べると精度が低いので、音声での入力がうまくいかないことが多いです。
今後Siriがアップデートされたとしても、Siriと対話すること(開発)には苦労するでしょう。

しかし、それでも僕がSiriproxyを使うのには理由があります

ハックの対象が広がる
Siriの行動範囲は手のひらサイズのデバイスの中だけではありません。
いくつかの例を紹介しましょう。
まずは、ガレージのドア

SiriProxy on the Raspberry Pi - YouTube
次に、車のエンジン

Siri - "Start my car" - with my Acura TL. - YouTube
最後に、テレビのチューナー

SiriProxy, Raspberry Pi, Sky+HD Update - YouTube
このように、Siriを使って身の回りのハックが出来るようになるのもSiriproxyのおかげです。


Siriに代わりにやってもらう
ご存知の方も多いとは思いますが、Siriに特定の単語で話しかけた後に「とツイート」と付け足すことで、Twitterに文章を送信してくれます。
つまりSiriのおかげで、Twitterクライアントを起動し、テキスト作成アイコンをタッチし、文字を入力をし、送信をするといった手間を省くことが出来るのです。
ただ、残念なことにあなたのSiriは多くのアプリケーションと仲良しというわけではないので、こういったことが出来るアプリは制限されています。
x時に起こして, 電話をかけて, Facebookに投稿, アプリケーションを起動, リマインダーに登録......といったことは出来ますが、これだけで満足ですか?
Siriに「チェックイン」と話しかけることで、foursquareAPIを叩いてチェックインなんてことが出来れば便利だとは思いませんか?

Siriはとても賢いので、自身が何をするべきかを事前に教えさせすれば、後のことは彼女が全てやってくれます。
彼女にタスクを伝えることはそんなに難しいことではありません。
そう、Siriproxyならね

Float Classの `-' メソッドを上手く再定義出来ない

ginzanomamaさんのブログは更新が多くて勉強になるので好きです。
昨日更新されたrubyの演算子を再定義するとFloatがなんか変 - みんなのちからになりたいという記事が面白かったので僕も試してみました。

class Float
  ['+', '-', '*', '/'].each do |num|
    define_method(num) do |other|
      "SUCCESS"
    end
  end
end


以下僕のデバッグ(pがあると読みづらいので意図的に消しています)

x = 1.0
y = 1.0

x + y
#=> "SUCCESS"

x - y
#=> 0.0

x - y.to_i
#=> "SUCCESS"

あれれ?

x - y.to_s
#=> "SUCCESS"

x - y.class
#=> "SUCCESS"

x - "success"
#=> "SUCCESS"

x - y.to_f
#=> 0.0

小数点同士の引き算の場合のみ、再定義したはずの`-'メソッドが呼び出されないようですね。
ということは、Floatの`-'メソッドはFloatのサブクラスで定義されていたりするんですかね?

Floatの`-'メソッドが再定義出来ない演算子に指定されている可能性も考えましたが......ううむ.......。
帰宅したらもう一度考えてみます

追記
数時間後

円すげえ

円周率百万桁というページから円周率をコピーして、ターミナルに貼付けたんですが、値が大き過ぎて張り付け終わるのに10分弱もかかってしまいました。
もう一度言いますが、100万桁です。

f:id:nekova:20130314055851g:plain

そのままでは読みづらいので、空白や改行を消します。

時間がかかりすぎたことに腹を立てていますね。

円周率ではどの数字が一番多く使われているのかを調べました。
String#scanメソッドで配列にして、Array#lengthで数えます。

一番多かったのは7で、逆に一番少なかったのは6でした(と思います)
と言ってもそれらの誤差は0.08%未満です。

円の凄さを噛み締めたらGistにあげることとかがどうでもよくなってしまったのでコードが一行も残ってないんですが、楽しかったです。

気付いたらruby-2.0.0-p0をインストールしていた

Homebrew+rbenvでRuby 2.0.0-p0インストール - 130単位を読んでいた時に、何気なく

$ rbenv install -l

をしたのですが、2.0.0-p0が見つかりませんでした。
homebrewをupdateしたり、fomulaをupgradeしたり、ruby-buildをインストールし直したりしましたが上手くいかなかったので調べてみると、どうやらruby-buildをgithubからcloneした場合と、homebrewでinstallした場合でアップデートの方法が異なるようです。
僕はgithubからcloneした(みたいですが覚えていない)ので、git pullすることにしました。

$ cd ~/.rbenv
$ git pull
$ cd ~/.rbenv/plugins/ruby-build
$ git pull

これでrbenvに2.0.0-p0が追加されました。
ruby2.0を使うつもりはないんですが、せっかくですしインストールしてみることにしました。

$ RUBY_CONFIGURE_OPTS="--with-readline-dir=`brew --prefix readline` --with-openssl-dir=`brew --prefix openssl`" rbenv install 2.0.0-p0
Homebrew+rbenvでRuby 2.0.0-p0インストール - 130単位

できました!

$ rbenv global 2.0.0-p0
$ rbenv rehash
$ ruby -v


余談
https://twitter.com/nekonikovaaaan/status/308779903174733824

これはまた別のお話なのですが、rbenvでruby 1.9.3-p392をインストールして、

$ rbenv global 1.9.3-p392
$ rbenv rehash

とした後に、バージョンを聞こうとすると

$ ruby -v
$ rbenv: ruby: command not found

となってしまいました。
ただ、これもさきのinstall方法と同じように

$ RUBY_CONFIGURE_OPTS="--with-readline-dir=`brew --prefix readline` --with-openssl-dir=`brew --prefix openssl`" rbenv install 1.9.3-p392

をすると正しくインストールされ、ruby -vも出来るようになりました。

原因が未だに分かりません......。

会話をするようにRSpecを書きたいですね!

$ irb

とすれば会話をするようにRubyのコードを実行できますよね。
RSpecで同じことをしたいならinteractive_rspecを使いましょう。

$ gem install interactive_rspec
$ irspec
irb: warn: can't alias context from irb_context.

irbでailiasを設定していても、irspecでは使えないよ」と忠告してくれています。親切ですね。
早速テスト

irb:001:0> 'ほむほむ'.should == '暁美ほむら'
F

Failures:

  1) 
     Failure/Error: IRB.start_with_context new_extended_example_group
       expected: "暁美ほむら"
            got: "ほむほむ" (using ==)
     # (irb):1:in `<main>'

Finished in 0.00025 seconds
1 example, 1 failure

Failed examples:

rspec ./.rbenv/versions/1.9.3-p327/lib/ruby/gems/1.9.1/gems/interactive_rspec-0.0.2/lib/interactive_rspec.rb:44 # 
=> false

このようにテスト結果を返してくれます。

余談
irb:001:0>と省略して書いていますが実際はもっと長いです

irb(RSpec::Core::ExampleGroup::Nested_1):001:0>

2013年3月に読んだ本

文章の書き方

何度読んでも素晴らしい本です。
この本に対する思いの丈はいずれ文章にしたいと思います。

文章の書き方 (岩波新書)

文章の書き方 (岩波新書)


情熱プログラマ

良い本ですが、まだ早い。
「一番の下手くそであれ」は至言だと思うのですが、僕のレベルだとどこの会社に行っても一番の下手くそなので実践のしようがない。
著者が想定している読者と僕の実力がかけ離れていたのであまり実践的な本ではありませんでしたが、プログラマーとしてのキャリアを2年以上積んだ人が読むと参考になると思います。

情熱プログラマー ソフトウェア開発者の幸せな生き方

情熱プログラマー ソフトウェア開発者の幸せな生き方

インターネット

インターネットの歴史を単に列挙したくだらない本ではなかった点が良かった。
特に、国家や貨幣が作られることになった歴史的背景について考えれば、今後のインターネットをどう作っていかの道しるべとなるのではないかという指摘が素晴らしかった。

インターネット (岩波新書)

インターネット (岩波新書)


半分以上は読み終わっている本

メタプログラミングRuby

僕にはまだ早かったかもしれないけれど、1ページ読むごとに新たな発見があるので頑張って読んでいます。
基礎の本を終えたら挑戦してみると良いかもしれません。たとえ難しくても得られるものは大きいです。

メタプログラミングRuby

メタプログラミングRuby

アイの物語

単に短編SF小説を収録しているのではなく、語り部がそれらを紹介しているところに意味があるのかは最後まで読まないと分からない気がするので早く読み終えたい。
短編の中では、「詩音が来た日」がとても素敵です。

アイの物語

アイの物語


読むと宣言したのに読めていない本

オブジェクト指向入門

オブジェクト指向入門 (ASCII SOFTWARE SCIENCE Programming Paradigm)

オブジェクト指向入門 (ASCII SOFTWARE SCIENCE Programming Paradigm)

日本という方法

ファウンデーション