登壇者の自己紹介

岸本将志氏:基本的には、「ChatGPT」を使って、新しいサービスを作りますという話をしようと思っています。

内容としては、自己紹介とChatGPTを使ったサービスの概要と、どう実現しているかという話と、プロンプトを改善したという話と、システムの構成の話と、最後に今後の展望を話せればと思っています。

自己紹介です。株式会社DROBEの岸本と申します。主に、機械学習を用いたサービスの開発や、サービスの周辺のインフラなどをやっていて、いわゆる機械学習を専門としてやっている感じです。経歴としては、(スライドを示して)以下の感じです。

「DROBE」のサービスとは?

最初に、「DROBE」のサービスの流れを説明させてもらって、どういうデータが溜まっているかを説明したいと思います。

まず、ユーザーにアンケートに答えてもらいます。70問なのでけっこう多いのですが、そのアンケートの結果で、私たちはユーザーの好みを把握します。

(スライドを示して)AIとスタイリストがいて、ユーザーに対して商品を選んで、自宅へアイテムを届けます。ユーザーは自宅でそれを試着して、自分が気に入ったものだけを買って、それ以外を返品するというサービスになっています。

この時に、気に入った理由と気に入らなかった理由をフィードバックするという構造になっています。

さらに、商品が届く時には1枚の紙が入っています。ここに、届いたアイテムのコーディネートの例と、そのコーディネートのポイントを解説したものが書かれていて、自然言語によってコーディネートを解説するデータが蓄積されています。私たちは、これをスタイリングカルテと呼んでいます。

ここまでをちょっとまとめると、私たちが持っている主なデータは、ユーザーのプロフィールのデータと、アイテムのデータと、コーディネートのデータと、コーディネートのポイントをまとめた自然言語のデータです。

深くは説明しなかったのですが、ユーザーは任意で、スタイリングの要望を私たちに伝えることができます。例えば、「結婚式に着ていける服をお願いします」みたいにスタイリングの要望を伝えることもできます。

ChatGPTとStreamlitを使って1日で開発

実際にChatGPTを使ってサービスを開発しました。

どういうサービスか見てもらうと……サンプル例で「女子会のコーディネートを教えて」と入力をします。実際にAPIに聞いているので少し時間かかりますが……あっ、来ましたね。こんなふうに、「女子会にぴったりなコーディネートです」という文言と、DROBEにおけるコーディネートのアイテムが提示されます。こんな感じです。

自然言語で検索可能です。ChatGPTを使っているので、コンテキストや対話型の探索が可能となっています。

早くサービスを作りたかったので、どのデータを使うのがいいかを考えた上で、スタイリングカルテを使ったらできそうというので、「Streamlit」で1日で作りました。

こんなふうに検索窓で要望を伝えて検索すると、ChatGPTの回答とDROBEのコーディネートの解説をしてくれます。社内で共有したところ、けっこうポジティブな反応が得られたので、実際に作っていこうという流れになりました。

どうやって実現しているかというと、2段階あります。前準備として、私たちが持っているスタイリングカルテを取得してきて、OpenAIの「Embedding API」でカルテをベクトル化し、それをベクトル検索DBに保存するという流れでやっています。

実際のサービスにおいては、ユーザーが質問すると、OpenAIの「Chat Completion API」で回答を生成し、Embedding APIで回答をベクトル化し、ベクトル検索DBで、最近傍探索を行って、一番近いカルテに対するアイテムデータを取得してきて、回答とアイテムを実際に提示するという流れになっています。

問題その1 回答の文章とスタイリングカルテの雰囲気がまったく異なっていた

プロンプトについて、どのような工夫をしていたかという話をこれからします。基本的に、ハイパラメーターをデフォルトで使っています。最初は本当に単純なプロンプトを試していました。

systemのロールには、「あなたはファッションに詳しい親切なスタイリストです。テーマを与えたら、それに沿ったコーディネートを生成してください」という感じのプロンプトを与えて、userのロールには、実際にユーザーが入力した自然言語のテキストを与えるという感じのことをしました。

この時、回答の文章の雰囲気が、私たちが持っているスタイリングカルテとまったく異なっていて、Embeddingの類似度がうまく計算できないという問題がありました。また、出力の形式がけっこう不安定で、箇条書きが入ってきたり、文章が入ってきたり、コーディネートが複数生成されたりする問題がありました。

これに対しては、簡単な改善をしています。1つはFew-shotですね。ユーザーが実際に要望していた任意のリクエストと、それに対するスタイルのポイントにおいて、複数入力して、最後に本当のユーザーの入力を与えるようにしました。

もう1つは明確な指示です。私たちのサービスは女性向けのサービスなので、女性向けであることと、スタイリングカルテは文章なので、箇条書きではなく文章で与えてほしいということと、3行以内で回答してほしいということを与えています。

問題その2 回答のコーディネートのポイントと具体例なアイテムが完全には一致しない

