寿司AIガリオ開発秘話

この記事は、Tech KAYAC Advent Calendar 2018 の19日目の記事になります。

こんにちは!面白法人カヤックでサーバーサイドエンジニアをしている遠藤@ENZEN0129)と申します。

今回は最近弊社で開発した、IBM Cloudの最新技術を大いに無駄遣いしたガリオの開発秘話をお話して、読者の皆様にIBM CloudやWatsonを使って、どのようにAIを開発するかをお伝えできればと思います。

gario-ibm-watson.com

ガリオとは

f:id:ririn-eva0129:20181217181748j:plain

ガリオとは江戸っ子の寿司職人。寿司を徹底的に極めんとして創られたAIです。 髪の毛がコメツブだったりハチマキがエビだったりリーゼントがガリだったり様々な特徴があります。弊社のデザイナーにデザインしていただきました。

f:id:ririn-eva0129:20181217174040g:plain

「ガリオ」のシステムアーキテクチャ

ガリオのシステムアーキテクチャはこのようになっています。

f:id:ririn-eva0129:20181217174303j:plain

またガリオを支える各種技術については「ガリオを支えるIBM Cloudの各サービスのご紹介」をご覧ください。

ガリオでのIBM Cloudの活用

基本的な会話を実現するにあたって意識したこと

f:id:ririn-eva0129:20181217175411j:plain

ガリオの会話機能を実現するためにIBM CloudWatson Assistantを利用しています。

ここでは会話を実現するコツをご紹介します。
Watson Assistantでチャットボットの会話を実現するにあたって大切なことが3つあります。

1. 会話フローを設計する。

当たり前のように思えるかもしれませんが、会話を設計することがもっとも重要です。
会話フロー図を作成し、会話一覧を表でまとめてシナリオを作成してから作業にとりかかるのがキモです。

ガリオはほとんどの会話が一問一答形式ですが、一問一答でどれだけ自然な会話が実現できるかという点にこだわり、一部の会話だけ連続性を持たせるような設計にしました。

例えば「心握り寿司」「創作寿司」についてはユーザーのインプットを保持して、次の回答を動的に変更しているので、連続性のある会話が体験できます。

※「心握り寿司」「創作寿司」の詳細はメニューの「ガリオの職人技」をご参照ください。

2. インテントとエンティティを切り分ける設計

Watson AssistantにはIntentEntityという概念があります。Intentとはユーザーの意図を汲み取るもの、Entityは名詞やキーワードとお考えいただくとわかりやすいと思います。

Intentにはできるだけ名詞やキーワードを含まないようにすることが大切だと考えています。

例えば「お寿司が好き」というインテントを作成し、次のイメージのように定義したとしましょう。

f:id:ririn-eva0129:20181217174757j:plain

この「お寿司が好き」Intentと似た〇〇が好きのようなIntentが増えてしまうと解答精度が落ちてしまう恐れがあります。

f:id:ririn-eva0129:20181217174809j:plain

以下の例では、「お茶が好き」が「お寿司が好き」と認識されています

f:id:ririn-eva0129:20181217174813j:plain

そこで上のイメージのような例を、次のように設計することで解答精度が向上します。

Entityは名詞にあたる部分を以下のように定義します。※Entityには目的語を設定するのがベターです。

f:id:ririn-eva0129:20181217174830j:plain

Intentは「好き」と定義し以下のような意図を汲み取れるようにします。その上でtry itで同じ内容を再実行します。

f:id:ririn-eva0129:20181217174845j:plain

以下の例では、先程の「お茶が好き」がEntityの「お茶」とIntentの「好き」と判定されています。

f:id:ririn-eva0129:20181217174852j:plain

このようにIntentEntityの役割をしっかり分けることでより精度の高いチャットボットを構築することができます。

3. contextを有効活用する

Watson AssistantにおけるContext(コンテキスト)とは、ノードをまたがって状態を保持する領域のようなものとお考えください。

ユーザーが入力してくれた名前、日付、その他様々な情報をその後の会話でも保持しておきたい場合にContextを駆使することで連続した会話や気の利いたレスポンスをすることができます。

