Closed4

今更ながら「Transformers」に入門する ⑥TUTORIALS: Chatting with Transformers

kun432kun432

Chatting with Transformers

https://huggingface.co/docs/transformers/v4.48.0/en/conversations

いわゆるチャットモデルの使い方についてのチュートリアルになっている。

このチュートリアルは日本語が用意されていないので注意。

準備

Colaboratory T4で。

!pip install -U transformers bitsandbytes
!pip install torch
!pip freeze | egrep -i "transformers|bitsandbytes|torch"
出力
bitsandbytes==0.45.0
sentence-transformers==3.3.1
torch @ https://download.pytorch.org/whl/cu121_full/torch-2.5.1%2Bcu121-cp310-cp310-linux_x86_64.whl
torchaudio @ https://download.pytorch.org/whl/cu121/torchaudio-2.5.1%2Bcu121-cp310-cp310-linux_x86_64.whl
torchsummary==1.5.1
torchvision @ https://download.pytorch.org/whl/cu121/torchvision-0.20.1%2Bcu121-cp310-cp310-linux_x86_64.whl
transformers==4.48.0

Quickstart

以下のモデルを使用させていただく。

https://huggingface.co/AXCXEPT/llm-jp-3-3.7b-instruct-EZO-Humanities

まずはパイプラインを使ったシンプルなパターン。

モデルのダウンロード&ロード。

import torch
from transformers import pipeline

pipe = pipeline(
    "text-generation",
    "AXCXEPT/llm-jp-3-3.7b-instruct-EZO-Humanities",
    torch_dtype=torch.bfloat16,
    device_map="auto"
)

よくある会話履歴フォーマットを作成する。

chat = [
    {
        "role": "system",
        "content": "あなたは親切な日本語のアシスタントです。ユーザの質問に対して簡潔に答えます。" 
    },
    {
        "role": "user",
        "content": "神戸でオススメの観光スポットを5つリストアップして。"
    }
]

推論。

response = pipe(chat, max_new_tokens=1024)
print(response[0]['generated_text'][-1]['content'])
出力
神戸は異国情緒あふれる港町で、美しい景観と豊かな文化が魅力の都市です。以下に、神戸でオススメの観光スポットを5つご紹介します。

1.北野異人館街
神戸の異人館街は、明治時代に外国人が住んでいた洋館が立ち並ぶエリアです。「風見鶏の館」や「萌黄の館」、「うろこの家」など、異国情緒あふれる建物が点在しています。

2.南京町
神戸の中華街で、約100軒の店舗が軒を連ねています。中華料理の食べ歩きや、点心の購入が楽しめます。

3.神戸ポートタワー
神戸港のシンボルで、展望台からは神戸の街並みや海を一望できます。夜にはライトアップされ、美しい夜景が広がります。

4.神戸ハーバーランド
ショッピングモールやレストラン、映画館などが集まる複合施設です。モザイクガーデンやumieなどの商業施設が立ち並び、家族連れやカップルに人気です。

5.神戸北野美術館
北野異人館街にある美術館で、国内外の名画や彫刻が展示されています。


神戸は美しい街並みと豊かな文化が融合した魅力的な都市です。ぜひ、訪れてみてください。

レスポンスにはすべての会話履歴が含まれている。

import json

print(json.dumps(response, indent=2, ensure_ascii=False))
出力
[
  {
    "generated_text": [
      {
        "role": "system",
        "content": "あなたは親切な日本語のアシスタントです。ユーザの質問に対して簡潔に答えます。"
      },
      {
        "role": "user",
        "content": "神戸でオススメの観光スポットを5つリストアップして。"
      },
      {
        "role": "assistant",
        "content": "神戸は異国情緒あふれる港町で、美しい景観と豊かな文化が魅力の都市です。以下に、神戸でオススメの観光スポットを5つご紹介します。\n\n1.北野異人館街\n神戸の異人館街は、明治時代に外国人が住んでいた洋館が立ち並ぶエリアです。「風見鶏の館」や「萌黄の館」、「うろこの家」など、異国情緒あふれる建物が点在しています。\n\n2.南京町\n神戸の中華街で、約100軒の店舗が軒を連ねています。中華料理の食べ歩きや、点心の購入が楽しめます。\n\n3.神戸ポートタワー\n神戸港のシンボルで、展望台からは神戸の街並みや海を一望できます。夜にはライトアップされ、美しい夜景が広がります。\n\n4.神戸ハーバーランド\nショッピングモールやレストラン、映画館などが集まる複合施設です。モザイクガーデンやumieなどの商業施設が立ち並び、家族連れやカップルに人気です。\n\n5.神戸北野美術館\n北野異人館街にある美術館で、国内外の名画や彫刻が展示されています。\n\n\n神戸は美しい街並みと豊かな文化が融合した魅力的な都市です。ぜひ、訪れてみてください。"
      }
    ]
  }
]

