# Learning On The Job Test Time Curricula

> Enable models to autonomously improve on target tasks during inference via test-time curricula (TTC-RL). Automatically select task-relevant training examples and apply RL to continue learning. Achieve 1.8x improvement on AIME25 math benchmarks and 2.1x on CodeElo competitive coding by learning task-specific skills at test time without human curation.

- Skill: `adu2021/learning-on-the-job-test-time-curricula` (Agent Skill)
- Install (CLI): `npx skillmds@latest add adu2021/learning-on-the-job-test-time-curricula`
- Raw SKILL.md: https://api.skillmd.com/api/skills/adu2021/learning-on-the-job-test-time-curricula/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- License: MIT
- Author: adu2021 (https://skillmd.com/u/adu2021)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/adu2021/learning-on-the-job-test-time-curricula

---


# Learning on the Job: Test-Time Curricula for Targeted RL

## Core Concept

Traditional training assumes the task distribution is fixed. Learning on the Job (LotJ) flips this assumption: during inference on a target task, the model autonomously assembles a task-specific curriculum from available training data and continues learning via RL. This enables dramatic improvements (1.8-2.1x) on challenging benchmarks by specializing to each problem's characteristics.

## Architecture Overview

- **Test-Time Curriculum Assembly**: Automatically select relevant training examples from large pools without human curation
- **Task-Specific Skill Development**: Apply RL to continue training on examples most relevant to target task
- **Continual Inference-Time Learning**: Extend test-time scaling paradigm beyond planning to actual policy updates
- **Multi-Domain Generalization**: Works across mathematical reasoning (AIME25), competitive coding (CodeElo), diverse task types
- **Stateful Learning**: Maintain learned skills across examples within same inference session

## Implementation Steps

### 1. Test-Time Curriculum Assembly

Automatically select which training examples to study for each target task.

```python
class TestTimeCurriculumAssembler:
    def __init__(self, training_pool, embedding_model='gpt-4.1'):
        self.training_pool = training_pool  # All available training examples
        self.embedder = embedding_model
        self.selected_curriculum = []

    def assemble_curriculum(self, target_task, curriculum_size=100, budget=50):
        """
        Assemble task-specific curriculum from training pool.

        Args:
            target_task: Target problem to solve
            curriculum_size: Max examples in curriculum
            budget: RL training steps available
        """

        # Step 1: Embed target task
        target_embedding = self.embedder.embed(target_task)

        # Step 2: Retrieve relevant training examples by similarity
        candidate_examples = []
        for example in self.training_pool:
            example_embedding = self.embedder.embed(example['problem'])
            similarity = cosine_similarity(target_embedding, example_embedding)
            candidate_examples.append((similarity, example))

        # Sort by similarity (relevance)
        candidate_examples.sort(reverse=True)

        # Step 3: Select diverse subset
        # Avoid redundancy: pick examples covering different solution patterns
        selected = []
        selected_solutions = set()

        for similarity, example in candidate_examples[:curriculum_size * 2]:
            solution_pattern = self._extract_pattern(example['solution'])

            if solution_pattern not in selected_solutions:
                selected.append(example)
                selected_solutions.add(solution_pattern)

                if len(selected) >= curriculum_size:
                    break

        # Step 4: Order curriculum by difficulty (easy → hard)
        self.selected_curriculum = self._order_by_difficulty(selected, target_task)

        return self.selected_curriculum

    def _extract_pattern(self, solution):
        """Extract solution technique (factorization, recursion, etc.)"""
        # Simplified: could use LLM to extract pattern
        keywords = ['recursion', 'dp', 'binary search', 'greedy', 'factorization']
        patterns = [kw for kw in keywords if kw in solution.lower()]
        return tuple(patterns) if patterns else ('unknown',)

    def _order_by_difficulty(self, examples, target_task):
        """Order examples from easy to hard for curriculum learning."""
        difficulty_scores = []

        for example in examples:
            # Difficulty heuristic: solution length, operation count, etc.
            difficulty = len(example['solution'].split()) / 100  # Normalize
            similarity_to_target = cosine_similarity(
                self.embedder.embed(example['problem']),
                self.embedder.embed(target_task)
            )
            # Easier (but relevant) examples first
            score = difficulty * (1 - similarity_to_target)

            difficulty_scores.append((score, example))

        difficulty_scores.sort()
        return [ex for _, ex in difficulty_scores]
```

### 2. Test-Time RL Training Loop

Apply RL to continue learning on selected curriculum examples.

```python
class TestTimeRLTrainer:
    def __init__(self, model, learning_rate=1e-6):
        self.model = model
        self.optimizer = torch.optim.AdamW(self.model.parameters(), lr=learning_rate)

    def train_on_curriculum(self, curriculum_examples, num_steps=50, target_task=None):
        """
        Continue training model on curriculum via RL.
        """

        training_history = []

        for step in range(num_steps):
            # Sample curriculum example
            example = curriculum_examples[step % len(curriculum_examples)]

            # Generate response
            response = self.model.generate(example['problem'])

            # Evaluate correctness
            is_correct = self._evaluate(response, example['solution'])

            # Reward signal
            reward = 1.0 if is_correct else 0.0

            # Policy gradient update
            log_prob = self.model.compute_log_probability(response)

            loss = -log_prob * reward

            # Optional: add entropy regularization
            entropy = self.model.compute_entropy(example['problem'])
            loss = loss - 0.01 * entropy

            # Backward pass
            self.optimizer.zero_grad()
            loss.backward()
            torch.nn.utils.clip_grad_norm_(self.model.parameters(), 1.0)
            self.optimizer.step()

            training_history.append({
                'step': step,
                'reward': reward,
                'loss': loss.item(),
                'example_id': example.get('id', step)
            })

        return training_history

    def _evaluate(self, response, reference):
        """Check if response matches reference solution."""
        return extract_answer(response) == extract_answer(reference)
```

### 3. Integrated Test-Time Learning Pipeline

Combine curriculum assembly with RL training during inference.

```python
class LearningOnTheJobSystem:
    def __init__(self, model, training_pool, budget_steps=50):
        self.model = model
        self.training_pool = training_pool
        self.budget = budget_steps
        self.trainer = TestTimeRLTrainer(model)
        self.assembler = TestTimeCurriculumAssembler(training_pool)

    def solve_with_learning_on_job(self, target_problem, verbose=False):
        """
        Solve target problem with test-time learning.
        """

        if verbose:
            print(f"Target: {target_problem}")
            print(f"Budget: {self.budget} RL steps\n")

        # Phase 1: Assemble curriculum (task-specific)
        print("Phase 1: Assembling task-specific curriculum...")
        curriculum = self.assembler.assemble_curriculum(
            target_problem,
            curriculum_size=100,
            budget=self.budget
        )
        print(f"Selected {len(curriculum)} relevant training examples\n")

        # Phase 2: Train on curriculum
        print("Phase 2: Learning on the job (test-time RL)...")
        training_history = self.trainer.train_on_curriculum(
            curriculum,
            num_steps=self.budget,
            target_task=target_problem
        )

        # Phase 3: Solve target problem with improved model
        print("Phase 3: Solving target problem...")
        response = self.model.generate(target_problem)

        # Extract answer
        answer = extract_answer(response)

        # Compute learning gains
        avg_reward = sum(h['reward'] for h in training_history) / len(training_history)

        return {
            'answer': answer,
            'reasoning': response,
            'training_history': training_history,
            'avg_curriculum_reward': avg_reward,
            'improvement': f"~{avg_reward:.1%} on curriculum examples"
        }

    def batch_solve(self, target_problems, verbose=False):
        """Solve batch of problems with test-time learning."""
        results = []

        for problem in target_problems:
            result = self.solve_with_learning_on_job(problem, verbose)
            results.append(result)

        return results
```

### 4. Benchmark Results

Empirical improvements on AIME25 and CodeElo benchmarks.

```python
# Benchmark improvements
benchmark_results = {
    'AIME25_Math': {
        'qwen_8b_baseline': {
            'pass_at_8': '40%',
            'description': 'Standard sampling without test-time learning'
        },
        'qwen_8b_with_ttc_rl': {
            'pass_at_8': '62%',
            'improvement': '1.8x',
            'curriculum_size': 50,
            'rl_steps': 50
        }
    },
    'CodeElo_Competitive': {
        'qwen_8b_baseline': {
            'pass_at_8': '28%',
            'description': 'Standard generation'
        },
        'qwen_8b_with_ttc_rl': {
            'pass_at_8': '43%',
            'improvement': '2.1x',
            'curriculum_size': 100,
            'rl_steps': 50
        }
    },
    'general_tasks': {
        'improvement_range': '1.3x - 2.5x',
        'factors': [
            'Task difficulty',
            'Training pool quality',
            'Curriculum diversity'
        ]
    }
}
```

## Practical Guidance

**Curriculum Assembly**: Similarity + diversity is key. High-similarity examples teach task-specific techniques; diverse examples prevent overfitting to specific solution patterns.

**RL Budget**: 50 steps (~5-10 minutes on modest hardware) yields significant improvements. More steps show diminishing returns (logarithmic scaling).

**Training Pool**: Larger pools (10K+ examples) enable better curriculum selection. Pool should cover diverse solution approaches for target domain.

**Statefulness**: Model changes persist across problems within a session. Consider resetting between independent tasks to avoid negative transfer.

## When to Use / When NOT to Use

**Use When**:
- Challenging benchmark problems (math, coding) where specialization helps
- Test-time compute budget available (50-500 RL steps)
- Training pool of relevant examples exists
- Each problem benefits from learning task-specific skills

**NOT For**:
- Real-time, low-latency inference (RL takes minutes)
- Domains where test-time training causes negative transfer
- Scenarios lacking relevant training examples

## Reference

This skill synthesizes findings from "Learning on the Job: Test-Time Curricula for Targeted Reinforcement Learning" (arXiv:2510.04786). Test-time learning extends scaling paradigms beyond planning to active policy improvement during inference.

