FDUA 第３回金融データ活用チャレンジに参加してみた！ #4 OCR

# この投稿で書いていること
・「FDUA 第３回金融データ活用チャレンジ」にチャレンジ
・テーマの 「RAG」 について取り組んだ内容
・「今後」やっていきたいこと

# はじめに
FDUA 一般社団法人金融データ活用推進協会、金融庁共催の「第３回金融データ活用チャレンジ」に参加してみました。

https://signate.jp/competitions/1515

さて、FDUA 第３回金融データ活用チャレンジに参加してみた！ 最後になる #4 OCRです。
ここでは、事前のデータストアをどのように作成したかを書きます。

:::note alert
かなり具体的な内容を記載しています。
もし不都合がある場合はお知らせ頂けると幸いです。
:::


# データストア&emsp;<font color="Blue">RAGでもっとも重要なパート！</font>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4006424/63363411-6283-4cc8-b5b7-014710b26b4f.png)

#1 データの準備で少し書きましたが、もう少し詳細に書くと、
&emsp;1.OCR Azure Document Intelligence の機能で段組み、テキスト、表、図の座標位置を抽出
&emsp;2.図がある座標位置から図を切り出し
&emsp;3.生成AIで図の説明を生成
&emsp;4.全体要約
&emsp;5.index用の mdファイルを作成
&emsp;6.すべての mdファイルを対象にindexを作成、この時に全体要約をEmbedding
としています。


## mdファイルの例
4.pdf の7ページを題材にすると以下のようになります。
かなりの量があるので大分省略しますが、当該ページのテキスト、表、図の説明（表であれば表の内容）をOCR+生成AIで抽出作成します。

```
サステナビリティ戦略社会価値の創造生活文化の向上|ブランド事業
~ブランド価値向上への取り組み「D社」ブランドが創造する・・・・
・・・・略

1. **人物の手**:
   - 白い手袋を着用しており、清潔さや物体の保護を意識していることが伺えます。
   - 右手でルーペを持ち、左手でリングを支えています。

2. **ルーペ**:
   - 銀色の金属製のルーペで、拡大鏡部分がはっきりと見えます。
   - ルーペは小型で、精密な観察に適したデザインです。

3. **リング**:
   - 左手で持たれているリングは金属製のように見えます。
   - 詳細な観察が行われていることから、宝石や貴金属の検査、または品質確認の作業である可能性があります。

4. **背景**:
   - 背景はぼやけており、緑色の作業台のようなものが見えます。
   - 作業環境は清潔で整然としている印象を受けます

### 縦軸と横軸
- **縦軸（左側）**: 「プライス軸」と記載されており、下から上に向かって「Low（低価格）」から「High（高価格）」へと進みます。
- **横軸（上部）**: 「Mode（格好いい）」「Feminine（女性らしい）」「Authentic（伝統的/トラディショナル・クラシック）」の3つのカテゴリに分かれています。

・・・略・・・

### 各エリアの説明
1. **Mode（格好いい）エリア**:
   - 左側の緑色の背景部分。
   - 「D社 XXXX+」というブランドが配置されています。
   - このエリアは「格好いい」イメージを持つ製品が含まれています。

2. **Feminine（女性らしい）エリア**:
   - 中央のピンク色の背景部分。
   - 「D社」というブランドが大きく配置されています。
   - 「XXXX of XXXX」という記載も見られます。
   - このエリアは「女性らしい」イメージを持つ製品が含まれています。

3. **Authentic（伝統的/トラディショナル・クラシック）エリア**:
   - 右側の青色の背景部分。
   - 「XXXXXXX D社」というブランドが配置されています。
   - このエリアは「伝統的」または「クラシック」なイメージを持つ製品が含まれています。

### 表形式での整理

| エリア                     | 背景色       | 配置ブランド/製品       | 特徴                     |
|----------------------------|--------------|--------------------------|--------------------------|
| **Mode（格好いい）**       | 緑色         |  D社 XXXX+               | 格好いいイメージ         |
| **Feminine（女性らしい）** | ピンク色     |  D社、XXXX of XXXX      | 女性らしいイメージ       |
| **Authentic（伝統的）**    | 青色         | XXXXXXX D社             | 伝統的/クラシックなイメージ |

・・・略・・・

| 年度（期）         | 売上高（百万円） | 店舗数（店舗） |
|--------------------|------------------|----------------|
| 2023年度（2024年2月期） | 13,597           | 99             |
| 2024年度（2025年2月期） | 15,200           | 109            |
| 2026年度（2027年2月期） | 18,400           | 129            |

・・・以下全部省略
```

