〇〇:「資料があるならRAGを作ればいいじゃない。」

はじめに

こんにちは。GMOアドパートナーズ 24年新卒の嘉山です。Slackで社内規程や制度について質問できるRAG(Retrieval Augmented Generation)アプリ「tomoc(トモック)」を、新卒2人で開発しました。本プロジェクトが発足してからというもの、界隈のテック系の記事を眺めていると「RAG」系のテーマが大半を占めており、昨今のRAGの流行り方は尋常じゃありません。(※ 確証バイアス:自分がすでに持っている先入観や仮説を肯定するため、自分にとって都合のよい情報ばかりを集める傾向のこと。)

そこで一度、プロジェクト発足からリリースまでの直近数ヶ月を振り返ってみると、実際に手を動かしてコーディングしていく時間と同じくらい、いやそれ以上に技術選定やシステム構成、UIのデザイン、分析フロー、データの運用方法といった、「設計」の部分に多くの時間を費やしてきたことに気がつきました。そこで、開発の中で得た知見を共有することで、同じような悩みを抱えている方々の手助けになればというささやかな願いの下、本記事を執筆させていただきました。非エンジニアの方々にも読んでいただけるよう多少砕けた表現や解説が混在し、厳密性には欠ける部分もあると思いますが、ご容赦いただけますと幸いです。

本記事の概要

本記事では、社内向けRAGアプリケーション「tomoc」のシステム構成やデータの運用フロー、使用した技術スタックなどを紹介させていただきます。

tomocは、Slack上で社内の規程や制度に関する質問できるAIチャットボットです。これにより、パートナー(社員)は何かわからないことがあった時に、逐一担当の方に連絡することなく必要な情報に素早くアクセスすることができるようになりました。回答させたい社内資料(PDF、スプレッドシート、スライドなど)は、指定したGoogle共有ドライブに追加するだけでOKです。

システムは大きく分けて以下の3つの部分で構成されています。

  1. データ投入部(Data Import):共有ドライブにデータを投入し、データストアを作成する機能
  2. チャット部(User Interface):Slack上で質問や回答、フィードバックを行える機能
  3. 分析部(Analytics):利用ログを収集・可視化し、回答精度の向上や情報不足を検出する機能

また、開発チームと共有ドライブ運用チームで定例ミーティングを実施し、共有ドライブ内の情報の品質向上や不足情報の補完、新規資料の作成計画などを議論しています。

想定読者

  • RAGについてざっくりと知りたい方
  • これからRAGの開発をしようと思っている方
  • RAGのシステム設計で悩んでいる方
  • RAGのデータ運用で悩んでいる方
  • どんなツールやサービスを使っているのか知りたい方

紹介しないこと

  • RAGの理論に関する解説
  • 具体的な実装コード

そもそもRAGって何。

本題に入る前に、RAGについて簡単に解説させていただきます。RAGは、大規模言語モデル(LLM)の強みを活かしつつ、独自に用意したデータストアから情報を検索し、回答を生成する仕組みを指します。簡単に言うと、「AI自身がわからないことがあっても、事前の準備した資料を調べてから回答してくれるシステム」です。

例えば、パブリックに公開されていない社内独自の規程や制度に関する質問をした場合、従来の普通のLLM(例えばChatGPT)ではトレーニング用データに存在しない情報については、正しい回答を生成することはできません。他方、RAGの場合は事前に情報源となるデータを準備し、回答を生成する前にその中から質問に関連する情報を検索します。そしてそこから抽出された情報を元に回答を生成するため、一般公開されていないクローズドな情報に関する質問にも回答できるというのがRAGの大きな特徴です。

RAGの仕組み