その他Tips

  • Watson Assistantで定義した内容はJSONで構成されていて、ファイル出力することが可能なので、Gitなどのバージョン管理ツールでしっかり管理すると有事の際に安心です。
  • ダイアログは管理コンソールで上から定義した順番に評価されます。
  • ダイアログを追加したり修正した場合Try itですぐに動作確認できます。
  • Content Catalogを利用することで実装コストが減ります。

最新情報

Watson Assistantはつい最近Version2がリリースされました。 参考記事:Watson Assistant API V1/V2の違い

このV2へのバージョンアップはかなり強力なアップデートなのですが、既存のコンテキストの概念などが変わります。

大きな変更点を参考記事から引用すると以下になるようです。

  • Watson AssistantのAPIにはV1とV2があり、非互換部分があります&機能も違います
  • V2 APIはAssistantとSkillをベースにしたアーキテクチャー変更に対応したものであり、長期的にはV2を使っていくのがよいです
  • V2 APIではAssistantとの会話を司るSessionというオブジェクトを意識する必要があります
  • V2 APIではContextは自動的に維持されるのでV1の時のようにユーザーアプリで毎回送り返す必要はありません
  • V2 APIのContextでユーザー変数を使う場合は"skills"->"main skill"->"user_defined"(←ここまで決めうち1)の下に{"hogevar": "hogevalue"}の形で書く必要があります

現在V1での実装も可能ですが、これからWatsonでチャットボットを実装される方はV2を利用することをおすすめします。

AIチャットボットのテストの話

ガリオのテスト方法について

ガリオのテストは全て人力で行いました。その結果、様々な課題が浮き彫りになったので、経緯をお話ししたいと思います。

ガリオの機能を検証するためにExcelなどの表に会話のシナリオ一覧を記載して、期待する回答が得られるかを一つ一つチェックしたり、同僚に遊んでみてもらってフィードバックをもらったり、ソフトウェアテストを得意とする方々にテストを依頼したりしました。しかしこのテスト方法は非常に非効率的なテスト方法でした。

会話フローの修正が発生しIntentEntityDialogを更新することで、それまで正常に動作していた会話が成立しなくなってしまったり、予想外の返答がきたりと様々な問題が発生しました。

Watson AssistantIntentEntityを更新することで再学習プロセスが走ります。 その際に今までの優先順位などが変わる可能性があり、ダイアログを追加する場所によって、期待していた回答が得られなくなる可能性があります。

したがって修正する度に全体的におかしな点がないか再確認する必要があります。

以上の課題を踏まえて、どのようにテストをすれば効率的な開発ができるかを次に話します。

理想的なテスト方法について

会話フローをまとめた表からテストを実行するように自動化してあげることが良いと考えています。

例えばSpreadSheetやExcelで会話フロー一覧を定義し、その表の列にユーザーインプットが記載されていたら、その文言を読み込んでWatson AssistantmessageAPIをコールするScriptを組んで、結果を表に出力するだけでかなりの工数削減になります。

このようなテストフローを組まなかったことにより、余計な工数をかけてしまったことから、システムの構築より優先すべきことだったかもしれないと思いました。反省点です。

心握り寿司(感情分析)と創作寿司(提案機能)の話

f:id:ririn-eva0129:20181217175511p:plain

企画段階でガリオには感情分析機能を実装したいと考えました。 Watsonで感情分析といったらTone Analyzerですが、今回のシステムではTone Analyzerは使っていません。

Tone Analyzerが日本語未対応だったことや、期待する感情の種類が足りていなかったことなど、様々な理由があり起用することを断念しました。

そのTone Analyzerに変わって感情分析を担っているのがDiscoveryです。

では、どのようにDiscoveryで感情分析を実現したのかを説明します。

感情について調査したところ、感情は大きく分けると8つの基本感情で構成されるようです。そのモデルを参考に以下のように分類するように定義しました。

  • 喜び
  • 信頼
  • 恐れ
  • 驚き
  • 悲しみ
  • 嫌悪
  • 怒り
  • 期待

これらの8つの項目にさらに中項目を定義しました。喜びを例に挙げると以下になります。

  • 喜び
    • 平穏
    • 喜び
    • 恍惚

このように3*8=24種類の感情を分析できるように設計しています。

そして24種類の以下のようなJSONデータを作成してDiscoveryに学習させています。

