見出し画像

LLM の chat_template に気をつけろ!

nouu の白川です。

毎週のように新しいより高精度な LLM が出てきてキャッチアップするのも大変ですね。量子化された小さなモデルなら Google Colab などでチャチャッと試すのは意外と簡単なのですが、公式が提供しているサンプルからはみ出た事をしようとすると罠にハマることがあります。

その一つが chat_template です。chat_template は instruction / chat モデルを使うときの入力フォーマットを定義した文字列です。

最近出た話題の日本語 LLM の Swallow の場合は下記のようなフォーマットで入力します。

tokyotech-llm/Swallow-7b-instruct-hf の説明をもとに作成:

以下に、あるタスクを説明する指示があります。リクエストを適切に完了するための回答を記述してください。

### 指示:
以下のトピックに関する詳細な情報を提供してください。

### 入力:
東京工業大学の主なキャンパスについて教えてください

### 応答:

これくらいならパッと見てなるほどなと理解できますが、たとえば、これまた最近出た GPT-3.5 を超えた(?)と話題 ELYZA-japanese-Llama-2-13b の場合は下記のようになります。

elyza/ELYZA-japanese-Llama-2-13b-instruct の説明をもとに作成:

<s>[INST] <<SYS>>
あなたは誠実で優秀な日本人のアシスタントです。
<<SYS>>

仕事の熱意を取り戻すためのアイデアを5つ挙げてください。 [/INST]

<s> やら [INST] やらといった機械的な文字列が付与されています。

この形式は Llama (Llama2) の形式です。ELYZA-japanese-Llama-2-13b-instruct は Llama2 を継続学習したモデルで、chat_template も Llama2 のフォーマットに従っているようです。

こんなに複雑だと自分では適切にテキストを構築できなさそうに思えるかもしれません。よく見ると謎の半角空白や改行がされていたりして、なんだか怪しげです。空白を抜いたらどうなるのでしょう…?

chat_template が定義されていれば大丈夫

ですが、心配することはありません。Hugging Face に登録されているモデルの tokenizer_config.json に chat_template が定義されていれば、それをもとに transformers が自動的に入力テキストを組み立ててくれます。より具体的には、tokenizer の apply_chat_template というメソッドで定義された chat_template に従いテキストが構築されます。

chat_template の詳細に関しては下記を参照してください。

chat_templateが定義されているとは限らない

ここで残念なお知らせですが、全てのモデルに chat_template が登録されているかというと、実はそんなことはありません。

apply_chat_template の仕様によると、chat_template が定義されていない場合、親クラスまでフォールバックし、default_chat_template が定義されている場合はそれを使うと記載されています。ELYZA-japanese-Llama-2-13b-instruct の tokenizer_config.json には chat_template が定義されていないのですが、 ELYZA-japanese-Llama-2-13b-instruct の tokenizer は LlamaTokenizer なので、LlamaTokenizer の default_chat_template が自動で適用されるということになります。よかったよかった。

独自形式のテンプレートをもつ LLM の場合…

しかし、独自形式のテンプレートを持つLLMの場合は事情が異なります。先程の Swallow-7b-instruct-hf の tokenizer_config.json を見てみると、tokenizer_class は LlamaTokenizer ですが、chat_template が定義されていません。したがって、Swallow-7b-instruct-hf で指示されているテンプレートに従って自力でテキスト構築をしないと、Swallow-7b-instruct-hf は Llama のテンプレートに従ってテキストを構築することになります。試してみるとわかりますが、結構悲惨なことになります

下記は、tokyotech-llm/Swallow-7b-instruct-hf を AWQ 形式に量子化した TheBloke/Swallow-7B-Instruct-AWQ で試したものです。コードはこちらの Colab にあるので、興味ある方はお試しください。

まずはchat_templateを設定しないで生成した場合です。

入力:

<s>[INST] <<SYS>>
以下に、あるタスクを説明する指示があります。リクエストを適切に完了するための回答を記述してください。
<</SYS>>

東京工業大学の主なキャンパスについて教えてください [/INST]

出力:

<<SYS>>
・大岡山キャンパス:本学の主要なキャンパスで、工学部と理工学研究科があります。
・すずかけ台キャンパス:情報環境学部と知識科学研究科があります。
・田町キャンパス:先端科学技術研究センターがあります。
・津田沼キャンパス:社会人教育や学生寮があります。

<</SYS>>

