世界崩壊少女『初希アイ』 開発備忘録:その2 GoogleVision解析と形態素解析の実装、他

世界崩壊少女『初希アイ』 開発備忘録:その1 DALLEで投稿文から写真を作ればいいんだ!
1月24日から始めた世界崩壊少女のオープンテスト。 日々のバージョンアップは順調で、このまま稼働は継続できそうなので、ここらで今日までの開発記を書いておきます。おもいつき… 1月19日(日)、基本情報技術の試験勉強をしていた時、プログラミン...

 前回の続きです。

 今週も世界崩壊少女の開発を続けていました。

 前回から一週間ですが、2〜3ヶ月ほどやり続けた疲労感を感じます。年なんでしょうかね。

 

GoogleVisionによる画像解析の実装

 生成される画像の質は上げていける、というやれてる感を掴めたものの、どうしても解決できない問題がありました。

 それは人間の姿やテキストを要素に含めてしまうことです。
 画像は一例です。

  

 世界崩壊少女は主人公である初希アイを除き、全人類が絶滅した世界です。Xに投稿される画像はその世界をスマホで撮影した、というコンセプトです。人の姿はもちろん、テキストが浮かんでいるような、アーティスティックのはいらないんです。

 

GoogleVisionでラベル付けをしてアウトな画像を弾く

 最初に思いついたのが、

  • 画像を解析して要素を取得して、人間の顔やテキストの要素があれば、内部的に判別できるようにする

 という処理でした。それができるツールとして、GoogleVisionを使うことにしました。

 体験利用分の無料クレジット枠があり、その後も毎月1,000ユニットまでは無料(1,000ユニット使用後から使用料発生)。

 デモ版があり、無料で試せるのでやってみてください。

試してみる  |  Cloud Vision API  |  Google Cloud

 生成した画像をこいつに食わせれば、画像に写っている要素をテキストで拾うことができるわけです。

 テキストで拾えれば、コード上で分岐がつくれます(重要)。

 

実際にAPIから使ってみた結果

 まず、画像生成の基になる、投稿予定文を用意します。

メディーバルヨーロッパ風の世界で、みんなが初希アイになった!不思議な世界でこれからどうなる? #X #初希アイ

 こちらはそもそもテキストが不採用ですが、テスト用の文章です。

 ここからまたChatGPTのAPIに投げて、文章内容から写真に撮影できる要素を取得します。柔軟な回答が必要なものはChatGPTが活躍します。概念や感情など、カメラで撮影不可能な単語は無視する指示を含めています。

 そしてChatGPTから返ってきた要素がこちら。

1. Medieval European style world
2. Adventurers
 (1. 中世ヨーロッパ風の世界 2. 冒険者たち)

 この時点でアウトな画像が生成される感じがぷんぷんしますね。

 この取得した要素と、世界観設定を合わせた生成指示を、DALL-E-2に渡して返ってきた画像がこちらです。

 世界崩壊少女の世界には、絶対にない光景ですね。「撮影用の人形が置いてあった!」ならいいですが、いただいた投稿文を根底から改変するような真似を常用したくはありません。

 こういうものが生成された時、これまではただアップされるのを黙ってみているしかなかったのですが、GoogleVisionを使うとこの通り、

ラベル検出結果:
cloak (信頼率: 50.74%) ←マント
テキスト認識結果: []
検出結果: [‘喜び: 1, 悲しみ: 1’, ‘喜び: 1, 悲しみ: 1’]
ランドマーク検出結果: []
ロゴ検出結果: []
画像解析が完了しました。

 顔を検出できました! 表情として渡してくれるようです。(顔が判別できないただの人の姿はラベルで拾えるかどうかなのですが、ここはまだ様子見です)

 ここまでくれば、あとはif文でどうにでもなりますね。

 こうして、顔・テキストを検出した場合は、

  • 画像の生成をやり直す
  • その画像を採用しない 

 の二択の分岐をつくることができたわけです。

 費用の関係で、今は画像を採用しない一択ですが、画像生成の成功率があがっていけば、再生成の実装を基本処理にしたいです。今は作り直しの結果に期待できないです。

 というのも、画像生成はいただいた投稿文を基に生成するのがコンテンツの趣旨なので、前工程のストーリーから生成した投稿文が変わらない限り、撮影対象として取得する要素も変わりません。したがって、生成される画像も大して変わらない、再生成してもあまり意味がない、ということです。

 別途、検討した選択肢として、OpenAIで使用しているDALL-E-2には画像エディット処理があり、指定した範囲に別の画像生成処理を施せます。やろうと思えば、テキストや人間の部分を消したり変えたりできるわけです。

 しかし、その範囲を指定するためのマスク用画像が必要で、これを動的に生成するのが難しいので今回は見送りました。