コンペ参加者は分かると思うのですが、参加されてない方の為に別サンプルで説明すると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4006424/c1226371-2d87-4aa0-98db-ecd962be7edb.png)
こんなPDFが以下のようにテキストに変換されます。
```
#### DIの構造解析= /sections/0

#### DIの構造解析= /paragraphs/0
(金融庁共催) 第3回金融データ活用チャレンジ

#### DIの構造解析= /paragraphs/1
生成AIを活用して企業のESGレポートや統合報告書に関連する質問に回答しよう!

#### DIの構造解析= /sections/1

#### DIの構造解析= /sections/2

#### DIの構造解析= /paragraphs/2
背景

#### DIの構造解析= /paragraphs/3
近年、企業の持続可能性や社会的責任への関心が高まる中、ESG (環境·社会·ガバナンス)レポートや統合報告書は、企業の透 明性や信頼性を示す重要な情報源として位置付けられています。 しかし、これらの報告書には膨大なデータや詳細な情報が含まれ ており、関係者が必要な情報を迅速かつ的確に把握することは容 易ではありません。

#### DIの構造解析= /paragraphs/4
そこで、本コンペティションでは、企業のESGレポートや統合報 告書に関連する質問に対して自動的かつ正確に回答できるRAGシ ステムの構築を目指します。

#### DIの構造解析= /paragraphs/5
RAGシステムの構造イメージ

#### DIの構造解析= /figures/0
Caption: RAGシステムの構造イメージ
この図は、ユーザーからの質問に基づいて情報を収集し、回答を生成するプロセスを示したフローチャートです。以下に図の構成要素とその流れを詳しく説明します。

---

### 図の全体構成
図は4つの主要なセクションに分かれています：
1. **Retrieve（緑色のセクション）**
2. **Store（黄色のセクション）**
3. **Augment（赤色のセクション）**
4. **Generate（青色のセクション）**

それぞれのセクションが矢印でつながり、情報の流れを示しています。

---

### 詳細なプロセス説明

| ステップ番号 | セクション名 | 説明 |
|--------------|--------------|------|
| **①** | ユーザー → UI | ユーザーが質問を入力します。UI（ユーザーインターフェース）を通じてシステムに質問が送信されます。 |
| **②** | Retrieve | 質問に基づいてデータベース（DB）から関連情報を検索します。 |
| **③** | Retrieve | 検索結果として関連情報を収集します。 |
| **④** | Augment | 質問と収集した関連情報を組み合わせてプロンプトを構築します。 |
| **⑤** | Generate | 構築されたプロンプトを使用して、LLM（大規模言語モデル）が回答を生成します。 |
| **⑥** | UI → ユーザー | 生成された回答がUIを通じてユーザーに返されます。 |

---

### 各セクションの詳細

#### 1. **Retrieve（緑色のセクション）**
- **データベース（DB）**：質問に関連する情報を格納している場所。
- **矢印の流れ**：
  - UIから質問が送られ、データベースに対して検索（②）が行われます。
  - 検索結果として関連情報が収集（③）され、UIに戻されます。

#### 2. **Store（黄色のセクション）**
- **データ整形**：データをPDFや他の形式に変換して保存するプロセス。
- **データの流れ**：
  - データベースに格納されている情報が整形され、PDFなどの形式で利用可能になります。

#### 3. **Augment（赤色のセクション）**
- **プロンプトの構築**：質問と収集した関連情報を組み合わせて、LLMが理解しやすい形式に変換します。
- **矢印の流れ**：
  - Retrieveセクションから収集された情報がここで処理され、次のGenerateセクションに送られます。

#### 4. **Generate（青色のセクション）**
- **LLM（大規模言語モデル）**：質問と関連情報を基に回答を生成するAIモデル。
- **矢印の流れ**：
  - Augmentセクションで構築されたプロンプトを受け取り、回答を生成します。
  - 生成された回答はUIを通じてユーザーに返されます。

---

### 図の視覚的要素
- **色分け**：各セクションが異なる色で示されており、プロセスの流れが視覚的にわかりやすくなっています。
  - Retrieve：緑
  - Store：黄色
  - Augment：赤
  - Generate：青
- **矢印**：情報の流れを示すために使用されています。
  - 緑の矢印：Retrieveセクション内の流れ。
  - 赤の矢印：AugmentからGenerateへの流れ。
  - 青の矢印：GenerateからUIへの流れ。

---

### 補足
- **UI（ユーザーインターフェース）**：ユーザーとシステムの間の接点。
- **PDF**：データ整形の一例として示されていますが、他の形式も含まれる可能性があります。
- **LLM（大規模言語モデル）**：AI技術を活用した回答生成の中核。

---


#### DIの構造解析= /paragraphs/23
課題

#### DIの構造解析= /paragraphs/24
本コンペティションでは、J-LAKE(*パートナー企業であるDATAZORAのKIJIサービス提 供データを含む)の情報を用いてRAGシステムを構築していただきます。提供された データを元に、質問(query.csv) に対する回答を生成し、その回答の精度を競います。 生成した回答は、指定のフォーマットに従い、投稿してください。

#### DIの構造解析= /sections/3

#### DIの構造解析= /paragraphs/25
評価方法

#### DIの構造解析= /paragraphs/26
● 各質問に対する回答の質を測定する方法で評価します。

#### DIの構造解析= /paragraphs/27
● 回答は、以下の基準でLLM(gpt-40)によって「Perfect」「Acceptable」「Missing」「Incorrect」のいずれかに分類さ れ、得点が付与されます。

#### DIの構造解析= /paragraphs/28
● 得点の合計を質問数で割った平均値がスコアとなります。

#### DIの構造解析= /paragraphs/29
· スコアは 、- 1(全てIncorrect) から 1(全てPerfect)の範囲で出力されます。

#### DIの構造解析= /paragraphs/30
· スコアは、回答を投稿いただいた後に、LLMによる評価を1度だけ実行した結果を元にします。

#### DIの構造解析= /paragraphs/31
● temperatureは0に設定してシードも固定していますが、微妙な回答内容の場合はLLMの判断に僅かなゆらぎが発生 することがあります。

#### DIの構造解析= /paragraphs/32
● 本問題は日本語以外の回答も可能ですが、すべて日本語で回答することを前提としています。

#### DIの構造解析= /tables/0
行数: 5
列数: 3

テーブルデータ:
 

分類: Perfect
得点: 1
評価基準: 質問に対して正確に答え、虚偽の内容が含まれていない回答。

分類: Acceptable
得点: 0.5
評価基準: 質問に対して有用な答えを提供しているが、答えの有用性を損なわない程度の軽微な誤りが含まれている回答。

分類: Missing
得点: 0
評価基準: 質問に対して「わかりません」「見つけられませんでした」などの具体的な答えがない回答。

分類: Incorrect
得点: -1
評価基準: 質問に対して間違った、または関連性のない回答。

#### DIの構造解析= /paragraphs/48
※参考:CRAG
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4006424/5c4e494b-f2c5-4d45-9b6e-dd7b3095fbf0.png)
このように解析されておりました。
paragraphs/n の番号が飛ぶのは、figures/n(図) や tables/n(表) 内のテキストにもparagraphsとして抽出されるためですが、不要なので図表の paragraphs はカットしています。

###
~~1枚のPDFだけを処理するサンプルコードをのせておきます~~　すみません、あまりにも分かりずらかったので修正します。
この辺詳しくは、
@nohanaga(Nobusuke Hanagasaki)さんの
[【最新】Azure AI Document Intelligence による文書構造の解析（Markdown、図、セクション）](https://qiita.com/nohanaga/items/1263f4a6bc909b6524c8) 、
@mahiya (Masayuki Hiyama)さんの[Azure Document Intelligence で PDF ファイルから図形を抽出して画像として出力する](https://qiita.com/mahiya/items/48bc924dfd54326cd78c)
を参考にされてください。

###
<details><summary>1枚のPDFだけを処理するサンプルコード</summary>

```

