melissa kate
<< Little Jane

Continual Learning Pipeline for v11

Overview

Iteratively improve the model by:

  1. Training on base data (books/plays) to learn Victorian conversation style
  2. Adding new graded data (modern prompts → Victorian responses)
  3. Replacing base data with held-out portion in subsequent rounds
  4. Eventually discarding base data entirely, just adding new graded data

Data Strategy

Base Data (books/plays)

Split into two halves to avoid memorization:

New Data (graded conversations)

Always included, keeps growing:

To add more graded data:

Data Size Strategy

Original SFT: 37,943 records, 0.11 passes in 300 steps

Continual learning rounds 1-2:

Why sample?

Pipeline

Step 1: Round 1 - Train from anneal on first half of base data

cd /Users/melissa/Code/tiny-chat
python3 v11/mkm_train/build_continual_dataset.py --round 1
python3 v11/mkm_train/sft.py \
    --init-from v11/models/anneal/checkpoints_anneal_e_bl_mixed/ckpt_final.pt \
    --data v11/data/continual_round1.jsonl \
    --checkpoint-dir v11/models/sft_round2/r1 \
    --lr 2e-5 \
    --val-frac 0.15 \
    --max-iters 300

What happens:

Step 2: Round 2 - Train on second half of base data

cd /Users/melissa/Code/tiny-chat
python3 v11/mkm_train/build_continual_dataset.py --round 2
python3 v11/mkm_train/sft.py \
    --init-from v11/models/sft_round2/r1/ckpt_best.pt \
    --data v11/data/continual_round2.jsonl \
    --checkpoint-dir v11/models/sft_round2/r2 \
    --lr 1e-5 \
    --val-frac 0.15 \
    --max-iters 300

What happens:

Step 3+: Round N - Train on new graded data only

cd /Users/melissa/Code/tiny-chat
python3 v11/mkm_train/build_continual_dataset.py --round 3 --no-base
python3 v11/mkm_train/sft.py \
    --init-from v11/models/sft_round2/r2/ckpt_best.pt \
    --data v11/data/continual_round3.jsonl \
    --checkpoint-dir v11/models/sft_round2/r3 \
    --lr 5e-6 \
    --val-frac 0.2 \
    --max-iters 300

What happens:

Note: Round 3+ uses --no-base flag to skip base JSON entirely

Testing Your Model

After each round, test with:

cd /Users/melissa/Code/tiny-chat
python3 v11/chat.py --checkpoint v11/models/sft_round2/r1/ckpt_best.pt

Or for a quick test without interactive chat:

cd /Users/melissa/Code/tiny-chat
python3 << 'EOF'
import sys
sys.path.insert(0, 'v11')
from chat import load_checkpoint, tokenize, generate
import sentencepiece as spm
import torch

device = "mps" if torch.backends.mps.is_available() else "cpu"
model = load_checkpoint('v11/models/sft_round2/r1/ckpt_best.pt', device)
sp = spm.SentencePieceProcessor(model_file='v11/tokenizers/tokenizer_v11_16k.model')

prompts = ["What's for dinner?", "I'm going to the movies."]
for prompt in prompts:
    conversation = [{"role": "user", "content": prompt}]
    prompt_tokens, _ = tokenize(conversation, sp, eos=False)
    response = generate(model, sp, prompt_tokens, device, max_new=40, temp=0.8)
    print(f"Q: {prompt}\nA: {response}\n")
EOF

Key Parameters

ParameterRound 1Round 2Round 3+
Init fromAnneal checkpointPrevious roundPrevious round
Base dataSampled 15KSampled 15KNone
New data3.9K3.9KGrowing
LR2e-51e-55e-6
Val frac0.150.150.2
Max iters300300300

Notes