RAGの動きは次の5ステップです:

  1. データストアを準備する
    • PDFやスプレッドシートなどの資料を、「チャンク」という「文章を扱いやすいサイズに分割したテキストのまとまり」に分割します。
    • さらにそれを「エンべディング」という「単語や文章をAIが理解できる数値化されたベクトル表現に変換する処理」を行い、データストアに保管します。
    • エンべディング後の「ベクトル」は単語の意味的な類似度に基づいて値が決定されます。
  2. 質問を受け付ける
    • ユーザーからの質問を受け取ります。
  3. 必要な情報を検索する
    • ユーザーからの質問をベクトル化して質問の意味を理解します。
    • その質問に関連する情報をデータストア内のチャンクから類似度を基準に検索します。
  4. 回答を生成する
    • 検索した情報をもとに、LLMが質問に対する回答を生成します。
  5. 回答を返す
    • 最後に生成された回答をアプリ画面を通じてユーザーに返します。

RAGと普通のLLMはどう違うの?

  1. 外部情報の活用
    • RAG: データストアを利用して回答を生成するため、学習時に与えられなかった情報に関しても回答することができます。
    • LLM: トレーニング時点のデータに依存するため、未学習の情報には対応できません。
  2. 専門的・特化型の回答
    • RAG: 専門的なドメインデータを利用しているため、特化型の精度が高くなります。
    • LLM: 一般的な回答には優れていますが、専門性の高い回答では限界があることがあります。
  3. 情報の透明性
    • RAG: 検索元のデータ(チャンク)を根拠として提示できるため、回答の信頼性と透明性が高いです。
    • LLM: モデル内部のブラックボックス的な推論に基づくため、根拠の説明が困難な場合があります。

”ファインチューニング”との違いは?

  1. データの利用方法
    • RAG: 既存のトレーニング済みLLMを利用し、データストアから情報を検索して回答を生成します。モデル自体のパラメータは更新しません。
    • ファインチューニング: 特定のデータを使ってモデルを再トレーニングし、新しい知識を直接モデルに埋め込みます。
  2. 情報の更新頻度
    • RAG: データストアを更新するだけで、新しい情報をリアルタイムで反映可能です。
    • ファインチューニング: 更新には再トレーニングが必要で、新しいデータを利用するまで時間とコストがかかります。
  3. コストと実装の手間
    • RAG: 初期構築においてデータストアの構築が必要になりますが、モデル自体の再トレーニングが不要なため、長期運用のコストを低く抑えられます。
    • ファインチューニング: 再トレーニングのたびに高性能なハードウェア(GPUなど)が必要で、専門知識や時間も要求されます。
  4. 情報の透明性
    • RAG: 参照元データを回答に紐付けて提示可能なため、ユーザーに対する説明責任を果たしやすいです。
    • ファインチューニング: モデル内部の知識に基づいて回答するため、透明性や根拠提示には限界があります。

プロジェクト発足の背景

弊社では連結会社ということもあり、連結会社間の複雑な社内規程や制度の管理が大きな課題となっていました。各連結会社が共通の規程を導入している場合もあれば、独自の規程を持つ場合もあり、この規程の多様性が情報管理の難化をもたらしていました。さらに、今後経営統合も予定されており、さらなる複雑化が予想されています。

これまで、規程や制度に関連する資料は数多く作成され、それらは主にGoogle共有ドライブで管理・運用されてきました。しかし、この運用では「どの会社」の「どの情報」が「どこにあるのか」を正確に把握することが難しく、必要な情報への迅速なアクセスが困難な状況が続いていました。その結果、パートナーは情報を探すのに多くの時間を費やしたり、総務部門への問い合わせが増加したりする問題が発生していました。

そこで、「今まで作った資料をまとめてAIに突っ込んでなんか良い感じに答えてくれるAIとか、欲しくない?」というアイデアから、本プロジェクトが発足しました。

発足時の課題

