Azureで社内文書から回答可能な生成AIチャットサービスを作った話

はじめに

本記事では、Azure環境で、社内文書から情報を抽出し、ユーザーの質問に対する回答を生成する機能を開発した件についてお話しします。
以前以下の記事でリリース当初の話を記載しているので興味のある方はご覧ください。
Azure OpenAI Serviceで社内版ChatGPTのChatPCAを構築した話

目次

  1. リリースの背景
  2. 結論
  3. 概要の説明
  4. 取り組んだこと
  5. 今後の課題
  6. まとめ
  7. 注釈

リリースの背景

弊社では兼ねてより社内イントラ用のボットサービスが利用されていました。
ただ、こちらはルールベースで読み込ませた定型の資料内容以外のことには回答ができないものとなっていました。
そのため、日々蓄積する社内データに対して柔軟に対応して回答することは現実的に難しい課題点がありました。
そういった中、昨今話題になっているChatGPTを初めとした生成AI技術を活用してこうした課題を解決していきたいニーズがあり、 社内向けチャットサービスであるChatPCA(*1)をリリースしています。

リリース後、全社員6000人近くの方から注目をいただく中運用をしていたのですが、更なる課題点が浮上し、今回リリースするに至った新機能を開発しました。 それが「社内文書検索機能(*2)」になります。

弊社の社内文書は基本的にMicrosoft Sharepointで管理されていまして、

  • どういった文書をどこからどのように探したら良いかが不透明
  • 社内文書を検索して見つけても文書の中から該当箇所を探すのは大変、、

といった声もある一方、2024年4月から新卒や中途のメンバーが大勢ジョインするといった背景もあり、尚更こういった要望は強く挙がっていました。そこで今回文書の特定回答の生成を同時に行える機能の開発に踏み切るに至りました。

結論

機能面

  • 既存の標準チャットではできなかった社内用語を元にした回答が可能になった
  • 社内の勤怠や申請フロー等々、業務上の基本的な情報に関する質問に回答が可能になった

大変だった/苦労したこと

  • GPT-4を使うと運用コストとして負担が大きいため、GPT-3.5でパフォーマンスを担保する必要があった
    • ハイブリッド検索でパフォーマンスを補完
  • LangChainのバージョンアップによる周辺パッケージのデグレ
    • 初めはVercel AI SDKを使っていたが、GPT-4でchat_historyが反映されなくなるバグがあってピュアなLangChainにリプレイスする必要があった
      • こちらの話は別の形でできたらと思います。

概要の説明

アーキテクチャ

ChatPCA社内文書検索のアーキテクチャ
ChatPCA社内文書検索のアーキテクチャ

チャットUI

  1. 基本的にAzureを使った構成になっています。
  2. 認証済みのユーザーはWAF Policyの付与されたAzure Front Doorを経由してApp Service上のアプリにアクセスします。
  3. ユーザーが社内文書検索機能を使うと、Azure AI Searchを通して質問に関連する社内文書を検索します。
  4. Azure OpenAI Serviceを通して、質問と社内文書から回答を生成します。
  5. チャット履歴や関連する分析用のデータはCosmos DB上に保存されます。

社内文書の取り込み

  1. Microsoft Sharepoint上から社内文書をBlob Storageに取り込みます。
  2. Azure Functionsで必要なメタデータの加工を行います。
  3. Azure AI Searchで検索用インデックスを作成します。
  4. Azure OpenAI Serviceを通して、社内文書データのベクトル化を行います。

分析&可視化

  1. Cosmos DBからAzure Machine Learningを通して分析用データの転送と加工を行います。
  2. Power BI上で分析データの可視化を行います。

技術選定

ChatPCA技術選定
ChatPCA技術選定

  • TypeScript & Next.js
    • フロントエンドメンバーがメインでアプリ全体の開発を行うため、社内知見の多いNext.jsを使い、言語はTypeScriptで統一しています。
  • NextAuth.js
    • MicrosoftのGraphAPIを用いて認証を行いますが、Next.jsと相性の良いNextAuth.js (v5ではAuth.jsと呼ばれる) を選定しています。
  • Azure
    • こちらはAzure OpenAI Serviceで社内版ChatGPTのChatPCAを構築した話にて選定理由を説明しています。ご一読いただければと思います。
    • Azure AI Search
      • ベクトルDBとして利用。Azure内のサービスとして親和性が高く、ハイブリッド検索やセマンティック検索など、RAGとして必要な機能が豊富な点が選定理由です。
  • Azure Cosmos DB(NoSQL)
    • 6000人規模の社員全員が同時に利用するため、スケーラビリティの高いNoSQLサービスであるAzure Cosmos DBを選定しています。
  • Vitest
    • Jestよりも実行速度が高く、選定時にv1系がリリースされたこともあり、今後のポテンシャルを見て選定しています。
  • Playwright
    • 並行処理性能がCypressよりも優れているため選定しています。
  • Github Actions
    • 部署内でデファクトスタンダードとなっており、またself-hostで実行が可能なGitHub Actionsを用いています。
  • Azure OpenAI(AOAI)
    • 導入当時に最も業界知見の多いLLMモデルとして選定。また、社内のコンプライアンス規定によりリージョンを日本国内に絞る必要があったことも選定理由の一つです。
  • LangChain.js
    • 今後さまざまなLLMモデルやベクトルDBと疎結合にするために利用しています。

