Module-LLMのNPU用モデルへ変換する(InternVL2編)

## 目的
　Module-LLM(ax630c)のNPUでInternVL2を動かすために、InternVL2のVLMモデルをaxmodelへの変換を行います。

本記事はこちらを元に翻訳して作成しました。

https://zhuanlan.zhihu.com/p/4118849355


## 背景

InternVL2（中国語名：書生·万象）は上海人工知能研究所のOpenGVLabが発表したマルチモーダル大規模モデルです。このモデルは、マルチ分野質問応答（MMMU）などのタスクで優れた性能を示し、多様なモーダルデータを処理する能力を備えています。

本稿では、InternVL2ファミリーの中で最小のInternVL2-1Bモデルを通じて、その技術的特徴を概観的に紹介します。同時に、アイチップスマートのAX650NとAX630Cという2つのエッジAIチップでInternVL2-1Bを適用する基本的な方法も共有します。これにより、エッジ側でのマルチモーダル大規模モデル展開に関わる開発者に新しい視点を提供し、エッジ側でのマルチモーダル大規模モデルの探求を促進することを目指します。

InternVL2-1B

GitHubリポジトリ：https://github.com/OpenGVLab/InternVL
公式ブログ：InternVL2 https://link.zhihu.com/?target=https%3A//internvl.github.io/blog/2024-07-02-InternVL-2.0/
オンラインデモ：https://internvl.opengvlab.com/

### 特徴
- マルチモーダル処理能力：
- より大規模なバージョンと同様に、InternVL2-1Bは画像とテキストデータの統合処理をサポートし、クロスモーダルコンテンツの理解と生成を目指しています。

- 軽量化設計：
- 1Bパラメータ規模は比較的小さなモデルサイズを意味し、これによりInternVL2-1Bはモバイルデバイスやエッジコンピューティングなど、リソースが制限された環境への展開に適しています。パラメータは少ないものの、緻密な設計により良好な性能を維持しています。

- 段階的アライメント学習戦略：
- 小から大へ、粗から精へという方式で学習を行い、より少ない計算リソースで高い効果を達成すると同時に、モデルの知識転移能力も促進しています。

- 効率的なアーキテクチャ設計：
- 限られたパラメータで最適な性能を実現するため、InternVL2-1Bは特別に最適化されたネットワーク構造や注意機構を採用し、少ないパラメータ数でも効果的に複雑な視覚言語の関連性を捉えることができます。

- 多様なダウンストリームタスクのサポート：
- 小型モデルではあ- りますが、InternVL2-1Bは画像説明生成や視覚的質問応答など、一連の基本的な視覚-言語タスクを実行でき、ユーザーに一定の機能の多様性を提供しています。

- オープンソースコードとモデルの重み
OpenGVLabの一貫した方針に従い、InternVL2-1Bのコードと事前学習モデルもオープンソースで提供され、研究者や開発者が利用しやすくなっています。




## Pulsar2のインストール

まずPulsar2 ドキュメントの「開発環境準備」セクションに従って、dockerイメージをインストールしPulsar2のdocker環境に入っていることを前提とします。

https://qiita.com/nnn112358/items/37a4dac27bca23ec7754#pulsar2%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

https://pulsar2-docs.readthedocs.io/en/latest/user_guides_quick/quick_start_prepare.html#dev-env-prepare

## ax-llm-buildプロジェクトのダウンロードと実行

ax-llm-buildは、LLMとVLMをコンパイルする際に必要な各種補助ツールやスクリプトファイルを一時的に格納するためのリポジトリです

## ax-llm-buildとは

Pulsar2ツールチェインでは、CVモデルの変換には、pulsar2 llm_buildコマンドを使いましたが、LLMモデルの変換には、pulsar2 llm_buildコマンドを使います。