プロジェクト発足時は具体的な仕様については何も決まっておらず、以下のような課題を検討するところから始まりました。

  • 質問者によって正しい回答が変わる問題:連結会社では、同じ質問内容でも質問者が所属する企業によって適切な回答が異なる場合があります。これに対してどうやってシステムで対応するべきか。
  • ユーザーインターフェース問題:連結パートナーが日常的に使用しているツールと開発コストを考慮すると、質問形式は「検索」か「チャット」か、媒体は「社内ポータルサイト」か「Slack」か。

開発期間とコスト

開発期間

  • 期間:2〜3ヶ月
    • 設計:1〜2ヶ月くらい
      • 技術選定:具体的なクラウドサービスやツールの選定を行いました。
      • アーキテクチャ設計:データ投入機能、UI、ログ収集、スケジューリング、モニタリング、アラート設計など、全体的なアーキテクチャの設計を行いました。
      • Google Cloud Next Tokyo ‘24への参加:最新のRAGに関する技術情報や事例の発表を聴講させていただき、さらに実際に他企業開発担当者の方に質問に伺わせていただきました。
    • 実装期間:1ヶ月くらい
      • プロトタイプの開発:基本的な機能を持つパイロット版アプリを作成し、連結全体リリース前に社内テストを実施しました。
      • 機能拡張とチューニング:社内テスト時のユーザーからのフィードバックをもとに機能追加や精度改善を実施しました。

コスト

  • データ投入
    • 初期費用:約2万円
      • 読み込ませるデータのファイル形式と量に完全に依存します。主にデータのエンベディングにかかる費用です。
      • 弊社の場合、具体的な数値は覚えていませんが数百ファイルはありました。
      • 初っ端からそこそこ良い感じの精度で回答を生成できたのはマジでこのおかげです。
  • インフラコスト
    • 月額費用:4,000〜5,000円
      • Cloud Runの稼働時間やリクエスト数、データの更新頻度やその量など、様々な要因に応じて変動します。
    • コスト削減の工夫:稼働時間外はインスタンス数をゼロにするなど、無駄なコストを削減する設定を行いました。

使用した主なツールと機能

Google Cloud

Agent Builder

  • 概要:自然言語処理を活用し、チャットボットを簡単に作成するツール。
  • 機能:データを分割・ベクトル化してデータストアを構築。
  • メリット:GUIで直感的に構築可能、高度な自然言語理解対応。

Cloud Run

  • 概要:コンテナ化アプリをサーバーレスで実行。
  • 機能:自動スケーリング、コンテナの高速デプロイ。
  • メリット:コスト効率が高く、インフラ管理不要。

BigQuery

  • 概要:大規模データのクエリ分析が可能なデータウェアハウス。
  • 機能:リアルタイム分析、標準SQL対応。
  • メリット:自動スケール、高速クエリ実行。

Google Cloud Storage(GCS)

  • 概要:高可用性と耐久性を持つオブジェクトストレージ。
  • 機能:ストレージクラス選択、バージョニング対応。
  • メリット:他のGoogle Cloudサービスとシームレスな連携

Looker Studio

  • 概要:データの可視化とレポート作成が可能なBIツール。
  • 機能:多様なデータソース接続、インタラクティブなダッシュボード作成。
  • メリット:操作が直感的、基本機能は無料。

Python

Slack Bolt

  • 概要:Slackアプリ開発用フレームワーク。
  • 機能:イベント駆動型処理、対話的UI要素作成。
  • メリット:簡単に実装可能、豊富なドキュメント。

Discovery Engine API

  • 概要:検索技術を活用し、カスタム検索やRAGシステムを構築可能。
  • 機能:質問内容を理解し関連データを検索、LLMで回答生成。
  • メリット:RAGの基本機能をほぼ全て担う。

その他

  • Google ドライブ:チームでのファイル保存・共有。
  • Docker:アプリのコンテナ化による一貫した動作環境。
  • Slack:チーム間の効率的なコミュニケーションツール。

システム構成