ChatGPT DALL・Eで画像生成してみよう| Gluegent | サイオステクノロジー株式会社

 

形態素解析処理を組みわせてラベルと照合する

 前述した通り、現在は顔やテキストが検出できた時点で不採用送りですが、内部的には、形態素解析と組み合わせて、投稿文と画像の要素の適合率が判別できるようになっています。

 形態素解析とは文章を単語(形態素)に分割し、それぞれの品詞を解析する処理のことです。

 例えば「私はりんごが好きです」という文章を形態素解析すると、

 

 このようになります。これらがさっきの画像検出のように、テキスト情報として取得できます。

 ここから名詞をスポイルして、GoogleVisonで取得したラベル情報と照合することで、テキスト通りの画像が生成できたかどうかをなんとなく判別できるわけです。ちなみに、形態素解析は英語に特化した「NLTK」を使っています。(LolipopのSSHにはMecabとspaCyが入らなかったです)

 処理自体は組み込めたものの、画像の解析精度がまだ人間の認識レベルになっておらず、現在は確認用に組み込んでいるだけです。

 というのも、どうみてもただの「川」なのに、画像の解析結果では「Water resources」(水資源)だったりするわけです😞。間違っていないけど、単語の一致でTrue/Falseを分けている処理なのでかなり都合が悪い。

 画像とテキストを比較できるサービスは他にもあるので、今後、少しずつ開拓していきます。今気になっているのは「Hugging Face」かな。

 余談ですが、Xにしゅうまい君という、日本語っぽいのにめちゃくちゃな文章をひたすらツイートしているbotアカウントがいます。このしゅうまい君も形態素解析を活用しており、マルコフ関数モデルでバラした言葉を組み立てているわけです。

 

テキストの浮かんでいる画像ばかりつくるようになった!

 ここまで実装できた頃、急にテキストが浮かぶ画像ばかり生成するようになり、そのデバッグに丸一日潰れてしまったことがありました。

 原因は、至極単純なものでした。

promt = f”{以下のTEXTを表現した画像を生成しろ} TEXT: {画像にしてほしい文章}

 このプロンプト指示の「TEXT:」という部分を画像生成の要素として認識していたのです。この記述の仕方をやめてからテキストが浮かんでしまう確率がぐんと下がりました。

 

ストーリーを世界観・キャラクター設定にあった内容にする

 一番苦労するだろうと思っていた画像生成処理のゴールは見えたのですが、このテスト中に、一旦は落ち着いていた投稿文生成の課題が浮き彫りになりました。

 さっきの異世界転生系みたいに、世界観に合わないものは夢だったことにしろ、と指示していたのですが、これの成功率が思っていた以上に低かったのです。

 かといって指示を厳しめにすれば、問題ないテキストまで夢だった扱いにするし、そこまで締めたところで、さして成功率が高くなるわけでもありません。

 

