LINEのjapanese-large-lm-instruction-sftをDatabricksで試す

**一日に何度も大きなニュースを出すんじゃない！楽しいじゃないか！**

というわけで、LINE社の日本語LLMにInstruction Tuningしたモデルがリリースされましたので、試します。

https://engineering.linecorp.com/ja/blog/3.6b-japanese-language-model-with-improved-dialog-performance-by-instruction-tuning

流れは、前回の下記記事と同様です。

https://qiita.com/isanakamishiro2/items/159ae600bb999ba6d1c0

なお、今回は推論含めて全てGPU無しのクラスタ(ノードタイプ:i3.xlarge)で実行しています。

# 準備

必要なモジュールをインストール。
```python
%pip install -U -qq ctranslate2 sentencepiece transformers accelerate
dbutils.library.restartPython()
```

その上で、hugginface hubからモデルをダウンロード。
モデルが```line-corporation/japanese-large-lm-3.6b-instruction-sft```であること以外は前記事と同様です。

# 準備2

transformersのサンプルコードは[公式](https://huggingface.co/line-corporation/japanese-large-lm-3.6b-instruction-sft)にあるので割愛することにし、最初からCTranslate2に変換します。

src_pathはhuggingfaceモデルの保管場所、output_dirは変換モデルを保管する場所です。

```python
!ct2-transformers-converter --model {src_path} --copy_files spiece.model tokenizer_config.json special_tokens_map.json --output_dir {output_dir} --quantization int8_bfloat16 --low_cpu_mem_usage
```

# CTranslate2で推論

では、やってみましょう。
※推論結果は量子化によって多少精度が落ちている可能性があります。
Promptは```ユーザ:``` と ```システム:```で指定する形式ですね。

```python
import ctranslate2
import transformers
import torch

model_path = "変換済みモデルのパス"

# ジェネレーターとトークナイザーの準備
device = "cuda" if torch.cuda.is_available() else "cpu"
generator = ctranslate2.Generator(model_path, device=device)
tokenizer = transformers.AutoTokenizer.from_pretrained(model_path, use_fast=False)
```

```python
def generate_batch(instruction:str) -> str:

    prompt = f"ユーザー: {instruction}\nシステム: "

    # 推論の実行
    tokens = tokenizer.convert_ids_to_tokens(
        tokenizer.encode(prompt, add_special_tokens=False)
    )
    results = generator.generate_batch(
        [tokens],
        max_length=256,
        sampling_topk=10,
        sampling_temperature=0.1,
        repetition_penalty=1.1,
        include_prompt_in_result=False,
        cache_static_prompt=True,
        return_scores=True,
    )

    text = tokenizer.decode(results[0].sequences_ids[0])
    return text
```

## 日本語質問①

```python
print(generate_batch("四国の県名を全て列挙してください。"))
```

```:結果
四国は4県で構成されている:
- 徳島県
- 香川県
- 愛媛県
- 高知県
```
公式サンプル。ちゃんとできてますね。

## 日本語質問②

```python
print(generate_batch("大規模言語モデルについて説明してください。"))
```

```:結果
大規模言語モデル(LLM)は、大量のテキストデータでトレーニングされた大規模な言語モデルです。LLMは、特定のタスクを実行するように訓練されており、そのタスクに関連するパターンと知識に基づいて回答を生成することができます。

LLMは通常、自然言語処理(NLP)タスクに使用されます。これは、人間が理解できる自然言語のテキストデータを処理するタスクです。LLMは、テキストデータのパターンを学習し、新しいテキスト入力の予測を行うために使用できます。これにより、NLPアプリケーションのパフォーマンスを大幅に改善できます。

たとえば、医療画像分類や金融サービスなどの特定のドメインの問題に対するLLMの有効性が実証されています。これらのドメインでは、LLMSを使用して、画像内のオブジェクトの種類を特定したり、金融資産の価値を評価したりすることができます。

全体として、LLMは、従来の機械学習アルゴリズムよりも幅広い分野で使用できる強力なツールになります。
```
すごい、とてもそれっぽい。

## 英語質問

```python
print(generate_batch("Tell me 5 key points to success the business"))
```

```:結果
1. UX(ユーザーエクスペリエンス)
2. CTA(コールトゥアクション)
3. ASO(アプリストア最適化)
4. CPA(顧客獲得単価)
5. KPI(重要業績評価指標)
```
これはどう考えたらいいのか。。。


## 日本語要約

```python
# 織田信長のWikipediaの一部を要約させる
# https://ja.wikipedia.org/wiki/%E7%B9%94%E7%94%B0%E4%BF%A1%E9%95%B7

print(generate_batch("""
以下の文章から、織田信長がどういった人物だったかを40文字程度で要約しなさい。

織田 信長（おだ のぶなが）は、日本の戦国時代から安土桃山時代にかけての武将・大名。戦国の三英傑の一人。

尾張国（現在の愛知県）出身。織田信秀の嫡男。家督争いの混乱を収めた後に、桶狭間の戦いで今川義元を討ち取り、勢力を拡大した。足利義昭を奉じて上洛し、後には義昭を追放することで、畿内を中心に独自の中央政権（「織田政権」[注釈 4]）を確立して天下人となった戦国時代を代表する英雄である[2]。しかし、天正10年6月2日（1582年6月21日）、家臣・明智光秀に謀反を起こされ、本能寺で自害した。

これまで信長の政権は、豊臣秀吉による豊臣政権、徳川家康が開いた江戸幕府への流れをつくった画期的なもので、その政治手法も革新的なものであるとみなされてきた[3]。しかし、近年の歴史学界ではその政策の前時代性が指摘されるようになり、しばしば「中世社会の最終段階」とも評され[3]、その革新性を否定する研究が主流となっている[4][5]。      
"""))
```

```:結果
織田信長は、1534年に尾張の守護・斯波氏の一族として生まれた。若くして頭角を現し、織田家の家督争いでは有力な後継者の一人となった。その後、織田氏は守護の地位を取り戻し、尾張と美濃の一部を支配する大勢力となる。しかし、その力はやがて衰え、守護代や国人領主が台頭した。信長はこの時代の転換点に立ち会い、新興の豪族である今川氏や斎藤氏などの有力な大名を打ち破った。桶狭間の戦いで今川義元を破り、戦国乱世における新たな時代を切り開いたのである。

信長は、軍事的才能だけでなく、外交的な手腕でも知られていた。彼は、敵対していた武田信玄や上杉謙信など他の有力な戦国大名とも同盟を結び、領土を拡大していった。また、キリスト教の布教を積極的に支援し、南蛮貿易によって得た莫大な富をもとに、独自の中央政権を確立して天下統一を果たした。しかし、天正10年6月2日(1582年6月21日)、家臣であった明智光秀による本能寺の変により、
```
「以下の文章から」が無視されているかな。
おそらく元々の知識から回答してますし、40文字程度という指定を無視していますね。
ただ、プロンプトの入れ方に問題がある気がするので、そこの改善で直るかも。

# まとめ
少し触っただけですが、3.6Bというパラメータ数の割に、非常によくできたLLMだと思います。
この規模だとCPUでの推論でも実用に耐えそうですし、ユースケースによっては非常に有用なモデルだと思いました。
日本でもオープンソースのLLMがどんどん盛り上がっていくことを願っています。

# おまけ

パクリですが。。

```python
print(generate_batch("まどか☆マギカでは誰が一番かわいい？"))
```

```:結果
ほむらです。
```
ほむほむ可愛いよね。