前提

  • 社内資料の蓄積:RAGの回答精度は参照する資料の量と質に完全依存します。なので、過去に作成された社内資料が多数存在し、かつ内容に矛盾点や誤りが含まれていないことが重要です。

概要

システムは以下の3つの主要部分で構成されています。

  1. データ投入部:Data Import
  2. チャット部:User Interface
  3. 分析部:Analytics

データ投入部:Data Import

データ投入部は、RAGが検索時に使用する社内資料データをデータストアに取り込む部分です。

資料の格納

  • 共有ドライブへのアップロード:各部署や担当者が、回答に使用したい社内資料を任意のGoogle共有ドライブにアップロードします。
  • 多様なファイル形式の対応:PDF、Word、Excel、PowerPoint、Googleドキュメント、スプレッドシート、スライドなど、さまざまな形式の資料を扱えます。

共有ドライブとGCSバケットの同期

  • 同期の目的:開発着手時点では共有ドライブとAgent Builderのデータストアの連携ができなかったため、共有ドライブの中身を一度Google Cloud Storage(GCS)バケットに同期します。
  • ディレクトリ構造の保持:共有ドライブのフォルダ構成をそのままGCSバケットに反映し、資料の組織化を維持します。
  • 自動同期
    • スケジュール:Cloud Schedulerを使用して、平日午前1時に同期処理を自動実行します。
    • 同期処理:Cloud Run Jobsを利用して、共有ドライブとGCSバケット間の差分を検出し、更新・追加されたファイルのみを同期します。
  • メタデータの付与
    • ファイルURLの保持:共有ドライブ上の各ファイルのURLをGCSバケット内の対応するファイルにメタデータとして付与します。これにより、回答時に参照元のリンクを提供できます。

GCSバケットとデータストアの同期

  • テキストの抽出とチャンク化
    • テキスト抽出:GCSのバケットにアップロードされた資料からテキストデータを抽出します。PDFや画像など、非テキスト形式の場合はOCRを使用します。
    • チャンク化:長文のテキストを適切なサイズに分割し、処理効率と検索精度を向上させます。
  • ベクトル化(エンベディング)
    • エンベディングモデルの使用:Googleが提供するGeminiを使用し、テキストチャンクをベクトル表現に変換します。
    • ベクトルストアへの格納:ベクトル化されたデータをAgent Builderのデータストアに格納し、類似度検索に備えます。

※ これから開発を始める人へ

  • データストアの連携元 
    • 開発着手時:データストアとGoogle共有ドライブを連携できないからGCSバケットを中継させてファイルを同期しました。
    • :直でデータストアはGoogle共有ドライブと連携可能です。
      •  
  • 同期頻度の設定
    • 開発着手時:コスト管理の点で同期処理をCloud Schedulerで定期実行していました。
    • :Agent BuilderのGUI上で設定できます。

チャット部:User Interface

チャット部は、ユーザーが実際にシステムと対話するフロントエンドの部分です。チャット画面は主に「ユーザーの質問」「tomocからの回答」「参照ファイルリンク」「フィードバック機能」に分けることができます。

質問

  • 質問方法
    • ダイレクトメッセージ(DM):ユーザーはtomocに直接メッセージを送信して質問します。
    • チャンネル内メンション:チャンネルでtomocをメンションして質問することも可能です。

回答

  • スレッド内での回答
    • スレッド管理:質問と回答は同じスレッド内でやり取りされ、他の質問と混在しません。
    • 文脈の保持:スレッド内の過去のメッセージをコンテキストとして参照し、文脈を考慮した質問が可能です。

参照ファイル

  • 回答へのリンク添付
    • 参照元の明示:回答に使用した資料の共有ドライブリンクをメッセージ内に添付します。
    • 詳細確認の容易化:ユーザーが回答の根拠を直接確認でき、信頼性を高めます。