True/Falseを返させてChatGPTの返答から分岐をつくる

 もう一度の指示で生成されたものに期待はできない! と判断し、基準に満たないものは再生成させる処理を組み込むことにしました。

 これは画像生成の処理の方で、撮影できる要素だけを返せていたので、テキスト生成でも、プロンプトとして伝えている世界観とキャラクター設定に矛盾しない場合はTrue、矛盾する場合はFalseを返せという指示を挟んでみることにしたわけです。

 これが思っていた以上にうまくいって、ほぼ確実にTrueかFalseを返してくれるようになりました。if文で拾えます。

 あとはひたすらプロンプトの見直しと処理の流れの検討です。
 こちらが最初の頃の処理の流れです。処理の流れとプロンプトを簡略化しお見せします。

  • Process 1 投稿予定文を読んで、設定から矛盾する記述に対して修正案を出せ。
  • Process 2 修正案を元に投稿文を修正しろ。修正案がなければそのままで良い。
  • Process 3 投稿文を評価し、設定に適合するならTrue しなければFalseを返せ。

 TrueになるまでProcess1〜3をループ。5回やってもダメなら最後のテキストを採用。

 こうして、例えば、「学校で友達を遊んだ!」は「動物と遊んだ!」という風に改変されるまでテキストの改稿を繰り返す処理ができたわけです。大体5回目になる頃にはおかしなところが直っているのですが、それでも成功率は半々といったところ。

 何百回試したかわかりませんが、やっている内に、Process 1の時点で問題ないのに修正案が出されたり、より酷くなっているのに、Process 3の処理でTrueが出たりと、評価のムラが広すぎることが傾向としてみえてきました。

 そこでWEB版のChatGPTに相談し、返ってきた助言を基にプロンプトに新たな指示を追加しました。

  • Process 3 投稿文を分析・評価し、文末に、設定に適合するならTrue しなければFalseを返せ

 なぜTrueだったのか、なぜFalseにしたのか、ChatGPTの判断を確認するようにしたわけです。これが貴重な手がかりとなり、Falseの判断基準が広すぎることがわかりました。

 例えば、りんごを思い浮かべてください。

  • 赤い
  • 丸い
  • へた
  • 美味しい

 このような特徴があります。りんごを指でさして「赤いです」と言っても何も間違っていないので、Trueです。

 ChatGPTも、一緒に渡した世界観・キャラクター設定を読んで、同じような柔軟な判定をしてくれていると思っていたのですが、この賢いバカはFalseを返していたのです。なぜなら、丸くて、へたがあり、美味しい、という要素が含まれていないからです。

 「学校で食料を見つけた!」という文章なら、世界観設定を知っている私たちは、”人類が滅んだ世界の誰もいない廃校のような状態の学校”を想像するでしょう。ChatGPTにも世界観を伝えているのでその判断はできると思っていましたが、実際には「設定によると、全ての経済活動は停止していることになっているので、学校があるのはおかしい」という判断をしていたわけです。

 こうして、せっかく問題ないテキストでも、そんな感じの判定でFalseが返されていました。アスペルガー的には親近感を覚えますが、こいつ使えねぇなぁ、というのが正直なところです。

 ただ、この問題を乗り越えるにあたり、ベストな解決案を出してくれたのはやはりChatGPTでした。

 完全適合ではないけどTrueにできる中間的な判断基準を明記しろ、ということです。

  • Process 3 投稿文を分析・評価し、文末に、設定に適合するならTrue しなければFalseを返せ。やや問題はあっても設定からみて矛盾がないならTrueにしろ。

 こうして成功率が一段あがりましたが、まだまだ合格ラインは出せません。

 何十回、何百回とテストをして、してほしくない判断をしないようにプロンプトを調整します。

 作業の大半は中間評価の具体化になりました。

 他に大きく変わったのは、

  • Process1とProcess3の評価基準を統一化
  • Process1の時点でもTrueなら採用する
  • 文章改稿後に「修正しました」などのシステム的メッセージが含まれている場合は「start over」を返させて、処理を最初からやり直す分岐処理(投稿文が未加工の状態から)
  • 改稿された文章の文字数が多い場合もやり直し。

 ChataGPTはとにかくいちゃもんが大好きで、例えば、設定に矛盾していないのに「初希アイがここでそうするとは考えにくい」「SNSに投稿する文章としては倫理的に問題がある」などと、一つ対処したかと思えば、どうにかしてFalseにしようとしてくるわけです。

 こうして、最初2〜3行だった評価基準が次々と増えていき、最終的にこのテキスト生成処理に関わるプロンプトは1,800文字近くになりました。そこに加えて、およそ3,000文字近くの世界観設定とキャラクター設定を渡しています。

 これだけ大量のテキストを渡しているのに、分析結果がわりとしっかりしているのには驚きです。

 ===== コメント生成処理 開始 =====

— 1回目の処理開始 —

today_event:
 When I entered the old house in the forest, it was filled with many dolls… It was scary, so I immediately ran away.
(訳:森の中の古い家に入ると、たくさんの人形が置かれていた…。怖くなって、すぐに逃げ出した。)

分析と評価:
【分析結果】:
この投稿は、初希アイが森の中の古い家に入ったときに、たくさんの人形があることを伝える内容です。初希アイはその出来事を怖がり、すぐに逃げ出したという状況が記述されています。この内容は、初希アイの好奇心や探検精神、また人形が怖いと感じる10歳の少女としての側面を表しています。しかしながら、この出来事が物語全体と初希アイのキャラクター設定に適合しているかを検討する必要があります。

【評価結果】:
Level 2: True

 こうしてこのテキストは無事にTrue(採用)となり、次工程へと渡されました。

x.com

 

コード全体の見直し

 必要機能の実装ができたあとはコード全体の可読性や補助処理の実装でした。

 例えばモジュール周りは専用の.pyファイルにする、変数の名前の見直し、実行ログの保存処理、テキスト生成と画像生成でファイル分割などなど、システム管理しやすいようにしました。

 一度、関数内に組み込んだ処理を抜き出して再整形するのはほんと無駄で、最初の段階でどこに何の処理を入れるのか決めておくことがいかに大切かを痛感しました。

 

現在

 現在は必要機能に加えて、可読性や補助処理のところまでできる範囲で整えた、という感じです。

 今後はプロンプトの見直しをしながら、本番サービスに向けてセキュリティ面を検討していくつもりです。

 現在はAmazonギフト券プレゼント企画を実施しているのでお気軽にご参加くださいjね。

x.com
世界崩壊少女『初希アイ』ストーリー投稿フォーム
あなたの物語が彼女の運命を左右する!? 世界崩壊少女『初希アイ』ストーリー投稿フォーム

コメント

タイトルとURLをコピーしました