```bash
usage: pulsar2 llm_build [-h] [--input_path INPUT_PATH] [--output_path OUTPUT_PATH] [--prefill_len PREFILL_LEN]
                        [--parallel PARALLEL] [--model_config MODEL_CONFIG] [--kv_cache_len KV_CACHE_LEN]
                        [--post_topk POST_TOPK] [--post_weight_type {bf16,s8}] [-t {fp16,bf16,fp32}]
                        [-w {fp16,bf16,fp32,s8,s4}] [-c CHECK_LEVEL] [--chip {AX620E,AX650}] [--prompt PROMPT]

オプション引数:
-h, --help            ヘルプメッセージを表示して終了
--input_path INPUT_PATH
                        モデルまたはnpyファイルのパス
--output_path OUTPUT_PATH
                        出力するax_modelのパス
--prefill_len PREFILL_LEN
                        プリフィルのトークン長
--parallel PARALLEL   ビルド並列数
--model_config MODEL_CONFIG
                        設定ファイル
--kv_cache_len KV_CACHE_LEN
                        kv_cacheの長さ
--post_topk POST_TOPK
                        モデル出力のインデックスと確率
--post_weight_type {bf16,s8}
                        ポスト重み型
-t {fp16,bf16,fp32}, --hidden_state_type {fp16,bf16,fp32}
                        隠れ状態のデータ型
-w {fp16,bf16,fp32,s8,s4}, --weight_type {fp16,bf16,fp32,s8,s4}
                        重みのデータ型
-c CHECK_LEVEL, --check_level CHECK_LEVEL
                        チェックレベル 0:実行 1:レイヤーチェック 2:計算 1+1
--chip {AX620E,AX650}
                        チップ
--prompt PROMPT       check_level==2の場合のプロンプト
```


## InternVL2-1Bのダウンロード:

AXERA-TECHのax-llm-buildプロジェクトをダウンロードします。
huggingface_hubから、InternVL2-1BのLLMモデルをダウンロードします。

```bash
git clone https://github.com/AXERA-TECH/ax-llm-build.git
cd ax-llm-build
pip install -U huggingface_hub
mkdir -p OpenGVLab/InternVL2-1B/
huggingface-cli download --resume-download OpenGVLab/InternVL2-1B/ --local-dir OpenGVLab/InternVL2-1B/
```

## LLMモデルの変換

InternVL2-1BのLLMモデルをpulsar2 llm_buildでAXモデルへの変換を行います。

```bash
pulsar2 llm_build --input_path OpenGVLab/InternVL2-1B/ --output_path OpenGVLab/InternVL2-1B-AX620E --kv_cache_len 1023 --hidden_state_type bf16 --prefill_len 128 --chip AX620E
```

## 埋め込み処理と最適化:

```bash
chmod +x ./tools/fp32_to_bf16
chmod +x ./tools/embed_process.sh
./tools/embed_process.sh OpenGVLab/InternVL2-1B/ OpenGVLab/InternVL2-1B-ax650

```


## 出力されるファイル

最終的にInternVL2-1B-ax620Eディレクトリには以下のファイルが含まれます：

```bash
OpenGVLab/InternVL2-1B-ax620E/
├── intervl_vision_part_224.axmodel         // vit-lモデル (325MB)
├── model.embed_tokens.weight.bfloat16.bin  // 埋め込みファイル (259MB)
├── qwen2_p128_l0_together.axmodel          // llmレイヤー (16MB)
├── qwen2_p128_l10_together.axmodel         // 以下同様のレイヤーファイル
...
├── qwen2_p128_l9_together.axmodel
└── qwen2_post.axmodel                      // 後処理モデル (141MB)
```


## 補足

こちらで変換するInternVL2のモデルは、pulsar2の開発者であるqqc 氏によって、実行するバイナリとあわせて公開されています。単にModule-LLMでお試しする場合はこちらのファイルの入手が推奨です。

ファイル構成：
- run_internelvl2.sh - 実行スクリプト
- main_internvl - メインプログラム
- internvlフォルダ - プリコンパイル済みのモデルファイルと埋め込みファイルを含む
- internvl_tokenizer.py - transformerライブラリベースのtokenizerパーサーサービス
- readme.txt - ボード上での実行手順と注意事項
- 

<blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://t.co/Bmlc5O70oh">https://t.co/Bmlc5O70oh</a> We will periodically update some commonly used open-source models. Welcome to use them.such as YOLO11、YOLO World v2、DepthAnything……</p>&mdash; qqc (@qqc1989) <a href="https://twitter.com/qqc1989/status/1855507945989038424?ref_src=twsrc%5Etfw">November 10, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>