Phi3 の日本語能力評価をNejumi LLMリーダーボード Neo を使ってやってみる

:::note info
本記事はMicrosoft が2024/04/23 に公開した[Phi-3-mini-128k-instruct](https://huggingface.co/microsoft/Phi-3-mini-128k-instruct) の日本語能力を[Nejumi LLMリーダーボード Neo](https://wandb.ai/wandb-japan/llm-leaderboard/reports/Nejumi-LLM-Neo--Vmlldzo2MTkyMTU0) を使って評価してみた記事になっています。
:::

---
目次
- [1. 背景と概要](#1-背景と概要)
- [2. Nejumi LLMリーダーボード Neo とは](#2-nejumi-llmリーダーボード-neo-とは)
- [3. LLM の日本語評価](#3-llm-の日本語評価)
  - [3.1. モデル共通の準備](#31-モデル共通の準備)
  - [3.2. モデルの設定 （本記事のメイン）](#32-モデルの設定-本記事のメイン)
    - [3.2.1. yaml ファイルの作成](#321-yaml-ファイルの作成)
    - [3.2.2. yaml ファイルの配置](#322-yaml-ファイルの配置)
  - [3.3. テストの実行](#33-テストの実行)
  - [3.4. 本番評価の実行](#34-本番評価の実行)
- [4. まとめ](#4-まとめ)
---

## 1. 背景と概要
昨今新しいモデルが矢継ぎ早にリリースされています。すぐに他のモデルと性能を比較したいものの、リーダーボードに反映されるまで時間がかかることもあります。そのような時に自分で日本語評価を行えるように、2024/05/08 現在リーダーボードに掲載されていないPhi3 の日本語評価を行った手順を記事にいたしました。
大枠はnpaka 先生の記事[「Nejumi LLMリーダーボード Neo の LLMベンチマークの使い方」](https://note.com/npaka/n/n44252e28e70a)を参考にさせていただいております。まだリーダーボードで評価されていないモデルを評価するときに必要だった部分の説明が本記事のメイン部分となっています。


## 2. Nejumi LLMリーダーボード Neo とは

[Nejumi LLMリーダーボード Neo](https://wandb.ai/wandb-japan/llm-leaderboard/reports/Nejumi-LLM-Neo--Vmlldzo2MTkyMTU0) とは、「言語理解（llm-jp-eval）」と「言語生成（MT-Bnech)」という2 つの軸でLLM の日本語能力を評価したランキングのことです。

llm-jp-eval は私も参加しているLLM 勉強会が作成したもので、次のような評価項目があります([参考リンク](https://github.com/llm-jp/llm-jp-eval/blob/main/DATASET.md))。
- NLI (Natural Language Inference)
- QA (Question Answering)
- RC (Reading Comprehension)
- MC (Multiple Choice question answering)
- EL (Entity Linking)
- FA (Fundamental Analysis)
- MR (Mathematical Reasoning)
- STS (Semantic Textual Similarity)
- HE (Human Examination)

実際に業務で使えるかを判断するには、（STS とHE を除いた項目の平均値であるAVG_jaster ではなく）個々のタスクの点数を見ると良いかもしれません。

MT-Bench は、対話形式でのテキスト生成能力を評価するベンチマークになっています。評価はGPT-4 によって行われます（そのため、gpt 系モデルが良く評価されている可能性がある）。評価項目は以下です。
- coding
- extraction
- humanities
- math
- reasoning
- roleplay
- stem
- writing

項目にroleplay があるのが面白いですね。評価が難しそうです。


## 3. LLM の日本語評価
基本的にはnpaka 先生の記事[「Nejumi LLMリーダーボード Neo の LLMベンチマークの使い方」](https://note.com/npaka/n/n44252e28e70a)と同じです。モデルの設定部分について注意が必要な部分をより詳細に書いています。

### 3.1. モデル共通の準備
1. Google Colab を開き、「ツール」→「ランライムの変更」を選択する
![スクリーンショット 2024-05-08 18.59.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624969/a27e02a9-766b-219a-48d9-a41158657f38.png)

2. A100 を選択し「保存」を押下する
![スクリーンショット 2024-05-08 19.02.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624969/397285ef-c178-9315-0cdc-9f484286c545.png)

3. Code ブロックで以下を実行する
```python
!git clone --recurse-submodules https://github.com/wandb/llm-leaderboard
%cd llm-leaderboard
!pip install -r requirements.txt
```
　
4. 左枠にある鍵アイコンを押下し、OpenAI でアカウント登録して作成したAPI キーを値の部分にコピペする。名前部分は`OPENAI_API_KEY` とし、ノートブックからのアクセスを ON にする。
![スクリーンショット 2024-05-08 19.05.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624969/2a4202a3-dce6-dd70-856f-b670664f8da8.png)
　
5. 環境変数の設定を行う。`import openai` 入れないとMT-Bench の評価ができなかったため、追加している。
```python
# 環境変数の設定
import os
import openai # 追加
from google.colab import userdata
os.environ["OPENAI_API_KEY"] = userdata.get("OPENAI_API_KEY")
os.environ["PYTHONIOENCODING"] = "utf-8"
os.environ["LANG"] = "ja_JP.UTF-8"
```

### 3.2. モデルの設定 （本記事のメイン）
設定ファイルである「config.yaml」を作成して、「configs」フォルダ直下に配置する。

#### 3.2.1. yaml ファイルの作成
モデルのhugging face におけるpath やシステムプロンプトを設定していく。今回Phi3 での評価には以下のようなconfig.yaml ファイルを作成し使用した。作成にあたっては、リーダーボードに載っているモデルのyaml ファイルが参考になった（[リンク](https://wandb.ai/wandb-japan/llm-leaderboard/artifacts/config/config/v291/files/config.yaml)）。

```yaml:config.yaml
wandb:
  log: True
  entity: "<Your wandb account>"
  project: "llm-leaderboard"
  run_name: "microsoft/Phi-3-mini-128k-instruct"

github_version: "2.0.0"

testmode: true

# if you don't use api, please set "api" as "false"
# if you use api, please select from "openai", "anthoropic", "google", "cohere"
api: false

model:
  _target_: transformers.AutoModelForCausalLM.from_pretrained
  pretrained_model_name_or_path: "microsoft/Phi-3-mini-128k-instruct" #if you use openai api, put the name of model
  trust_remote_code: true
  device_map: "auto"
  load_in_8bit: false
  load_in_4bit: false
  use_wandb_artifacts: false

generator:
  top_p: 1.0
  top_k: 0
  temperature: 0.1
  repetition_penalty: 1.0

tokenizer:
  pretrained_model_name_or_path: "microsoft/Phi-3-mini-128k-instruct"
  use_fast: true

# for llm-jp-eval
max_seq_length: 2048
dataset_artifact: "wandb-japan/llm-leaderboard/jaster:v3" #url of wandb reference artifacts
dataset_dir: "/jaster/1.1.0/evaluation/test"
target_dataset: "all"
log_dir: "./logs"
torch_dtype: "bf16" # {fp16, bf16, fp32}
custom_prompt_template: null
# 以下のようなプロンプトにすると、スコアが下がるため一旦null としている。
# "
\n以下はタスクを説明する指示と、追加の背景情報を提供する入力の組み合わせです。要求を適切に満たす回答を書いてください。\n\n {instruction} \n\n {input} 
\n\n
"
custom_fewshots_template: null

metainfo:
  basemodel_name: "microsoft/Phi-3-mini-128k-instruct"
  model_type: "open llm" # {open llm, commercial api}
  instruction_tuning_method: "None" # {"None", "Full", "LoRA", ...}
  instruction_tuning_data: ["None"] # {"None", "jaster", "dolly_ja", "oasst_ja", ...}
  num_few_shots: 0
  llm-jp-eval-version: "1.1.0"

# for mtbench
mtbench:
  question_artifacts_path: 'wandb-japan/llm-leaderboard/mtbench_ja_question:v0' # if testmode is true, small dataset will be used
  referenceanswer_artifacts_path: 'wandb-japan/llm-leaderboard/mtbench_ja_referenceanswer:v0' # if testmode is true, small dataset will be used
  judge_prompt_artifacts_path: 'wandb-japan/llm-leaderboard/mtbench_ja_prompt:v1'
  bench_name: 'japanese_mt_bench'
  model_id: null # cannot use '<', '>', ':', '"', '/', '\\', '|', '?', '*', '.'
  question_begin: null
  question_end: null
  max_new_token: 1024
  num_choices: 1
  num_gpus_per_model: 1
  num_gpus_total: 1
  max_gpu_memory: null
  dtype: bfloat16 # None or float32 or float16 or bfloat16
  # for gen_judgment
  judge_model: 'gpt-4'
  mode: 'single'
  baseline_model: null
  parallel: 1
  first_n: null
  # for conv template # added
  custom_conv_template: true
  # the following variables will be used when custom_conv_template is set as true
  conv_name: "custom"
  conv_system_message: "
\n以下は、タスクを説明する指示と、文脈のある入力の組み合わせです。要求を適切に満たす応答を書きなさい。
\n
"
  conv_roles: "('
', '
')"
  conv_sep: "\n\n### "
  conv_stop_token_ids: "[2]"
  conv_stop_str: "###"
  conv_role_message_separator: ": \n"
  conv_role_only_separator: ": \n"
```

新しいモデルを評価したいときに変更する部分は以下の項目である。
- アカウント名
    -`entity: "<Your wandb account>" `
Wandb に登録したアカウント名〇〇を`entity: "〇〇" `のように入れる。他の言い方で言うと、
    - 個人ページの左上に表示されるアカウント名
    - Profile をシェアしようとすると、`wandb.ai/〇〇` のように表示される、〇〇

　
- モデルのpath
    - `run_name: "microsoft/Phi-3-mini-128k-instruct"`
    - `pretrained_model_name_or_path: "microsoft/Phi-3-mini-128k-instruct"`
    - `pretrained_model_name_or_path: "microsoft/Phi-3-mini-128k-instruct"`
    - `basemodel_name: "microsoft/Phi-3-mini-128k-instruct"`

※Hugging Face のモデルのpath からコピペする(phi3 は[こちら](https://huggingface.co/microsoft/Phi-3-mini-128k-instruct))。
![スクリーンショット 2024-05-09 13.12.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624969/de22a33f-f08b-46b6-076f-02707a1c14b6.png)

　
- プロンプト
    - llm-jp-eval 用のプロンプト
        - `custom_prompt_template: null`
        - `custom_fewshots_template: null`
    - MT-Bench 用のプロンプト
        - `conv_system_message: "
\n以下は、タスクを説明する指示と、文脈のある入力の組み合わせです。要求を適切に満たす応答を書きなさい。
\n
"`
        - `conv_roles: "('
', '
')"`

※基本的に各モデルに指定された（学習に使用された）プロンプト様式があるので、それに従う（Phi-3 は[こちら](https://huggingface.co/microsoft/Phi-3-mini-128k-instruct)を参考にした）。ただ、llm-jp-eval の方では逆にスコアが下がってしまったので、null としている（llm-jp-eval のプロンプトの様式が問題か。特定のプロンプト様式になってしまっている気がする）。ちなみに、MT-Bench ではプロンプト様式を設定すると、全体的にスコアの上昇が見られた。

　
- 文を分ける記号separator 等
    - `conv_sep: "\n\n### "`
    - `conv_stop_str: "###"`
    - `conv_role_message_separator: ": \n"`
    - `conv_role_only_separator: ": \n"`

※phi 系モデルのyaml ファイルはなかったため、gpt-4-turbo のyaml ファイルを参考に設定した。
※参考になりそうなyaml ファイルは以下である。
- [v291: Claude-Opus](https://wandb.ai/wandb-japan/llm-leaderboard/artifacts/config/config/v291/files/config.yaml)
- [v280: Command-R+](https://wandb.ai/wandb-japan/llm-leaderboard/artifacts/config/config/v280/files/config.yaml)
- [v250: Gemini Pro 1.5](https://wandb.ai/wandb-japan/llm-leaderboard/artifacts/config/config/v250/files/config.yaml)
- [v248: GPT-4-turbo-0409](https://wandb.ai/wandb-japan/llm-leaderboard/artifacts/config/config/v248/files/config.yaml)
- [v245: Llama-3 70B](https://wandb.ai/wandb-japan/llm-leaderboard/artifacts/config/config/v245/files/config.yaml)
- v242: Llama-3 8B
- v217: Mistral-large
- v215: Gemma-2B
- v208: gpt-3.5-turbo
- v191: ELYZA 13B
- v142: Calm2
- v134: Mistral 7B
- v110: Qarasu 14B
- v48: Mixtral



#### 3.2.2. yaml ファイルの配置
「config.yaml」を作成したら、「configs」フォルダ直下に配置する。
![スクリーンショット 2024-05-08 20.00.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624969/da1c9609-828d-5b55-2632-edda9a8296a6.png)



### 3.3. テストの実行
上記で設定したyaml ファイルで、`testmode: true`　とすると、少ないデータでの評価が行える。モデルによって実行時間は変わる。上記設定のPhi3 では終了までに20 分ほどかかった。OpenAI のAPI の利用料金は9 ドルほどだった。

```python
# 評価テストの実行
!python scripts/run_eval.py
```
私はシステムプロンプト（`custom_prompt_template` など）の良し悪しをこのテスト部分で試した。システムプロンプトでスコアがかなり変わる印象を受けた。適切なプロンプトが大事。適切かどうか分からない場合は一旦null で良いと思う。

テストが無事に終わったら、以下のようなリンクが出力されるので結果を確認する。
![スクリーンショット 2024-05-08 20.03.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624969/501435c8-6b9a-b3ce-d4e3-8a7d699fb7ec.png)

下記のような画面に遷移する。「Export as CSV」を押下すると、csv ファイルをダウンロードできる。
![スクリーンショット 2024-05-08 20.05.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624969/2b4c376a-49b6-e786-bada-64504228f2e7.png)
また、Tables の右下のボタンから他のテーブルへ遷移できる。
![スクリーンショット 2024-05-08 20.07.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624969/535c24f4-bda8-ac50-fb92-8b8260386d3c.png)


### 3.4. 本番評価の実行
テスト段階でしっかりと結果が出されていれば、いよいよ本番の評価に移る。Phi3 において実行時間は4時間近くかかった。
上記で設定したyaml ファイルで、`testmode: false`　とし、テスト評価と同じコードを実行すれば良い。
```python
# 本番評価の実行
!python scripts/run_eval.py
```

評価結果はテスト評価時と同様にして見ることができる。MT-Bench の平均値は5.688 で、jaster の平均値は0.3622 であった。
![スクリーンショット 2024-05-08 21.21.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624969/3f9c7824-85e5-442f-b8c8-d365f4001bea.png)
![スクリーンショット 2024-05-08 21.21.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624969/95626ca0-4105-1e4b-ddf9-9515371289d2.png)


また、自分で評価した結果はNejumi LLM リーダーボード Neo に追加することができ、既にリーダーボードにあるモデルと比較することができる。その方法はnpaka 先生の記事[「Nejumi LLMリーダーボード Neo の LLMベンチマークの使い方」](https://note.com/npaka/n/n44252e28e70a)を参照にしていただきたい。


## 4. まとめ
本記事では、Nejumi LLM リーダーボード Neo に掲載されていないモデルについて評価を行う方法をご紹介いたしました。他の方のお役に立てれば幸いです。