SignateのRAGコンペ挑戦記
今までKaggleやSignateはいろいろ出てきましたが、今回のRAGコンペは初めてで個人的にかなり勉強になったので、備忘も兼ねてブログを書きます。なお結局精度は出なかったので、精度向上に向けて精進していきます。
コンペ概要
企業のESGレポートや統合報告書(pdf)に関する質問に対して、自動で正確に回答するRAGシステムを構築するコンペでした。
- 評価方法: LLM (GPT-4o) による「Perfect」「Acceptable」「Missing」「Incorrect」の4段階評価
- 提供ツール: Microsoft Azure OpenAI, Dataiku, DataRobot Japan など
詳細はこちら: (金融庁共催)第3回金融データ活用チャレンジ
大まかな流れ
RAG実装では、下記の想定を考えました。
ツールは提供されたAzure OpenAIを使用しました。Azure OpenAIは回答の生成部分での使用のみとのことでしたので、それ以外は複数のツールを試してみることにしました。
実際のプログラムコードはこちら
1. vector store作成
1-1. OCR
まずはPDFのデータの読み込みを実施します。
このコンペではうまくpdfを読み取れるかが精度向上の鍵となり、話題も多かったように思えます。そのため、複数の方法をを下記の通り検討しました。
| 方法 | 内容 |
|---|---|
| pypdfium2 | OCRではないが、CPUで動くPythonライブラリの中では精度が良かったと思う。後述のyomitokuを知るまではpdf解析はこちらを使用。ただし、テーブルやグラフの情報があまり読み取れなかった。 |
| Azure OpenAI(画像入力) | 画像を入力して、テキストを要約してもらう方法。当初はルールがわかっていないのでこちらも検討に入れていたが、前処理にすることはNGとのことで断念した。案件などでRAGを使用する分にはいいかもしれない |
| Azure Document Intelligence | PDF解析ツール。可視化もしてくれて使いやすいが、課金が必要のため使用しなかった。 |
| yomitoku | 締め切り前日にコンペとは関係ないところで教えてもらったライブラリ。CPUでも動くが、GPUで動かすと高速になる。OCRを使用しているため精度も悪くない。個人利用であれば無料で使えるので、最終的にはこのライブラリに決定。(ただし、締め切り前日に変えたため) |
yomitokuはGPUをすれば2時間弱で解析が終了し、表やグラフも適切に読み取ってくれそうだったのですごいですね。
1-2. 企業名付与
PDFを分割してRAGを実施するので、例えば売上情報があっても、どこの売上かがわからなくなってしまいます。そこで、PDFがどの企業を表すかを各文のはじめにタイトルとして挿入しました。
精度向上に寄与したかはわかりませんが、多少の効果はあったかと思います。
1-3. ベクトル化
ベクトル化ではFAISSを使用しています。
また、PDFの分割方法についてはページごとに一つのベクトルを作成し、vector storeを構築しました。
他の方の解法を見ていると、1ページではなくMarkdownのタグなどで分割する方法を取り入れている方がいて、そちらも試せばよかったと思います。
2. 回答生成
2-1. ベクトル検索
ベクトル検索は、質問をベクトル化し、1で作成したベクトルストアの中から参考となるドキュメントを探していきます。
ページ単位での分割ので、類似度が最も高いドキュメントを1つ入れていきました。
情報がない場合は「分かりません」と出力するようにしているため、 その場合はi番目に類似度が高いドキュメントを挿入しました。 (iでループ。回しすぎると情報がない場合でも回答してしまう可能性があるため、 3回まで実施しました。)
2-2. 回答生成
2-1で検索したドキュメントを使用し、回答生成をしました。検証していくうちに、下記が問題となっていきました。
- 端的に答えないと精度が上がらない
- 小数第n位を四捨五入→小数第(n+1)位を四捨五入してしまう。
- 表から最大値を取得できない(一部だけ見て最大値を判別してしまう。)
また、回答のみを生成する場合うまく回答されない場合があるので、まず過程を示してから回答を出していくとうまくいきました。
プロンプト
次のテキストは関連したドキュメントをMarkdownに変換したものである。
これを元に、質問に対して**計算過程を明確に説明し、最後に答えを出せ**。
- **数値を求める場合**
1. 必要な数値をすべてリストアップする。
2. 計算式を明示し、途中計算をすべて書く。必ず下記に記載の計算規則に従うこと。
3. **計算過程をステップごとに示し、答えを最後に書く**。
4. **もう一度質問と計算規則をかきだし、照らし合わせて問われていることが間違っていないか確認し、誤りを防ぐ**。
もし質問に正確に答えることができない、または推測が入っている場合は**「分かりません」**と答えること。
- **計算規則**
- 小数第n位を四捨五入する場合は第n位で四捨五入を行い、答えは小数第(n-1)桁とすること。
- 最大値を求める場合は、リストアップした中から上位を算出し、その中で最大のものを求めること。
- **情報が不足している場合**
- **「分かりません」** と明確に回答し、足りない情報を指摘する
最終プロンプト
次のテキストは質問に理由をつけて答えてもらったものである。
これをもとに質問に答えを単語のみ答えよ。複数ある場合は複数の単語で答えよ。
情報が不足している場合には「分かりません」と答えよ。
質問:`{question}`
理由と答え:`{process_answer}`
考察
率直に思った点から。
プロンプトによって回答が大きく変わることを実感しました。通常のテーブルコンペだと結果を見てもわからないことが多いですが、今回は正解は自分から作ることができるので、いかに結果を見て修正できるかが重要なポイントであったと感じます。(私は最初の10問くらいしか確認できませんでした…)
また、「分かりません」と出力することはスコアが-1になることからできるだけ避けなければなりません。情報がないときにわからないとすることは重要であり、こちらも制御が難しかったです。(他の方の回答で、複数回実施し、回答が不一致のものを「分かりません」としていて、勉強になりました。)
また、プロンプトの作り方も甘く、条件をどれだけ入れられるかによってどんどん精度が変わっていったように思います。こちらは他の方のプロンプトも参考にしたいところです。
vector storeについて
Document Interigenceや生成AIを使用する解法が多かったですが、yomitokuを使い、精度も生成AIと引けを取らないほどだったので私は満足です。
最後に
RAGコンペは初めてでしたが、非常に奥が深く、知識、観察力、マシンスペックなど様々な要因が絡み合ってできているものでした。生成AIの内部の構造はわからないにしろ、結果が明白なのでどうすればより良くなるとの道筋はえやすかったかなと思います。今後もRAGコンペや生成AIコンペにチャレンジしていきたいです。
Comments
Loading comments...