DEV Community

shashank ms
shashank ms

Posted on

Large Language Model Training Dataset with Chain-of-Thought Reasoning and Transfer Learning

I built a synthetic dataset generator that uses a large teacher model to write chain-of-thought reasoning traces, then validates them with a smaller student model to produce clean training pairs for fine-tuning. It is useful for ML engineers who need domain-specific reasoning data without paying token-based costs that scale with prompt length.

What you'll need

Step 1: Configure the Oxlo.ai client

I use the OpenAI SDK as a drop-in replacement pointed at Oxlo.ai. This keeps the code portable and lets me swap between models without touching client initialization.

from openai import OpenAI
import json

client = OpenAI(
    base_url="https://api.oxlo.ai/v1",
    api_key="YOUR_OXLO_API_KEY"
)

Step 2: Define the teacher system prompt

The teacher model needs explicit instructions to emit structured chain-of-thought. I keep the system prompt in a constant so I can tune it without touching the rest of the pipeline.

TEACHER_SYSTEM_PROMPT = """You are a synthetic data generator. The user will provide a math or logic problem. Respond only with a JSON object containing:
- "problem": the original problem
- "chain_of_thought": a detailed step-by-step reasoning trace
- "answer": the final concise answer

Do not include markdown fences or commentary outside the JSON."""

Step 3: Generate reasoning traces with the teacher model

I use Kimi K2.6 as the teacher because its chain-of-thought reasoning is strong for structured problems. Because Oxlo.ai charges a flat rate per request, a long system prompt does not inflate the cost.

def generate_trace(problem: str) -> dict:
    response = client.chat.completions.create(
        model="kimi-k2.6",
        messages=[
            {"role": "system", "content": TEACHER_SYSTEM_PROMPT},
            {"role": "user", "content": problem},
        ],
    )
    raw = response.choices[0].message.content
    return json.loads(raw)

problem = "A train travels 120 km in 2 hours. How far will it travel in 5 hours at the same speed?"
trace = generate_trace(problem)
print(json.dumps(trace, indent=2))

Step 4: Validate traces with the student model

To simulate transfer learning, I run each trace past a smaller, efficient model. Qwen 3 32B checks whether the reasoning is coherent and the answer is correct. If the student disagrees, we drop the sample.

VALIDATOR_SYSTEM_PROMPT = """You are a grader. Given a problem, a chain-of-thought reasoning trace, and an answer, respond with only VALID or INVALID. A response is VALID only if every reasoning step is correct and the final answer is accurate. Respond with one word only."""

def validate_trace(trace: dict) -> bool:
    payload = json.dumps(trace)
    response = client.chat.completions.create(
        model="qwen-3-32b",
        messages=[
            {"role": "system", "content": VALIDATOR_SYSTEM_PROMPT},
            {"role": "user", "content": payload},
        ],
    )
    verdict = response.choices[0].message.content.strip().upper()
    return verdict == "VALID"

is_good = validate_trace(trace)
print("Accepted:", is_good)

Step 5: Batch process and export to JSONL

I wrap the pipeline in a loop over a seed list of problems. Each accepted example is written as one JSON line, ready for fine-tuning frameworks like Axolotl or LLaMA-Factory.

problems = [
    "A train travels 120 km in 2 hours. How far will it travel in 5 hours at the same speed?",
    "If 3 workers can build a wall in 6 days, how long will it take 9 workers?",
    "What is the sum of the first 10 positive integers?",
]

dataset = []
for p in problems:
    try:
        t = generate_trace(p)
        if validate_trace(t):
            dataset.append(t)
    except Exception as e:
        print(f"Failed on problem: {p}, error: {e}")

with open("cot_dataset.jsonl", "w") as f:
    for item in dataset:
        f.write(json.dumps(item) + "\n")

print(f"Wrote {len(dataset)} examples to cot_dataset.jsonl")

Run it

Test the full pipeline end to end with a single problem before burning through a batch.

from openai import OpenAI
import json

client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")

TEACHER_SYSTEM_PROMPT = """You are a synthetic data generator. The user will provide a math or logic problem. Respond only with a JSON object containing:
- "problem": the original problem
- "chain_of_thought": a detailed step-by-step reasoning trace
- "answer": the final concise answer

Do not include markdown fences or commentary outside the JSON."""

VALIDATOR_SYSTEM_PROMPT = """You are a grader. Given a problem, a chain-of-thought reasoning trace, and an answer, respond with only VALID or INVALID. A response is VALID only if every reasoning step is correct and the final answer is accurate. Respond with one word only."""

def generate_trace(problem: str) -> dict:
    response = client.chat.completions.create(
        model="kimi-k2.6",
        messages=[
            {"role": "system", "content": TEACHER_SYSTEM_PROMPT},
            {"role": "user", "content": problem},
        ],
    )
    return json.loads(response.choices[0].message.content)

def validate_trace(trace: dict) -> bool:
    response = client.chat.completions.create(
        model="qwen-3-32b",
        messages=[
            {"role": "system", "content": VALIDATOR_SYSTEM_PROMPT},
            {"role": "user", "content": json.dumps(trace)},
        ],
    )
    return response.choices[0].message.content.strip().upper() == "VALID"

problem = "A car rental costs $50 per day plus $0.20 per mile. How much for 3 days and 200 miles?"
trace = generate_trace(problem)
print("Generated trace:")
print(json.dumps(trace, indent=2))
print("Validation:", validate_trace(trace))

Example output:

Generated trace:
{
  "problem": "A car rental costs $50 per day plus $0.20 per mile. How much for 3 days and 200 miles?",
  "chain_of_thought": "First, calculate the daily cost: 3 days * $50/day = $150. Next, calculate the mileage cost: 200 miles * $0.20/mile = $40. Finally, add them: $150 + $40 = $190.",
  "answer": "$190"
}
Validation: VALID

Wrap-up

Swap the teacher model to DeepSeek V3.2 to keep generation costs on the free tier while you prototype. Once your dataset is clean, feed it into a fine-tuning pipeline for Llama 3.3 70B or Qwen 3 32B on Oxlo.ai to see if the smaller model learns the reasoning style through distillation.

Top comments (0)