NEXTSCAPE blog

株式会社ネクストスケープの社員による会社公式ブログです。ネスケラボでは、社員が日頃どのようなことに興味をもっているのか、仕事を通してどのような面白いことに取り組んでいるのかなど、会社や技術に関する情報をマイペースに紹介しています。

MENU

AI Challenge Dayの問題を社内プロジェクトとして解いてみた

 こんにちは、Azureビジネス部の金重です。

 今年の4月にACSII×Microsoft主催のAI Challenge Dayというイベントに、JBS(日本ビジネスシステムズ)との混合チームで参加しました。イベントはコンテスト形式で2日間の開催でしたが、RAGの構築の知見を社内で共有する為に、社内プロジェクトとして当日の問題に対して3か月ほど仕組みの改善を試みました。

blog.jbs.co.jp

社内プロジェクト化の経緯

 イベントでは、世界遺産トラベルアシスタントのチャットAIの構築を2日間のタイトなスケジュールの中で行いました。2日間でAzure OpenAI Service(GPTモデル)やAzure AI Search(ドキュメント検索)といったAzureリソースの準備から一連の実装、得点を取るための仕組みの最適化といった作業を実施して、なんとか発表までに完成させた形になりました。

 今回のイベント参加は貴重な経験になったのですが、この経験を参加者だけで閉じたものとして一度で終わらせてはいけないと考えました。また、弊社内でも生成AIに関する案件を進める中で感じていたこととして、案件の中では業務に即した課題に追われ、日々進歩する生成AI技術の中でも試したい技術を試しきれていない状況でした。

 そこで、部内での知見の共有・蓄積を行う為に、社内プロジェクトとして展開しました。*1RAGを含め生成AIの課題として精度の向上を測るにあたって、気になる手法を試すことで感覚を掴み、案件で採用するか事前に検討したり、実装の際に速度を向上させることを期待して、今回採用する手法も検討しました。

参加メンバーについても、部内の各メンバーの知見の蓄積の為に、途中でメンバーを交代しながら改善を進めました。更に定期的に進捗共有を部内全体で行いました。

課題概要

概要は先ほどの記事をご覧ください。
【Microsoft×生成AI連載】【やってみた】AI Challenge Dayに参加しました - JBS Tech Blog (再掲)

課題を解くにあたって、以下のリソースが提供されました。

  • コンテストに使用するAzureサブスクリプション
  • QA形式の問題40問
    • テキストを入力とする問題35問
    • テキスト+画像を入力とする問題5問
  •  日本の世界遺産に関するデータセット
    • Wikipediaのページをテキスト・Word・PDFといった形式に変換したファイル
    • お土産などの商品のcsvファイル
    • 世界遺産の画像
  • 評価用スクリプト
    • 実行すると、問題40問とその回答に対して、それぞれ25点満点で点数を算出する
    • 25点の内訳は、5つの評価基準(fluency, similarity, cosine_similarity, relevance, groundedness)に対して5点満点で評価させ、40問の平均を取る*2
    • 評価には問題文、回答に加え、運営側で用意した正答及びコンテキスト(今回だとAzure AI Searchで検索した、回答の根拠となる情報)を使用する

具体的には以下の様な問題で、全て日本の自然遺産に関してWikipediaをソースとして回答する問題となっています。Wikipedia内に直接記載があるものから、複数のページから寺社の創建年を検索し、古い順に並び変えるような問題など、多様な問題がありました。問題の詳細については考察の余地もあった為、後述します。

  • 問題:宇治上神社の境内には隕石との説もある巨石があるが、何と呼ばれている?
  • コンテキスト:宇治上神社のWikipediaページが記載されたWordファイルから抽出
  • 正答:宇治上神社の境内には「天降⽯」・「岩神さん」と呼ばれる巨⽯があり、磐境信仰による創祀という説もある。