```
</details>

<details><summary>生成AIに図を説明させる(サンプルコードの import figure_vision)</summary>

```

```
</details>

<details><summary>図を切り出す(サンプルコードの from polygon_cut import crop_image_from_file)</summary>

```

```
</details>

:::note warn
途中で分かったこと
Azure Document Intelligenceは表形式をJSONにしてくれますが、
[{"row_count": 29, "column_count": 15, "cells": [{"row_index": 0, "column_index": 0, "content": "国名/地域"}, ・・・

このようなJSONだとハルシネーションが起きました（正しく記述があるのに誤った回答をする唯一のハルシネーションでした）

JSONを生成AIでテキストにする以下のような形にしてあげるとハルシネーションを取ることができました。

#### 各国・地域別データ  
   
1. **中国**  
   - 人口: 1,411.4百万人  
   - GDP: 17,701億米ドル  
   - 一人当たりGDP: 12,541米ドル  
   - 総需要 (億食):  
     - CY2014: 444.0  
     - CY2015: 404.3  
     - CY2016: 385.2  
     - CY2017: 389.6  
     - CY2018: 402.5  
     - CY2019: 414.5  
     - CY2020: 463.6  
     - CY2021: 439.9  
     - CY2022: 450.7  
     - CY2023: 422.1  
   - 一人当たり消費量/年: 29.7食  
   
2. **香港**  
・・・

JSON解釈できるハズなのになぜだろう・・・:thinking:
チャチャっと整形できるのでまぁいいのですが謎です。

```
【JSONのまま】
質問:2023年で即席めんの一人当たりの年間消費量が最も多い国はどこか。
md:18.md
主語=2023年で即席めんの一人当たりの年間消費量
*質問は分解されなかった 内容は、2023年で即席めんの一人当たりの年間消費量が最も多い国はどこか。
{'18_28.md', '18_29.md', '18_32.md', '18_69.md', '18_38.md'}
**2023年で即席めんの一人当たりの年間消費量が最も多い国はどこか。 は 韓国
```
```
【JSONをテキスト化】
質問:2023年で即席めんの一人当たりの年間消費量が最も多い国はどこか。
md:18.md
主語=2023年で即席めんの一人当たりの年間消費量
*質問は分解されなかった 内容は、2023年で即席めんの一人当たりの年間消費量が最も多い国はどこか。
{'18_32.md', '18_69.md', '18_38.md', '18_28.md', '18_29.md'}
**2023年で即席めんの一人当たりの年間消費量が最も多い国はどこか。 は ベトナム
```

:::

# この処理をしたうえで、
## 39工場問題
そうこれです。何工場か？の質問に39工場と回答するこれです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4006424/76dfeafb-c1bc-4dd6-85d5-722826c6adaa.png)
Azure Document Intelligenceで読み取ると、
※5地域39工場
になります。どうやら色やフォントサイズで分けてくれないようです。確かモノクロにして処理しているとも聞いた事があります。

これも生成AIで処理すると、
```
開始時期:
2018年度に初めてグループ内で「CO₂ゼロ工場」を実現。
進展状況:
2021年度までに5地域・9工場で「CO₂ゼロ工場」を達成。
その後、取り組みを拡大フェーズへと移行。
```
読み取ってくれますが、<font color="red">図も表も生成AIで処理させているので、テキストもだともう全部じゃん！！</font>あとテキスト部分を切り取って処理するのも面倒で効率が悪すぎます。
o1やo3などの高位モデルならPDF1ページ全部処理させても正確に読み取ってくれるかもしれませんが、o1持ってないですし、推論するところと、させないところは分けていきたいので、今回はパターン一致によるOCR補正処理をしました。

処理方法は、
&emsp;1.正規表現 ※[0-9]+ で※n を抽出
&emsp;2.並びを見る 39工場のpdfだと[1, 2, 1, 2, 39, 4, 5, 1, 1, 1, 3, 4]こうなります。
&emsp;3.順番に見て行って、自分と自分の一つ先を比べたときに自分より小さい数字のものを補正します。
&emsp;4.ただし次の数字が1だった場合は補正しません。
これでOCR結果の補正をしました。

あと、[1, 2, 1, 2, 1, 2, 2, 3, 4, 5, 12016, 22019, 32022, 4, 5]こんなのもありました。
※1 2016 ※2 2019 ※3 2022 なんでしょうね。
こちらも補正可能ですが、今回は課題と無関係なので補正なしとしてます。

正しい内容を誤変換してしまう可能性もあるので、もっとしっかりロジックを考える必要がありますが、そもそもが間違っていること、ざっと見た限り誤変換することのなかったのでこの方法を採用しています。
※1 ※2 ※39 ※4 の ※4 が ※1だったらダメじゃん！ってのは理解してまして助け方は色々考えないとと思ってます

```
質問:E社グループのCO2ゼロ工場数において、2021年度までに何工場実現しましたか。
md:10.md
主語=E社グループのCO2ゼロ工場数
*2つに質問分解 内容は、{"question":"E社グループのCO2ゼロ工場数は？,2021年度までに実現した工場数は？"}
**分解された質問=E社グループのCO2ゼロ工場数は？
{'10_155.md', '10_42.md', '10_45.md', '10_13.md', '10_12.md'}
====>9工場
****************************************************
**分解された質問=2021年度までに実現した工場数は？
{'10_68.md', '10_155.md', '10_42.md', '10_13.md', '10_62.md'}
====>9工場
```
データが正しければ、回答は簡単:thumbsup_tone1:


## 11年間のチャート問題

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4006424/fcd8a329-16e8-4010-8ab0-57f16eeeeab2.png)
これがどうも解釈できない。。。。

汎用的なプロンプトが書けるかもありますが、まずは正確に解釈できるプロンプトをプレイグラウンドで考えます。
```
prompt
凡例を読み取って
色が重要なので慎重に
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4006424/7cadc1f1-bd23-4857-8b8d-1f6c7b9aa18f.png)
いやちょっと違う。。。

