CyberACE Tech Blog
🏃

『CARU』で試験的に接客AIエージェントを作った話

に公開

はじめに

CyberACE でチャットコマースサービス「CARU」の開発をしている tfuka と申します。
今回、CARUにてLLMを活用したAIチャットボットを試験的に開発し、顧客への導入まで完了しました。本記事では、その開発プロセスで得られた知見や反省点を共有します。

プロジェクト概要

開発体制

  • 開発期間: 2ヶ月
  • チーム構成: 4名(PdM兼務1名、内定者アルバイト1名を含む)
  • 実質的な開発メンバー: 3名

私は以前社内でLLM勉強会を開催したことがあり、LLMの基礎知識は持っていましたが、エージェント開発の経験はありませんでした。他メンバーもAIチャットやエージェントの開発経験はなく、試行錯誤の連続となりました。

要件定義

本プロジェクトの主な要件は以下の通りです。

  • 顧客のLP(ランディングページ)にポップアップを表示し、AIチャットへ誘導してコンバージョンを獲得する
  • 導入先は特定の1社。PoCとして試験的に開発・導入を行う
    • 今回は1社限定であるが、今後複数社に対応できるようなAIの設計にする
  • AIがユーザーに質問とその選択肢を提示し、ユーザーがそれに回答する形式でチャットが進行する
  • AIはユーザーとの会話の後、最終的に商品を提示する

↓sgswtkyに事前にDifyで作成いただいていた完成イメージ

スケジュール

  • プロトタイピングと効果検証: 1ヶ月
  • 本番実装: 2-3週間
  • QA: 1週間

プロトタイピングフェーズ

初期エージェント構成

要件から、今回開発するエージェントは以下のような挙動が必要そうです。

  • ユーザーとの対話を通じてニーズを引き出す
  • 会話の流れで、適切なタイミングで商品へ誘導する

これらの挙動を実現するため、Difyを用いて以下のようなプロトタイプを作成しました。

概念図

ノード 説明
購入意欲判定 これまでの会話内容をもとに、ユーザーが商品を購入する可能性をLLMがフィーリングで推定します。
質問生成 ユーザーのニーズを引き出すための質問と、その選択肢を生成します。
商品案内 これまでの会話内容をまとめ、ユーザーを商品へ誘導する返答を生成します。

エージェントへの顧客情報の組み込み

メインのチャットエージェントとは別に、顧客・商品のLPを読み込み、エージェントで使用できる形式に変換するための前処理ワークフローも構築しました。
LLMのコンテキストに顧客・商品情報を提供する方法としては、RAGやDBからの動的取得など、様々なアプローチが考えられますが、今回は開発期間とシステムの複雑性を考慮し、シンプルに例ベースで各ノードのプロンプトに直接埋め込んでおく方式を採用しました。

開発中に直面した課題と対策

上記の初期エージェントをもとにプロトタイピングを進める中で、以下のような技術的課題に次々と直面することになりました。

  • AIが顧客情報に関して誤った情報を生成する
  • AIのレスポンスが遅すぎる
  • モデル間の性能差が想像以上に大きい
  • AIがプロンプトの指示を守らない

AIが顧客情報に関して誤った情報を生成する

プロトタイプ開発中、顧客情報に関するハルシネーション(事実と異なる情報の生成)が頻発する課題に直面しました。
単純にプロンプト内で「正確な情報のみを提供すること」と指示するだけでは効果が不十分だったため、以下のようにReflectionパターンを採用することで対応しました。

AIのレスポンスが遅すぎる

Reflectionパターンの導入により品質は向上したものの、ワークフローの直列処理が増加した結果、レスポンスタイムが著しく遅延する問題が発生しました。平均で10秒程度かかるケースもあり、離脱防止を目的としたチャットとしては致命的な遅さでした。

目標設定・方針