取り組んだこと

  1. プロンプトに関して
  2. チャンク分割
  3. インデックスのAnalyzer
  4. 検索クエリの生成
  5. 検索スコアの閾値
  6. 文書の取得
  7. 回答の生成

プロンプトに関して

  • プロンプトチューニング
    • 日本語で扱うことを想定しているため、基本的に日本語で指示用のプロンプトを作成しています。
      • 検索クエリと回答生成用のLLMにそれぞれプロンプトテンプレートを指定
  • 検索クエリを生成するLLM用のプロンプト
    • チャット履歴 + ユーザーの入力プロンプトで検索クエリを生成
  • 回答を生成するLLM用のプロンプト
    • チャット履歴 + コンテキスト(文書データ) + ユーザーの入力プロンプトで回答を生成

チャンク分割

  • 文書を適切な粒度に分割しています。
    • 分割したチャンクをそれぞれ埋め込みベクトルに変換し、Azure AI Searchに保存
    • チャンク分割と埋め込みベクトルの生成にはAzure AI SearchのSkillsetを使用
  • チャンクサイズ
    • 1000で指定
  • オーバーラップ(文書同士の重なり度合い)
    • 200で指定

インデックスのAnalyzer

  • Azure AI Searchのインデックスとは?
    • 検索可能なコンテンツ
      • 様々なメタデータ(ファイルのタイトル、中身、作成日時等々)で全文検索、ベクトル検索、ハイブリッド検索、フィルタリング等々が可能になる
    • Elasticsearch等で使うインデックスと似たような意味合い
  • 全文検索をする際に必要な設定

    • トークン化、文脈理解、意味解析等々が可能になる
  • Azure AI Searchにおける、日本語向けのAnalyzer(検索分析エンジン)の主な種類

    • Standard Lucene
    • Japanese Lucene
    • Japanese Microsoft

検索クエリの生成

  • 検索クエリを生成するLLM
    • クエリの生成速度とコストを考慮してGPT-3.5を使用
  • チャット履歴とユーザーの入力を加味して適切な文書検索用のクエリを生成してくれる
    • 生成したクエリをベクトル化して関連する文書を取得する

検索クエリの課題-1

  • ベクトル検索単体だと、ベクトル空間上で距離の遠い文書を取りに行けない課題がある
    • そこで、ハイブリッド検索(全文検索とベクトル検索の組み合わせ)を行う
  • 全文検索を組み合わせることで
    • ベクトル空間上で距離の遠い文書を全文検索のスコアで補完して取りに行けるようになる

    ハイブリッド検索1
    ハイブリッド検索1

    • (補足*)マメールとは、パーソルキャリアの社内用語で、「企業担当者様へお送りする採用動向やキャンペーン情報を載せたメール」という意味です。

検索クエリの課題-2

  • 検索クエリの課題-1を解消してもまだ課題がある
  • 例えば、AZといった短い & 他の用語と衝突しやすい単語
    • AZは他にもAvailability Zone等の意味を持っていてLLMも混同する
  • なので、ハイブリッド検索をしても文書への距離が遠い分参照ができていない問題が発生する。
  • 解決策として、
    • Azure AI Searchのアナライザーの前段に独自の形態素解析のトーカナイザーを配置することで検索の精度を向上させた。

    ハイブリッド検索2
    ハイブリッド検索2

    • (補足*)AZとは、パーソルキャリアの社内用語で、お預かりする求人案件が増えたときに使われます。

検索スコアの閾値

  • 現状は検索して取得するドキュメントチャンクの数は6つにしています。ただ、その中のプロンプトが全て検索対象として適切なものとして含まれているとは限らず、不適切なプロンプトが混ざることで回答に乱れが出てしまいます。
    • それを防ぐために閾値となる検索スコアを設けることでノイズを弾いています。
      • 現状は0.015とし、環境変数で指定することでいつでも変更ができるようにしています。

    検索スコアの閾値
    検索スコアの閾値