JSONデータ例

{
  "data_type": "心握り寿司",
  "emotion": "喜び",
  "strength": "恍惚",
  "key_words": [
    "随喜",
    "喜ぶ",
    "よろこぶ",
    .....
  ],
  "response": {
    "text": "そりゃめでてぇな!",
    "image": "https://example.com/images/tai.jpg"
  }
}

上記のJSONの説明としては
emotionが8つの大分類でstrengthが3つの中項目になります。
key_wordsに関連するキーワードを登録します。
responseはユーザーに回答する情報になります。

まずはユーザーの入力をこれらのデータが格納されたDiscoveryに対してNatural Language Queryで参照することにより、key_wordsとマッチングします。マッチングしたJSONに含まれるresponseを返却することでTone Analyzerを代用することにしました。

また同じメカニズムを使って創作寿司も実装しています。

創作寿司のJSONの構成は以下のようになって、心握り寿司と殆ど同じ構成になります。

{
  "data_type": "AI創作寿司",
  "genre": "都道府県",
  "area": "北海道",
  "key_words": [
    "北海道",
    "ほっかいどう",
    "ホッカイドウ",
    "ホッカイドー",
    ...
  ],
  "responses": [
    {
      "cuisine": "ジンギスカン",
      "patterns": [
        {
          "text": "寿司はどうでい?舌の上でとろけるぜ。",
          "image": "url"
        }
      ]
    },
    ...
  ]
}

寿司スキャン(画像解析)の話

f:id:ririn-eva0129:20181217175614p:plain

今回ガリオの開発で最も苦労したのは寿司スキャン機能でした。
Visual Recognitionは少ない画像データでも画像解析できるようになる機能ですが、開発が進むに連れ致命的な問題が発覚しました。

その問題とは白身系のネタがあまりにも似ていることです。

正直、私たち人間でも知識がないと判断できないくらい見た目が似ているネタもあります。

この人間でも難しい画像解析の精度をあげるために、ありとあらゆる手を尽くしました。
どのようにして画像解析の精度を向上させたかを説明いたします。

学習用画像データへのこだわり

最初はプロジェクトの関係者で寿司を食べに。。いえ撮影しました。個室を予約して、寿司を食べずにひたすら写真を撮るとても怪しい団体でした。次々に運び込まれる寿司をただひたすら撮影してました。定員の女性が奇怪な目でこちらを見ていた顔が忘れられません。

そんなこんなで集めた写真をVisual Recognitionに学習させて、いざ検証してみると全然精度がでませんでした。

なぜ精度がでないのか、あらゆる仮説を立てて改善を試みたところ、いくつかわかったことがあります。

精度が上がらなかったと思われる理由 - 寿司の皿の模様や色が多種多様であること - 撮影者によって光の当たり具合がバラバラであったこと - 学習させる画像の枚数が多かったり少なかったりまばらであったこと - 撮影者によって撮り方にムラがあること

これらの問題を解消するためにもう一度寿司パーティ。。いえ撮影しました。
前回の反省を踏まえて、今回は大量の寿司をお持ち帰りしました。
色があるネタは白いお皿に移して撮影し、白身のネタは黒いお皿に移して撮影しました。

すると前回とは比べ物にならないくらい精度が向上しました。
どうやら皿の色や模様、被写体の光の当たり具合がとても重要なように思えます。

しかし精度が上がったとはいえ、まだまだ運用に耐えうる精度ではありませんでした。
ですが、そんな何度も寿司パーティ。。いえ寿司を撮影するわけにはいきません。

今ある学習用データをもとにどのようにすれば、精度を向上できるのか考えに考えました。
そこで閃いたのが2段構えの画像解析です。

2段構えの画像解析とは

2段構えの画像解析とは、その名の通り画像解析を2回して精度を向上させるという発想です。

具体的にいうと、Visual RecognitionにはCustom Classifierというオリジナルの学習モデルを作成する機能があるのですが、これを2階層にすることで精度の向上を測りました。

まずは1つ目の階層で「赤身」「白身」「イカ・タコ」「軍艦」などのざっくりとした分類を判定します。

f:id:ririn-eva0129:20181217180253j:plain