```
prompt
英語で考えて下さい
凡例を読み取って
色が重要なので慎重に
色の判別と色は英語でいいよ
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4006424/cde3f12d-1882-4b64-add2-192cda455969.png)
正しい、このまま課題の問題「セグメント別営業利益において、2014年〜2024年の11年間の海外市場の平均額は何億円か。少数第一位を四捨五入して答えよ。」を投げると、
```
このグラフから読み取れる「海外市場（Cyan / 水色）」の営業利益を2014年から2024年まで合計し、その平均を求めます。以下の手順で計算を進めます。
 

1. 各年の海外市場の営業利益を読み取る
2014年/3: 74億円
2015年/3: 80億円
2016年/3: 92億円
2017年/3: 99億円
2018年/3: 111億円
2019年/3: 87億円
2020年/3: 97億円
2021年/3: 34億円
2022年/3: 47億円
2023年/3: 4億円
2024年/3: 66億円
 

2. 合計を求める
合計を計算します。

[
74 + 80 + 92 + 99 + 111 + 87 + 97 + 34 + 47 + 4 + 66 = 791 , \text{億円}
]
 

3. 平均を求める
11年間の平均を計算します。

[
\text{平均} = \frac{791}{11} \approx 71.91 , \text{億円}
]
 

4. 少数第一位を四捨五入する
[
71.91 , \text{億円} \to 72 , \text{億円}
]
 

