Goal: turn a model that continues text into a model that answers questions.
Why this step matters¶
Your model from Step 11 predicts what comes next. Ask it a question and it may well reply with more questions, because that is what it saw in the data.
Supervised fine-tuning (SFT) fixes this. You show it thousands of examples of the pattern “someone asks, someone answers well”, and it learns the shape of that pattern.
What you do¶
1. Get instruction data in Sanskrit¶
This is the hard part. Options, roughly best to worst:
Written by native speakers and scholars. Expensive, slow, and by far the best.
Translated from English instruction datasets. Cheap. But translated instructions produce a model that sounds translated — the phrasing, the assumptions, and the register are all wrong.
Generated by a large model. Cheapest. Check the licence, and check the quality by hand on a sample. Generating question-and-answer pairs from your own corpus works better than generating them from nothing, because the content is grounded in real text.
Mix them. But note: a few thousand genuinely excellent examples beat a hundred thousand mediocre ones. This is not a slogan, it has been measured repeatedly.
Task types worth including for Sanskrit:
Translate this passage into English
Analyse the grammar of this line
Split this compound
Answer this question about this text
Write in the style of this text
2. Choose a chat template and never change it¶
The chat template is the special markup that says where the user’s turn starts and the assistant’s turn starts.
If you train with one template and serve with a different one, the model breaks in confusing ways that look like a quality problem rather than a formatting problem.
This is one of the most common bugs in the whole field.
3. Mask the loss on the prompt¶
Train the model only on the answers, not on the questions. You do not want it learning to generate user questions.
4. Choose full fine-tuning, LoRA, or QLoRA¶
Here the advice differs from Step 11, and the reason matters:
LoRA works very well for teaching new behaviour — a style, a format, a way of responding.
LoRA works less well for teaching new knowledge.
Step 11 already gave the model the Sanskrit knowledge. This step is teaching behaviour. So LoRA is a good choice here, and full fine-tuning would be a good choice there.
5. Do the same for Urdu¶
Use a separate adapter so you can compare, and so you can serve either one from the same base model.
Where people usually get stuck¶
The chat template mismatch.
Print your fully formatted training example, character by character, including every special token. Then print what your serving code produces. Compare them.
They must be identical. Not similar. Identical.
You are ready to move on when¶
Your model answers a Sanskrit question with a Sanskrit answer, in the right format, without wandering off into unrelated text.
🧑💻 Runnable code for this step¶
Instruction tuning (SFT) changes the shape of your data from raw text to
pairs. Keeping prompt and completion separate is what lets the trainer
score the answer only, not the parroted question:
# one line of sanskrit_sft.jsonl
{"prompt": "Translate this Sanskrit line into English:\nअहिंसा परमो धर्मः।",
"completion": "Non-violence is the highest virtue."}from trl import SFTTrainer, SFTConfig
from peft import LoraConfig
cfg = SFTConfig(output_dir="./adapter", num_train_epochs=3,
per_device_train_batch_size=2, gradient_accumulation_steps=8,
learning_rate=2e-4, max_length=1024,
completion_only_loss=True, # ← score the answer, not the question
bf16=True, report_to="none")
trainer = SFTTrainer(model=model, args=cfg, train_dataset=ds,
peft_config=LoraConfig(r=16, lora_alpha=32,
task_type="CAUSAL_LM",
target_modules="all-linear"),
processing_class=tokenizer)
trainer.train()