例えば1階層目で「赤身」と判定された場合は、2階層目の「マグロ」「トロ」「サーモン」などを学習したモデルに対して画像解析をします。

f:id:ririn-eva0129:20181217180312j:plain

1階層目で「軍艦」と判定された場合は、2階層目の「いくら」「うに」「ネギトロ」などを学習したモデルに対して画像解析をします。

このようにまずは大分類で大まかにターゲットを絞ってから、特定のネタに特化したモデルに画像解析をかけることによって精度が飛躍的に向上しました。

正直に申し上げるとまだまだ改善の余地もあります。白身に関しては全然精度がまだでていません。
しかしこの短期間で寿司という特徴が似通っている非常に難しい素材に対して、ここまで精度を向上できたのは素晴らしい成果だと思っております。

それとこれは余談なのですが、回転寿司など比較的安価なお寿司の画像を学習素材に使ったので、高級店に行くとほとんど制度が出ないらしいです。

Cloud Internet Serviceの話

Cloud Internet Service(以下CIS)は以下のようなセキュアなインターネットサービスを提供するために必要な様々な機能が1つに集約されたサービスです。

  • Webアプリケーションファイアウォール(WAF)
  • DDoS攻撃からの保護
  • ロードバランシング
  • Health Check
  • グローバルロードバランシング
  • キャッシュ
  • TLS

CISは脅威をブロックし、不正なボットやクローラを制限し、帯域幅とサーバー・リソースを浪費する可能性のある、グローバルに分散したクラウド・サービスです。グローバルHTTP(S)リバース・プロキシーおよび管理対象DNSサービス・プロバイダーとして機能します。

他にもアプリケーションおよびインフラストラクチャの停止によるダウンタイムを回避するために、Webサービスおよびアプリケーションの信頼性を向上させるのに役立ちます。たとえば、グローバルロードバランシングでは、Webサービスとアプリケーションを複数の地域に展開できます。

CISは、グローバル・ロード・バランシングが使用可能になっているときに、お客様の要求を最も近い地域に経路指定します。
いずれかの領域に障害が発生した場合、その要求は最も近い次の場所にルーティングされるため、お客様はダウンタイムの影響を受けません。
WebサイトまたはAPIに障害が発生した場合、CISから自動的に通知が送信され、復元時に通知されます。

これらの素晴らしい機能をとても少ない手順で設定できるCISは、とても強力なサービスです。

Watsonの魅力

今回の開発にあたって思ったWatsonの魅力をご紹介します。

WatsonはAIと言っても複雑な知識は全く不要でAPIを呼び出すだけで結果を得ることができます。
短期間かつ少ないデータでAIを構築できることが最大の魅力と言って過言ではないでしょう。

他にもIBM CloudやWatsonはPaaSやAPIとして利用できるのも魅力的でした。 基本的なWebの知識さえさればすぐに利用できるので、比較的に学習コストが少なく簡単にサービスに導入することができます。

すでにWatsonの様々な導入事例があります。 なかでもコールセンターや自動チャットでの活用が多いようですね。

時間と検証を重ねれば、コールセンターのような複雑な業務でもAIが活かせるにも ガリオのようなプロジェクトでもWatsonを利用することで自由度の高いAIを利用したサービスを素早く開発することが可能です。

また今回利用したVisual Recognitionは少ない画像でそこそこの精度が出る画像解析ができました。今回は寿司という非常に似たものが多い素材を解析するため、カスタムモデルを何度も作成し直したり素材を再撮影したりなど紆余曲折ありましたが、特徴があるものは数枚学習させればそこそこ精度が出るということもコスト面でもとても魅力的です。

そのため費用面でも非常に低コストで運用が可能です。特にメイン機能であるWatson Assistantの利用料金に関しては運用開始して1週間で¥2,000もコストがかかっていないことがわかりました。

そしてガリオを通して一番印象的だったのはWatsonを利用することでAIを超短期間で構築できたことです。開発から完成まではなんと実質2ヶ月です。開発者の人数もリードエンジニア1名とサポートエンジニア1名という非常に少ない体制で制作しました。

さらに学習コストが少ないことも印象的でした。後述しますが、参考記事を読みながら実装すれば誰でもAIチャットボットをつくることが可能です。