よって、これに新しいメッセージを追加すれば、会話が継続する。

chat = response[0]['generated_text']
chat.append(
    {"role": "user", "content": "ありがとう。その中で一番を選ぶとすれば、どれがオススメ?"}
)
response = pipe(chat, max_new_tokens=1024)
print(response[0]['generated_text'][-1]['content'])
出力
神戸の観光スポットの中で一番を選ぶのは難しいですが、以下の理由から「北野異人館街」をオススメします。

1. 歴史的背景:
   - 北野異人館街は、明治時代に外国人が住んでいた洋館が多く、当時の生活様式や文化を感じることができます。
   - 各館のガイドツアーや展示を通じて、当時の生活や歴史を深く知ることができます。

2. 多様な建物:
   - 「風見鶏の館」や「萌黄の館」、「うろこの家」など、異なる建築様式の洋館が立ち並び、それぞれが個性的で魅力的です。
   -洋館の内部を見学することで、当時の生活環境や家具、装飾品などを直接目にすることができます。

3. 美しい景観:
   - 北野異人館街は、神戸の市街地から少し離れた場所に位置しており、静かで落ち着いた雰囲気があります。
   - 街並み全体が絵になる風景で、写真撮影にも最適です。

4. アクセスの良さ:
   - JR三ノ宮駅から徒歩圏内にあり、公共交通機関を利用しやすいです。
   - 周辺にはカフェやレストランも多く、休憩や食事を楽しむこともできます。

5. 季節ごとのイベント:
   - 春には桜の名所としても知られ、秋には紅葉が楽しめます。
   - 季節ごとに異なる魅力を楽しむことができる点も魅力的です。

以上の理由から、「北野異人館街」は神戸の観光スポットとして特にオススメです。

パイプラインを使わずにAutoModel・AutoTokenizerを使って書くと以下となる(上から続けて実行する場合はランタイム再起動だけしておくと良い)

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

# チャットプロンプト
chat = [
    {
        "role": "system",
        "content": "あなたは親切な日本語のアシスタントです。ユーザの質問に対して簡潔に答えます。" 
    },
    {
        "role": "user",
        "content": "神戸でオススメの観光スポットを5つリストアップして。"
    }
]

# 1: モデルとトークナイザーをロード
model_id = "AXCXEPT/llm-jp-3-3.7b-instruct-EZO-Humanities"
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    device_map="auto",
    torch_dtype=torch.bfloat16
)
tokenizer = AutoTokenizer.from_pretrained(model_id)

# 2: チャットにテンプレートを適用
formatted_chat = tokenizer.apply_chat_template(
    chat,
    tokenize=False,
    add_generation_prompt=True
)
print("フォーマット化されたチャット:\n====\n", formatted_chat, "\n====\n")

# 3: チャットをトークン化(一つ上でtokenize=Trueを付与すればここは省略できる)
inputs = tokenizer(
    formatted_chat,
    return_tensors="pt",
    add_special_tokens=False
)

# トークン化された入力をモデルが配置されている同じデバイス (GPU/CPU) に移動
# 追記: token_type_idsはこのモデルでは使用されず、そのままだとエラーになるので取り除く
inputs = {key: tensor.to(model.device) for key, tensor in inputs.items() if key != "token_type_ids"}
print("トークン化された入力:\n====\n", inputs, "\n====\n")

# 4: モデルからテキストを生成
outputs = model.generate(**inputs, max_new_tokens=1024, do_sample=True, temperature=0.1)
print("生成されたトークン:\n====\n", outputs, "\n====\n")