フィードバック

  • ユーザー評価の収集
    • Good / Badボタン:簡単な評価を収集し、回答の品質を把握します。
    • 6段階評価:回答の関連性や正確性、情報量などに関するより詳細な満足度を取得し、分析に活用します。

  • 申請・報告
    • 不足情報の報告:ユーザーが回答に満足できなかった場合、追加で学習してほしい情報や修正要望を申請できます。
    • 記名・匿名の選択:ユーザーのプライバシーに配慮し、申請方法を選択可能です。

インフラコストの最適化

  • Cloud Runの設定
    • 稼働時間内:平日9:00〜19:00は最小インスタンス数を1に設定することでコールドスタートを抑制し、ユーザーのリクエストに即応できるようにします。
    • 稼働時間外:稼働時間外は最小インスタンス数を0に設定し、リクエストがあった場合のみインスタンスを起動します。

分析部:Analytics

分析部ではまず、ユーザーとtomocのインタラクション発生時に匿名でその時のログを収集し、BigQueryテーブルに蓄積します。そこからシステムの利用状況や回答の質をモニタリングし、共有ドライブの管理・運用に活用する部分です。

ログの収集

  • インタラクションログの保存(一部抜粋): 
    • 項目:
      • 日時
      • ユーザーID(匿名)
      • 所属企業
      • 質問内容
      • 回答内容
      • 参照情報
      • フィードバック結果
    • 保存先:BigQueryにリアルタイムでデータをストリーミング挿入します。

可視化

  • Looker Studioによるダッシュボード作成
    • モニタリング:インタラクションログに蓄積されたデータからダッシュボードを作成し、システムの状態やユーザーの利用状況を常に把握できます。
主要可視化指標
  • 利用状況
    • リクエスト数
    • 利用者数(DAU)
  • フィードバック
    • Good / Bad評価
    • 6段階評価
  • 回答の質
    • 情報充足度カテゴリの割合(下記参照)
情報充足度評価
  • 目的:Google共有ドライブの情報不足が原因で適切な回答を提供できなかったケースを検出し、今後、不足情報の補完、及び新規資料作成する上での洞察を得ます。
  • LLMによる自動評価
    • 評価プロセス
      • 入力:「質問」、「回答」、「参照情報(チャンク)」をLLMに入力します。
      • 出力:与えられた入力から情報充足度の評価とその理由、不足情報と追加の提案を出力します。
    • 評価項目
      • 情報充足度カテゴリ:ログを「十分」「やや十分」「やや不十分」「不十分」に分類します
      • カテゴリ選定理由:情報充足度カテゴリの評価結果の理由を示します。
      • 不足している情報の特定:欠けている情報を具体的に指摘します。
      • 追加すべき内容の提案:今後どのような情報を追加すべきかを提案します。
  • 実際の例
    • 入力 
      • 質問:「宮崎オフィスの印刷機の使用方法を教えて欲しいです」
      • 回答:「この度は、tomocにご質問いただき、誠にありがとうございます。宮崎オフィスの印刷設定についてご質問いただきましたが、ご提供いただいた資料からは、宮崎オフィスの具体的な印刷設定に関する情報は確認できませんでした。申し訳ございませんが、お答えすることができません。提供いただいた資料からは… 」
      • 参照情報:※ 具体的なチャンクの内容は社外秘
    • 出力
      • 情報充足度カテゴリ:不十分
      • カテゴリ選定理由:宮崎オフィスの印刷機に関する情報がデータストアに存在しないため。
      • 不足情報:宮崎オフィスで使用している印刷機の種類、設定方法、利用手順など。
      • 追加すべき内容:宮崎オフィスの印刷機の操作マニュアルや設定ガイドを共有ドライブに追加する。