改善の流れ

 改善の進め方として、約1週間ごとに実装の改善及び評価のサイクルを回しました。コンテストでも得られた知見として、評価を短いサイクルで行い、実装の改善を定期的に評価することでした。その為、実装したものは評価して結果良くなったかどうかを記録することを意識しました。*3今回は部内でのノウハウの蓄積も目的としたため、週末に部内での進捗報告及び次週の改善内容の相談タイミングを設け、実際の問題を見ながら実装及び分析する人の感覚を共有した上で、改善に役立てられそうな知識は部内全体から募集しました。

 初週は基本的なRAGの構築を実施して、最低限の機能で評価を行いました。この時点ではWikipediaの情報も一部検索用にインデックス化できていないものもあり、結果15点台とコンテスト当日よりも低い結果となりました。

 2週目にはWikipediaのインデックス化に際してOCRを実施しました。コンテスト当日もいち早く課題に気づいて改善した箇所なのですが、Wikipediaページと言ってもテキストではなく印刷されたページをスキャンしただけのようなPDFファイルもありました。こういったファイルではPDF解析ライブラリでは内容を読み取れない為、OCRで文字を読み取る必要があります。その他にも検索の設定などいくつか改善をして、20点台まで点数が向上しました。

 その後も毎週RAGの仕組みを更新して、最終的な点数としては21.858点まで向上しました。しかし、その間は実はあまり点数は向上せず、問題毎に改善したものと逆に改善策によって点数が悪化したものがありトレードオフが繰り返される形になりました。問題が1000,2000問とあるような設定であれば点数がより信頼できるようになりますが、今回は40問ということもあり、1問の問題で回答を間違って10/25点程度下がると全体の点数も0.3点程度下がるといった風に1問の影響が大きいものでした。

 純粋な点数の向上を主目的とすることによる課題が見えた為、途中で改善の方針を転換し、全体の点数ではなく各問題にフォーカスしてその問題の改善を狙うことにしました。本プロジェクトの目的としてもノウハウの蓄積が主だった為、具体的な問題にアプローチする改善策をノウハウとして持って実案件でも扱えるようにすることにしました。最終的には点数もある程度向上しましたが、改善する為にデータの前処理から検索、生成といった各所で出来ることを検討した時間に意義があったと感じています。

最終的なアーキテクチャおよび実施した改善策

Azureの構成としては、Document Intelligenceを使用したRAGの一般的な仕組みを踏襲しており、公式ドキュメントでも紹介されているような「データソースをDocument Intelligenceでインデックス化、ユーザーの質問文からAzure AI Searchでインデックスを検索、Azure OpenAI Serviceで回答を生成」といった各要素によって構成しました。*4

Azure AI Document Intelligence (旧称 Form Recognizer) を使用した取得拡張生成 - Azure AI services | Microsoft Learn

Azure AI Document Intelligence を使った RAG によるセマンティック・チャンキングのスクリーンショット。

検索→回答生成の処理の流れについては改善の中で工夫しました。ベーシックなRAGの検索→回答生成の流れだけではなく、検索に使用するクエリを生成した上で、検索を複数回行う仕組みを導入しています。このアーキテクチャ構成のもと、各ステップでの処理を改善しました。

データセット内の各問題や問題設定の特徴によって必要な改善策も変わる為、問題と共に改善策を抜粋して紹介します。

課題

前処理

  • 読み取れないドキュメント:今回検索に使用するデータセットはtxt, pdf, pptx, docxの4つのファイル形式でした。テキストとしてそのまま抽出可能なファイルもあるのですが、PowerPointやPDFファイルは解析が必要になります。更に、PDFファイルの中には紙のページのスキャンをしたようなものも含まれており、実質的な画像ファイルもありました。
  • インデックス化による情報の欠落:いくつかの課題がありました。
    • まず、表形式の構造の欠落が課題となりました。具体的な課題としては、月ごとの気温が表形式で記載されているページがあり、これをテキストにしてしまうと"6月 7月 8月 \n 30.0 29.2 28.5"のように構造が見えなくなってしまいます。
    • また、Wikipediaの様なドキュメントは章立てされています。PowerPointでもページごとにタイトルが設定されていることがあります。それらはHTMLファイルであればヘッダータグが付いていますが、その情報をただOCRで読み取るだけでは情報が抜け落ちてしまいます。また、それらを検索対象としてチャンク化する際にも文字数(トークン数)で区切ってしまうと情報が欠落してしまう課題がありました。

検索

  • 自由な質問文のフォーマット:RAGの仕組みで検索するにあたって、ユーザーの質問文でそのまま検索することは望ましくありません。問題文の中でも、「清水寺 電車 アクセス」の様にキーワードのみ列挙している質問文もあれば、文章になっているもの、「きよみず寺は応仁の乱のときどうなりましたか?」のように固有名詞が平仮名になってしまっているものもありました。一般的には質問のテンプレートを用意する等の方法で運用的に回避することもありますが、自由な質問に対して回答する為に、適切に検索をかける必要がありました。
  • 一回の検索で必要な回答が揃わない:検索の課題として、必要なドキュメントを網羅することと、必要ないドキュメントを弾くことがあります。例えば4つの寺の創建年を並び替える問題では、4つのWikipediaのページから創建年の情報のみを抜き出す必要があります。しかし、一回では検索しきれなかったり、代わりに関係ない情報が先にヒットしてしまうことがあります。前提として、質問文に対して妥当なドキュメントと検索クエリに対して妥当なドキュメントは乖離する可能性がある為、回答を一発で網羅するのは困難であると感じました。