答え:
72億円
```
正しく回答してくれました。
ただこれを一律全部の「図のOCR+生成AI」で処理してよいのか？、また、処理したとしてもどれぐらい揺らぎが発生するか？この辺時間切れで今回は断念しました。

:::note info
少し追記
全体影響を避け、また特別なケースとして、複雑な図表を検知してオンデマンドで高度に解析でもいいかも。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4006424/7fba3935-9b25-47ef-8dfd-59410d6b1159.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4006424/e74da82b-11d1-4525-8d71-2a296ebe52c9.png)

```
============================================================================
質問:セグメント別営業利益において、2014年〜2024年の11年間の海外市場の平均額は何億円か。少数第一位を四捨五入して答えよ。
md:7.md
主語=セグメント別営業利益
*質問は分解されなかった 内容は、セグメント別営業利益において、2014年〜2024年の11年間の海外市場の平均額は何億円か。少数第一位を四捨五入して答えよ。
{'7_25.md', '7_81.md', '7_47.md', '7_7.md', '7_22.md'}
**セグメント別営業利益において、2014年〜2024年の11年間の海外市場の平均額は何億円か。少数第一位を四捨五入して答えよ。 は 7_7.md の高度分析が必要です
🤖 7_7.md の高度分析を開始します。
・・・・・
🤖 高度分析が終了しました。
🤖 高度分析結果で回答を生成します。
-----------------回答レビュー-----------------
-----------------回答調整-----------------
セグメント別営業利益において、2014年〜2024年の11年間の海外市場の平均額は何億円か。少数第一位を四捨五入して答えよ。 
=>72億円
==========================
```
実装できそうかも

:::


# OCRまとめ
テキスト&emsp;&emsp;：Azure Document Intelligenceの機能一発でほぼいける + ルールベース補正処理を追加で（だれかライブラリ作ってくれないかな）
表形式&emsp;&emsp;&emsp;：JSONをテキスト化した方が精度が上がるっぽい

図のチャート：解釈できるものの、「問題なくいける場合 ※ほとんどのケースで正しいです」と、図によって（色や細かい表現がある場合など）のプロンプトの切り替えの解決が必要
ここは割り切ってもいいところかもしれませんし、LLMやSML+ファインチューニングで分類させて個別処理させてもいいかもしれません。ちょっとまだ解決方法模索中です。

となりました。


# 最後に
今回この機会で改めてRAGについて考えることができたのと、1年前とは違い精度100%近く出す方法がありそうだなと考えさせられたところで、かなり長い投稿になってしまいましたが、「FDUA 第３回金融データ活用チャレンジに参加してみた！」を終わります。