# 5: 出力を文字列にデコード
decoded_output = tokenizer.decode(outputs[0][inputs['input_ids'].size(1):], skip_special_tokens=True)
print("デコードされた出力:\n====\n", decoded_output)
出力
フォーマット化されたチャット:
====
 <s>以下は、タスクを説明する指示です。要求を適切に満たす応答を書きなさい。

### 指示:
神戸でオススメの観光スポットを5つリストアップして。

### 応答:
 
====

トークン化された入力:
====
 {'input_ids': tensor([[    1, 46337, 78440, 60970, 29083, 76016, 56252, 70725, 78439, 75658,
         29083, 76811, 29179, 72952, 29131, 70147, 29083, 71559, 56856, 28949,
            18,    18, 27338, 49615, 28752,    18, 74195, 29235, 58792, 28998,
         75780, 60702, 29083, 28787, 30077, 64320, 58064, 56102, 28949,    18,
            18, 27338,   279, 70147, 28752,    18]], device='cuda:0'), 'attention_mask': tensor([[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]],
       device='cuda:0')} 
====

生成されたトークン:
====
 tensor([[    1, 46337, 78440, 60970, 29083, 76016, 56252, 70725, 78439, 75658,
         29083, 76811, 29179, 72952, 29131, 70147, 29083, 71559, 56856, 28949,
            18,    18, 27338, 49615, 28752,    18, 74195, 29235, 58792, 28998,
         75780, 60702, 29083, 28787, 30077, 64320, 58064, 56102, 28949,    18,
            18, 27338,   279, 70147, 28752,    18, 74195, 29282, 73651, 70297,
         55022, 72938, 78443, 74878, 71491, 29321, 76144, 29275, 71114, 29314,
         77912, 28998, 76914, 78439, 65777, 78474, 74195, 29235, 58792, 28998,
         75780, 60702, 29083, 28787, 30077, 74621, 78453,    18,    18, 28745,
         28728, 67202, 32879, 29091, 31600, 30410,    18, 74195, 28998, 32879,
         29091, 31600, 30410, 78440, 71402, 71455, 29179, 68429, 29314, 30710,
         57934, 55116, 72677, 29314, 74388, 65283, 58721, 78439, 29584, 30808,
         30604, 33428, 28998, 31600, 29582, 30701, 29584, 33977, 30663, 28998,
         31600, 29582, 29046, 29584, 55249, 55882, 29495, 29582, 78549, 73651,
         70297, 55022, 69825, 29314, 29090, 29015, 78465,    18,    18, 28755,
         28728, 67306, 30993,    18, 74195, 28998, 65349, 78443, 31387, 35297,
         33259, 28998, 69775, 29314, 33259, 29083, 30597, 31202, 78519, 65348,
         71151, 28998, 77688, 78530, 29090, 29579, 28998, 76292, 29314, 72105,
         78448,    18,    18, 28775, 28728, 74195, 63511, 61015,    18, 74195,
         30918, 28998, 60298, 78443, 69409, 29682, 78636, 74195, 28998, 75522,
         30701, 29731, 29083, 28974, 30611, 78558, 30760, 78442, 64152, 78554,
         74878, 68475, 29314, 69745, 78448,    18,    18, 28786, 28728, 74195,
         62109, 64266,    18, 60249, 64043, 30701, 64594, 29046, 71426, 78850,
         77377, 75616, 71265, 78439, 63966, 59180, 30701,   399,   428, 78496,
         67969, 71265, 29314, 74388, 65281, 29046, 69113, 76660, 30701, 58976,
         29179, 65641, 78439,    18,    18, 28787, 28728, 74195, 67202, 74921,
            18, 67202, 32879, 29091, 31600, 30410, 78494, 74921, 78443, 68112,
         28998, 67782, 30701, 69955, 29314, 69410, 78589,    18,    18,    18,
         74195, 29282, 74878, 75522, 29321, 76144, 29275, 71114, 29314, 75476,
         56086, 77913, 29275, 76914, 78439, 56296, 29046, 75883, 79823, 78488,
             2]], device='cuda:0') 
====

