ASCII × Microsoft の生成AIコンテスト「第2回 AI Challenge Day」参加レポート

# はじめに
2024/6/11,12に開催された「第2回 AI Challenge Day」に参加してきました！
本イベントは、株式会社角川アスキー総合研究所主催 × 日本マイクロソフト株式会社協賛の生成AIのハッカソンです。RAGアーキテクチャを用いた質問応答システムを構築し、質問に対する回答精度を競い合います。
BIPROGYは、普段AI全般の技術検証・製品開発および適用を行っている部隊のメンバー5人で参加してきました。その結果、Microsoftのパートナー企業10社が参加する中、**回答精度評価スコアが1位**となり「**World Wide Learning賞**」を受賞しました！
発表会と授賞式はYouTubeで公開されています。

https://www.youtube.com/watch?v=FpIdmebWe9A

本記事では、イベントの概要および弊社の実装内容についてご紹介します。

# AI Challenge Dayの概要
## テーマ
第2回のテーマは、第1回と同様に「世界遺産トラベルアシスタント」でした！ただし、第1回とはデータセットや問題の難易度が異なるそうです。
質問には仮想遺産についての質問も含まれるため、LLMが事前に学習している情報ではなく、用意されたデータセットの情報から回答を生成する必要があります。

![スクリーンショット 2024-06-25 185915.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3819903/6d5226c2-34b7-2968-3c55-5d209c08824f.png)

また、テキストのみのFAQだけでなく、画像を含む質問に回答するマルチモーダルな実装も必要となります。

![スクリーンショット 2024-06-25 191340.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3819903/5f92c12b-6843-3004-5f4a-a5fbfb1f8248.png)

## 評価方法
上記のテーマについて、回答精度を競い合いました。回答精度の評価については、生成された回答を評価し、スコアを計算するスクリプトが提供されました（25点満点）。スコアはLLMに計算させます。以下がLLMにスコアを計算させるプロンプトの一例です。2日目の発表会までに各チームでこのスクリプトを実行し、回答精度評価スコアを計算しておきます。

![スクリーンショット 2024-06-26 123720.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3819903/121a2632-b4dc-9d71-8067-2403522cb62e.png)

ただし、評価対象は回答精度評価スコアのみではなく、実際の業務やビジネスを想定したカスタマーストーリーを描けているか、セキュリティ・耐障害性・性能を考慮した構成になっているかなども評価し、最終的な得点が決まります。（当チームが回答精度評価スコア1位だったにも関わらず、グランプリおよび準グランプリを逃した要因でもあります...）

## データセット
回答生成に使用するデータセットが提供されました。データセットにはドキュメントファイルと画像ファイルがありました。
ドキュメントファイルは、PDF・Word・PowerPoint・CSV・テキストファイルです。PDF・Word・PowerPointは、ファイル内に画像が含まれていました。
画像ファイルは、PNG・JPG・GIFがありました。


# RAGとは
RAGとは、LLMが事前に学習している内容以外について回答させたい場合に使用する仕組みです。質問に回答するために必要な情報を検索し、検索結果の情報をもとにLLMに回答を生成させます。
今回のテーマでは、LLMが事前に学習していない仮想遺産についても回答できるようにする必要があるため、RAGの構築が必須となります。

![スクリーンショット 2024-06-26 125841.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3819903/12760541-3c11-e5ee-3770-f0d07bc4d2c8.png)

# 実装内容
ここからは当チームの実装内容について、「試したけど採用しなかったこと」や「時間的にできなかったけどやりたかったこと」も含めてご紹介します。

## アーキテクチャ
最終的に以下の構成にしました。基本的なRAGの構成を採用しています。詳細については後述しますが、ポイントは以下の通りです。
- PDF・Word・PowerPointはAzure AI Document Intelligenceで文字起こし
- 画像ファイルはAzure AI VisionのVectorize Image APIでベクトル化
- ドキュメントファイルと画像ファイルはインデックスを分けてAzure AI Searchに投入  

![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3819903/648952a6-d797-b222-8c18-dedeac1d56fd.png)

## ドキュメントファイルの検索
### 前処理
まずファイル形式と中身を確認し、インデックスのフィールド定義を決定しました。
その後、インデックスにデータを投入するための前処理をファイル形式ごとに実装しました。

#### テキストファイル
より質問に関連する部分を検索しやすくするために、文字数が多い場合はテキストを一定サイズのチャンクに分割してからインデックスに投入しました。

#### CSV
1行を1チャンクとしてインデックスに投入しました。

#### PDF・Word・PowerPoint
- 最初の実装（最終的には採用せず）　
PyMuPDF・python-docx・python-pptxライブラリを使用して、テキストデータを取得しました。また、ページ内に画像がある場合は、画像についてGPT-4oに説明させた文章を、ページ内のテキストデータの末尾もしくは先頭に追加しました。
最後に、テキストファイルと同様、文字数が多い場合はチャンクに分割してからインデックスに投入しました。
- 最終的な実装
上記の方法ではテキストが抽出できないファイルがあることが判明し、最終的にはAzure AI Document Intelligenceを使用してテキストを抽出しました。スキャナーでPDF化されたファイルや、図形内にテキストが記載されているWordファイルが含まれていたためです。
Azure AI Document Intelligenceを使用したところ、それらのファイルのテキストデータも抽出できるようになり、回答精度が向上しました。
    - 最初の実装：回答精度評価スコア = 21.9（※ マルチモーダルな質問は除いた点数）
    - 最終的な実装：回答精度評価スコア = 22.501