回答生成

  • 複数種類のタスクが混在している:今回の課題では世界遺産アシスタントとして、検索したデータをそのまま要約するだけではなく、植物のリストから種類数を数え上げたり、足し算をする必要がありました。

改善策

前処理

  • Document Intelligenceによる文書の解析:Microsoftの解説でもベストプラクティスとして紹介されていたのですが、Azure Document Intelligenceという文書構造の解析サービスを用いてWikipediaの各ページをドキュメント化しました。先述の通り印刷物のスキャンのようなファイルもあり、画像認識の方式でドキュメント化する必要があったことから、特に認識精度が高いとされるこちらのサービスを使用しました。また、結果の出力フォーマットの指定ができ、テキストだけでなくHTML、マークダウンが選択できます。これを構造化したフォーマットで出力することで、生成AIが表形式のドキュメントを機械的に解釈しやすくなります。
  • セマンティックチャンキング:ドキュメントの章立ての情報を保存する為に、今回はセマンティックチャンキングと呼ばれる意味的な単位で区切る方法を取りました。具体的にはマークダウン化したドキュメントのHeader1~3の単位で区切りました。これによって、動物を紹介するセクションが50文字、植物を紹介するセクションが1000文字と内容によって文章量にばらつきがある場合でも”動物”、”植物”といったような意味的な単位でドキュメントを区切ってチャンク化することができます。
    • 宇治上神社について調べると、概史、外部リンクといった章・セクションごとに検索結果を取得できています。 
  • 画像のインデックス化:Wikipediaページ内の画像についても、多角的に情報を活用する為にベクトル検索の為のベクトル化を実施し、画像を入力として類似する画像を検索できるようにしました。*5

検索

  • 検索クエリ生成:ユーザーの質問文が多様である課題に対して、検索クエリのフォーマットを統一する為に、GPTモデルを使用してユーザーの質問文から検索クエリとなるキーワードを抽出しました。
    • 例えば、「きよみず寺は応仁の乱のときどうなりましたか?」のような質問に対して、「清水寺 応仁の乱 影響 歴史」といった風にキーワードに変換します。他にも、「以下の神社を創建年の古い順に正しく並べ替えよ。
      厳島神社、日光東照宮、春日大社、宇治上神社」といった質問に対して、検索に必要な「法隆寺 創建年 清水寺 東大寺 中尊寺 薬師寺 順番」をキーワードとして生成します。
  • 検索を繰り返す:CRAGという仕組みを参考にして、必要なドキュメントが一回でヒットしきれなかった場合に再度検索するようRAGの仕組み自体を改善しました。検索で10件検索した後に、GPTモデルを用いて各ドキュメントの関連性を評価した上で、関連しないドキュメントをコンテキストから削除しました。加えて検索結果の一覧が回答に不十分な場合は検索クエリを再度生成して3回まで検索しなおす実装を追加しました。*6
    • 例えば、神社の創建年を調べる問題で、5つの神社の内「清水寺、法隆寺、薬師寺」の3つについて検索出来た場合、残りの2つの寺社を検索する為に「中尊寺 創建年 東大寺 創建年」で再度検索します。

回答生成

  • gpt-4oの検討:コンテストではあくまで点数やアーキテクチャの工夫、エンタープライズ向け構成等の観点で評価されていましたが、本番向けにはユーザー体験が重視されます。当時はgpt-4oがまだ出ていなかったのですが、回答速度を考えるとgpt-4oの採用が考えられます。点数は変わらなかったものの、回答の文言の質は変わったように見えました。評価に生成AIを用いているといっても機械によるRAGとしての評価には変わりないので、実際の人間の感触による評価で決定されるべきものだと感じました。

 今回はデータの前処理と検索の工夫がメインで回答生成については基本的なプロンプトから変更せずにいました。問題としては純粋な要約から植物の種類の数え上げ、足し算といったタスクがあり、Function Calling等で問題毎に回答の仕方を変えることで改善する余地がありました。しかし、コンテストの設定では問題が判明している為、各問に最適化し過ぎた施策となる可能性があった為、優先度を下げました。

 代わりにAssistants APIで同じ問題を試してみたのですが、アップロードしたファイルと質問に対して「まずはファイル検索」「回答が出揃っているか判断」「各ドキュメントをもとに回答生成」といった流れを実施してくれました。Assistants APIではタスクのフローの細かい制御まではできなくとも、こういった方針で生成AI自らにタスクを繋いでいくことができれば改善できるのではないかと感じました。

