SupraLabs 推論コーパスを用いた LLM のストリーミング・キュレーション・ファインチューニングガイド
本文の状態
日本語全文を表示中
詳細モードで約8分の本文を読めます。
同じ出来事の情報源
この情報源を基点に整理
MarkTechPost
SupraLabs は推論に特化した大規模コーパスを公開し、Hugging Face を経由したストリーミング処理やデータフィルタリング、LoRA による効率的なファインチューニングを含む完全な Colab パイプラインを提供する。
Continue in AI NEW LAB
このニュースを、実務の判断につなげる
AI NEW LABで、試したことや先に確認したい条件を共有できます。まずはログインなしで読めます。
AI NEW LABで論点を見るAI深層分析を開く2026年8月14日 12:20
AI深層分析
キーポイント
推論特化コーパスの公開とアクセス方法
SupraLabs は「reasoning-corpus-4K-5M-v1」という大規模データセットを Hugging Face Hub に公開し、ストリーミング機能を活用して代表サンプルのみをローカル環境に読み込む手法を提示している。
データ品質向上のための厳格なフィルタリング
ソース分布やトークン長パターン、推論と回答の比率を分析し、不適切なトレーニング例を除去する一連の品質フィルタリング工程が実装されている。
構造化された推論タグを用いたファインチューニング
残存したサンプルを Chat 形式に変換し、明示的な推論タグ(<|thought_trace|>等)を組み込むことで、SmolLM2-135M-Instruct を LoRA と TRL の SFTTrainer を用いて適応させる。
再現可能な Colab パイプラインの提供
データのスケーラブルなアクセスから分析、キュレーション、ファインチューニング、構造化推論、Parquet 形式でのエクスポートまでを統合した Google Colab ツールチェーンが構築された。
推論比率の計算と可視化
思考トレースと回答の文字数から推論比率(think / (think + answer))を算出し、トークン長との相関や分布を可視化する。
重要な引用
In this tutorial, we build an end-to-end workflow for working with the SupraLabs reasoning corpus.
We transform the retained samples into a chat-based supervised fine-tuning format with explicit reasoning tags
By combining scalable data access, exploratory analysis, dataset curation, parameter-efficient fine-tuning, structured inference, and Parquet export, we create a complete Google Colab pipeline
We calculate reasoning and answer character counts, measure the reasoning-to-response ratio, and visualize the relationships across the dataset.
編集コメントを表示
編集コメント
推論能力の向上は現在の LLM 開発における重要な課題であり、SupraLabs が提供するデータセットとパイプラインは実用的な解決策として注目される。特にストリーミング処理やフィルタリング手法の詳細は、大規模データを扱う開発者にとって即座に活用できる価値がある。
Source Article
元記事を日本語で読む
本文に関係しない購読案内、埋め込み通知、サイト内プロモーションは除いています。
このチュートリアルでは、SupraLabs の推論用コーパスを活用するためのエンドツーエンドのワークフローを構築します。まず Hugging Face Hub から代表的なサブセットをストリーミングで取得し、そのソース分布、トークン長の傾向、タスク構成、推論と回答の比率などを調査します。その後、一連の品質フィルタを適用して不適切なトレーニング例を除去します。
残ったサンプルは、明示的な推論タグを含むチャット形式の教師あり微調整(SFT)フォーマットに変換し、TRL の SFTTrainer を用いて LoRA によるパラメータ効率的な微調整で SmolLM2-135M-Instruct を適応させます。
スケーラブルなデータアクセス、探索的解析、データセットのキュレーション、パラメータ効率的な微調整、構造化推論、Parquet エクスポートを組み合わせることで、大規模なマルチモデル推論コーパスをコンパクトな推論特化型言語モデルに変換する Google Colab 用の完全なパイプラインを作成します。
import subprocess, sys
def pip_install(pkgs):
subprocess.check_call([sys.executable, "-m", "pip", "install", "-q", *pkgs])
subprocess.call([sys.executable, "-m", "pip", "uninstall", "-y", "-q", "torchao"])
pip_install([
"datasets>=3.0.0",
"transformers>=4.46.0",
"trl>=0.12.0",
"peft>=0.13.0",
"accelerate>=1.0.0",
"bitsandbytes",
"matplotlib",
"pandas",
])
import os, re, json, math, random, itertools, warnings
import pandas as pd
import matplotlib.pyplot as plt
import torch
from collections import Counter
from datasets import load_dataset, Dataset
warnings.filterwarnings("ignore")
random.seed(42)
torch.manual_seed(42)
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Device: {DEVICE}")
if DEVICE == "cuda":
print(f"GPU: {torch.cuda.get_device_name(0)}")
DATASET_ID = "SupraLabs/reasoning-corpus-4K-5M-v1"
SAMPLE_SIZE = 8_000
print(f"\nStreaming {DATASET_ID} ...")
stream = load_dataset(DATASET_ID, split="train", streaming=True)
stream = stream.shuffle(seed=42, buffer_size=30_000)
rows = list(itertools.islice(stream, SAMPLE_SIZE))
ds = Dataset.from_list(rows)
print(f"Materialized sample: {len(ds):,} rows")
print(f"Columns: {ds.column_names}")
ex = ds[0]
print("\n" + "=" * 70)
print("EXAMPLE ROW")
print("=" * 70)
print(f"repo_id : {ex['repo_id']}")
print(f"tok_len : {ex['tok_len']}")
print(f"user : {ex['user'][:300]} ...")
print(f"thought_trace : {ex['thought_trace'][:300]} ...")
print(f"assistant : {ex['assistant'][:300]} ...")
Colab 環境を設定し、必要な機械学習ライブラリをインストールして、互換性のない torchao パッケージを削除します。利用可能な計算デバイスを検出し、Hugging Face のストリーミング機能を通じて SupraLabs Reasoning Corpus に接続して、データセット全体をダウンロードするのを防ぎます。ストリームされたレコードをシャッフルし、代表的なサンプルを実体化して、1 つの行の構造と内容を調査します。
Copy CodeCopiedUse a different Browser
df = ds.to_pandas()
print("\nTop 15 source repos in sample:")
src_counts = df["repo_id"].value_counts()
print(src_counts.head(15).to_string())
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
axes[0, 0].hist(df["tok_len"], bins=60, color="#4C72B0", edgecolor="white")
axes[0, 0].set_title("Token length distribution")
axes[0, 0].set_xlabel("tok_len"); axes[0, 0].set_ylabel("rows")
src_counts.head(12).plot(kind="barh", ax=axes[0, 1], color="#55A868")
axes[0, 1].invert_yaxis()
axes[0, 1].set_title("Top-12 source repos (sample)")
df["think_chars"] = df["thought_trace"].str.len()
df["answer_chars"] = df["assistant"].str.len()
df["reason_ratio"] = df["think_chars"] / (df["think_chars"] + df["answer_chars"] + 1)
axes[1, 0].hist(df["reason_ratio"], bins=50, color="#C44E52", edgecolor="white")
axes[1, 0].set_title("Reasoning ratio (think / (think + answer))")
axes[1, 0].set_xlabel("ratio")
axes[1, 1].scatter(df["tok_len"], df["reason_ratio"], s=4, alpha=0.25, color="#8172B2")
axes[1, 1].set_title("tok_len vs reasoning ratio")
axes[1, 1].set_xlabel("tok_len"); axes[1, 1].set_ylabel("ratio")
plt.tight_layout()
plt.show()
print("\nSummary stats:")
print(df[["tok_len", "think_chars", "answer_chars", "reason_ratio"]]
.describe().round(2).to_string())
def tag_task(row):
u = row["user"].lower()
a = row["assistant"]
if "`" in a or re.search(r"\b(def |class |import |function|#include)", a):
return "code"
if re.search(r"(prove|equation|integral|theorem|\\frac|\\int|solve for)", u):
return "math"
if re.search(r"\b(patient|diagnosis|symptom|treatment|clinical)\b", u):
return "medical"
if re.search(r"\b(which of the following|options?:|a|b)\b", u):
return "mcq/logic"
return "general"
df["task"] = df.apply(tag_task, axis=1)
print("\nHeuristic task mix:")
print(df["task"].value_counts(normalize=True).round(3).to_string())
サンプリングしたデータセットを pandas DataFrame に変換し、ソースリポジトリとトークン長の分布を分析します。推論部分と回答部分の文字数を計算し、推論から応答までの比率を測定して、データセット全体での関係性を可視化します。さらに、軽量なヒューリスティックルールを適用して、各レコードが「コード」「数学」「医療」「多肢選択問題」のいずれに分類されるか、あるいは「一般タスク」であるかを判定します。
Copy CodeCopiedUse a different Browser
トークン数のフィルタリングを行う関数です。学習に適したトークン予算の範囲内にあるサンプルのみを保持します。
行ごとの重複率をチェックする関数で、特定の行が過度に繰り返される(ループモデルなど)場合はデータを除外します。
データセットのサイズを確認し、保持された行数とその割合を表示します。
使用するモデル ID を「HuggingFaceTB/SmolLM2-135M-Instruct」に設定します。必要なトークナイザーと因果言語モデルを Hugging Face から読み込みます。パドントークンが未設定の場合は、EOS トークンを代わりに使用します。
システムプロンプトは、「注意深い推論アシスタントとして、...タグ内で段階的に思考し、最終回答を提供してください」という内容です。
データ行をチャット形式に変換する関数で、システムメッセージ、ユーザーの質問、そして思考プロセスと最終回答を組み合わせたアシスタントの応答を作成します。
変換されたデータを学習用データセットとして読み込み、不要な列を削除してシャッフルします。学習データ 1,500 件、評価データ 100 件の割合で分割し、それぞれのサイズを確認します。
最後に、トレーニングサンプルのレンダリング結果(一部省略)を表示します。
print(tokenizer.apply_chat_template(train_ds[0]["messages"], tokenize=False)[:800])
不適切なトークン長、不完全な応答、過度な反復、あるいは推論内容の偏りがあるサンプルを除去する品質フィルタリングパイプラインを構築しました。SmolLM2 トークナイザーを読み込み、各保持されたレコードをシステムプロンプト、ユーザーメッセージ、そして推論強化されたアシスタント応答を含む構造化された会話に変換します。その後、整形したデータをシャッフルし、トレーニング用と評価用のサブセットを作成して、教師あり微調整に使用する最終的なチャットテンプレートを確認します。
Copy CodeCopiedUse a different Browser
from trl import SFTTrainer, SFTConfig
from peft import LoraConfig
try:
import peft.import_utils as _piu
import peft.tuners.lora.torchao as _plt
_piu.is_torchao_available = lambda: False
_plt.is_torchao_available = lambda: False
except Exception:
pass
model = AutoModelForCausalLM.from_pretrained(
MODEL_ID,
dtype=torch.bfloat16 if DEVICE == "cuda" else torch.float32,
).to(DEVICE)
peft_config = LoraConfig(
r=16,
lora_alpha=32,
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
sft_config = SFTConfig(
output_dir="smollm2-reasoning-demo",
max_length=2048,
per_device_train_batch_size=2,
gradient_accumulation_steps=8,
num_train_epochs=1,
learning_rate=2e-4,
lr_scheduler_type="cosine",
warmup_steps=10,
logging_steps=10,
eval_strategy="steps",
eval_steps=50,
save_strategy="no",
bf16=(DEVICE == "cuda"),
gradient_checkpointing=True,
report_to="none",
)
trainer = SFTTrainer(
model=model,
args=sft_config,
train_dataset=train_ds,
eval_dataset=eval_ds,
peft_config=peft_config,
processing_class=tokenizer,
)
print("\nStarting fine-tune (≈10–20 min on a T4 with these settings)...")
trainer.train()
print("Done. Final eval loss:", trainer.evaluate().get("eval_loss"))
SmolLM2 という因果言語モデルを読み込み、パラメータ効率の高い学習のために LoRA アダプターを設定します。最適化、バッチ処理、評価、精度、勾配チェックポイントの設定は TRL の SFTConfig を通じて定義されます。SFTTrainer を初期化した後、厳選された推論会話データでモデルを微調整し、最終的なトレーニング性能を評価します。
コードのコピー | コピー済み | ブラウザを変更する
def generate(question, max_new_tokens=512, temperature=0.7):
msgs = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": question},
]
prompt = tokenizer.apply_chat_template(
msgs, tokenize=False, add_generation_prompt=True
)
inputs = tokenizer(prompt, return_tensors="pt").to(DEVICE)
with torch.no_grad():
out = trainer.model.generate(
**inputs,
max_new_tokens=max_new_tokens,
temperature=temperature,
top_p=0.9,
do_sample=True,
pad_token_id=tokenizer.pad_token_id,
)
text = tokenizer.decode(out[0][inputs["input_ids"].shape[1]:],
skip_special_tokens=True)
m = re.search(r"(.*?)(.*)", text, re.DOTALL)
if m:
print("─" * 60, "\nTHINKING:\n", m.group(1).strip()[:1500])
print("─" * 60, "\nANSWER:\n", m.group(2).strip())
else:
print(text)
print("\n\n### TEST 1: logic puzzle")
generate("If all bloops are razzies and all razzies are lazzies, "
"are all bloops definitely lazzies? Explain briefly.")
train_ds.to_parquet("reasoning_subset_train.parquet")
eval_ds.to_parquet("reasoning_subset_eval.parquet")
print("\nSaved: reasoning_subset_train.parquet / reasoning_subset_eval.parquet")
推論関数を作成し、新しい質問に同じシステムプロンプトを適用して、微調整済みモデルから回答を生成します。生成された推論プロセスと最終的な答えを分離し、ロジック問題や算数問題でモデルを検証しました。最後に、処理済みのトレーニングデータセットと評価データセットを Parquet ファイルとしてエクスポートし、大規模な実験での再利用に備えます。
結論として、私たちは大規模な推論データの探索から小規模言語モデルの訓練までをつなぐ実用的なパイプラインを開発しました。このプロセスでは、コーパスを効率的にストリーミングし、内部構成を分析した上で、トークン数、重複度、完全性、そして推論のバランスといった基準で例をフィルタリングしています。得られたデータは、一貫した会話形式のトレーニング構造に変換されました。その後、SmolLM2 に LoRA を適用して微調整し、適応後のモデルを検証。生成された推論プロセスと答えを確認し、厳選したデータセットを将来の実験用にエクスポートしました。このワークフローは、ソース情報を意識したデータの混合やカリキュラム学習、より大きな学生モデルの訓練、長いコンテキストへの対応、そして Colab のメモリに全データを保持する必要なく行える生産規模の推論モデル開発など、再利用可能な基盤を提供します。
完全なコードはこちらで確認できます。Twitter でフォローも歓迎です。また、15 万人以上の ML エンジニアが参加する SubReddit にぜひご参加ください。ニュースレターへの登録もお忘れなく。あ、Telegram も使っていますか?今なら Telegram でも私たちに参加できます。
原文を表示
In this tutorial, we build an end-to-end workflow for working with the SupraLabs reasoning corpus. We stream a representative subset directly from the Hugging Face Hub, inspect its source distribution, token-length patterns, task composition, and reasoning-to-answer ratios, and then apply a series of quality filters to remove unsuitable training examples. We transform the retained samples into a chat-based supervised fine-tuning format with explicit <think> reasoning tags and use them to adapt SmolLM2-135M-Instruct with LoRA through TRL’s SFTTrainer. By combining scalable data access, exploratory analysis, dataset curation, parameter-efficient fine-tuning, structured inference, and Parquet export, we create a complete Google Colab pipeline for turning a large multi-model reasoning corpus into a compact reasoning-focused language model.
Copy CodeCopiedUse a different Browser
import subprocess, sys
def pip_install(pkgs):
subprocess.check_call([sys.executable, "-m", "pip", "install", "-q", *pkgs])
subprocess.call([sys.executable, "-m", "pip", "uninstall", "-y", "-q", "torchao"])
pip_install([
"datasets>=3.0.0",
"transformers>=4.46.0",
"trl>=0.12.0",
"peft>=0.13.0",
"accelerate>=1.0.0",
"bitsandbytes",
"matplotlib",
"pandas",
])
import os, re, json, math, random, itertools, warnings
import pandas as pd
import matplotlib.pyplot as plt
import torch
from collections import Counter
from datasets import load_dataset, Dataset
warnings.filterwarnings("ignore")
random.seed(42)
torch.manual_seed(42)
DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Device: {DEVICE}")
if DEVICE == "cuda":
print(f"GPU: {torch.cuda.get_device_name(0)}")
DATASET_ID = "SupraLabs/reasoning-corpus-4K-5M-v1"
SAMPLE_SIZE = 8_000
print(f"\nStreaming {DATASET_ID} ...")
stream = load_dataset(DATASET_ID, split="train", streaming=True)
stream = stream.shuffle(seed=42, buffer_size=30_000)
rows = list(itertools.islice(stream, SAMPLE_SIZE))
ds = Dataset.from_list(rows)
print(f"Materialized sample: {len(ds):,} rows")
print(f"Columns: {ds.column_names}")
ex = ds[0]
print("\n" + "=" * 70)
print("EXAMPLE ROW")
print("=" * 70)
print(f"repo_id : {ex['repo_id']}")
print(f"tok_len : {ex['tok_len']}")
print(f"user : {ex['user'][:300]} ...")
print(f"thought_trace : {ex['thought_trace'][:300]} ...")
print(f"assistant : {ex['assistant'][:300]} ...")
We configure the Colab environment, install the required machine learning libraries, and remove the incompatible torchao package. We detect the available compute device, connect to the SupraLabs reasoning corpus through Hugging Face streaming, and avoid downloading the complete dataset. We shuffle the streamed records, materialize a representative sample, and inspect the structure and contents of an example row.
Copy CodeCopiedUse a different Browser
df = ds.to_pandas()
print("\nTop 15 source repos in sample:")
src_counts = df["repo_id"].value_counts()
print(src_counts.head(15).to_string())
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
axes[0, 0].hist(df["tok_len"], bins=60, color="#4C72B0", edgecolor="white")
axes[0, 0].set_title("Token length distribution")
axes[0, 0].set_xlabel("tok_len"); axes[0, 0].set_ylabel("rows")
src_counts.head(12).plot(kind="barh", ax=axes[0, 1], color="#55A868")
axes[0, 1].invert_yaxis()
axes[0, 1].set_title("Top-12 source repos (sample)")
df["think_chars"] = df["thought_trace"].str.len()
df["answer_chars"] = df["assistant"].str.len()
df["reason_ratio"] = df["think_chars"] / (df["think_chars"] + df["answer_chars"] + 1)
axes[1, 0].hist(df["reason_ratio"], bins=50, color="#C44E52", edgecolor="white")
axes[1, 0].set_title("Reasoning ratio (think / (think + answer))")
axes[1, 0].set_xlabel("ratio")
axes[1, 1].scatter(df["tok_len"], df["reason_ratio"], s=4, alpha=0.25, color="#8172B2")
axes[1, 1].set_title("tok_len vs reasoning ratio")
axes[1, 1].set_xlabel("tok_len"); axes[1, 1].set_ylabel("ratio")
plt.tight_layout()
plt.show()
print("\nSummary stats:")
print(df[["tok_len", "think_chars", "answer_chars", "reason_ratio"]]
.describe().round(2).to_string())
def tag_task(row):
u = row["user"].lower()
a = row["assistant"]
if "`" in a or re.search(r"\b(def |class |import |function|#include)", a):
return "code"
if re.search(r"(prove|equation|integral|theorem|\\frac|\\int|solve for)", u):
return "math"
if re.search(r"\b(patient|diagnosis|symptom|treatment|clinical)\b", u):
return "medical"
if re.search(r"\b(which of the following|options?:|\(a\)|\(b\))", u):
return "mcq/logic"
return "general"
df["task"] = df.apply(tag_task, axis=1)
print("\nHeuristic task mix:")
print(df["task"].value_counts(normalize=True).round(3).to_string())
We convert the sampled dataset into a pandas DataFrame and analyze the distribution of source repositories and token lengths. We calculate reasoning and answer character counts, measure the reasoning-to-response ratio, and visualize the relationships across the dataset. We also apply lightweight heuristic rules to classify each record as a code, mathematics, medical, multiple-choice, or general task.
Copy CodeCopiedUse a different Browser
def filter_length(row, min_tok=200, max_tok=3000):
"""Keep samples within a training-friendly token budget."""
return min_tok <= row["tok_len"] <= max_tok
def filter_degenerate(row):
"""Drop empty/near-empty thoughts or answers."""
return len(row["thought_trace"]) > 100 and len(row["assistant"]) > 20
def filter_repetition(row, max_line_repeat=0.30):
"""Drop traces where one line repeats too often (looping models)."""
lines = [l.strip() for l in row["thought_trace"].split("\n") if l.strip()]
if len(lines) < 5:
return True
most_common = Counter(lines).most_common(1)[0][1]
return (most_common / len(lines)) <= max_line_repeat
def filter_reason_ratio(row, lo=0.15, hi=0.97):
"""Keep samples that actually reason but don't ONLY reason."""
t, a = len(row["thought_trace"]), len(row["assistant"])
r = t / (t + a + 1)
return lo <= r <= hi
n0 = len(ds)
ds_f = ds.filter(filter_length)
ds_f = ds_f.filter(filter_degenerate)
ds_f = ds_f.filter(filter_repetition)
ds_f = ds_f.filter(filter_reason_ratio)
print(f"\nFiltering: {n0:,} -> {len(ds_f):,} rows "
f"({100 * len(ds_f) / n0:.1f}% retained)")
MODEL_ID = "HuggingFaceTB/SmolLM2-135M-Instruct"
from transformers import AutoTokenizer, AutoModelForCausalLM
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
if tokenizer.pad_token is None:
tokenizer.pad_token = tokenizer.eos_token
SYSTEM_PROMPT = (
"You are a careful reasoning assistant. Think step by step inside "
"<think>...</think> tags, then give your final answer."
)
def to_chat(row):
return {
"messages": [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": row["user"]},
{"role": "assistant",
"content": f"<think>\n{row['thought_trace']}\n</think>\n\n{row['assistant']}"},
]
}
train_ds = ds_f.map(to_chat, remove_columns=ds_f.column_names)
train_ds = train_ds.shuffle(seed=42)
N_TRAIN, N_EVAL = 1_500, 100
eval_ds = train_ds.select(range(N_TRAIN, min(N_TRAIN + N_EVAL, len(train_ds))))
train_ds = train_ds.select(range(min(N_TRAIN, len(train_ds))))
print(f"\nTrain: {len(train_ds):,} | Eval: {len(eval_ds):,}")
print("\nRendered training sample (truncated):")
print(tokenizer.apply_chat_template(train_ds[0]["messages"], tokenize=False)[:800])
We construct a quality-filtering pipeline that removes samples with unsuitable token lengths, incomplete responses, excessive repetition, or unbalanced reasoning content. We load the SmolLM2 tokenizer and transform each retained record into a structured conversation containing a system prompt, user message, and reasoning-enhanced assistant response. We then shuffle the formatted data, create training and evaluation subsets, and inspect the final chat template used for supervised fine-tuning.
Copy CodeCopiedUse a different Browser
from trl import SFTTrainer, SFTConfig
from peft import LoraConfig
try:
import peft.import_utils as _piu
import peft.tuners.lora.torchao as _plt
_piu.is_torchao_available = lambda: False
_plt.is_torchao_available = lambda: False
except Exception:
pass
model = AutoModelForCausalLM.from_pretrained(
MODEL_ID,
dtype=torch.bfloat16 if DEVICE == "cuda" else torch.float32,
).to(DEVICE)
peft_config = LoraConfig(
r=16,
lora_alpha=32,
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
sft_config = SFTConfig(
output_dir="smollm2-reasoning-demo",
max_length=2048,
per_device_train_batch_size=2,
gradient_accumulation_steps=8,
num_train_epochs=1,
learning_rate=2e-4,
lr_scheduler_type="cosine",
warmup_steps=10,
logging_steps=10,
eval_strategy="steps",
eval_steps=50,
save_strategy="no",
bf16=(DEVICE == "cuda"),
gradient_checkpointing=True,
report_to="none",
)
trainer = SFTTrainer(
model=model,
args=sft_config,
train_dataset=train_ds,
eval_dataset=eval_ds,
peft_config=peft_config,
processing_class=tokenizer,
)
print("\nStarting fine-tune (≈10–20 min on a T4 with these settings)...")
trainer.train()
print("Done. Final eval loss:", trainer.evaluate().get("eval_loss"))
We load the SmolLM2 causal language model and configure LoRA adapters for parameter-efficient training. We define the optimization, batching, evaluation, precision, and gradient-checkpointing settings through TRL’s SFTConfig. We initialize the SFTTrainer, fine-tune the model on the curated reasoning conversations, and evaluate its final training performance.
Copy CodeCopiedUse a different Browser
def generate(question, max_new_tokens=512, temperature=0.7):
msgs = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": question},
]
prompt = tokenizer.apply_chat_template(
msgs, tokenize=False, add_generation_prompt=True
)
inputs = tokenizer(prompt, return_tensors="pt").to(DEVICE)
with torch.no_grad():
out = trainer.model.generate(
**inputs,
max_new_tokens=max_new_tokens,
temperature=temperature,
top_p=0.9,
do_sample=True,
pad_token_id=tokenizer.pad_token_id,
)
text = tokenizer.decode(out[0][inputs["input_ids"].shape[1]:],
skip_special_tokens=True)
m = re.search(r"<think>(.*?)</think>(.*)", text, re.DOTALL)
if m:
print("─" * 60, "\nTHINKING:\n", m.group(1).strip()[:1500])
print("─" * 60, "\nANSWER:\n", m.group(2).strip())
else:
print(text)
print("\n\n### TEST 1: logic puzzle")
generate("If all bloops are razzies and all razzies are lazzies, "
"are all bloops definitely lazzies? Explain briefly.")
train_ds.to_parquet("reasoning_subset_train.parquet")
eval_ds.to_parquet("reasoning_subset_eval.parquet")
print("\nSaved: reasoning_subset_train.parquet / reasoning_subset_eval.parquet")
We create an inference function that formats new questions with the same system prompt and generates responses from the fine-tuned model. We separate the generated <think> section from the final answer and test the model on logic and arithmetic problems. We finally export the processed training and evaluation datasets as Parquet files for reuse in larger experiments.
In conclusion, we developed a practical pipeline that connects large-scale reasoning-data exploration with small-language-model training. We streamed the corpus efficiently, analyzed its internal composition, filtered examples using token, repetition, completeness, and reasoning-balance criteria, and converted the resulting data into a consistent conversational training structure. We then fine-tuned SmolLM2 with LoRA, evaluated the adapted model, inspected its generated reasoning and answers, and exported the curated datasets for future experiments. This workflow provides a reusable foundation for source-aware data mixing, curriculum learning, larger student models, longer-context training, and production-scale reasoning model development without requiring the entire dataset to reside in Colab memory.
Check out the FULL CODES here. Also, feel free to follow us on Twitter and don’t forget to join our 150k+ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.
Need to partner with us for promoting your GitHub Repo OR Hugging Face Page OR Product Release OR Webinar etc.? Connect with us
The post Create a Reasoning-Focused LLM: A Practical Guide to Streaming, Curating, and Fine-Tuning the SupraLabs Reasoning Corpus appeared first on MarkTechPost.
関連記事
今日のまとめ
AIデイリーブリーフで今日の重要ニュースをまとめ読み