この記事は CyberAgent Developers Advent Calendar 2023 14日目の記事です。

 

はじめまして。AmebaLIFE事業本部にてバックエンドエンジニアをしている山田(n04ln)と照井(must_muscle)です。

 

Amebaでは、「Ameba家事ラクAI」という生成系AIを使った機能をテスト版として10/11より提供しています。

今日はその裏側をお話しします。

 

Ameba家事ラクAIとは

Azure OpenAIを活用した家事に関する悩みを相談できる対話型AI機能です。

お悩みに合わせたAIキャラクターを選択し、Amebaアプリ内のチャットで家事にまつわる悩みを相談すると、AIキャラクターが日々の暮らしに役立つヒントを提供します。

Ameba家事ラクAIについて

 

Azure OpenAI Serviceについて

Ameba家事ラクAIでは、バックエンドの生成AIとしてAzure OpenAI Serviceを使用しています。

 

類似のサービスやOpenAIと比較し、Azure OpenAI Serviceを選定した理由としては、

  • 社内Slackでのbotなどの生成AIの活用事例があったこと
  • 導入時の調査時点でSLAが99.9%

だったことが挙げられます。

 

また、Azure OpenAI Serviceにはコンテンツフィルタが標準で搭載されており、セキュリティ面でも安全という判断をしました。

 

アーキテクチャについて

AmebaアプリのバックエンドではAWSにて、EC2によるApp向けBFFとEKSを用いたマイクロサービスとしてのアプリケーションの2種類が稼働しています。

 

EC2とEKSでサーバーの環境が別れている理由としては、現在Amebaでは刷新プロジェクトが進行中のため、App向けBFFの置かれている旧環境とEKSで稼働している新環境が両方稼働している状況となっています。環境間の連携のため、gateway serverがgRPC Reflectionを利用して外部からのHTTPリクエストをgRPC(protobuf)へ変換してリクエストを流しています。

 

既存の簡略なアーキテクチャ図
既存の簡略なアーキテクチャ図

 

一般的なChatGPTによるチャットサービスでは、APIの返却方式にSSE(Server-Sent Events)を利用して順次出力されたトークンを返却させ、クライアント側で受信した分を少しずつ表示していくことで高レイテンシな中でもUXを悪くしないように考慮されているサービスが多いかと思います。

実際に、家事ラクのユースケースでもAzure OpenAI Serviceにて平均して10s程度もしくはそれ以上のレイテンシがあります。

 

Ameba家事ラクAIでも、同様にServer-Sent Eventsを用いた実装にする予定でした。しかしその場合、バックエンドでgRPC Reflectionを用いたgRPC(protobuf)とJSONの相互変換を行っている既存のゲートウェイがストリーミングへ未対応だったためその対応をしなくてはいけません。検討した結果、実装工数の兼ね合いから今回はテスト版ということでServer-Sent Eventsを用いた実装は見送っています。

 

Server-Sent Eventsを使わない選択をしたので、当初はサーバーへのリクエストごとにAzure OpenAI Serviceへリクエストをするようにし、アーキテクチャは以下のようになりました。

 

当初の同期的に繋げて実装した際のアーキテクチャ図
当初の同期的に繋げて実装した際のアーキテクチャ図

 

単純なREST APIでの実装になるのですが、この実装ではAmeba家事ラクAIのユースケースとしてメッセージを送信、受信する頻度はかなり高いため、高レイテンシな接続を常に開きっぱなしというのはサーバー側にも負荷がかかってしまいます。実際にサーバー、アプリでの上記アーキテクチャの実装後にAzure OpenAI Serviceを繋げて検証してみたところ、やりとりの往復をする度に前のやりとりもAPIに渡さなければいけないため、チャットをしていくにつれて処理するトークン数の増加により劇的にレイテンシが悪化し、高いサーバー負荷と高レイテンシによってチャットサービスとして非常に使いづらいものへとなってしまいました。

では実際にリリースをするにあたり、どのように負荷を抑えたかというと、

 

実際に今回採用したアーキテクチャ
実際に今回採用したアーキテクチャ

 

上記のように、

  1. メッセージ送信のAPIでは、ユーザーから送信されたメッセージをエンキューのみ行い、応答を返す
  2. 裏に用意したWorkerにてデキューする
  3. 以前の文脈をDBから取得し、Azure OpenAI Serviceにリクエストをする
  4. Azure OpenAI Serviceの結果をDBに保存する
  5. クライアントからのチャットルームの取得にて、結果を返却する

 

このようにすることで、メッセージの受信時にはキューへの格納のみを行うことで即座に返却をし、またワーカーでの処理終了後のAppからのリクエストでチャットの返答を返すようにすることで、低負荷でのサービスの提供を実現しました。

 

最後に

今回はAmeba家事ラクAIの裏側についてまとめました。Ameba家事ラクAIでは既存のアーキテクチャを考慮しキューを用いた非同期的な処理とすることで低負荷で低遅延な処理を行うようにしています。また、UXをさらに考慮するならServer-Sent Eventsでの実装をしたほうが良いと思います。

 

Ameba家事ラクAIはAmebaを利用されている主婦のお悩みをこれからも解決できるよう、今後も機能の追加予定です!どうぞご期待ください。

2020年新卒入社。現在はAmebaLIFE事業本部にてバックエンドエンジニアをしています。好きな食べ物は梅ねりです。
2022年新卒入社のバックエンドエンジニアです。現在はAmebaLIFE事業本部で開発をしています。