コンテストを案件に活かすために

 今回コンテストから改善を続ける中で、データセットや問題の工夫の他に、分析の中で評価指標の妥当性についても気になりました。結論として、コンテストにおける評価の為の指標としては良いものの、実際の案件を進めるにあたっては、評価指標を再考する必要があると感じました。

データセット・問題の工夫

 今回改善策を実施する中で気づいた範囲ではありますが、コンテストで点数を取るための障壁となるような工夫された問題が沢山ありました。データセットであれば、単純にファイル形式が複数種類存在することや、OCRで読み取る必要があるファイル等、実際の案件でも出会う可能性があります。私自身、昔画像認識の課題でガビガビの画像が出てきてどうにも認識しようがないときがあったので、データを綺麗にする段階がとても重要であると感じました。

 問題についても、例えば問題文の表記ゆれやひらがなのみでの質問等、ユーザーの質問の多様性を考慮されていました。実際には質問文をテンプレート化してアプリケーション的に回避することも考えられますが、逆にそういった工夫が必要であることを認識しました。評価の点数を上げることを考えると入力を固定して精度を向上させることにのみ注力してしまいがちですが、ユーザーの利用イメージまで想定してUIから変えることも視野に入れる必要があります。

各評価指標の考察

 今回は5つの評価指標(fluency, similarity, cosine_similarity, relevance, groundedness)が採用されていましたが、これらの評価について考察します。分析にあたって、各指標毎に点数の遷移を記録し、ヒートマップ形式で全体の傾向や困難な問題の洗い出しを行いました。

 まず、各指標についての結果を観察します。fluencyは日本語だと流暢性、文章が流暢で文法的に正しいかです。こちらについてはgpt-4-1106-preview及びgpt-4oで実行して殆どの問題で4点か5点となっており、改善が必要なものではありませんでした。

 次にrelevanceとsimilarityです。relevanceは質問に対する回答の妥当性、similarityは運営側で用意された正答と生成された回答の類似度です。傾向として、similarityは平均0.5点ほどrelevanceより低い結果となりました。考察として、正答との類似度を測る場合、人間から見ると内容的に正しいものでもsimilarityが低くなっている問題も多いと感じました。特に正答は文章が簡潔で、回答は丁寧かつ多めに回答しているものもあるので、情報が完備しているか?という判定が必要そうでした。また、回答としても「桜の名所をこたえよ」といった問題の場合正答としては3つ列挙する必要があるものの、回答としては1つ答えれば確かに妥当であると感じるものもありました。

 次に、groundednessです。これは質問と回答の他にコンテキストを基にして、回答が根拠に基づいた回答をしているか(=ハルシネーションを起こしていないか)評価するものとなっています。これについて点数を見ると、全ての問題で1か5という極端な数字となっていました。回答の中には「4つの寺社の内、1つは具体的な年数はありませんがXX時代と推測されます…」のように一部だけコンテキストに即していない場合でも1が付く評価となっており、少し厳しめに感じました。また、今回の様に問題数も限られ取得したいドキュメントが明確な問題設定では、回答の妥当性を測る前段階として、問題毎に検索してほしいドキュメントを列挙し、F値などの指標でそれらを完備しているか測る評価方法も妥当かもしれません。

 最後にcosine_similarityです。similarityはgpt4モデルに正答と回答を入力して類似度を測っていたのですが、こちらは正答と回答をそれぞれadaモデルでベクトル化して、そのコサイン類似度を測っています。文章のような長い文言に対してベクトル化する強みがありますが、立ち位置としては類似度を2観点で評価しているようで、similarityとは大きく乖離する問題も少ないようでした。