暫定的に、レスポンスタイムの目標値を平均5秒以内と設定しました。これでもレスポンスタイムとしては決して速いとは言えませんが、AIチャットという特性上、ユーザーにある程度許容してもらえる範囲と判断しました。
目標達成には約2倍の高速化が必要ですが、その程度であればモデル周りの調整を行うことで達成できそうです。

具体的な対策
  1. より高速なLLMへの変更
    モデル自体の応答速度を重視した選定を行います。GeminiであればFlash, OpenAIであればGPT-4o-miniなどです。
  2. プライベート環境でのLLM利用
    パブリックなAPIエンドポイントではなく、Azure・GCP等のプライベート環境でホストされるLLMを使用することで、高速化を図ります。
    パブリックAPIでは共有リソースを使用するため他のユーザーのリクエストと競合しますが、プライベート環境では専用の計算リソースを確保できるため、より安定して高速なレスポンスが得られそうです。こちらの記事を拝見し、楽観的ではありますがプライベート環境では約2倍の高速化ができると期待しました。

モデル間の性能差が想像以上に大きい

当初、エージェント開発におけるモデル選定の重要性を十分に理解しておらず、LLM部分には暫定的にClaudeを使用していました。しかし、前述の応答速度の課題と料金面での懸念から、別モデルへの変更を試みることにしました。
CARUのインフラはGCP上に構築されていたため、応答速度に優れるGeminiへの移行を検討しました。ところが、モデル変更後、チャットの品質が著しく低下してしまいました。
具体的には、会話のトーンが非常に冷淡になり、またプロンプトで指定した指示を守らないケースが増加しました。
結果として、プロンプトの全面的な見直しとモデルパラメータの再調整が必要となり、後続の本番実装フェーズにおいても品質に不安を抱える状態が長く続きました。この経験から、モデル選定は開発の最初期に行うことが重要だと感じました。

AIがプロンプトの指示を守らない

応答内容が上手く調整できなかったり、JSON形式で応答するよう指示しているはずが上手くJSON出力せずデコードエラーが頻発するなど、AIが期待通りの動作をしない問題にも苦しめられました。

この問題に対しては以下のように対処する方針を決めました。

  • 応答内容が重要な処理(質問生成・商品案内)では、より高度なモデルを用いる
  • 上記以外では高速なモデルを用いる
  • JSON出力に失敗した場合、リトライ

品質管理体制の構築

また、この時期は人手でAIの出力品質を評価していたため、開発メンバーがAIチャットのデグレに気づきにくい状況が発生していました。

この課題への対策として、週1回の品質評価会を定例化し、強制的なデグレチェックを実施する体制を構築しました。今後は評価の自動化を進めたいと考えています。

本番実装フェーズ

モデル変更によりチャットの品質が落ちてしまいましたが、開発期限も迫っているため本番実装フェーズに移行し、並行してモデル選定・AIチャットの調整を行いました。

ワークフロー実装の移行

プロトタイピングフェーズで検証したワークフローを、LangGraphを使用した本番実装へ移行しました。
チームメンバーはLangGraphの使用経験がなかったため、実装着手前に2-3日間の学習期間を確保しました。
LangGraphはDifyと同様にノードベースでワークフローを構築できるため、Difyで作成したワークフローの形をほぼ変えずに移行でき、移行作業自体は特に問題なく完了できました。

システムアーキテクチャ

既存のCARU Webのインフラを活用しつつ、エージェント部分は独立したCloud Runインスタンスとして構築しました。
CARU Webはもともと、顧客ごとにフロントエンドのコードを一部分離して管理していたため、フロントではその仕組みを利用しました。

幸い、CARUのインフラはPulumiで構成管理されていたため、CDN・ロードバランサー・WAFなど、本番環境で必須となる各種インフラ設定を含めて、比較的容易に環境をクローンすることができました。

モデル選定

前述の通り、以下の方針に基づきモデルの選定を行いました。

  • 応答内容が重要な処理(質問生成・商品案内)では、より高度なモデルを用いる
  • 上記以外では高速なモデルを用いる