AIと聞くとすごく難しそうだったり専門知識が必要そうに感じてしまいますが、Watsonは難しい知識は不要です。
Watsonを利用してAIチャットボットを作る上で必要なものはやってみる勇気だけです。

そしてIBM Cloudはほとんどのサービスや機能を無料で利用できます。(※制限や制約はあります)

ガリオを支えるIBM Cloudの各サービスのご紹介

Watson Assistantとは

Watson Assistant はチャットボット等、ユーザーとコンピューターが自然言語で対話可能なアプリケーションを簡単に開発するためのサービスです。
機械学習の適用により、ユーザーからの自然言語での入力を理解し、適切な応答を返すことができます。
開発者はシンプルで洗練された統合開発ツールを用いることで、対話の流れを直感的な操作でつくることができます。
また、さまざまな業務に特化した事前定義済みのコンテンツを活用することで、より迅速なアプリケーション開発することが可能です。

参考リンク

Discoveryとは

大量のデータを検索するとともに、データからパターンや傾向を読み取り、適切な意思決定を支援します。
主な機能として、文書取込機能、エンリッチ機能、クエリ機能の3つがあります。
また、Watson Knowledge Studioとの連携により特定の業界や企業特有の言葉や言い回しについても教え込み、より賢く業務を支援することが可能です。

参考リンク

Visual Recognitionとは

Visual RecognitionはWatsonの画像認識機能です。
すぐに使えるようにWatsonが既に学習をしており、画像・映像フレームに写った複数のものや、情景を分析・認識することができます。
また、機械学習によりWatsonに独自の学習をさせることもできます。
すでに、自社製品の認識・分類や、製造ラインにおける欠陥検出といった多種多様な業務で、高い精度の画像認識を少ない画像枚数による短時間の機械学習で実現しています。
さらに、日本語・英語を含む多数の言語で認識結果を返すことができます。

参考リンク

Cloud Foundryとは

Cloud Foundryはアプリを簡単に開発、デプロイ、および拡張することができます。各種プログラミング言語のSDKが用意されているので様々なアプリケーションに対応することができます。

参考リンク

Cloudantとは

Cloudantはデータが必要とされる場所にデータを配置してくれる管理不要の NoSQL データベース・サービスです。オフラインでもオンラインでもデータへのアクセスすることができます。

参考リンク

Cloud Internet Servicesとは

Cloud Internet Services は、Cloudflare の 150 以上の Global Points of Presence (PoP) を使用して、インターネットに接続されているアプリケーション、Web サイト、およびサービスに対して、信頼性、パフォーマンス、およびセキュリティーを提供します。
これには、ドメイン・ネーム・サービス (DNS)、グローバル・ロード・バランサー (GLB: Global Load Balancer)、Distributed Denial of Service (DDoS) 対策、Web アプリケーション・ファイアウォール (WAF: Web Application Firewall)、Transport Layer Security (TLS) およびキャッシングが含まれています。

※詳しくは後述

Auto Scaleの話

Auto-Scaling for IBM Cloud サービスを使用すると、アプリケーションのコンピュート容量を自動的に増減できます。
定義する自動スケーリング・ポリシーに基づいて、アプリケーション・インスタンスの数が動的に調整されます。

IBM CloudやWatsonを学習する上で参考になる記事一覧

参考にさせていただいた記事も多数あります。著者の皆様ありがとうございます。

おわりに

いかがでしょう。いろいろなAIとしての機能を無駄遣いした、ガリオですが思ったより簡単そうじゃなかったですか?

ガリオで実現している機能は、ありとあらゆるビジネスやサービスで応用が可能です。

まずはIBM Cloudのライトアカウント(無料アカウント)で技術検証してみるのはいかがでしょうか。 AIサービスを試して見るだけなら、ライトアカウントで十分すぎるくらいになんでもできます。

しかも無料期間なども設けられていないのでかなりオススメです。

ガリオを実装することでIBM Cloudの様々なサービスを利用することができました。

なかでもWatsonは非常に簡単に自由度の高いAIを構築できるので、みるみる成果が得られて、開発者として本当に楽しかったです。

今回は以上になります。

明日はの飛鷹さんがカヤック独自の職能? リエゾンについてを語ります。