- やりたかったこと
    - 座標情報を用いた適切な位置への画像情報の挿入
    Azure AI Document Intelligenceはページ内の画像の座標を取得できるため、テキストデータの途中の適切な位置に画像情報を差し込むことを試みました。しかし、時間の都合上実装まではできませんでした。ファイル内の画像情報がうまく使えていれば、より精度向上ができたかもしれません。

### Azure AI Search の検索方法
Azure AI Searchで使用できる検索方法は以下の3つです。また、テキストベースの検索方法では二次ランク付けにより品質を高めるセマンティックランカーも利用できます。
- フルテキスト検索
- ベクトル検索
- ハイブリッド検索（フルテキスト検索 + ベクトル検索）

ドキュメントファイル用インデックスの検索については、ドキュメント検索において比較的精度が良いと言われているハイブリッド検索に、セマンティックランカーを利用したセマンティックハイブリッド検索を採用しました。
その際、テキストのベクトル化にはAzure Open AI ServiceのEmbeddingモデルを使用しました。

### Embeddingモデルの比較
テキストのベクトル化に使用するEmbeddingモデルについて、以下のモデルを比較しました。その結果、（誤差程度ではありますが）評価スコアが高かった**text-embedding-3-large**モデルを採用しました。
- text-embeddings-ada-002：回答精度評価スコア = 19.333（※ マルチモーダルな質問は除いた点数）
- **text-embedding-3-large**：回答精度評価スコア = 19.967

### パラメータチューニング
以下のパラメータについて、いくつかの条件で比較し、一番評価スコアが高かった値を採用しました。**結果的には、top_kのチューニングが回答精度向上に大きく貢献しました。**
#### top_k
top_kとは、検索結果の上位何件を回答生成に使用するかを示す値です。
従来のモデルではtop_kを大きくしすぎるとトークン制限に引っかかってしまうという問題がありました。しかし、今回使用したGPT-4oはコンテキストが128kのため、思い切ってtop_kが大きい値でも試してみました。
結果は以下の通りです。**top_k=20を超えるとスコアが大幅に上がりました！** 情報をある程度多く与えても、GPT-4oがその中からうまく回答を生成してくれるようです。
その中でも評価スコアが一番高かった、**top_k=20**を採用しました。
- top_k = 5：回答精度評価スコア = 19.967（※ マルチモーダルな質問は除いた点数）
- top_k = 8：回答精度評価スコア = 20.533
- **top_k = 20**：回答精度評価スコア = 21.9
- top_k = 25：回答精度評価スコア = 21.6
- top_k = 30：回答精度評価スコア = 21.533
#### チャンクサイズとオーバーラップ
チャンクサイズとは、テキストデータをチャンクに分割する際のサイズです。
また、オーバーラップは、隣り合ったチャンクについてどの程度重なりを持たせるかを示す値です。
チャンクサイズとオーバーラップについて、以下の組み合わせで比較しました。結果、評価スコアにあまり差はありませんでしたが、一番高かった **チャンクサイズ=800, オーバーラップ=100** を採用しました。
- **チャンクサイズ=800, オーバーラップ=100**（top_k=20）：回答精度評価スコア = 21.9（※ マルチモーダルな質問は除いた点数）
- チャンクサイズ=800, オーバーラップ=400（top_k=20）：回答精度評価スコア = 21.867
- チャンクサイズ=1600, オーバーラップ=200（top_k=10）：回答精度評価スコア = 21.233

## 画像ファイルの検索
### 前処理
画像ファイルについては、ドキュメントファイルと異なるインデックスのフィールドを定義し、別のインデックスにデータを投入しました。
主なフィールドは以下の通りです。
- 画像のベクトル：画像をベクトル化した値
ベクトル化にはAzure AI VisionのVectorize Image APIを使用しました。
- 説明文：画像についてGPT-4oに説明させた文章
- 説明文のベクトル：説明文をベクトル化した値
- ファイル名：画像のファイル名
ファイル名に固有名詞（例：清水寺）が含まれていたため、後述するマルチステップ検索のドキュメントの絞り込みに使用しました。

### マルチステップ検索
画像ファイルがあるマルチモーダルな質問の場合は、以下のマルチステップ検索を実行しました。
1. 質問に添付された画像をベクトル化
1. 画像ファイル用インデックスに対してベクトル検索を実施
1. ドキュメントファイル用インデックスに対して、2の結果から得られた画像と紐づくドキュメントに絞り込んでから、質問文でセマンティックハイブリッド検索を実施
1. 検索結果から回答生成

## 評価サイクルの高速化  
その他の工夫点として、LLMOpsを導入し評価サイクルの高速化を実施しました。
具体的には、回答精度評価スクリプトの入力ファイルの自動作成や、並列化処理による高速化により、スコア計算にかかる時間を短縮しました（30分→5分程度）。
評価サイクルを高速化したことにより、回答精度評価スクリプトを何度も実行することができました。その結果、精度改善サイクルを多く回すことができ、スコア向上につながったと思います。

# 結果
最終的な回答精度評価スコアは21.45点となり、**全10社中1位のスコア**でした！（2位とは0.05点差なので僅差ですが...）
精度で上位を目指していたので、1位という結果はとても嬉しかったです。
その結果、回答精度評価スコアやLLMOpsの導入を評価いただき、「**World Wide Learning賞**」を受賞することができました。
反省点は、精度向上に注力するあまり、カスタマーストーリーや発表資料の作りこみ、UI構築の時間が取れずにグランプリ・準グランプリを逃してしまったことです。機会があればリベンジしたいです！

![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3819903/7ff8a04f-870a-1749-dfd2-c478d0351a25.png)