0. はじめに
データセットを作っていて、ふと思ったんですよ。
Harmonyって何なんだっけ?
chat templateと何が違うの?
というか、正直、
「messagesって最終的にどういう文字列になってモデルに入ってるんだ?」
と急に気になったのが始まりです。
普段は、
messages = [
{"role": "user", "content": "こんにちは"}
]
みたいなのを書いて、
tokenizer.apply_chat_template(messages, tokenize=False)
終わり。
僕も今まで、「まあTokenizerがいい感じにしてくれるんだろう」くらいに思っていました。
ただ、最近reasoning付きの学習データを作って学習すると、なんだかモデルが崩れる時があるんですよね。
- モデルごとに形式が違うのは知ってるけど、Harmony形式って全然違うの?
- Harmonyってchannelってのがあるらしい
- channelって自分で作れるの?
という疑問が出てきました。
そして今回、
- llm-jp/llm-jp-4-33b-thinking
- Qwen/Qwen3.8-27B
のChat Templateを実際に眺めて、少し改造してみました。
さらに、llm-jp/llm-jp-4-8b-thinkingをベースに追加学習し、通常channelと今治弁用channelで出力を比較するところまで試しました。
先に結果を書くと、今回確認した出力では、analysis_imabariからfinal_imabariへ遷移し、方言表現を含む回答が出ました。ただし、通常のanalysis / finalでも方言が出るケースがあり、標準語と今治弁を完全に分離できたわけではありません。おそらく、analysis_imabariとfinal_imabariしか追加学習していないことが原因だと思います。
公開した学習済みモデルはこちらです。
なお、QwenについてはChat Templateの整形確認までです。この記事で紹介する追加学習と生成結果は、LLM-jp-4の8B版のものです。また、この記事のコードはllm-jp-4の素のモデルに対してチャットテンプレートを変える場合などを記載しています。
結論から書くと、思っていた以上に 面白かった です。
先人たちの苦労と工夫と、まだまだこれからの発展性がありそうです。
1. 今回やりたかったこと
僕は地元である、今治に関するLLMを作るため、データセットを作っています。
その流れで、
- 通常の思考
- 通常の回答
- 今治弁での思考
- 今治弁での回答
みたいなものを分離して学習できないかな、と考えました。
ま、かるいフォーマルな感じと、地元の友達と話す感じと言えばいいでしょうか?
例えばHarmonyに使えるchannelを固定させて、今治弁で回答させたり、標準語で回答させられればそんな雰囲気が出そうです。
つまり、Harmonyに
[analysis, final]
と渡したら、標準語で思考、回答し、
[analysis_imabari, final_imabari]
と渡したら、今治弁で思考回答する
みたいにできたら面白そうです。
ということで、Chat Templateを自分で変更して、こういう形式の学習データを作れるのかを試しました。
今回は、テンプレートの改造、学習用テキストの作成、LoRAによる追加学習、学習後の出力確認までを紹介します。
ただし、「独自channelを含む出力が得られること」と「channelだけで文体を安定して制御できること」は別です。実際に試してみると、この違いが見えてきました。
2. そもそもChat Templateって何?
僕自身、基本の「き」しか理解していませんでした。例えば、
messages = [
{
"role": "user",
"content": "今治市のおすすめ観光地を教えてください。",
},
{
"role": "assistant",
"content": "しまなみ海道がおすすめです。海の景色を楽しみながら走れます。",
}
]
というmessagesがあります。
これをそのままLLMへ渡しているような気になりますが、実際にはモデルごとの専用形式へ変換されています。
シンプルに理解するためにQwen系で見てみましょう。ざっくり、以下のようになっています。
<|im_start|>user
今治市のおすすめ観光地を教えてください。<|im_end|>
<|im_start|>assistant
しまなみ海道がおすすめです。海の景色を楽しみながら走れます。<|im_end|>
つまり、
Pythonのdict
↓
Chat Template
↓
モデルが読む文字列
↓
tokenize
↓
LLM
という流れ。
ここで、最初の疑問を整理します。Chat Templateはmessagesをモデル用の形式へ変換するルール、Harmonyは会話を表現する形式です。 同じものではなく、Chat TemplateでHarmony系の形式に整形する、という関係です。
apply_chat_template(..., tokenize=False)を使うと、この変換後の文字列を確認できます。TransformersのChat Template解説も参考になります。
なお、以下のQwenの例は区切りを説明するための模式例です。thinkingを含む実際の例は後半で扱います。
3. まずllm-jp-4を見てみる
次に、Harmony系の形式を使う llm-jp/llm-jp-4-33b-thinking を見ていきます。
このモデルでは、assistantの出力をchannelで分けるChat Templateを使っています。HarmonyはOpenAIが公開している会話の表現形式です。僕も最初、「Harmony?なんかとなんかが調和した感じ??共鳴か何かしてるの?」くらいでした。
Harmonyではassistantのメッセージに、例えば、
analysis
commentary
final
というchannelを持たせられます。channel名そのものは通常の文字列で、境界を示す特殊トークンとは別です。OpenAIのHarmony解説に構造が説明されています。
この記事の<|channel|>や<|return|>などの表記は、LLM-jp-4のテンプレート・出力に合わせています。OpenAIのHarmonyと、特殊トークンの表記まで同じものとして読まないようにしてください。
ここで思いつきました。
channelが文字列なら増やせるのでは?方言をしゃべるchannelと標準語でしゃべるchannelが共存できるのでは? という単純な発想です。
4. llm-jp-4の通常形式を出力してみる
最初にテンプレートを調べたのは33B版です。後半で学習する8B版とは分けて考えます。
from transformers import AutoTokenizer
import datetime
tokenizer = AutoTokenizer.from_pretrained("llm-jp/llm-jp-4-33b-thinking")
date = datetime.date.today()
messages = [
{"role": "user", "content": "今治市のおすすめ観光地を教えてください。"},
{
"role": "assistant",
"thinking": "サイクリングを楽しめるしまなみ海道を挙げる。",
"content": "しまなみ海道がおすすめです。",
},
]
print(tokenizer.apply_chat_template(
messages,
reasoning_effort="low",
add_generation_prompt=False,
tokenize=False,
))
注目したいのはassistant部分です。以下は、その構造を説明するための抜粋例です。モデルが生成した回答ではなく、上のmessagesに書いた文を整形しています。
<|start|>assistant<|channel|>analysis<|message|>サイクリングを楽しめるしまなみ海道を挙げる。<|end|>
<|start|>assistant<|channel|>final<|message|>しまなみ海道がおすすめです。<|return|>
これを見たとき、「あ、本当にchannelって書いてあるんだ」と思いました。
実際に文字列で見ると、かなり分かりやすいです。
assistant
├─ analysis:thinkingの内容
└─ final:contentの内容
LLM-jp-4のこの形式では、<|end|>がメッセージの終了、<|return|>がassistantターンの終了を表します。
5. じゃ、analysis_imabariを作れるんじゃね?
ここで悪い癖が出ます。「文字列なら変えられるのでは?」と思ってしまいました。
そこで、analysis finalに加えて、analysis_imabariとfinal_imabariを扱えるようChat Templateを書き換えてみました。
まず、仕組みを説明するための改造例です。長いのでトグルで閉じておきます。
この掲載例と、後半の学習で保存したテンプレートには日付や既定のchannel一覧などに差があります。学習済みモデルを試す際は、モデルと一緒に公開したTokenizerを使ってください。
改造版chat template
imabari_template = r'''
{%- macro build_system_message() -%}
{%- if model_identity is not defined %}
{%- set model_identity = "You are LLM-jp-4, a large language model trained by LLM-jp." %}
{%- endif %}
{{- model_identity + "\n" -}}
{%- if knowledge_cutoff is not defined %}
{%- set knowledge_cutoff = "2025-12" %}
{%- endif %}
{{- "Knowledge cutoff: " + knowledge_cutoff + "\n" -}}
{%- if conversation_start_date is not defined %}
{%- set conversation_start_date = strftime_now("%Y-%m-%d") %}
{%- endif %}
{{- "Current date: " + conversation_start_date + "\n\n" }}
{%- if reasoning_effort is not defined %}
{%- set reasoning_effort = "medium" %}
{%- endif %}
{{- "Reasoning: " + reasoning_effort + "\n\n" }}
{%- if valid_channels is not defined %}
{%- set valid_channels = ["analysis_imabari", "final_imabari", "commentary", "analysis", "final"] %}
{%- endif %}
{%- if "user" not in valid_channels %}
{%- set valid_channels = ["user"] + valid_channels %}
{%- endif %}
{%- if "commentary" not in valid_channels %}
{%- set valid_channels = valid_channels[:1] + ["commentary"] + valid_channels[1:] %}
{%- endif %}
{{- "# Valid channels: " + (valid_channels | join(", ")) + ". Channel must be included for every message." }}
{%- endmacro -%}
{{- "<|start|>system<|message|>" }}
{{- build_system_message() }}
{{- "<|end|>" }}
{%- if messages and (messages[0].role == "developer" or messages[0].role == "system") %}
{%- set developer_message = messages[0].content %}
{%- set loop_messages = messages[1:] %}
{%- else %}
{%- set developer_message = "" %}
{%- set loop_messages = messages %}
{%- endif %}
{%- if developer_message %}
{{- "<|start|>developer<|message|># Instructions\n\n" + developer_message + "\n\n<|end|>" }}
{%- endif %}
{%- for message in loop_messages %}
{%- if message.role == "user" %}
{{- "<|start|>user<|message|>" + message.content + "<|end|>" }}
{%- elif message.role == "assistant" %}
{%- if message.thinking is defined and message.thinking %}
{%- if message.thinking_channel is defined %}
{{- "<|start|>assistant<|channel|>" + message.thinking_channel + "<|message|>" + message.thinking + "<|end|>" }}
{%- else %}
{{- "<|start|>assistant<|channel|>analysis<|message|>" + message.thinking + "<|end|>" }}
{%- endif %}
{%- endif %}
{%- set response_channel = message.channel | default("final") %}
{{- "<|start|>assistant<|channel|>" + response_channel + "<|message|>" + message.content + "<|return|>" }}
{%- endif %}
{%- endfor %}
{%- if add_generation_prompt %}
{%- if generate_thinking is defined and generate_thinking %}
{{- "<|start|>assistant<|channel|>" + (thinking_channel | default("analysis")) + "<|message|>" }}
{%- else %}
{{- "<|start|>assistant<|channel|>" + (channel | default("final")) + "<|message|>" }}
{%- endif %}
{%- endif %}
'''
正直、Jinja って読みにくい。
Pythonならまだ追えるんですが、こいつらが大量に出てくると、一瞬どこを見ているのか分からなくなります。
{%- if
{{-
{%-
Djangoでもある程度使ってきましたが、ここまで長いと目がチカチカします。
6. 今治弁用channelを出力してみる
学習データ側を以下にしてみます。
training_messages_imabari = [
{
"role": "user",
"content": "今治市のおすすめ観光地を教えてください。",
},
{
"role": "assistant",
"thinking_channel": "analysis_imabari",
"thinking": "今治の代表的な観光地を選び、今治弁で説明する。",
"channel": "final_imabari",
"content": "今治なら、まずはしまなみ海道がおすすめじゃけん。景色がきれいで、サイクリングにも向いとるよ。",
},
]
ポイントはここです。
"thinking_channel": "analysis_imabari""channel": "final_imabari"
そして、chat_templateに渡して、出力を確認してみましょう。
training_text = tokenizer.apply_chat_template(
training_messages_imabari,
reasoning_effort="high",
knowledge_cutoff="2026-03",
conversation_start_date=date.strftime("%Y-%m-%d"),
valid_channels=["analysis_imabari", "final_imabari"],
chat_template=imabari_template,
tokenize=False,
add_generation_prompt=False,
)
print(training_text)
<|start|>system<|message|>You are LLM-jp-4, a large language model trained by LLM-jp.
Knowledge cutoff: 2026-03
Current date: 2026-09-15
Reasoning: high
# Valid channels: user, commentary, analysis_imabari, final_imabari. Channel must be included for every message.<|end|>
<|start|>user<|message|>今治市のおすすめ観光地を教えてください。<|end|>
<|start|>assistant<|channel|>analysis_imabari<|message|>今治の代表的な観光地を選び、今治弁で説明する。<|end|>
<|start|>assistant<|channel|>final_imabari<|message|>今治なら、まずはしまなみ海道がおすすめじゃけん。景色がきれいで、サイクリングにも向いとるよ。<|return|>
おお。出た。😍
テンションが上がってまいりました!
この段階では、Chat Templateとして、analysis_imabari final_imabariを持ったtraining textを作れています。
7. でも、ちょっと待てよ
ここで一度冷静になります。
Chat Templateで、analysis_imabariと書けたからといって、モデルが、analysis_imabariとは今治弁で考えるchannelですと理解したわけではありません。ただ文字列として出力できただけです。極端な話、analysis_udonでも、analysis_takoyakiでもChat Template上は書けます。
だから、テンプレートの整形確認だけで分かるのは、「独自形式の学習データを作れる」というところまでです。このあと実際に学習して、生成時にもその形式が出てくるかを確かめます。この辺、Chat Templateをいじっていると何でもできた気分になるので注意が必要ですね。
8. 学習時と推論時で少し違う
ここも最初ちょっと混乱しました。
学習データの場合は、assistantの正解まで全部含まれています。なので、add_generation_prompt=Falseです。
一方、推論では、
user
↓
ここからassistantが生成
という状態にしたい。
そこで、add_generation_prompt=Trueを使います。
例えば、
inference_messages = [
{
"role": "developer",
"content": "質問に正確かつ簡潔に回答してください。",
},
{
"role": "user",
"content": "今治市のおすすめ観光地を教えてください。",
},
]
に対して、
inference_prompt = tokenizer.apply_chat_template(
inference_messages,
chat_template=imabari_template,
valid_channels=["analysis_imabari", "final_imabari"],
thinking_channel="analysis_imabari",
channel="final_imabari",
generate_thinking=True,
tokenize=False,
add_generation_prompt=True,
)
print(inference_prompt)
とします。
最後は、
<|start|>assistant<|channel|>analysis_imabari<|message|>
になります。つまり、「ここからanalysis_imabariを書いてね」 という開始位置まではChat Template側で作れます。
ただし、
analysis_imabari
↓
final_imabari
へモデル自身が遷移できるかは別です。後半では、ここを実際の出力で確認します。
また、この改造テンプレートでは、generate_thinking=Trueのとき、channel="final_imabari"は後続の回答channelを強制しません。開始位置にはthinking_channelだけが使われ、その後の切り替えはモデルの生成に任せています。
valid_channelsも、システムプロンプト内の一覧を書き換える指定です。それだけで生成可能なトークンを制限する仕組みではありません。
9. 次にQwen3.8を見てみる
さて。llm-jp-4で、analysis_imabariができたので、僕はこの時点で、「Qwenも似たような感じだろう」と思っていました。
違いました。かなり違いました。
今回確認したQwen3.8のChat Templateは、Harmony型のchannelではなく、
<think>
...
</think>
でthinkingを表現しています。
つまり、
assistant
├─ <think>...</think>
└─ 通常回答
という形です。
llm-jp-4とは思想が違います。この辺を見ていると、「messagesという共通インターフェースのおかげで、裏側の違いを今まで意識せず使えてたんだな」と感じます。
Hugging Face、マジありがたい。
⸻
10. Qwen3.8の通常Chat Templateを確認
このQwenの整形確認では、モデル本体はロードせず、Tokenizerだけを使います。
from transformers import AutoTokenizer
from copy import deepcopy
tokenizer = AutoTokenizer.from_pretrained(
"Qwen/Qwen3.8-27B",
revision="1d4bf0f2ff6012fd82039f2fa52739d0dd7c60c0",
)
official_template = tokenizer.chat_template
今回はChat Template自体を調べたいので、revisionも固定しています。
後から公式側のChat Templateが変わって、「あれ?記事と違う」 となると困るためです。
messagesはこんな感じ。
messages = [
{
"role": "system",
"content": "質問に正確かつ簡潔に回答してください。",
},
{
"role": "user",
"content": "今治市でサイクリングを楽しめる場所を一つ教えてください。",
},
{
"role": "assistant",
"reasoning_content": "サイクリングが楽しめるしまなみ海道を挙げる。",
"content": "しまなみ海道がおすすめです。海の景色を楽しみながら走れます。",
},
]
Qwen3.8の場合は、reasoning_contentにthinkingを入れています。
実際に変換してみます。
print(
tokenizer.apply_chat_template(
messages,
reasoning_effort="medium",
preserve_thinking=True,
add_generation_prompt=False,
tokenize=False,
)
)
出力。
<|im_start|>system
質問に正確かつ簡潔に回答してください。<|im_end|>
<|im_start|>user
今治市でサイクリングを楽しめる場所を一つ教えてください。<|im_end|>
<|im_start|>assistant
<think>
サイクリングが楽しめるしまなみ海道を挙げる。
</think>
しまなみ海道がおすすめです。海の景色を楽しみながら走れます。<|im_end|>
なるほど。
これはこれで分かりやすい。
11. 今回のQwenテンプレートにはHarmony型channelがない
ここで問題発生です。
僕がやりたいのは、analysis_imabari final_imabariです。
でも、今回確認したQwenのテンプレートには、LLM-jp-4のような<|channel|>で分ける構造がありません。
じゃあどうするのか。
少し考えて、「普通のテキストとしてラベルを入れればいいのでは?」となりました。
つまり、
<think>
[analysis_imabari]
...
</think>
[final_imabari]
...
です。
かなり力技に見えます。でもこういうの、僕は嫌いじゃないです。😂
12. QwenのChat Templateを部分的に書き換える
とはいえ、公式Chat Template全部を自分でコピーして書き換えるのは少し怖いです。
公式側で細かい処理をたくさんしています。
なので、変更したい部分だけ置換する方法にしました。
from transformers import AutoTokenizer
from copy import deepcopy
tokenizer = AutoTokenizer.from_pretrained(
"Qwen/Qwen3.8-27B",
revision="1d4bf0f2ff6012fd82039f2fa52739d0dd7c60c0",
)
official_template = tokenizer.chat_template
def replace_once(source, old, new):
assert source.count(old) == 1, (
f"公式テンプレートの想定箇所と不一致: {old}"
)
return source.replace(old, new, 1)
このreplace_once()は、今考えると結構大事でした。
単純に、replace()するだけでもいいのですが、公式テンプレートが変更された場合、気付かないまま変な場所を書き換える可能性があります。
そこで、
assert source.count(old) == 1
として、想定した場所が1箇所だけ存在するときだけ変更するようにしています。
少し面倒ですが、こういうところで止まってくれた方が安心です。
13. analysis_imabariラベルを挿入
変更部分はこんな感じです。
imabari_template = official_template
imabari_template = replace_once(
imabari_template,
"{%- set reasoning_content = reasoning_content|trim %}",
"""{%- set reasoning_content = reasoning_content|trim %}
{%- if message.thinking_channel is defined and message.thinking_channel %}
{%- set reasoning_content = '[' + message.thinking_channel + ']\\n' + reasoning_content %}
{%- endif %}
{%- if message.channel is defined and message.channel %}
{%- set content = '[' + message.channel + ']\\n' + content %}
{%- endif %}""",
)
imabari_template = replace_once(
imabari_template,
"{{- '<think>\\n\\n</think>\\n\\n' }}",
"{{- '<think>\\n\\n</think>\\n\\n' + ('[' + channel + ']\\n' if channel is defined and channel else '') }}",
)
imabari_template = replace_once(
imabari_template,
"{{- '<think>\\n' }}",
"{{- '<think>\\n' + ('[' + thinking_channel + ']\\n' if thinking_channel is defined and thinking_channel else '') }}",
)
Chat Templateをいじる前は、「数行追加すれば終わるでしょ」くらいに思っていました。
実際は、学習時の出力と推論開始時の出力の両方を考えないといけないので、少し頭を使いました。この辺もやってみないと分からないものですね。
14. Qwen3.8で今治弁形式を出してみる
messages側を変更します。
training_messages_imabari = deepcopy(messages)
training_messages_imabari[0]["content"] = (
"思考の先頭に [analysis_imabari]、"
"回答の先頭に [final_imabari] を置き、"
"今治弁で回答してください。"
)
training_messages_imabari[-1].update(
thinking_channel="analysis_imabari",
channel="final_imabari",
reasoning_content="しまなみ海道を挙げ、今治弁で説明する。",
content="しまなみ海道がおすすめじゃけん。"
"海の景色を楽しみながら走れるよ。",
)
そして、
print(
tokenizer.apply_chat_template(
training_messages_imabari,
chat_template=imabari_template,
reasoning_effort="medium",
preserve_thinking=True,
add_generation_prompt=False,
tokenize=False,
)
)
結果。
<|im_start|>system
思考の先頭に [analysis_imabari]、回答の先頭に [final_imabari] を置き、今治弁で回答してください。<|im_end|>
<|im_start|>user
今治市でサイクリングを楽しめる場所を一つ教えてください。<|im_end|>
<|im_start|>assistant
<think>
[analysis_imabari]
しまなみ海道を挙げ、今治弁で説明する。
</think>
[final_imabari]
しまなみ海道がおすすめじゃけん。海の景色を楽しみながら走れるよ。<|im_end|>
できました。
ただ、ここでllm-jp-4とはかなり違います。llm-jp-4の場合、
<|channel|>analysis_imabari
です。
つまりChat Templateの構造上、channelとして存在しています。
一方Qwenでは、
[analysis_imabari]
はただのテキストです。LLMからすると普通のToken列です。これは同じように見えて結構重要な違いだと思います。
15. Qwenの推論時はどうなる?
推論時も確認します。
print(
tokenizer.apply_chat_template(
training_messages_imabari[:-1],
chat_template=imabari_template,
reasoning_effort="medium",
thinking_channel="analysis_imabari",
channel="final_imabari",
enable_thinking=True,
add_generation_prompt=True,
tokenize=False,
)
)
すると最後が、
<|im_start|>assistant
<think>
[analysis_imabari]
になります。
ここまではChat Templateで準備できます。でもこの後、
</think>
[final_imabari]
をモデルが生成してくれる保証はありません。
つまり、[analysis_imabari]まではこちらから置けるけど、[final_imabari]はモデル自身に覚えてもらう必要があります。
この辺を見ると、「Chat Templateを変えたら全部解決!」という話ではないことがよく分かります。
16. HarmonyとQwen、結構違う
整理するとこんな感じです。
| 項目 | llm-jp-4 / Harmony系 | Qwen3.8 |
|---|---|---|
| reasoning | channel=analysis |
<think>...</think> |
| final | channel=final |
<think>後の本文 |
| thinking用key | thinking | reasoning_content |
| 独自channel | Template上は作成可能 | Harmony型channelは存在しない |
| 今回の形式 | analysis_imabari | [analysis_imabari] |
| 推論開始 | 独自channelから開始可能 |
<think>内のラベルから開始 |
| 学習・出力確認 | 8B版で実施。結果は後半で紹介 | 今回の独自ラベル形式での学習は未実施 |
最初は、「reasoning modelなら大体似たような形式なんだろう」と思っていました。
全然違いますね。むしろ、「モデルごとにChat Templateを確認せず学習データを作る方が怖い」と思うようになりました。
17. ここで少し脱線:特殊Tokenなのか普通の文字列なのか
今回調べながら気になったことがあります。
例えば、
<|start|>
<|channel|>
<|message|>
みたいなものを見ると、「なんか全部特殊Tokenっぽい」と思います。
一方、[analysis_imabari]は普通の文字列です。さらに、LLM-jp-4で<|channel|>の後ろに書いたanalysis_imabariも、名前自体は通常の文字列です。
つまり今回の違いは、「名前が特殊トークンかどうか」よりも、メッセージのヘッダーに置くか、本文中のラベルとして置くかです。独自channel名を書くことと、Tokenizerに新しい特殊トークンを追加することは別の操作です。
例えばQwenで、[analysis_imabari]とすると、Tokenizerによって複数Tokenへ分割される可能性があります。でも、それが悪いのか?というと、必ずしもそうでもなさそうです。LLMは普通の自然言語の文字列だって学習します。例えば、### Instructionや、### Responseを使ったSFTデータも昔からあります。
なので、[analysis_imabari]でも十分学習できる可能性はありますが、special tokenにした方がいいのか、普通の文字列の方がいいのか、ここは実験してみるしかないんでしょうね。
18. 実際に8Bモデルを追加学習した
さて、ここまではテンプレートの話でした。
ここからは実際に学習した話です。
ベースモデルにはllm-jp/llm-jp-4-8b-thinkingを使いました。最初にテンプレートを眺めた33B版ではなく、8B版です。
学習には、今治に関するQAとthinkingを持つデータセットを使いました。
ikedachin/imabari_wiki_qa_v4_reasoning_effort_llmjp4
学習用13,262件、検証用1,473件です。question、thinking、answerを会話形式へ変換し、thinkingをanalysis_imabari、回答をfinal_imabariに割り当てました。
ここは誤解しやすいのですが、通常channelと今治弁用channelの両方を均等に学習させた比較実験ではありません。今回の追加学習では今治弁用channelに割り当てたデータを使っています。
主な学習設定は次のとおりです。学習ノートブックとモデルカードに記載した設定をまとめています。
| 項目 | 設定 |
|---|---|
| ベースモデル | llm-jp/llm-jp-4-8b-thinking |
| 学習方法 | LoRAによるSFT |
| ライブラリ | Transformers / TRL / PEFT |
| Trainer | SFTTrainer |
| エポック数 | 1 |
| 学習率 | 2e-4 |
| 最大系列長 | 8,192 tokens |
| デバイスごとのバッチサイズ | 2 |
| 勾配累積 | 8 steps |
| LoRA rank / alpha / dropout | 8 / 16 / 0.0 |
| LoRA対象 | q / k / v / o projection、gate / up / down projection |
| Packing | 無効 |
学習後はLoRAアダプターをベースモデルへマージし、改造したChat Templateを持つTokenizerと一緒に保存しました。
公開したものはマージ済みモデルなので、推論時に別途LoRAアダプターを読み込む必要はありません。
reasoning_effortについて、今回の学習でできていなかったこと
ここは、結果を読む前に書いておきます。
データセットにはlow、medium、highのラベルがあります。しかし今回の学習用テキストへの変換処理では、各レコードのreasoning_effortやchat_template_kwargsをapply_chat_templateへ渡していませんでした。
そのため、学習プロンプトはテンプレートの既定値である、
Reasoning: medium
になっています。元のデータにlowやhighのラベルがあっても、そのラベルに対応したヘッダーで学習したわけではありません。
後半では推論時にlow、medium、highを変えますが、これは推論プロンプトを変えたときの観察です。「今回の追加学習で3段階のreasoning effortを学習できた」という評価にはなりません。
JSONに情報が入っていることと、モデルへ渡す文字列に反映されていることは違う。Chat Templateを調べていたはずなのに、自分の学習処理でもこの確認が必要でした。
19. 学習済みモデルの出力を確認する
確認に使った質問は、次の一つです。
今治西高ってどんな高校か教えてください。
これに対して、次の6条件の出力を見ました。
| channelの組み合わせ | reasoning_effort |
|---|---|
analysis → final
|
low / medium / high
|
analysis_imabari → final_imabari
|
low / medium / high
|
質問本文には「今治弁で答えてください」とは書いていません。channel一覧と生成開始channel、reasoning effortを指定しています。
公開モデルで同じ6種類のプロンプトを試すためのコード例です。以下の生成設定は再実行用の例であり、後述する既存ログと完全に同一の出力を保証するものではありません。既存ログには全生成設定が記録されていないためです。
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
model_id = "ikedachin/llm-jp-4-8b-thinking_imabari_qa_v4_reasoning_effort_v1"
tokenizer = AutoTokenizer.from_pretrained(model_id)
model = AutoModelForCausalLM.from_pretrained(
model_id,
dtype=torch.float16,
device_map="auto",
)
model.eval()
messages = [
{"role": "user", "content": "今治西高ってどんな高校か教えてください。"}
]
channel_settings = {
"standard": {
"valid_channels": ["analysis", "final", "commentary"],
"thinking_channel": "analysis",
"channel": "final",
},
"imabari": {
"valid_channels": ["analysis_imabari", "final_imabari", "commentary"],
"thinking_channel": "analysis_imabari",
"channel": "final_imabari",
},
}
for mode, settings in channel_settings.items():
for effort in ("low", "medium", "high"):
chat_kwargs = {
**settings,
"reasoning_effort": effort,
"add_generation_prompt": True,
"generate_thinking": True,
}
print(f"\n=== {mode} / {effort} ===")
print(tokenizer.apply_chat_template(
messages, tokenize=False, **chat_kwargs
))
inputs = tokenizer.apply_chat_template(
messages,
tokenize=True,
return_tensors="pt",
return_dict=True,
**chat_kwargs,
)
inputs = {key: value.to(model.device) for key, value in inputs.items()}
with torch.inference_mode():
output_ids = model.generate(
**inputs,
max_new_tokens=1024,
do_sample=False,
pad_token_id=tokenizer.eos_token_id,
)
# 入力も含めて、開始channelと生成後の遷移を確認する
print(tokenizer.decode(output_ids[0], skip_special_tokens=False))
# 生成した部分だけも確認する
input_length = inputs["input_ids"].shape[1]
generated_ids = output_ids[0, input_length:]
print(tokenizer.decode(generated_ids, skip_special_tokens=False))
FP16のモデルを動かせるだけのメモリがある環境を想定しています。また、公開モデルに保存したテンプレートの日付は2026-09-19で固定されています。
このコードで使うvalid_channels、generate_thinking、thinking_channel、channelは、今回の改造テンプレートが解釈する引数です。どのモデルでも同じように使えるTransformers共通の設定ではありません。
20. 結果:独自channelへの遷移は確認できた
手元の出力確認.mdに記録した6条件を整理すると、こうなりました。
| channel指定 | effort | ログ上の遷移 | 文体・出力の様子 |
|---|---|---|---|
| 通常 | low |
analysis → final
|
短い説明。標準語の文体 |
| 通常 | medium |
analysis → final
|
thinkingに見出しが付き、思考・回答とも方言表現あり |
| 通常 | high |
analysis → final
|
thinkingに見出しが付き、思考・回答とも方言表現あり |
| 今治弁用 | low |
analysis_imabari → final_imabari
|
思考・回答とも方言表現あり。最終回答は1文 |
| 今治弁用 | medium |
analysis_imabari → final_imabari
|
思考・回答とも方言表現あり |
| 今治弁用 | high |
analysis_imabari → final_imabari
|
思考・回答とも方言表現あり |
「思考」は、ここではanalysis側に生成されたテキストを指します。モデル内部の処理を直接観察した、という意味ではありません。
通常channel・low
まず、通常channelのlowです。ログからassistant部分を抜粋します。
<|start|> assistant<|channel|> analysis<|message|> 今治西高は愛媛県今治市にある公立の高等学校で、1902年に創立された歴史ある学校です。<|end|><|start|> assistant<|channel|> final<|message|> 今治西高は、愛媛県今治市にある公立の高等学校です。1902年に創立された歴史ある学校として知られています。<|return|>
この例は、analysisもfinalも標準語の文体でした。
今治弁用channel・medium
次に、今治弁用channelのmediumです。同じくassistant部分の抜粋です。
<|start|> assistant<|channel|> analysis_imabari<|message|> ## 思考プロセス
### 1. 質問の整理
今治西高がどんな高校かを聞かれとるけん、学校の概要や歴史、特徴を整理するんよ。
### 2. 答えへの接続
愛媛県今治市にある公立の高等学校や。1902年に創立され、2022年に創立120周年を迎えたんよ。今治市を代表する進学校として知られとるけん、この事実が答えにつながるんよ。<|end|><|start|> assistant<|channel|> final_imabari<|message|> 今治西高は、愛媛県今治市にある公立の高等学校なんよ。1902年に創立され、2022年に創立120周年を迎えたんよ。今治市を代表する進学校として知られとるんよ。<|return|>
おお。出た。😍
テンプレートで正解文を並べただけのときと違い、今回は学習後のモデルが本文と後続のchannelヘッダーを生成しています。
ただし、analysis_imabariの開始ヘッダーは入力側で用意したものです。モデルが生成した遷移として注目するのは、その後の<|end|>からfinal_imabari、そして<|return|>までの部分です。
今回の今治弁用3条件では、いずれもこの遷移を確認できました。
これは嬉しい結果です。ただし、一つの質問のログなので、一般的な成功率を示したものではありません。
21. でも、文体の切り替えはまだきれいに分離できていない
通常channelなら標準語、今治弁用channelなら今治弁。
最初にやりたかったのは、こういう使い分けでした。
ところが、通常channelのmediumやhighでも、
今治西高がどんな高校かを聞かれとるけん、学校の概要や歴史、特徴を整理するんよ。
というthinkingが出ています。回答にも「〜なんよ」「〜しとる」などの表現が出ました。
つまり今回の結果は、channelの形式は指定に対応していても、文体がそのchannelだけに限定されるわけではない、というものです。
そもそも、通常のanalysisという名前が「標準語専用」を意味するわけではありません。今回はこちらがそう使い分けたいと考えた、という話です。
追加学習で今治弁のデータを使った影響が通常channelにも出た可能性はあります。ただし、追加学習前のベースモデルを同条件で比較していないので、原因はまだ切り分けられていません。
また、「方言らしい語尾が出ること」と「自然な今治弁になっていること」も別です。今回のログから言えるのは、方言表現を含む出力が得られたというところまでです。
reasoning_effortを上げれば良くなる、とは言えない
通常channelのlowは短い説明で、mediumとhighでは見出し付きのthinkingになりました。
一方、今治弁用channelではlowでも見出し付きのthinkingが出ています。
このログだけで「low → medium → highの順に深く考えられる」とは言えません。長い文章や見出しが出たことと、推論の質が上がったことは別だからです。
加えて、今回の追加学習は先ほど書いたとおりReasoning: mediumで行われています。3段階の制御を評価するには、学習時の条件付けから見直す必要があります。
回答内容の正確さは、別に確認が必要
出力には、学校の沿革や野球部の成績について具体的な年や数字が含まれます。しかしログ間では、全国制覇したとする年などの記述が食い違っています。
例えば通常channelのmediumでは「1975年に全国制覇」、highでは「1962年と1963年に全国制覇」と出ています。これらは生成文の観察であり、学校の事実として紹介しているものではありません。
この記事の出力例は、学校紹介の資料として裏取りしたものではなく、形式と文体を確認するためのログです。channelが狙った形になっていても、内容が正しいとは限りません。
今回の確認では、未学習の質問だけを使った評価や、正答率の測定までは行っていません。
22. 出力確認では特殊トークンを残した方が分かりやすい
今回、出力を読むうえで役に立ったのが、
tokenizer.decode(output_ids[0], skip_special_tokens=False)
です。
skip_special_tokens=Trueにすると区切りの特殊トークンは取り除かれますが、最終回答だけを抽出してくれるわけではありません。thinkingの本文や、通常の文字列であるassistant、final_imabariなどが残ることがあります。
また、生成部分だけをdecodeすると、入力として置いた最初のanalysis_imabariヘッダーは出てきません。
そのため、確認時には次の両方を見ておくと整理しやすかったです。
- 入力と生成を含む全体:どのchannelから始めたかを確認する
- 新しく生成した部分:モデル自身がどの境界やchannelを出したかを確認する
「モデルが独自channelを書いた」と思ったら、実はプロンプト側で置いていた、という読み違いを防げます。
23. 独自channelは本当に必要なのか?
学習して出力が出たことで、むしろ次の疑問がはっきりしました。
そもそも、独自channelを作る方がよいのでしょうか?
普通のanalysis / finalに「今治弁で回答してください」と指示する方法でも、似たことはできるかもしれません。
今回の実験では、独自channelの方が優れているとまでは分かっていません。
次は、例えば以下を同じ条件で比較したいです。
| 比較したいもの | 確認したいこと |
|---|---|
| 通常channel+今治弁の指示 / 独自channel | 独自channelにする効果があるか |
| 標準語と今治弁のデータを混ぜた学習 | 通常channel側の標準語を保てるか |
| thinkingだけ今治弁 / 回答だけ今治弁 / 両方今治弁 | 思考文と回答文のスタイルを分けられるか |
| effortをレコードごとに正しく渡した学習 | 3段階の条件付けが出力に反映されるか |
| LLM-jp-4 / Qwenの独自ラベル形式 | 形式の違いが学習後の出力にどう現れるか |
同じ質問だけでなく、学習に使っていない複数の質問で、channelの遷移、文体、正確さを分けて確認したいところです。
……また実験が増えました。😂
24. 今回わかったこと
今回試して分かったことをまとめます。
- Chat Templateはmessagesを整形するルールで、Harmonyは会話の表現形式。役割が違う。
- LLM-jp-4では、改造テンプレートで独自channelを含む学習テキストを作れる。
- Qwenの今回のテンプレートでは、thinking内や回答前へテキストラベルを追加する方法を試せた。ただし追加学習は未実施。
- LLM-jp-4の8B版を実際に追加学習し、今回の今治弁用3条件では
analysis_imabariからfinal_imabariへの遷移を確認できた。 - 通常channelでも方言表現が出たため、channelだけで文体を完全に分離できたわけではない。
- 今回の学習プロンプトは
Reasoning: mediumで、3段階のreasoning effortを条件付けて学習できたとは言えない。 - channelの形式、方言の自然さ、回答の正確さは、それぞれ評価する必要がある。
- 学習前の整形テキストと、学習後の特殊トークンを含む生成結果の両方を見ることが大事。
個人的には、最後の8番が一番大きかったです。
25. おわりに
最初は「Chat Templateを変えたら、今治弁用channelを作れるのでは?」という軽い思いつきでした。
実際にやってみると、テンプレートで学習用の文字列を作ることはできました。さらに8Bモデルを追加学習し、独自channelから回答へ進む出力も確認できました。
ここまでは嬉しいです。
でも、通常channelにも方言が出る。おそらく、今回は追加channelでしか学習をしていないせいだと推測しています。標準語のデータセットも作らないといけないですね。
学習してみたことで、「文字列を作れる」と「狙いどおりに制御できる」の間にある課題が、少し具体的になりました。
Chat Templateを単なる前処理だと思っていた頃より、JSONのその先にある、モデルが実際に読む文字列を見るようになった気がします。
公開したモデルを再度掲載します。
まだ実験は続きますが、まずは学習して出力を見るところまで進められました。また、chat_templateの理解が非常に深くなったことは私自身得る物が非常に多かったです。
最後まで読んでいただきありがとうございました。😊
ということで追記コーナー
標準語と今治弁で学習(20260923追記)
今度はreasoning_effot=highでしか、今治弁、標準語の切り替えができませんでした。w
切り替えられた例だけ記しておきます。
highの出力
high
標準語
valid_channels=['analysis', 'final', 'commentary']
['<|start|> system<|message|> You are LLM-jp-4, a large language model trained by LLM-jp.\nKnowledge cutoff: 2025-12\nCurrent date: 2026-09-19\n\nReasoning: high\n\n# Valid channels: user, analysis, final, commentary. Channel must be included for every message.<|end|><|start|> user<|message|> 今治西高校について教えてください。<|end|><|start|> assistant<|channel|> analysis<|message|> ## 思考プロセス\n\n### 1. 質問の整理\n\n聞かれているのは今治西高校についてなので、この学校がどのカテゴリに属しているか、そして具体的にどんな特徴を持っているかを整理する必要があります。質問文には「今治西高校について教えてください」とあるだけなので、学校名と所在地、それからその学校が属している分類や、関連する情報をまとめるのが目的です。\n\n### 2. カテゴリの特定\n\ncontextの「日本の高等学校一覧」という節を見ると、愛媛県の学校が並べられています。その中に今治西高校が載っているんですが、この学校は「愛媛県立今治西高等学校」という名前で、今治市に所在しています。この節では、日本の高等学校を都道府県別に分類して一覧にしているので、今治西高校は愛媛県の高等学校として位置づけられています。\n\n### 3. 分類の整合性確認\n\ncontextには「日本の高等学校一覧」の他に、「日本の高等学校(あ行)」や「日本の高等学校(か行)」といった、五十音順のリストも載っています。今治西高校は「あ行」のリストには載っていないんですが、「か行」のリストにも載っていないです。つまり、この学校は五十音順のリストではなく、都道府県別の一覧として整理されています。\n\n### 4. 関連情報の検証\n\ncontextには「日本の高等学校一覧」の他に、「日本の高等学校(あ行)」「日本の高等学校(か行)」「日本の高等学校(さ行)」「日本の高等学校(た行)」「日本の高等学校(な行)」「日本の高等学校(は行)」「日本の高等学校(ま行)」「日本の高等学校(や行)」「日本の高等学校(ら行)」「日本の高等学校(わ行)」といった、各行ごとのリストも載っています。今治西高校はこれらのリストには載っていないです。\n\n### 5. 結論への接続\n\n今治西高校は愛媛県に所在しているので、愛媛県の高等学校として位置づけられています。contextの「日本の高等学校一覧」という節に載り、他の五十音順のリストには載っていないです。つまり、今治西高校は愛媛県の高等学校として、日本の高等学校一覧に載る学校です。\n\n### 6. 最終的な確認\n\n質問文には「今治西高校について教えてください」とあるだけなので、学校名と所在地、それからその学校が属している分類や、関連する情報をまとめるのが目的です。contextの「日本の高等学校一覧」という節を見ると、愛媛県の学校が並べられています。その中に今治西高校が載っているんですが、この学校は「愛媛県立今治西高等学校」という名前で、今治市に所在しています']
今治弁
valid_channels=['analysis_imabari', 'final_imabari', 'commentary'],
['<|start|> system<|message|> You are LLM-jp-4, a large language model trained by LLM-jp.\nKnowledge cutoff: 2025-12\nCurrent date: 2026-09-19\n\nReasoning: high\n\n# Valid channels: user, analysis_imabari, final_imabari, commentary. Channel must be included for every message.<|end|><|start|> user<|message|> 今治西高校について教えてください。<|end|><|start|> assistant<|channel|> analysis<|message|> ## 思考プロセス\n\n### 1. 質問の整理\n\n今治西高校について質問されとるけん、この学校がどのカテゴリに属しとるか、そしてどのような特徴や歴史を持つかを整理する必要があるんよ。質問文には具体的な条件や比較対象が示されとらんけん、学校名そのものが答えの核心になるんや。今治西高校は愛媛県今治市に位置する公立の高等学校や。今治西高等学校という名称で、今治西高や今治西、西高、西、今治西高と略されとるんよ。この学校は、愛媛県立今治西高等学校として設置されとるけん、公立の高等学校という属性が明確や。\n\n### 2. 沿革と歴史の検証\n\n沿革の項目を見ると、1922年(大正11年)に今治高等女学校として創立されとるんよ。その後、1948年(昭和23年)に愛媛県立今治西高等学校として新制高等学校が発足したんや。この新制発足が現在の今治西高校の起点や。1950年(昭和25年)には愛媛県立今治西高等学校定時制課程が開設され、1951年(昭和26年)には愛媛県立今治西高等学校通信制課程が開設されとるんよ。1952年(昭和27年)には愛媛県立今治西高等学校定時制課程が廃止され、1953年(昭和28年)には愛媛県立今治西高等学校定時制課程が再開設されとる。1954年(昭和29年)には愛媛県立今治西高等学校定時制課程が廃止され、1955年(昭和30年)には愛媛県立今治西高等学校定時制課程が再開設されとる。1956年(昭和31年)には愛媛県立今治西高等学校定時制課程が廃止され、1957年(昭和32年)には愛媛県立今治西高等学校定時制課程が再開設されとる。1958年(昭和33年)には愛媛県立今治西高等学校定時制課程が廃止され、1959年(昭和34年)には愛媛県立今治西高等学校定時制課程が再開設されとる。1960年(昭和35年)には愛媛県立今治西高等学校定時制課程が廃止され、1961年(昭和36年)には愛媛県立今治西高等学校定時制課程が再開設されとる。1962年']
痛恨のミス発覚 chat_templateのミス(20260923追記)
ミスってありますよね💦(言い訳)
v1、v2とも共通したミスです。
<|start|>system<|message|>You are LLM-jp-4, a large language model trained by LLM-jp.\nKnowledge cutoff: 2025-12\nCurrent date: 2026-09-19\n\nReasoning: medium\n\n# Valid channels: user, analysis, final, analysis_imabari, final_imabari, commentary. Channel must be included for every message.<|end|>
わかりますかねぇ。
学習時に実はすべてのチャンネルを指定してしまっていました💦
気付けて良かった。誠意、修正して再学習中です。
早速、再学習(20260923深夜追記)
結果、reasoning_effort="high"は繰り返し出力が出てしまい、ダメダメでしたが、lowとmediumはいい感じでした。
low
low
標準語
<|start|> system<|message|> You are LLM-jp-4, a large language model trained by LLM-jp.
Knowledge cutoff: 2025-12
Current date: 2026-09-19
Reasoning: low
# Valid channels: user, analysis, final, commentary. Channel must be included for every message.<|end|><|start|> user<|message|> 今治の特産品について教えてください。<|end|><|start|> assistant<|channel|> analysis<|message|> ## 思考プロセス
### 1. 質問の整理
今治の特産品について質問されているため、この地域で生産されている代表的な品目に注目します。
### 2. 答えへの接続
タオルや造船、そしてみかんが今治の特産品として挙げられています。これらが今治を代表する特産品であるため、答えにつながります。<|end|><|start|> assistant<|channel|> final<|message|> 今治の特産品は、タオルや造船、みかんです。<|return|>
今治弁
<|start|> system<|message|> You are LLM-jp-4, a large language model trained by LLM-jp.
Knowledge cutoff: 2025-12
Current date: 2026-09-19
Reasoning: low
# Valid channels: user, analysis_imabari, final_imabari, commentary. Channel must be included for every message.<|end|><|start|> user<|message|> 今治の特産品について教えてください。<|end|><|start|> assistant<|channel|> analysis_imabari<|message|> ## 思考プロセス
### 1. 質問の整理
今治の特産品を聞かれとるけん、地域ごとの名物に注目するんよ。
### 2. 答えへの接続
愛媛県今治市の項目に、タオルや造船、村上海賊、さいさいきて屋が挙げられとる。ほうやけん、これらが特産品として整理できるんよ。<|end|><|start|> assistant<|channel|> final_imabari<|message|> 今治の特産品は、タオルや造船、村上海賊、さいさいきて屋なんよ。<|return|>
medium
medium
標準語
<|start|> system<|message|> You are LLM-jp-4, a large language model trained by LLM-jp.
Knowledge cutoff: 2025-12
Current date: 2026-09-19
Reasoning: medium
# Valid channels: user, analysis, final, commentary. Channel must be included for every message.<|end|><|start|> user<|message|> 今治の特産品について教えてください。<|end|><|start|> assistant<|channel|> analysis<|message|> ## 思考プロセス
### 1. 質問の整理
今治の特産品について質問されているため、この地域で特に有名な製品や産業に注目します。単に地名を挙げるのではなく、実際に生産されている具体的な品目を特定する必要があります。
### 2. 特産品の特定
今治はタオルの産地として有名です。タオルの生産が盛んなため、この分野が特産品として挙げられます。また、造船業も盛んで、今治造船が本社を置いています。造船業は産業として今治を支えているため、これも特産品として考えられます。
### 3. 答えへの接続
タオルと造船業の二つが、今治の特産品として挙げられます。タオルは繊維産業、造船業は重工業として、今治の産業構造を支えているため、この二つが答えにつながります。<|end|><|start|> assistant<|channel|> final<|message|> 今治の特産品は、タオルと造船業です。<|return|>
今治弁
<|start|> system<|message|> You are LLM-jp-4, a large language model trained by LLM-jp.
Knowledge cutoff: 2025-12
Current date: 2026-09-19
Reasoning: medium
# Valid channels: user, analysis_imabari, final_imabari, commentary. Channel must be included for every message.<|end|><|start|> user<|message|> 今治の特産品について教えてください。<|end|><|start|> assistant<|channel|> analysis_imabari<|message|> ## 思考プロセス
### 1. 質問の整理
今治の特産品について聞かれとるけん、この地域で特に有名な産業や製品に注目するんよ。単に地名を挙げるだけやなくて、実際に生産されとる具体的な品目を特定する必要があるんや。
### 2. 産業構造の確認
今治は瀬戸内海に面しとるけん、海運や造船業が盛んなんよ。また、タオルの産地として知られとるけん、繊維産業も重要な位置を占めとる。これらの産業が地域の経済を支えとる基盤や。
### 3. 特産品の特定
産業構造の中で、特に「今治タオル」が特産品として挙げられとるんよ。タオルは繊維産業と深く結びついとるけん、この地域を代表する製品として定着しとる。
### 4. 答えへの接続
聞かれとるんは特産品やけん、産業全体ではなく、その中でも特に有名な製品に絞るんよ。今治タオルは繊維産業の象徴やけん、この問いに対する答えとして適切や。ほうやけん、今治の特産品は今治タオルなんよ。<|end|><|start|> assistant<|channel|> final_imabari<|message|> 今治の特産品は、今治タオルなんよ。<|return|>
high
標準語
<|start|> system<|message|> You are LLM-jp-4, a large language model trained by LLM-jp.
Knowledge cutoff: 2025-12
Current date: 2026-09-19
Reasoning: high
# Valid channels: user, analysis, final, commentary. Channel must be included for every message.<|end|><|start|> user<|message|> 今治の特産品について教えてください。<|end|><|start|> assistant<|channel|> analysis<|message|> ## 思考プロセス
### 1. 質問の整理
聞かれているのは、今治の特産品についてです。今治という地域に絞って、その地域で生産されている代表的な商品や、地域と結びついている産業について整理する必要があります。単に「特産品」という言葉だけを捉えるのではなく、今治という地理的な枠組みの中で、どのような産業が根付いていて、それが特産品として位置づけられているのか、という視点で考えることが重要です。
### 2. 産業構造からの特産品の抽出
今治の産業構造を見ると、繊維産業が基幹産業として位置づけられています。繊維産業が基幹産業であるということは、この地域で繊維関連の産業が長い歴史と規模を持っていることを示しています。繊維産業が基幹産業である地域は、繊維関連の製品が特産品として発展しやすい傾向があります。
### 3. 具体的な特産品の特定
繊維産業が基幹産業である今治では、タオルが特産品として挙げられています。タオルは繊維産業と直結している製品であり、今治の繊維産業の歴史と規模が、タオルという特産品として結実しています。タオルは単なる日用品ではなく、今治の産業構造を象徴する特産品として位置づけられています。
### 4. 産業構造と特産品の整合性確認
繊維産業が基幹産業である今治では、タオルが特産品として挙げられています。この事実は、今治の産業構造と特産品の整合性を確認する上で重要です。繊維産業が基幹産業である地域は、繊維関連の製品が特産品として発展しやすい傾向があります。タオルは繊維産業と直結している製品であり、今治の繊維産業の歴史と規模が、タオルという特産品として結実しています。
### 5. 結論への接続
今治の産業構造を見ると、繊維産業が基幹産業として位置づけられています。繊維産業が基幹産業である今治では、タオルが特産品として挙げられています。タオルは繊維産業と直結している製品であり、今治の繊維産業の歴史と規模が、タオルという特産品として結実しています。この事実は、今治の特産品がタオルであることを示しています。
### 6. 補足的な確認
今治の特産品としてタオルが挙げられているのは、繊維産業が基幹産業であるという事実と整合しています。繊維産業が基幹産業である地域は、繊維関連の製品が特産品として発展しやすい傾向があります。タオルは繊維産業と直結している製品であり、今治の繊維産業の歴史と規模が、タオルという特産品として結実しています。この事実は、今治の特産品がタオルであることを示しています。
### 7. 最終的な整理
今治の特産品はタオルです。繊維産業が基幹産業である今治では、タオルが特産品として挙げられています。タオルは繊維産業と直結している製品であり、今治の繊維産業の歴史と規模が、タオルという特産品として結実しています。この事実は、今治の特産品がタオルであることを示しています。
### 8. 結論の確定
今治の特産品はタオルです。繊維産業が基幹産業である今治では、タオルが特産品として挙げられています。タオルは繊維産業と直結している製品であり、今治の繊維産業の歴史と規模が、タオルという特産品として結実しています。この事実は、今治の特産品がタオルであることを示しています。
### 9. 最終的な確認
今治の特産品はタオルです。繊維産業が基幹産業である今治では、タオルが特産品として挙げられています。タオルは繊維産業と直結している製品であり、今治の繊維産業の歴史と規模が、タオルという特産品として結実しています。この事実は、今治の特産品がタオルであることを示しています。
### 10. 結論の確定
今治の特産品はタオルです。繊維産業が基幹産業である今治では、タオルが特産品として挙げられています。タオルは繊維産業と直結している製品であり、今治の繊維産業の歴史と規模が、タオルという特産品として結実しています。この事実は、今治の特産品がタオルであることを示しています。
### 11. 最終的な整理
今治の特産品はタオルです。繊維産業が基幹産業である今治では、タオルが特産品として挙げられています。タオルは繊維産業と直結している製品であり、今治の繊維産業の歴史と規模が、タオルという特産品として結実しています。この事実は、今治の特産品がタオルであることを示しています。
.............(以下、カウントアップしながら延々続くwww)
今治弁
<|start|> system<|message|> You are LLM-jp-4, a large language model trained by LLM-jp.
Knowledge cutoff: 2025-12
Current date: 2026-09-19
Reasoning: high
# Valid channels: user, analysis_imabari, final_imabari, commentary. Channel must be included for every message.<|end|><|start|> user<|message|> 今治の特産品について教えてください。<|end|><|start|> assistant<|channel|> analysis_imabari<|message|> ## 思考プロセス
### 1. 質問の整理
聞かれとるんは、今治の特産品についてなんよ。今治は愛媛県の北東部に位置しよる都市やけん、この地域で生産されとる代表的な品目を特定する必要があるんよ。質問の焦点は「特産品」やけん、単なる農産物や工業製品ではなく、地域を代表するブランドとして定着しよる商品群に注目するんが大事なんよ。今治という地名が冠に付いとる商品や、この地域ならではの特色を持つ商品を中心に整理するんが、答えの筋道として自然なんよ。
### 2. 特産品の構成要素
今治の特産品は、繊維製品、タオル、造船、造船関連産業、造船関連部品、造船関連機械、造船関連資材、造船関連サービス、造船関連ソフトウェア、造船関連コンサルティング、造船関連教育、造船関連研究、造船関連出版、造船関連イベント、造船関連展示会、造船関連セミナー、造船関連フォーラム、造船関連シンポジウム、造船関連ワークショップ、造船関連交流会、造船関連ネットワーク、造船関連コミュニティ、造船関連団体、造船関連協会、造船関連組合、造船関連企業、造船関連工場、造船関連事業所、造船関連施設、造船関連インフラ、造船関連物流、造船関連輸送、造船関連販売、造船関連流通、造船関連マーケティング、造船関連広告、造船関連PR、造船関連ブランディング、造船関連デザイン、造船関連パッケージング、造船関連品質管理、.............(延々続く)
llm-jpのこのモデル。
実はものすごく素直で使いやすいモデルかもしれませんね。
とても学習効果が良く聞きそうです。
とはいえ、reasoning_effort="high"で繰り返し出力が出まくりなので、ちょっとデータセットを確認しなきゃならんですな!
ではまた
reasoning_effort="high"を問題を変えて楽しむ(20260923深夜すぎw追記)
とは言ったものの、やっぱりhighが気になる
ちょっとめんどくさい問題を作ってもらったので解かしてみた
【問題】
以下の条件をすべて満たす、1文だけの日本語の文章を作成してください。
1. 文章の中に「りんご」という言葉を必ず含める。
2. 文章全体の文字数は「ちょうど23文字」にする(句読点も含めます)。
3. 作成した文章と、その文字数のカウント(1文字ずつ分解したもの)をあわせて出力してください。
じゃ、回答を見てみよう
標準語
## 思考プロセス
### 1. 条件の整理
今回の問いは、文章の中に「りんご」という言葉を入れ、全体の文字数をちょうど23文字にするというものです。句読点も文字数に含めるため、この点は非常に重要です。さらに、作成した文章と、その文字数のカウントを1文字ずつ分解して出力する必要があります。つまり、文章そのものと、それを1文字ずつ区切ったリスト、この二つをセットで提示しなければなりません。条件を整理すると、まず「りんご」という語句が必須であること、次に文字数が23文字であること、最後にカウントの分解が正確であること、この三つが揃わなければなりません。
### 2. 文字数の検証
まず、文章の文字数を確認します。句読点も含めて23文字にしなければならないため、文章の長さを正確に測る必要があります。例えば、「りんごは赤い果物です。」という文章は、句読点を含めて13文字です。これでは足りません。23文字にするためには、もう少し長い文章にしなければなりません。しかし、長すぎると「りんご」という言葉の位置や、文章の自然さが崩れる恐れがあります。そのため、23文字という制限の中で、自然な文章を作る必要があります。
### 3. 文章の作成
23文字という制限の中で、「りんご」という言葉を入れ、自然な文章を作るには、いくつかの工夫が必要です。まず、文章の構造を考えます。主語と述語、修飾語などをバランスよく配置することで、自然な文章になります。例えば、「りんごは甘くて、シャキッとした食感が特徴です。」という文章は、句読点を含めて23文字です。この文章には「りんご」という言葉が入っており、文字数も23文字です。しかし、この文章は「りんご」という言葉の後に「は」が続くため、条件の「文章の中に『りんご』という言葉を必ず含める」には合っていますが、より自然な文章にするために、もう少し工夫が必要です。
### 4. カウントの分解
文章が23文字であることが確認できたら、次はその文字数を1文字ずつ分解してカウントします。例えば、「りんごは甘くて、シャキッとした食感が特徴です。」という文章は、句読点を含めて23文字です。この文章を1文字ずつ分解すると、り、ん、ご、は、甘、く、て、、、シ、ャ、キ、ッ、と、し、た、食、感、が、特、徴、で、す、。となります。この分解が正確であることを確認することで、文字数が23文字であることが裏付けられます。
### 5. 条件の最終確認
最後に、すべての条件が満たされているかを確認します。まず、「りんご」という言葉が入っているか確認します。この文章には「りんご」という言葉が入っています。次に、文字数が23文字であるか確認します。この文章は句読点を含めて23文字です。最後に、カウントの分解が正確であるか確認します。この文章は1文字ずつ分解すると、り、ん、ご、は、甘、く、て、、、シ、ャ、キ、ッ、と、し、た、食、感、が、特、徴、で、す、。となります。この分解が正確であるため、文字数が23文字であることが裏付けられます。
### 6. 結論
以上の検証から、この文章はすべての条件を満たしています。文章の中に「りんご」という言葉が入っており、全体の文字数はちょうど23文字です。さらに、その文字数のカウントを1文字ずつ分解して提示しています。そのため、この文章は条件をすべて満たしています。<|end|><|start|> assistant<|channel|> final<|message|> りんごは甘くて、シャキッとした食感が特徴です。
り、ん、ご、は、甘、く、て、、、シ、ャ、キ、ッ、と、し、た、食、感、が、特、徴、で、す、。<|return|>
今治弁
<|start|> system<|message|> You are LLM-jp-4, a large language model trained by LLM-jp.
Knowledge cutoff: 2025-12
Current date: 2026-09-19
Reasoning: high
# Valid channels: user, analysis_imabari, final_imabari, commentary. Channel must be included for every message.<|end|><|start|> user<|message|> 【問題】
以下の条件をすべて満たす、1文だけの日本語の文章を作成してください。
1. 文章の中に「りんご」という言葉を必ず含める。
2. 文章全体の文字数は「ちょうど23文字」にする(句読点も含めます)。
3. 作成した文章と、その文字数のカウント(1文字ずつ分解したもの)をあわせて出力してください。
<|end|><|start|> assistant<|channel|> analysis_imabari<|message|> ## 思考プロセス
### 1. 条件の整理
今回の問いは、1文だけの日本語の文章を作るんや。ただ文章を作るだけやなくて、その中に「りんご」という言葉を入れなあかん。さらに、文章全体の文字数が「ちょうど23文字」にならんといけん。ここで言う文字数には、句読点も含めるんやけん、その点も注意しなあかん。そして、作った文章と、その文字数のカウントを1文字ずつ分解して出すんや。つまり、文章とカウントの両方が条件に合うように、慎重に組み立てる必要があるんよ。
### 2. 文字数の確認
まず、文章の文字数を確認するんや。23文字という条件は、句読点も含めて数えるんやけん、この点を明確にするんが大事なんよ。文章を作る前に、23文字という枠の中で、どんな言葉を並べられるかを考えるんや。例えば、主語や述語、修飾語など、文章を構成する要素をどう配置するかで、文字数が変わるんや。また、句読点を入れるかどうかでも、文字数が変わるけん、その点も考慮しなあかん。
### 3. 文章の作成
次に、文章を作るんや。条件1で「りんご」という言葉を入れなあかんけん、この言葉を文章の中に入れるんや。条件2で23文字にならんといけんけん、文字数を数えながら文章を作るんや。例えば、「りんご」という言葉を入れた後、その後に続ける言葉を考えるんや。また、句読点を入れる場合は、その文字数もカウントするんや。文章全体の流れや、自然な日本語になるように、言葉を並べるんや。
### 4. カウントの確認
文章を作ったら、次に文字数をカウントするんや。1文字ずつ分解して、何文字あるかを確認するんや。句読点も1文字として数えるんやけん、その点も確認するんや。もし23文字にならんかったら、文章を修正するんや。例えば、言葉を追加したり、削除したりして、23文字に合わせるんや。また、句読点の位置や、文字の区切り方によっても、文字数が変わるけん、その点も確認するんや。
### 5. 条件の照合
最後に、作った文章とカウントが、条件に合うかを確認するんや。条件1で「りんご」という言葉が入っているか、条件2で23文字にならんか、条件3でカウントが1文字ずつ分解されているか、これらを確認するんや。もし条件に合わんかったら、文章を修正するんや。例えば、「りんご」という言葉の位置を変えたり、文字数を調整したりして、条件に合うようにするんや。
### 6. 結論
以上の手順で、条件に合う文章を作るんや。文章の中に「りんご」という言葉を入れ、23文字にならんようにし、句読点も含めて文字数をカウントするんや。そして、作った文章と、その文字数のカウントを1文字ずつ分解して出すんや。この手順を踏むことで、条件に合う文章を作ることができるんよ。<|end|><|start|> assistant<|channel|> final_imabari<|message|> りんごは甘くて、シャキッとした食感がええんよ。りんごは甘くて、シャキッとした食感がええんよ。りんごは甘くて、シャキッとした食感がええんよ。りんごは甘くて、シャキッとした食感がええんよ。りんごは甘くて、シャキッとした食感がええんよ。りんごは甘くて、シャキッとした食感がええんよ。りんごは甘くて、シャキッとした食感がええんよ。りんごは甘くて、シャキッとした食感がええんよ。りんごは甘くて、シャキッとした食感がええんよ。りんごは甘くて、シャキッとした食感がええんよ。りんごは甘くて、シャキッとした食感がええんよ。りんごは甘くて、シャキッとした食感がええんよ。りんごは甘くて、シャキッとした食感がええんよ。りんごは甘くて、シャキッとした食感がええんよ。.............(延々続く。涙)
ちょっと、EOSが弱いんかな?そんな気がするな
改めて、またっ!バイバイ