Llama の chat_template に引きずられたのか、<<SYS>> と <</SYS>> がついてしまいました。ささいなノイズかもしれませんが、アプリケーションで使用することを考えると、このような出力は到底無視できません。

念のためもう一回生成させてみました。

出力(2回目):

<<SYS>
Tokyo Institute of Technology (TIT)は、主に3つの主要なキャンパスで構成されています。最も重要なものは、日本の港区西麻布にある西麻布キャンパスです。これは、工学部と科学部の学生が通う場所です。また、東京都の八王子市にある東工大八王子キャンパスもあり、理工学部の学生が学びます。最後に、東京都日野市にある日野キャンパスがあり、情報理工学部の学生が学びます。

TITには4つの独立した学部と学校があります。まず、工学部と科学部があります。次に、東工大八王子キャンパスに理工学部があります。そして、東工大日野キャンパスに情報理工学部があります。最後に、東工大東京キャンパスにリベラルアーツセンターがあります。

TITの3つの主要なキャンパスに加えて、TITには12のキャンパス施設があります。これらのキャンパスには、図書館や研究所などの教育機関が含まれています。これらのキャンパスには、日本語や英語で利用できるさまざまな資料が含まれています。 </sy>

<</SYS>

やはり <<SYS>>と<</SYS>>が付きます。と思ったら、>が1個足りず、<<SYS>と<</SYS>でした。常に<<SYS>>と<</SYS>>で囲まれるなら後処理をすればよいのですが、出力が不安定だと後処理に頼るのも心もとないです。

次は指定された書式で生成させた場合です。

chat_template:

{% for message in messages %}{% if message['role'] == 'system' %}{{ message['content'] + '\n\n'}}{% elif message['role'] == 'user' %}{{ '### 指示:\n' + message['content'] + '\n\n### 応答:\n' }}{% endif %}{% endfor %}

入力:

以下に、あるタスクを説明する指示があります。リクエストを適切に完了するための回答を記述してください。

### 指示:
東京工業大学の主なキャンパスについて教えてください

### 応答:

出力:

東京工業大学は、主に4つの主要なキャンパスで構成されています。これらのキャンパスには、大岡山、すずかけ台、田町、そして広尾が含まれます。それぞれのキャンパスには独自の特徴と施設があり、学生にユニークな学習体験を提供します。大岡山キャンパスは東工大の本拠地であり、メインの建物や研究施設、図書館などが集中しています。すずかけ台キャンパスは、自然豊かな環境に位置し、主に理工学部の学生が学びます。田町キャンパスは、ビジネススクールや情報理工学院の一部の学部生が利用する近代的なビル群があります。最後に、広尾キャンパスはリベラルアーツカレッジであり、教養学位を取得するために学ぶすべての学生がここで勉強します。各キャンパスは、日本および世界中から来る多くの留学生を含む約25,000人以上の学生を収容しています。

出力(2回目):

東京工業大学は、日本最大かつ最も有名な工学および理数系の研究機関です。本学は1881年に設立され、現在では約50,000人の学生と2,000人以上の教授陣を擁し、世界中から留学生が集まっています。

東京工業大学の主なキャンパスは、大岡山キャンパス、すずかけ台キャンパス、田町キャンパス、横浜市金沢区に位置する六浦キャンパスの4つです。大岡山キャンパスは、東工大のメインキャンパスであり、学生寮や教室、図書館など、すべての主要施設がここに集中しています。すずかけ台キャンパスは、大岡山キャンパスから徒歩圏内に位置し、主に物理科学部と情報通信学部の生徒が利用している。田町キャンパスは、東工大の第3キャンパスで、主にバイオサイエンス学部の学生が利用しています。最後に、六浦キャンパスは、東工大唯一の独立したキャンパスで、主に環境・社会理工学部の学生が利用しています。

いずれもきれいに生成されました!

結論: chat_template に気をつけろ!

chat_template を正しく設定しないと LLM はその真価を発揮できません。モデルカードを良く読み、tokenizer_config.json を確認し、必要であれば chat_template を正しく設定しましょう。

tokenizer.chat_template = '<valid chat template here>'  # if not defined

そして、独自 chat_template な LLM を作成される場合は、 chat_template を明示的に設定していただけるとありがたいです。

それではよい LLM ライフを!
(気軽なお仕事のご相談もお待ちしています https://nouu.me/#contact )


この記事が気に入ったらサポートをしてみませんか?