ノード別の実行時間

選定の結果、各ノードでは以下のモデルを採用し、次のような実行時間となりました。

ノード 使用モデル 平均実行時間
購入意欲判定 openai/gpt-4o-mini 0.70s
質問生成 openai/gpt-4o-mini 2.34s
商品案内 openai/gpt-4o-mini 3.15s
ハルシネーション検出 vertex_ai/gemini-1.5-flash 1.05s
ハルシネーション修正 vertex_ai/gemini-1.5-flash 1.36s

なお、Geminiについては当時すでにgemini-2.5-flashがリリースされていましたが、比較検証を行ったところ、本ワークフローにおいてはgemini-1.5-flashの方が応答速度・出力品質ともに優れているという予想外の結果となったため、1.5-flashを採用しました。

実行フロー別の実行時間

ワークフロー全体としては、以下の実行時間を達成しました。

実行フロー 平均実行時間
質問生成フロー 5.33s
商品案内フロー 3.87s

目標としていた平均5秒以内のレスポンスタイムを、質問生成フローでは超過しているため、まだ追加で対応が必要な状態です。

Azure OpenAI Service の利用

追加の対応として、実際にAzure OpenAI Serviceへ移行した結果、以下のように大幅な速度改善が実現できました。

実行フロー別の改善結果

項目 OpenAI API Azure OpenAI API 改善率
全体平均 6.37s 3.75s 41.1%
質問生成フロー 6.99s 4.25s 39.2%
商品案内フロー 4.91s 2.28s 53.6%
最短時間 4.62s 1.80s 61.0%
最長時間 9.11s 5.50s 39.6%

ノード別の改善結果

ノード OpenAI Azure OpenAI 改善率
購入意欲判定 1.03s 0.55s 46.6%
質問生成 3.52s 1.35s 61.6%
商品案内 3.73s 1.46s 60.9%

この結果により、目標としていた平均5秒以内のレスポンスタイムを達成することができました。

最終調整とリリース

開発期限が迫る中、モデルの再選定に伴うプロンプトの調整を実施し、なんとかギリギリで要件を満たすチャット品質を確保しました。

QAフェーズでは大きな問題は発生せず、無事に顧客への導入を完了することができました。

プロジェクトの振り返り

リリース後の残課題

1. AIチャットの会話内容の幅が限定的

完成したチャットボットの会話の幅が想定より狭く、ビジネスサイドからAIチャット導入の価値について疑問の声が上がりました。
振り返ってみると、要件定義・設計フェーズに改善の余地があったと考えています。例えば、ワークフローとエージェントの違いについて全く触れられずにプロトタイプ開発がなされ、暫定的にワークフロー型のアーキテクチャで実装を進めることになりました。
現状では、「AIでなければ実現できない独自の価値」を提供できているとは言い難い状態です。

2. AIチャットのレスポンスがまだ遅い

顧客導入後、既存の固定シナリオチャットとAIチャットでA/Bテストを実施しました。しかし、AIチャットの方がシナリオ完了率・コンバージョン率ともに低いという結果となりました。
原因を分析した結果、AIのレスポンスタイムが長いことによりチャット離脱率が上昇しているという仮説が出たため、レスポンス速度を向上させるための追加開発を行いました。

具体的には、AIが質問と選択肢を生成した時点で、各選択肢に対する次の応答も並行して生成しておきます。ユーザーが選択肢をタップした瞬間、すでに生成済みの回答を即座に返すことで、体感的なレスポンスタイムをほぼゼロにすることができました。

3. AIの監視体制

LLMの挙動を完全に制御することは困難であるため、本番環境で稼働するAIの出力を継続的にモニタリングし、異常を検知した際にアラートを発出する仕組みが本来は必要です。
ただ今回のプロジェクトでは、1社限定の導入であり、異常応答の影響はある程度コントロールできるため、監視機能の導入は見送りました。
今後は複数社導入に向け、監視体制の構築を検討すべきと考えています。