ここまでで、だいたい一致はしてきたのですが、また1つ問題が出てきました。回答のコーディネートのポイントと、実際に私たちが提示しているアイテムが完全には一致しないという問題がありました。

例えば「今の季節の通勤服を教えて」という質問をした時に、「ベージュのテーパードパンツがいい」とChatGPTが回答します。それは正解です。でも、「白のシャツを合わせる」という文章が出ていたとしても、コーディネートとして水色の写真を返していたり、ベージュのパンプスがいいのに、黒を返しているという問題が起こりました。

これを解決するために、アイテムのメタ情報から、再度ChatGPTに投げて、コーディネートのポイントを再生成するという発想をしました。

このパンツの場合、カテゴリはパンツで、色はベージュで、素材がなんとか、柄がなんとか、シルエットがなんとかというメタ情報を私たちは持っているので、それぞれの情報を使って、アイテムのメタを取得した後に、こういった情報からOpenAIにもう1度投げて、コーディネートのポイントを再度返してもらうようにしました。

このコーディネートのポイントとアイテムをさらにユーザーに返すという構造にしています。

プロンプトにおける工夫

実際にどういうプロンプトかというと、こんな感じです。先にuserのロールを説明すると、itemsというキーをJSONで叩いています。itemsというキーに、実際のコーディネートのアイテムの色とかカテゴリとか、メタ情報を与えていて、リクエストというキーにuserの入力を与えています。

systemのロールに、入力が以下の形式、itemsとrequestの形式はJSONで与えられますと伝えていて、返答もJSONで返してほしいと伝えています。

さらに下の文章は、この後説明しようと思いますが、どういう工夫をしたかをまとめると、アイテムのメタ情報だけではなく、ユーザーの入力もJSONとして与えました。

というのも、itemsのメタ情報だけだと簡素なコーディネートの例だけを返してしまい、ユーザーに対して無機質な感じを与えてしまいます。そこにrequestというキーで実際のリクエストを与えると、「女子会にぴったりなコーディネートを提案します」という文言を書いてくれて、けっこういい感じな説明をしている感じですね。

先にプロンプトを言うと、「itemsのキーのアイテムだけを使って説明文を作ってください」という指令もしています。こうしないと、この例だと、シルバーのカーディガンを使って説明を作ることが実際あったので、その対策のためにこういうことをしています。一般的な、Hallucination対策だと思います。

あと、出力もJSONで生成するようにしました。実際はJSONじゃなくてもいいのですが、JSONじゃないと、グリーンやニットや柄など、itemsのメタ情報を全部使ってごちゃごちゃな回答をする感じがありました。JSONだとポイントを絞った回答が得られる傾向にあるので、こうしました。

これはサービスを作った後になるのですが、(スライドを示して)有名なコースを見たところ、ここに書かれているポイントを押さえていたので、それはよかったなと思いました。あとは、基礎を押さえていくことがけっこう大事だということがあらためてわかりました。

最後に少し、システム構成についてお話しします。あまり時間がないので、ある程度簡略化をしますが、バックエンドはAWSの「App Runner」で動かしていて、フロントエンドはNext.jsと「Vercel」で動かしている構成になっています。

現状の課題と今後の展望

今後の展望ですが、現状の課題として、「誰が言ったか」を考慮していないんですね。20代の人にも50代の人にも同じアイテムが提示されるという問題が1個あります。

あと、細かい要望が汲み取れず、1度出たアイテムに対して、(ユーザーが)「パンツだけもうちょっと暗い色がいい」と要望することはできません。スタイリングカルテとのEmbeddingの類似度だけで評価したので、全体的な傾向は取れますが、細かな要望が取れないようになっています。

展望としては、LLMと自分たちの検索エンジンとレコメンドエンジンを協調させるということを考えています。

具体的には、まずLLMでメタ情報を獲得してきて、検索エンジンでアイテムを検索して、レコメンドエンジンでパーソナライズする、みたいなことを考えています。

これを実際に作っていくために、開発環境をけっこう構築しています。これは具体的な例ですが、GPTを呼ぶバックエンドがあって、レコメンドエンジンが「PyTorch」で、検索エンジンが「Elasticsearch」なのですが、このレコメンドエンジンとElasticsearchが本番と同じようなデータを持っていて、GPTと協調するロジックがGoで書かれています。

これにより、エンジニアがプロンプトの改良だったり、協調動作のロジックだったりを書けばいいだけで、実際にフロントエンドの画面で確認できるような環境を構築しています。

画面は簡素な感じですが、こんな画面を作っています。例えば、「初夏の結婚式に着ていける服を教えて」みたいに入力すると……ちょっと調子が良くないかもしれないですね、すみません(笑)。

実際これで協調動作ができて、返ってきたメタ情報からElasticsearchの検索クエリを構築して、アイテムを検索して、それからレコメンドエンジンでランキングみたいな感じのロジックです。今はいったんここまでできている感じです。

以上です、ありがとうございました。

(会場拍手)