デコードされた出力:
====
 神戸は異国情緒あふれる港町で、美しい景観と豊かな文化が魅力の都市です。以下に、神戸でオススメの観光スポットを5つ紹介します。

1.北野異人館街
神戸の異人館街は、明治時代に外国人が住んでいた洋館が立ち並ぶエリアです。「風見鶏の館」や「萌黄の館」、「うろこの家」など、異国情緒あふれる建物が点在しています。

2.南京町
神戸の中華街で、約100軒の店舗が軒を連ねています。中華料理の食べ歩きや、点心の購入が楽しめます。

3.神戸ポートタワー
神戸港のシンボルで、展望台からは神戸の街並みや海を一望できます。夜にはライトアップされ、美しい夜景が広がります。

4.神戸ハーバーランド
ショッピングモールやレストラン、映画館などが集まる複合施設です。モザイクガーデンやumieなどの商業施設が立ち並び、家族連れやカップルに人気です。

5.神戸北野美術館
北野異人館街にある美術館で、国内外の名画や彫刻が展示されています。


神戸は美しい街並みと豊かな文化が融合した魅力的な都市です。ぜひ、訪れてみてください。 

量子化する場合

from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch

# 量子化の設定(4ビット・8ビット量子化から選択)
quantization_config = BitsAndBytesConfig(
    load_in_8bit=True,
    #load_in_4bit=True
)

model_id = "AXCXEPT/llm-jp-3-3.7b-instruct-EZO-Humanities"
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    device_map="auto",
    quantization_config=quantization_config  # 量子化の設定を追加してモデルをロード
)
tokenizer = AutoTokenizer.from_pretrained(model_id)

パイプラインの場合も

import torch
from transformers import pipeline, BitsAndBytesConfig

# 量子化の設定
quantization_config = BitsAndBytesConfig(
    load_in_8bit=True,
    #load_in_4bit=True
)

pipe = pipeline(
    "text-generation",
    "AXCXEPT/llm-jp-3-3.7b-instruct-EZO-Humanities",
    device_map="auto",
    model_kwargs={"quantization_config": quantization_config}  # 量子化の設定を追加してパイプラインを定義
)
kun432kun432

その他

  • モデルのサイズ
    • モデル名にある「8B」「70B」などのパラメータ数から判断できる。
    • 量子化しない場合、パラメータごとに約2バイトのメモリが必要
      • 例: 8Bモデルは80億パラメータ*2バイト≒約16GBは必要(その他のオーバーヘッドも含めると多少余分に必要)
    • Mixture of Expertsモデルの場合
      • 「8x7B」: 560億パラメータ
      • 「141B-A35B」: 1410億パラメータ
    • 量子化すると、パラメータあたりのメモリ量を8ビット・4ビットなどに減らすことができる。
      • その代わり性能が低下するトレードオフ
  • TextGenerationPipeline や AutoModelForCausalLM はデフォルトだとfloat32の精度でモデルをロードする。
    • パラメータごとに 4 バイト (32 ビット) が必要になる
    • 80 億のパラメータの「8B」モデルだと約 32 GB のメモリが必要になる
    • 最近のモデルはbfloat16が一般的で、パラメータごとに2バイトしか使用しない
      • torch_dtypeで指定する
  • 性能について
    • 生成速度の制約要因
      • チャットモデルのテキスト生成は、計算能力よりもメモリ帯域幅に制約される。
      • トークン生成時にはすべてのパラメータがメモリから読み出されるため、1秒あたりの生成トークン数は、メモリ帯域幅 ÷ モデルサイズ に比例。
    • ハードウェアの影響
      • コンシューマCPUの帯域幅は20~100GB/秒
      • データセンター向けGPUでは最大2~3TB/秒
      • 大きな帯域幅を持つハードウェアほど高速。
    • 速度向上の手法
      • モデルサイズを削減(量子化)
      • 高帯域幅のハードウェアを使用
      • 「支援生成」(speculative sampling: 投機的サンプリング)を活用し、複数トークンを一度に予測・検証。上級者向け。
    • MoEモデルの特徴
      • 一部のパラメータのみがアクティブになるため、同サイズの通常モデルよりも数倍高速。
      • ただし、「支援生成」の効果は薄い。
このスクラップは5ヶ月前にクローズされました