ikedachin/llm-jp-4-8b-thinking_imabari_qa_v4_reasoning_effort_v1
LLM-jp-4-8B-thinking — Imabari
日本語の説明は下にあります。 Japanese description is available below.
Overview
This model is a fully merged model created by taking [llm-jp/llm-jp-4-8b-thinking](https://huggingface.co/llm-jp/llm-jp-4-8b-thinking) as the base model.
It is tuned to generate reasoning text and answers with the style and linguistic flavor of the Imabari dialect. A custom chat template provides the analysis_imabari and final_imabari channels alongside the standard analysis and final channels.
What This Repository Contains
This repository contains the merged full model, not a LoRA adapter. Therefore, you do not need to load the base model separately at inference time.
- Base model:
llm-jp/llm-jp-4-8b-thinking - Base model license: Apache-2.0
- Model files: Merged weights in Safetensors format
- Tokenizer: Saved with the custom chat template used for training
- Training data license: CC BY-SA 4.0; see License below
Training Data
The following dataset was used for training:
- Dataset: ikedachin/imabari_wiki_qa_v4_reasoning_effort_llmjp4
- Creator:
ikedachin - License: CC BY-SA 4.0
- Training split: 13,262 records
- Validation split: 1,473 records
The dataset preserves questions and answers from Imabari Wiki QA v4 Validated and adds regenerated reasoning text based on source article context. It includes low, medium, and high reasoning-effort labels.
The training data is formatted as chat messages using the question, thinking, and answer fields. Reasoning text is assigned to `analysis_imabari`, and the final answer to `final_imabari`.
Training Method
This model was created through the following process:
- Use llm-jp/llm-jp-4-8b-thinking as the base model
- Format the QA data with the custom Imabari-channel chat template
- Perform supervised fine-tuning with LoRA using Transformers / TRL / PEFT
- Merge the trained LoRA adapter into the base model
- Save the merged model and Tokenizer
- Method: LoRA fine-tuning + merged model export
The model was fine-tuned with the following settings:
Reasoning-effort handling: All training prompts use `Reasoning: medium`, regardless of the original low, medium, or high label in the dataset. The inference template accepts all three values, but this training does not establish learning of the intended three-level conditioning.
Training Environment
- Libraries: PyTorch / Transformers / TRL / PEFT / Datasets
- Experiment tracking: Weights & Biases
- Model loading dtype:
torch.float16 - Training precision setting: BF16 when supported by the CUDA device; otherwise FP16 on CUDA
Usage
Load the model
pip install transformers torch accelerateUse the merged model directory, or replace model_name below with your uploaded Hugging Face repository ID. Always load the Tokenizer distributed with this fine-tuned model, because it contains the modified chat template.
The following example assumes an environment with sufficient memory for FP16 inference, such as the GPU environment used for training.
1. Default LLM-jp-4 behavior
The following describes the official chat template for llm-jp-4-8b-thinking, before the modifications made for this model.
- The system prompt lists `analysis`, `commentary`, and `final` as a fixed set of channels. The official template does not read a
valid_channelsargument. - For ordinary assistant messages, the template uses
analysisfor reasoning andfinalfor answers. It reads reasoning fromthinkingand the answer fromcontent; historical reasoning is normally omitted during inference. reasoning_effortis an existing LLM-jp-4 template option. It supplies the value inReasoning: ...and defaults to"medium".add_generation_prompt=Trueis a Transformers option used by the official template. The official template appends `<|start|>assistant`; it does not usegenerate_thinking,thinking_channel, orchannelto choose a starting channel.
Thus, the default channel names and reasoning-effort option come from LLM-jp-4. The configurable channel list and explicit starting-channel controls described next are modifications made for this fine-tuned model.
2. Features added in this model's chat template
This model's chat template has been modified to add `valid_channels`, making the previously fixed channel list in the system prompt configurable. The modifications also introduce the Imabari-dialect channel names `analysis_imabari` and `final_imabari`, along with controls for selecting the generation-start header.
The template retains the existing reasoning_effort option. The names analysis_imabari and final_imabari, and the arguments in the table above, are features of this repository's modified template, not additional standard LLM-jp-4 API options. Load this model's saved Tokenizer to use them.
The channel list and the starting channel are separate settings. valid_channels tells the model which channel names are available. thinking_channel or channel determines the header appended to the prompt. Setting only valid_channels does not change the starting channel.
This model's chat template also simplifies the official template for QA: it retains supplied historical reasoning, uses a fixed date, and does not include the official tool-call rendering. Selecting analysis and final in this modified template does not restore the complete official template behavior.
3. Using the added channel controls
First choose the channel list with valid_channels. Then choose whether to start with reasoning, and explicitly select the starting channel.
These are suggested lists for this modified template. Keep role="assistant" for assistant messages; a channel does not replace the role.
For example, the Imabari list produces the following system-prompt declaration. user is inserted by the template:
# Valid channels: user, analysis_imabari, final_imabari, commentary. Channel must be included for every message.Next, select the starting header. All rows below assume add_generation_prompt=True and use this model's modified template.
When `generate_thinking=True`, `channel="final_imabari"` does not force the later answer channel. The initial header uses only thinking_channel; the model generates subsequent channel transitions. To start directly in final_imabari, set generate_thinking=False and channel="final_imabari".
The following inference example uses the added Imabari controls together with the inherited reasoning_effort option. These prompt settings do not guarantee dialect consistency. See Reasoning-effort handling above for what this training run actually conditioned on.
Inference and inspecting outputs
This example prints the formatted prompt, input IDs, generated IDs before decoding, and decoded text with and without special tokens. The same chat_kwargs are used for prompt display and tokenization.
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
model_name = "ikedachin/llm-jp-4-8b-thinking_imabari_qa_v4_reasoning_effort_v1"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
dtype=torch.float16,
device_map="auto",
)
model.eval()
messages = [{"role": "user", "content": "今治の特産品について教えてください。"}]
chat_kwargs = {
# Existing LLM-jp-4 / Transformers options
"reasoning_effort": "medium", # "low", "medium", "high"
"add_generation_prompt": True,
# Options added in this model's modified template
"valid_channels": ["analysis_imabari", "final_imabari", "commentary"],
"generate_thinking": True,
"thinking_channel": "analysis_imabari",
"channel": "final_imabari", # Used when generate_thinking=False
}
# 1. Formatted prompt
prompt = tokenizer.apply_chat_template(messages, tokenize=False, **chat_kwargs)
print("=== Prompt ===")
print(prompt)
# 2. Tokenize
inputs = tokenizer.apply_chat_template(
messages,
tokenize=True,
return_tensors="pt",
return_dict=True,
**chat_kwargs,
)
print("=== Input token IDs ===")
print(inputs["input_ids"][0].tolist())
inputs = {key: value.to(model.device) for key, value in inputs.items()}
# 3. Generate
with torch.inference_mode():
output_ids = model.generate(
**inputs,
max_new_tokens=512,
do_sample=False,
pad_token_id=tokenizer.eos_token_id,
)
# output_ids includes the prompt
input_length = inputs["input_ids"].shape[1]
generated_ids = output_ids[0, input_length:]
# 4. Before decode
print("=== Full output token IDs (prompt + generation) ===")
print(output_ids[0].tolist())
print("=== Generated token IDs only ===")
print(generated_ids.tolist())
# 5. After decode
raw_text = tokenizer.decode(generated_ids, skip_special_tokens=False)
text = tokenizer.decode(generated_ids, skip_special_tokens=True)
print("=== Generated text: special tokens kept ===")
print(raw_text)
print("=== Generated text: special tokens removed ===")
print(text)
# 6. Entire conversation
print("=== Full conversation: special tokens kept ===")
print(tokenizer.decode(output_ids[0], skip_special_tokens=False))To try another row of the channel table, change chat_kwargs and rerun from the prompt creation step. For example, set "generate_thinking": False and "channel": "final_imabari" to start directly in the Imabari answer channel.
Reading the output (standard Transformers behavior)
- Before decode:
output_idsis a two-dimensional tensor with a batch dimension.output_ids[0]contains the prompt plus generated tokens;generated_idscontains only the new tokens..tolist()displays their integer IDs. - After decode, `skip_special_tokens=False`: Special-token markers remain visible, making message boundaries and channel transitions easier to inspect.
- After decode, `skip_special_tokens=True`: Registered special tokens are removed. This does not extract only the final answer: reasoning text, role names, and channel names may remain.
In this template, <|start|>, <|channel|>, <|message|>, <|end|>, and <|return|> delimit messages, headers, and turn endings. Names such as analysis_imabari are text between these markers. The initial assistant header is already part of the input, so it does not appear at the start of raw_text, which decodes only newly generated tokens. Decode output_ids[0] to see that header too. For multiple sequences, use tokenizer.batch_decode(output_ids, ...).
Output comparison: standard and added channels
The following examples answer the same question using the same fine-tuned model and modified template, with different valid_channels settings. They compare the original channel names with the added Imabari channel names; they are not a comparison against the unfine-tuned base model.
Question: 今治の特産品について教えてください。
Both examples use reasoning_effort="low", generate_thinking=True, and add_generation_prompt=True. thinking_channel is omitted in both, so their initial reasoning header is analysis. The changed setting is:
The standard-channel example uses expressions such as 「挙げられています」「です」, while the Imabari-channel example uses 「挙げられとるんよ」「なんよ」. The answer header also changes from `final` to the added `final_imabari`. The content differs as well, so these are generation examples rather than identical answers rewritten in two styles.
Standard channels: decoded output with special tokens
The excerpt includes the initial assistant header from the prompt:
<|start|> assistant<|channel|> analysis<|message|> 特産品としてタオルが挙げられています。<|end|><|start|> assistant<|channel|> final<|message|> 今治の特産品はタオルです。<|return|>Added Imabari channels: decoded output with special tokens
<|start|> assistant<|channel|> analysis<|message|> 今治の特産品として、タオルや造船、造船関連産業、タオル美術館、タオル美術館ホールが挙げられとるんよ。<|end|><|start|> assistant<|channel|> final_imabari<|message|> 今治の特産品は、タオルや造船、造船関連産業、タオル美術館、タオル美術館ホールなんよ。<|return|>Here, the model continues from analysis and produces an answer in final_imabari. Listing analysis_imabari in valid_channels does not change the already supplied analysis header.
Decoded output with special tokens removed
For the generated tokens only, skip_special_tokens=True removes the markers but retains the reasoning text and ordinary strings such as assistant and the answer channel name.
Standard channels:
特産品としてタオルが挙げられています。 assistant final 今治の特産品はタオルです。Added Imabari channels:
今治の特産品として、タオルや造船、造船関連産業、タオル美術館、タオル美術館ホールが挙げられとるんよ。 assistant final_imabari 今治の特産品は、タオルや造船、造船関連産業、タオル美術館、タオル美術館ホールなんよ。Starting explicitly in the added analysis_imabari channel
To start in the added reasoning channel too, use the following settings in the inference example and rerun from prompt creation:
chat_kwargs = {
"reasoning_effort": "low",
"add_generation_prompt": True,
"valid_channels": ["analysis_imabari", "final_imabari", "commentary"],
"generate_thinking": True,
"thinking_channel": "analysis_imabari",
}This changes the prompt suffix as follows. These are template-produced headers, not a new pair of generated answers:
To start directly in the added answer channel, set generate_thinking=False and add channel="final_imabari". The prompt then ends with <|start|>assistant<|channel|>final_imabari<|message|>.
The generated text for these explicit-start settings must be checked by running them; the two answer examples above use the default analysis start. Subsequent channel transitions remain model-generated. These examples illustrate formatting and dialect expressions, not verified factual accuracy or guaranteed style control.
Conversation history in the modified template
In this modified template, for previous assistant messages, put thinking_channel and channel inside each message dictionary. These fields format existing history. The top-level arguments to apply_chat_template select the header for the next generation and do not rewrite historical messages.
# Illustrative history
history = [
{"role": "user", "content": "今治の特産品について教えてください。"},
{
"role": "assistant",
"thinking_channel": "analysis_imabari",
"thinking": "今治の特産品として、タオルについて答えるんよ。",
"channel": "final_imabari",
"content": "今治タオルが有名なんよ。",
},
{"role": "user", "content": "もう少し詳しく教えてください。"},
]
print(tokenizer.apply_chat_template(history, tokenize=False, **chat_kwargs))The template formats a nonempty thinking field as a reasoning message and content as an answer message. If the per-message channels are omitted, it uses analysis and final. For history containing an answer only, omit thinking and retain the answer's channel. Setting generate_thinking=False affects the next generation header; it does not remove reasoning already present in history.
References: Transformers chat templates, Tokenizer decoding API.
Notes
Current limitation — channel-based style control: Output checks have shown that the model often uses Imabari dialect even when valid_channels specifies the standard analysis and final channels. Switching between standard Japanese and Imabari dialect through channel settings is therefore not yet reliable and needs further improvement. The output comparisons above illustrate individual examples, not consistent style separation.
- Generated answers and reasoning text may contain factual errors or inconsistent dialect expressions.
- The output examples are not a systematic evaluation of factual accuracy, dialect control, or reasoning-effort control.
- The custom template contains a fixed
Current date: 2026-09-19string. It does not automatically reflect the inference date. - When redistributing, continuing training, merging, using commercially, or publishing derivatives, review the base model's Apache-2.0 terms and the training data's CC BY-SA 4.0 terms, including applicable attribution and source notices.
Japanese Description / 日本語説明
概要
本モデルは、[llm-jp/llm-jp-4-8b-thinking](https://huggingface.co/llm-jp/llm-jp-4-8b-thinking) をベースモデルとしています。
今治方言の文体や語感を取り入れた思考文・回答を生成するように調整しています。独自のチャットテンプレートにより、標準の analysis / final に加えて、今治弁用の analysis_imabari / final_imabari チャネルを指定できます。
このリポジトリに含まれるもの
このリポジトリには LoRAアダプタではなく、マージ済みモデル本体 が含まれています。 そのため、推論時にベースモデルを別途読み込む必要はありません。
- Base model:
llm-jp/llm-jp-4-8b-thinking - ベースモデルのライセンス: Apache-2.0
- モデルファイル: Safetensors形式のマージ済み重み
- Tokenizer: 学習に使用した独自チャットテンプレートを保存
- 学習データのライセンス: CC BY-SA 4.0。詳細は後述の License を参照してください。
学習データ
学習には以下のデータセットを使用しています。
- Dataset: ikedachin/imabari_wiki_qa_v4_reasoning_effort_llmjp4
- 作成者:
ikedachin - ライセンス: CC BY-SA 4.0
- 学習データ: 13,262件
- 検証データ: 1,473件
Imabari Wiki QA v4 Validated の質問と回答を保持し、元記事の文脈を参照して思考文を再生成したデータセットです。low / medium / high の reasoning effort ラベルを含みます。
学習データは question・thinking・answer からチャット形式に整形し、思考文を `analysis_imabari`、最終回答を `final_imabari` に割り当てています。
学習方法
本モデルは以下の流れで作成しています。
- llm-jp/llm-jp-4-8b-thinking をベースモデルとして使用
- 今治弁チャネルを含む独自チャットテンプレートでQAデータを整形
- Transformers / TRL / PEFT を用いて LoRA による教師ありファインチューニングを実施
- 学習後の LoRA アダプタをベースモデルへマージ
- マージ済みモデルとTokenizerを保存
- Method: LoRA fine-tuning + merged model export
- 主な設定: 1 epoch、学習率
2e-4、最大系列長8,192トークン、デバイスあたりのバッチサイズ2、勾配累積8 - LoRA設定: rank 8、alpha 16、dropout 0.0。詳細は英語部分の設定表を参照してください。
reasoning effort の扱い: 学習時のプロンプトは、元データの low・medium・high のラベルにかかわらず、すべて `Reasoning: medium` に統一しています。推論時には3段階を指定できますが、この学習によって意図した3段階の条件付けを獲得したことを示すものではありません。
学習環境
- Libraries: PyTorch / Transformers / TRL / PEFT / Datasets
- 実験記録: Weights & Biases
- モデル読み込み時のdtype:
torch.float16 - 学習時の精度設定: CUDAデバイスがBF16に対応する場合はBF16、それ以外のCUDA環境ではFP16
使用方法
モデルの読み込み
pip install transformers torch accelerateマージ済みモデルの保存先、またはアップロード先の Hugging Face リポジトリIDを指定します。独自チャットテンプレートを使うため、ベースモデルのTokenizerではなく、この学習済みモデルに付属するTokenizerを読み込んでください。
以下のコードは、学習時のGPU環境など、FP16でモデルを読み込める十分なメモリがある環境を想定しています。
1. LLM-jp-4の標準の動作
まず、今回の改造前にあたる llm-jp-4-8b-thinking の公式チャットテンプレート の動作を説明します。
- システムプロンプトの利用可能なチャネルは、`analysis`・`commentary`・`final` に固定されています。公式テンプレートは
valid_channels引数を参照しません。 - 通常のassistantメッセージでは、思考文に
analysis、回答にfinalを使います。思考文はメッセージ内のthinking、回答はcontentから読み込みます。推論時の過去の思考文は、通常は履歴に展開されません。 reasoning_effortは LLM-jp-4にもともとある設定です。システムプロンプトのReasoning: ...に値を設定し、省略時は"medium"になります。add_generation_prompt=Trueは、公式テンプレートでも使われるTransformersの指定です。公式テンプレートが付ける末尾は `<|start|>assistant` までで、generate_thinking・thinking_channel・channelによる開始チャネルの指定は行いません。
つまり、標準のチャネル名や reasoning effort の指定はLLM-jp-4由来です。次に説明する「チャネル一覧の変更」と「生成開始チャネルの指定」は、今回のモデル用に加えた改造です。
2. 今回のchat_templateで追加した機能
このモデルのチャットテンプレートを改変し、固定だったシステムプロンプトのチャネル一覧を変更できるよう、`valid_channels` を追加しています。あわせて、今治弁用のチャネル名 `analysis_imabari`・`final_imabari` と、生成開始ヘッダーを選ぶ設定を追加しました。
既存の reasoning_effort は引き続き利用できます。一方、analysis_imabari・final_imabari という名前と、上表の引数は、このリポジトリの改造テンプレートで使う機能です。LLM-jp-4の標準APIに追加されたものではないため、このモデルに保存されたTokenizerを読み込んで使用してください。
チャネル一覧と、開始チャネルは別の指定です。 valid_channels は「利用可能なチャネル名」をモデルに伝え、thinking_channel または channel は「入力末尾に付ける生成開始ヘッダー」を決めます。valid_channels だけを変更しても、開始チャネルは変わりません。
また、今回のテンプレートはQA向けに簡略化しており、履歴に渡した思考文を保持し、日付を固定しています。公式のツール呼び出し用の整形処理は含めていません。この改造テンプレートで analysis・final を指定しても、公式テンプレート全体の動作に戻るわけではありません。
3. 追加機能を使ったチャネルの指定方法
最初に valid_channels でチャネル一覧を選びます。続いて、思考から始めるかどうかと、実際に開始するチャネルを指定します。
上表は、この改造テンプレートで使う指定例です。assistantメッセージの role は "assistant" のままにします。チャネル名を role に指定するものではありません。
例えば今治弁用の一覧を渡すと、システムプロンプトには次の宣言が入ります。user はテンプレート側で補われます。
# Valid channels: user, analysis_imabari, final_imabari, commentary. Channel must be included for every message.次に、生成開始ヘッダーを指定します。以下はすべて 今回の改造テンプレートで `add_generation_prompt=True` にした場合の動作です。
`generate_thinking=True` のとき、`channel="final_imabari"` は思考後の回答チャネルを強制しません。 開始ヘッダーには thinking_channel だけが使われ、その後のチャネル遷移はモデルが生成します。final_imabari から直接始めたい場合は、generate_thinking=False と channel="final_imabari" を指定します。
次の推論例では、追加した今治弁用の設定と、標準から引き継いだ reasoning_effort を組み合わせています。これらのプロンプト指定は、方言表現の一貫性を保証するものではありません。今回の学習で reasoning effort をどのように扱ったかは、前述の 学習方法 を参照してください。
推論と出力の確認
以下では、整形済みプロンプト、入力トークンID、decode前の生成トークンID、特殊トークンを残した出力・除いた出力を順に表示します。表示用と推論用で条件が変わらないよう、同じ chat_kwargs を使います。
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
model_name = "ikedachin/llm-jp-4-8b-thinking_imabari_qa_v4_reasoning_effort_v1"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
dtype=torch.float16,
device_map="auto",
)
model.eval()
messages = [{"role": "user", "content": "今治の特産品について教えてください。"}]
chat_kwargs = {
# LLM-jp-4・Transformersの既存の設定
"reasoning_effort": "medium", # "low", "medium", "high"
"add_generation_prompt": True,
# 今回の改造テンプレートで追加した設定
"valid_channels": ["analysis_imabari", "final_imabari", "commentary"],
"generate_thinking": True,
"thinking_channel": "analysis_imabari",
"channel": "final_imabari", # generate_thinking=False のときに使用
}
# 1. モデルに渡すプロンプト文字列
prompt = tokenizer.apply_chat_template(messages, tokenize=False, **chat_kwargs)
print("=== 入力プロンプト ===")
print(prompt)
# 2. プロンプトをトークンIDに変換
inputs = tokenizer.apply_chat_template(
messages,
tokenize=True,
return_tensors="pt",
return_dict=True,
**chat_kwargs,
)
print("=== 入力トークンID ===")
print(inputs["input_ids"][0].tolist())
inputs = {key: value.to(model.device) for key, value in inputs.items()}
# 3. 続きのトークンを生成
with torch.inference_mode():
output_ids = model.generate(
**inputs,
max_new_tokens=512,
do_sample=False,
pad_token_id=tokenizer.eos_token_id,
)
# output_idsには入力プロンプトも含まれる
input_length = inputs["input_ids"].shape[1]
generated_ids = output_ids[0, input_length:]
# 4. decode前:整数のトークンID列
print("=== 入力と生成を含むトークンID ===")
print(output_ids[0].tolist())
print("=== 生成部分のみのトークンID ===")
print(generated_ids.tolist())
# 5. decode後:生成部分のみを文字列に戻す
raw_text = tokenizer.decode(generated_ids, skip_special_tokens=False)
text = tokenizer.decode(generated_ids, skip_special_tokens=True)
print("=== 生成テキスト:特殊トークンあり ===")
print(raw_text)
print("=== 生成テキスト:特殊トークンなし ===")
print(text)
# 6. 入力と生成をまとめて確認
print("=== 会話全体:特殊トークンあり ===")
print(tokenizer.decode(output_ids[0], skip_special_tokens=False))別の形式を試す場合は、chat_kwargs を変更してプロンプト生成から再実行します。例えば "generate_thinking": False、"channel": "final_imabari" にすると、今治弁の回答チャネルから開始します。
出力の読み方(Transformers共通の動作)
- decode前:
output_idsはバッチ次元を持つ2次元のテンソルです。output_ids[0]は入力と生成の両方を含み、generated_idsは新しく生成された部分だけです。.tolist()で整数のID列を表示します。 - `skip_special_tokens=False` でdecode: メッセージ区切りなどの特殊トークンが残るため、チャネル遷移を確認できます。
- `skip_special_tokens=True` でdecode: 登録済みの特殊トークンを取り除きます。最終回答だけを抽出する処理ではありません。 思考本文や
assistant、final_imabariなどの通常の文字列が残る場合があります。
このテンプレートでは、<|start|> はメッセージ開始、<|channel|> はチャネル指定、<|message|> は本文開始、<|end|> はメッセージ終了、<|return|> はassistantターンの終了を表します。analysis_imabari などの名前は、その間に置かれる文字列です。最初のassistantヘッダーは入力側に含まれるため、生成部分だけをdecodeした raw_text の先頭には出ません。開始チャネルも含めて確認するには output_ids[0] をdecodeします。複数系列をまとめて文字列に戻す場合は tokenizer.batch_decode(output_ids, ...) を使います。
標準チャネルと追加チャネルの出力比較
同じ質問に対して、同じ学習済みモデル・同じ改造テンプレートを使い、valid_channels を変えた出力を比較します。比較するのは、もともとのチャネル名を使う場合と、追加した今治弁用のチャネル名を使う場合です。追加学習前のベースモデルとの比較ではありません。
質問: 今治の特産品について教えてください。
共通設定は reasoning_effort="low"、generate_thinking=True、add_generation_prompt=True です。どちらも thinking_channel を省略しているため、開始時の思考チャネルは既定の analysis になります。変更した設定と出力の違いは次のとおりです。
標準チャネル側では 「挙げられています」「です」、今治弁用チャネル側では 「挙げられとるんよ」「なんよ」 という表現になっています。また、回答ヘッダーも `final` から追加した `final_imabari` に変わっています。回答内容にも違いがあるため、同じ文章の語尾だけを変えた例ではなく、それぞれの条件で生成された出力例です。
標準チャネル:特殊トークンを残したdecode結果
入力側のassistant開始ヘッダーを含めた抜粋です。
<|start|> assistant<|channel|> analysis<|message|> 特産品としてタオルが挙げられています。<|end|><|start|> assistant<|channel|> final<|message|> 今治の特産品はタオルです。<|return|>追加した今治弁用チャネル:特殊トークンを残したdecode結果
<|start|> assistant<|channel|> analysis<|message|> 今治の特産品として、タオルや造船、造船関連産業、タオル美術館、タオル美術館ホールが挙げられとるんよ。<|end|><|start|> assistant<|channel|> final_imabari<|message|> 今治の特産品は、タオルや造船、造船関連産業、タオル美術館、タオル美術館ホールなんよ。<|return|>この例では、analysis から生成が始まり、回答時に final_imabari へ移っています。valid_channels に analysis_imabari を含めても、入力側に付けられた analysis ヘッダーが変わるわけではありません。
特殊トークンを除いたdecode結果
生成部分だけを skip_special_tokens=True でdecodeすると、区切りの特殊トークンは除かれますが、思考本文や assistant・回答チャネル名などの通常の文字列は残ります。
標準チャネル:
特産品としてタオルが挙げられています。 assistant final 今治の特産品はタオルです。追加した今治弁用チャネル:
今治の特産品として、タオルや造船、造船関連産業、タオル美術館、タオル美術館ホールが挙げられとるんよ。 assistant final_imabari 今治の特産品は、タオルや造船、造船関連産業、タオル美術館、タオル美術館ホールなんよ。追加した analysis_imabari から明示的に開始する場合
思考の開始チャネルも追加したものにするには、推論例の設定を次のように変更し、プロンプト生成から再実行します。
chat_kwargs = {
"reasoning_effort": "low",
"add_generation_prompt": True,
"valid_channels": ["analysis_imabari", "final_imabari", "commentary"],
"generate_thinking": True,
"thinking_channel": "analysis_imabari",
}これにより、入力プロンプトの末尾が次のように変わります。以下はテンプレートが作るヘッダーの比較であり、新たに生成した回答例ではありません。
追加した回答チャネルから直接始める場合は、generate_thinking=False に変更し、channel="final_imabari" を追加します。プロンプト末尾は <|start|>assistant<|channel|>final_imabari<|message|> になります。
これらの開始チャネルを明示した設定での生成本文は、実行して確認してください。上の2つの回答例は、既定の analysis から開始した場合のものです。開始後のチャネル遷移はモデルが生成します。出力例は形式と方言表現の違いを示すもので、回答内容の事実性や、常に同じ文体に切り替わることを保証するものではありません。
改造テンプレートでの会話履歴のチャネル指定
今回の改造テンプレートでは、過去のassistantメッセージに対して、thinking_channel と channel を各メッセージの辞書内に指定します。これは履歴の整形に使う値です。apply_chat_template の引数として渡す同名の値は、次に生成するヘッダー用で、過去のメッセージのチャネルを書き換えません。
# 会話履歴の形式例(モデルの実測出力ではありません)
history = [
{"role": "user", "content": "今治の特産品について教えてください。"},
{
"role": "assistant",
"thinking_channel": "analysis_imabari",
"thinking": "今治の特産品として、タオルについて答えるんよ。",
"channel": "final_imabari",
"content": "今治タオルが有名なんよ。",
},
{"role": "user", "content": "もう少し詳しく教えてください。"},
]
print(tokenizer.apply_chat_template(history, tokenize=False, **chat_kwargs))thinking に内容がある場合は思考メッセージ、content は回答メッセージとして整形されます。メッセージ内のチャネルを省略すると analysis / final が使われます。回答だけの履歴では thinking を省略し、回答の channel を残します。generate_thinking=False は次の生成開始ヘッダーに作用するため、履歴に含まれる思考文は削除されません。
参考:Transformers chat templates, Tokenizer decoding API.
Qiita
https://qiita.com/ikedachin/items/d4b85302db32e4bbb5cf
注意事項
現時点の課題:チャネルによる文体の切り替え
出力を確認したところ、valid_channels に標準の analysis・final チャネルを指定しても、今治弁になることが多く見られます。そのため、チャネル指定による標準語と今治弁の切り替えはまだ安定しておらず、今後の改善が必要です。上記の出力比較は個別の例であり、常に文体を切り替えられることを示すものではありません。
- 生成される回答・思考文には、事実誤認や方言表現の不一致が含まれる場合があります。
- 出力例は、事実性・方言の制御・reasoning effort の制御を体系的に評価した結果ではありません。
- 独自テンプレートの日付は
Current date: 2026-09-19に固定されており、推論時の日付に自動更新されません。 - 再配布、再学習、マージ、商用利用、派生モデルの公開時には、ベースモデルの Apache-2.0 条件と、学習データの CC BY-SA 4.0 条件、および必要な著作権表示・出典表示を確認してください。
License
This repository provides a fine-tuned model based on llm-jp/llm-jp-4-8b-thinking.
Base model
The base model is provided by llm-jp under the Apache License 2.0.
Training data notice
The training dataset, ikedachin/imabari_wiki_qa_v4_reasoning_effort_llmjp4, is provided by ikedachin under CC BY-SA 4.0.
Its dataset card identifies the following sources:
- Direct source: ikedachin/imabari_wiki_qa_v4_validated
- Original QA: ikedachin/imabari_wiki_qa_v4
- Original corpus: ikedachin/imabari_wiki_cpt_v3
For this model, the dataset's questions, reasoning text, and answers were formatted into custom Imabari-channel messages and used for LoRA fine-tuning. The resulting adapter was merged into the base model. Refer to the dataset card and its source cards for the original materials' attribution and modification history.
Practical interpretation
For transparency, this card uses license: other and describes the base model and training data terms separately.
Users should review:
- the Apache-2.0 terms applicable to the base model, and
- any attribution / ShareAlike obligations arising from the training data.
Creative Commons' guidance on AI training distinguishes a conservative approach to following ShareAlike from the legal question of whether copyright permission is required. Applicable obligations can depend on the use, distribution, and jurisdiction. The dataset license alone is not presented here as a definitive determination of the license governing the model weights.
Redistribution notice
If you redistribute this model, merge it into another model, publish derivatives, or use it commercially, review the applicable obligations of both the base model and the training data, including attribution, license notices, and source notices.
ベースモデルと学習データの条件を分けて記載しています。再配布や派生モデルの公開時には、両方の条件と、著作権表示・ライセンス表示・出典表示の要否を確認してください。
This section is provided for transparency and is not legal advice. この記載は法的助言ではなく、公開時の透明性を高めるための説明です。