得られた知見

一方で、全てが手探りの状態から2ヶ月で顧客導入まで完走したことで、次回以降の開発に活かせる実践的な学びを多く得ることができました。

1. AIならではの価値を追求し続ける

要件定義の段階では一応AI活用の意義を定義していましたが、実装を進める中でその価値が曖昧になり、最終的にビジネスサイドから疑問が提起される結果となりました。
開発プロセス全体を通じて、 「この機能は本当にAIでなければ実現できないのか」「既存機能と比較してどのような優位性があるのか」 と問い続けることが重要だと学びました。特に、開発の途中段階で技術的な課題に直面すると、つい実装可能性に意識が向いてしまい、本来の目的を見失いがちになります。
次回以降のプロジェクトでは、定期的に立ち戻って価値を再確認するプロセスを組み込みたいと考えています。

2. モデル選定の重要性

LLMのモデル間差異は想像以上に大きく、コストや性能を考慮したモデル選定は開発の最初期に行うべきだと学びました。途中でのモデル変更は、プロンプトの全面的な見直し、ワークフロー構成の変更、品質評価のやり直しなど、多大な追加工数を発生させます。

3. パフォーマンス要件の重要性

LLMは本質的にレスポンスが遅いため、ユーザー体験を損なわないパフォーマンス設計が極めて重要です。
特にCARUは離脱しそうなユーザーが対象のため、素早くレスポンスを返すことが特に重要なはずでしたが、要件定義段階ではそのことを認識できていませんでした。
そのため、Reflectionパターン等、パフォーマンス的には不利な方法を採用してしまいました。

4. コード品質の重要性

当初は1社限定のPoCという位置づけだったため、コード品質への配慮は最小限に留めていました。しかし開発・運用を経たあと、以下の理由からPoCであってもコード品質の重要性を再認識することになりました。

  • PoCであってもメンテナンス・機能追加の必要性は発生する(AI回答の事前生成)
  • 当初は1社限定であっても、運用開始後、普通に他社展開の話がなされる

今後はPoCであっても本番運用するコードは規約・アーキテクチャを定め、品質と開発速度のバランスを取りたいです。この辺りの考えについては、実践した後にまた記事にしたいと思います。

5. AIの品質保持・デグレチェックの重要性

今回、AIが満たす品質を早期に定義し、定期的にチェックを行う体制を整えることができました。
この体制が無ければAIのデグレに大いに苦しめられていたはずで、品質担保の重要性を再認識しました。

6. 短期間開発の有用性

最後に、メタ的な視点になるのですが、ノウハウが無い状態からスタートして2ヶ月で顧客導入までやり切ることで、「短期間で次に繋がる実践的な知見をたくさん得られた」 という経験ができたのが実は一番の学びだったのではないかと考えています。
PoCとして、短期間で顧客導入まで完走することには大きな価値がありそうです。本当に解決すべきコアな課題が明確になり、実践的な知見を効率的に獲得できると感じました。

おわりに

初めてのAIエージェント開発を2ヶ月で顧客導入まで完走した本プロジェクトは、多くの困難を伴いましたが、それ以上に貴重な学びを得られる機会となりました。

要件定義の課題、モデル選定の失敗、コード品質への認識不足など、様々な問題に直面しましたが、それらは全て次回以降の開発を成功させるための貴重な財産となりました。

特に、短期間で実際にリリースすることの重要性を体感できたことは、今後のプロジェクトにおいても活かしていける大きな学びです。完璧を追求するより、まず形にして学ぶというアプローチの価値を実感しました。

本記事が、同じようにAIエージェント開発を始める方々の参考になれば幸いです。
最後までお読みいただき、ありがとうございました。

CyberACE Tech Blog
CyberACE Tech Blog

Discussion