開発の工夫点

  • データ投入部
    • 課題:共有ドライブ内の古い情報は読み込ませたくないけど削除もしたくない!
    • 方法:「old」フォルダ配下のファイルは同期をスキップさせるような設計にしました。
    • 結果:古い情報は共有ドライブに残したままで、RAGの回答には反映されません。
  • チャット部
    • 課題:質問者の所属企業によって適切な回答が変わっちゃう!
    • 方法
      •  まず質問者のSlackワークスペースIDをリクエストから自動抽出します。
      • ワークスペースIDから所属企業を推定し、質問文に企業情報も含めてRAGに送信します。
    • 結果:回答を質問者の所属企業によって適応的に対応させることができます。

共有ドライブ運用フロー

繰り返しにはなりますが、RAGは共有ドライブ内の資料を情報源として回答を生成するので、回答精度は共有ドライブ内の資料の内容に依存します。そのため、共有ドライブ内の資料の管理・運用も重要なポイントの一つです。

申請・報告の収集と対応

  1. ユーザーからの申請フォーム
    • フィードバック機能の活用:ユーザーは回答に対して追加情報のリクエストや、誤った回答の報告を行うことができます。ユーザーは記名・匿名を選択できます。
  2. 自動通知とタスク管理
    • Slack通知:申請があると、開発チームや共有ドライブ管理チーム、関連部門の担当者が属する通知用チャンネルに自動で通知されます。
    • タスク管理システムとの連携:申請内容はタスク管理用のGoogleスプレッドシートに自動登録され、進捗状況を一元管理します。
  3. 対応フロー
    1. 申請・報告: ユーザーが情報追加や誤回答の報告を送信します。
    2. 対応依頼:共有ドライブ管理チームが申請内容に応じて適切な部署や担当者をアサインします。
    3. 対応処理:担当者は資料の追加・更新を行い、タスク管理用シートのチェックボックスを記入します。(チェックボックスにチェックがされたら自動で共有ドライブ管理チームに通知が送信されます。)
    4. 完了通知:対応完了の確認ができたら、申請者であるユーザーに完了の通知をします(記名の場合のみ)。

定例ミーティング

  • 開催頻度:隔週
  • 参加者:tomoc開発チーム、共有ドライブ管理チーム
  • 議題
    • 利用状況とフィードバックの共有:ダッシュボードをもとに、システムの利用状況やユーザーからのフィードバックを共有します。
    • 情報不足の特定と対策:情報充足度評価で「不十分」「やや不十分」とされたケースを分析し、必要な資料の追加や更新を計画します。
    • 運用ルールの見直し:共有ドライブのフォルダ構成やアクセス権限、資料の命名規則など、運用面での改善点を議論します。
    • 今後の機能拡張:ユーザーからの要望や技術動向を踏まえ、システムの機能拡張や改善策を検討します。

おわりに

今回、新卒2人で社内向けのRAGアプリ「tomoc」を開発し、使用したツールや機能、そして全体的なシステム構成について紹介しました。RAGの開発では、技術的な実装だけでなく、データの運用方法や社内の情報管理体制との調整など、多くの課題に直面し、すこぶる良い経験をさせていただいたなあと感じました。

また、tomocアプリ利用者数はじわじわと伸び続けており、リリースから3週間ほど経過した記事執筆時点で社内全体の10%を超えました。その中で快い評価の声をいただくこともあり、それが非常にやってよかったなと感じる場面でもありました。ただ、tomocが欲しい情報を正しく回答してくれるのは、事実として社内の多くの方が作成してきた資料の質が高いことが理由です。この場をお借りしてお礼を申し上げたいと思います。ありがとうございました。今後も更なるユーザビリティの改善に取り組んでいきたいと思います。

本記事が、僅かでもRAGシステムの設計やデータの運用方法で悩んでいる方々の一助を担うことができましたら本望です。最後までお読みいただき、ありがとうございました。

付記

弊社GMOアドパートナーズ株式会社の公式noteにて、本開発における裏話等が記載されたインタビュー記事も公開されておりますので、もしご興味をお持ちいただけましたら何卒。

※ Google Cloud は、 Google LLC の商標です。