文書の取得

  • 今回はLangChainを用いており、ドキュメントの取得方法としては主に以下の4通りのパターンがあります。
    • stuff
      • 一番シンプルな方法であり、文書チャンクをそのままLLMの入力プロンプトとして投入する
        Chains Stuff
        Chains Stuff
      • 個々の文書チャンクから並列に回答を作成し、最後に集約して回答を生成する
        • 並列に処理するため、文書チャンクの順番は考慮しない
          Chains Map Reduce
          Chains Map Reduce
    • refine
      • 個々の文書チャンクを順番にLLMに投入し、回答を生成していく
        • 直列に処理するため、文書チャンクの投入順が回答の内容に影響する
          Chains Refine
          Chains Refine
    • map_rerank
      • 個々の文書チャンクから並列にスコア付きの回答を作成し、スコアの高いものから回答を生成する
        Map Rerank
        Map Rerank
  • 今回はプロンプト長がLLMの入力にそのまま収められるサイズであり、元の記述をそのまま使いたかったため、Stuffを選択している。
    Chainsの選び方
    Chainsの選び方

回答の生成

  • ユーザーの指定したLLM(GPT-3.5かGPT-4)によって回答を生成します。
    • チャット履歴 + 関連文書 + ユーザーの入力 → 回答
  • 参照した文書データをLangChainのChainの機能を使って取得し、これを回答の末尾に加える。
    グラウンディング文書
    グラウンディング文書

今後の課題

プロンプト評価の仕組み作り

  • チームメンバーにエクセルシートに入力や結果、それに対する期待値や評価を記載いただいているが、これは現実的な運用ではない
  • そのため自動化が必要
    • 例:CI上でプロンプトの出力結果をスコアリングできるようにしたい
  • Langsmith, mlflow, Ragas等々、今後検証予定

社内文書の拡充

  • 現状の社内文書検索機能の課題
    • 参照している社内文書の質に大きく影響される点
      1. 参照している社内文書が間違っていれば回答を間違えてしまう(ハルシネーションが発生する)
      2. 社内文書が不足していればそもそも回答ができないため、関連する文書の拡充が必要
    • フォーマットを整えていく
      • LLM側で参照しやすいような形式に整備していく 例:社内用語の文書であれば、カテゴリ:社内用語といった説明を文書内に記載する
    • 非構造化データに対する扱い(Word, Excel, PowerPoint等の非構造化データ)
      • 埋め込みフォントやテキストボックス等々、それぞれのパターンに合わせた技術的な検証が必要

まとめ

こちらの記事では、Azure環境を利用して社内文書から情報を抽出し、ユーザーの質問に対して回答を生成するAIチャットサービス「ChatPCA」の開発プロセスについて詳細に説明しました。こちらのサービスは、従来のルールベースのチャットボットの限界を超え、社内のさまざまな文書から動的に情報を取得し、具体的な回答を生成する能力を持っています。

リリース後、多くの社員からの関心とともに、新たな課題が浮かび上がりましたが、それらを解決するために新機能の追加やシステムの改善が行われました。特に、GPT-3.5とGPT-4を活用した柔軟な検索機能と回答生成機能は、社内の運用において大きな進歩をもたらしました。また、LangChainを活用した文書取得と回答生成のプロセスは、システムの精度と効率を大幅に向上させることができました。

今後の課題としては、プロンプトの自動評価システムの構築や、社内文書の量と質の向上が挙げられます。これらの改善を通じて、ChatPCAはさらに多くのユーザーにとって有用なツールへと進化を遂げることが期待されます。

これらの技術的な取り組みは、他の企業にとっても参考になる事例となるでしょう。生成AIとAzureのポテンシャルを最大限に活用し、ビジネスプロセスの効率化と情報アクセスの向上を図ることが、今後の企業競争力の源泉となることは間違いありません。

注釈

  • *1: ChatPCAとは、Chat + PCA(パーソルキャリアの略称)のこと
  • *2: 2024年3月15日(リリース日)時点では、β版としてリリースをしている

梅本 誠也 Seiya Umemoto

デジタルテクノロジー統括部 デジタルソリューション部 クライアントエンジニアグループ エンジニア

韓国で5年間正規留学し、その間に業務委託で機械学習とデータエンジニアリング方面の開発を経験。新卒でアプリケーションエンジニアとしてフロントエンド、バックエンド、インフラを幅広く経験。パーソルキャリア入社後はデータエンジニアとして、社内のデータ分析基盤の構築と運用保守を担当。一方で、生成系AIを用いたアプリケーション開発にも携わっている。

※2024年5月現在の情報です。