人間による評価との違い 

 ここ最近では人間による評価だけではなくGPTモデル自身に評価をさせる論文を見かけるようになったり、かなり市民権を得ているように感じます。大量のデータの評価をするにあたっては、人手の問題もある為機械的に評価する手法が発展することは望ましいことだと感じました。

 その上で、人間の評価は妥当になる為、人間による評価も重要であると感じました。今回は検索精度や質問文に対する回答の妥当性といった定型化された評価ですが、実際のユーザーの感性として満足かどうかは変わってきます。私の場合、生成された回答だけでは背景をよく知らず、提示された情報の周辺情報までないと理解できず、(コンテストの要件には含まれていませんが)そのままドキュメントのURLを貼ってもらって自分で読み込んだ方が良いと感じました。このまま今回のシステムを改修すればこのフィードバックにも対応できるかもしれませんが、何にせよユーザーによる評価とフィードバックの機会は必要です。

 …実は、評価した結果を詳細に見ていく中で、relevance(妥当性)及びgroundedness(コンテキストに基づいた回答)は共に5点であるものの回答をよく見ると矛盾したことを言っているケースもありました。

「日本の複合遺産について教えて下さい」という質問に対して、正答は「日本には、文化遺産と自然遺産の両方の価値を持つ「複合遺産」として登録されている世界遺産はありません。」なのですが、以下の様にハルシネーションによって知床を複合遺産と回答していました。

Contextに基づいて、日本の複合遺産についてお答えします。

複合遺産とは、自然遺産と文化遺産の両方の価値を持つ世界遺産のことを指します。世界遺産には、文化遺産、自然遺産、そして複合遺産の3つのカテゴリーがあります。複合遺産は、新基準の(1) - (6)のクライテリアに1つ以上適用されれば文化遺産、(7) - (10)のクライテリアに1つ以上適用されれば自然遺産となりますが、いずれかのクライテリアに1つ以上適用されれば複合遺産となります。

Contextには具体的な日本の複合遺産の名前は記載されていませんが、日本には「知床」が複合遺産として登録されています。知床は北海道に位置し、豊かな自然環境とそれを支える生態系、そしてアイヌ文化などの文化的要素を含んでいます。これらの特徴が、複合遺産としての価値を形成しています。

以上がContextに基づいた日本の複合遺産に関する情報です。他の具体的な複合遺産についての情報は、Contextには含まれていないため、提供することはできません。

現状のGPTモデルが論理的な整合性に弱いこともあり、現状は完全に自動化するのは難しいように感じました。そういった結果も相まって、GPTモデルによる評価の妥当性について定期的にチェックした上で適切な用途で使う必要がありそうです。

おわりに

 また、日々OpenAI社の発表や様々な記事で新機能やそれを検証した情報が公開されていて、それらを目で追うだけでも大変になってきていますが、実案件で使用するにあたっては自分で手を動かすことが大切だと改めて感じました。

 今回実施した前処理や検索の手法は問題設定に合わせたもので、問題設定やデータの質が変わればまた異なる手法が必要になることが想定できます。しかし、それらの手法の感覚を掴むことが、実際の案件での手法の選択において役立つと感じました。

 また、評価指標についても、ChatGPT登場以前はGREU等のスコア評価や人間に依頼する手法が主でしたが、ここ最近登場したChatGPT自身にその結果を判定させる手法についても実際に判定させて評価を詳細に見たことも良い経験となりました。ChatGPTの回答がハルシネーションをしうる通り、スコア評価においても得手不得手があることを感じました。

 プロジェクト全体として、自分を含めて社内での生成AIやRAGのノウハウの蓄積として価値があるものだったと感じています。これからも、案件として生成AI関連技術を担当させていただくとともに研鑽の機会を作っていければと思いました。

*1:※当時の時点では問題の詳細設定や評価については公開不可の為、社内の関係者にのみ共有していました

*2:各指標はPrompt flowのメトリクスでも用意されています Azure AI Studio の Prompt flow の評価メトリクス紹介 ― ChatGPT どう評価する? #GPT-4 - Qiita

*3:他プロジェクトと並行での実施という都合もあり、実装に時間のかかるものは2週間に跨いでの実装を行うこととしました。

*4:ただし今回のプロジェクトはエンドユーザーを意識したアプリケーション開発ではなく評価のみの為、App UXやApp Serverの実装はせず、ローカルでコンソールアプリケーションを立ち上げて検索や回答生成、評価の一連の流れを実行しました。

*5:Azure AI Search の既存インデックスにベクトル表現(埋め込み)を追加し、AOAI から独自データとして参照する (zenn.dev)

*6:CRAGでは検索したデータに対して回答生成に妥当なデータかどうかを判定し、不十分な場合はWeb検索を行う仕組みです。今回はWeb検索の代わりにもう一度自前のデータに検索させるよう改変しました。 langgraph/examples/rag/langgraph_crag.ipynb at main · langchain-ai/langgraph · GitHub