Enable models to refine outputs dynamically during generation based on internal signals, reducing token consumption by 41.6% while improving accuracy by 8.2%.
Scanned 9/9/2026
Install to Claude Code
npx -y skills add ADu2021/skillXiv --skill proactive-self-refinement --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Proactive Self Refinement?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/adu2021-proactive-self-refinement)More formats (shields.io, HTML) on the badges page.
---
name: proactive-self-refinement
title: "A Stitch in Time: Proactive Self-Refinement for Language Models"
version: 0.0.2
engine: skillxiv-v0.0.2-claude-opus-4.6
license: MIT
url: https://arxiv.org/abs/2508.12903
keywords: [self-refinement, dynamic-revision, in-generation-improvement, token-efficiency]
description: "Enable models to refine outputs dynamically during generation based on internal signals, reducing token consumption by 41.6% while improving accuracy by 8.2%."
---
# A Stitch in Time: Proactive Self-Refinement for Language Models
## Core Concept
Traditional self-refinement works in fixed cycles: generate → evaluate → regenerate. This is inefficient because the model can't start refinement until generation completes.
Proactive Active Self-Refinement (PASR) lets models decide dynamically during generation whether, when, and how to refine. The model learns to detect when its reasoning is going wrong and self-correct mid-generation, like humans revising thoughts while speaking.
## Architecture Overview
- **Dynamic Refinement Trigger**: Learn to detect when refinement is needed
- **In-Generation Revision**: Backtrack and revise during generation
- **Internal Quality Signals**: Use model's own uncertainty/confidence
- **Learned Refinement Strategy**: Decide how aggressively to refine
- **Token Efficiency**: Avoid wasteful regeneration of correct portions
- **Adaptive Refinement**: Different tasks get different refinement patterns
## Implementation Steps
### 1. Define Refinement Points and Signals
```python
import torch
import torch.nn as nn
from typing import List, Tuple
class RefinementSignal:
"""Detect when refinement is needed"""
def __init__(self, model):
self.model = model
def compute_confidence(self, logits: torch.Tensor) -> float:
"""Compute model's confidence in current prediction"""
# Softmax probabilities
probs = torch.softmax(logits, dim=-1)
# Maximum probability = confidence
confidence = probs.max().item()
return confidence
def compute_entropy(self, logits: torch.Tensor) -> float:
"""Compute entropy of output distribution"""
probs = torch.softmax(logits, dim=-1)
entropy = -(probs * torch.log(probs + 1e-10)).sum().item()
return entropy
def compute_consistency(self, logits_list: List[torch.Tensor]) -> float:
"""Compute consistency across multiple forward passes"""
if len(logits_list) < 2:
return 1.0
# Compare top predictions
predictions = [logits.argmax().item() for logits in logits_list]
consistency = predictions.count(predictions[0]) / len(predictions)
return consistency
def should_refine(self, confidence: float, entropy: float,
token_count: int, max_tokens: int) -> bool:
"""Determine if refinement is needed"""
# Refine if: low confidence + high entropy + not too many tokens
low_confidence = confidence < 0.5
high_entropy = entropy > 2.0
reasonable_length = token_count < max_tokens * 0.8
return low_confidence and high_entropy and reasonable_length
```
### 2. Implement Dynamic Backtracking
```python
class DynamicBacktracker:
"""Backtrack and revise during generation"""
def __init__(self, model, tokenizer):
self.model = model
self.tokenizer = tokenizer
self.token_history = []
def find_refinement_point(self, current_tokens: List[int],
quality_scores: List[float]) -> int:
"""Find best point to backtrack to"""
# Backtrack to where quality dropped
min_quality_idx = 0
min_quality = quality_scores[0]
for i, score in enumerate(quality_scores):
if score < min_quality:
min_quality = score
min_quality_idx = i
# Don't backtrack too far (keep at least 20% of generated text)
min_backtrack = int(len(current_tokens) * 0.2)
backtrack_point = max(min_backtrack_idx, min_backtrack)
return backtrack_point
def revise_from_point(self, context_tokens: List[int],
backtrack_point: int, num_alternatives: int = 3):
"""Generate alternatives from backtrack point"""
# Truncate to backtrack point
revised_tokens = context_tokens[:backtrack_point]
alternatives = []
for temp in [0.7, 0.8, 0.9]:
# Generate alternative continuation
output = self.model.generate(
torch.tensor([revised_tokens]),
max_new_tokens=50,
temperature=temp,
do_sample=True
)
alternatives.append(output[0].tolist())
return alternatives
def select_best_alternative(self, alternatives: List[List[int]],
quality_fn) -> Tuple[List[int], float]:
"""Select best alternative based on quality"""
best_seq = None
best_quality = -1
for alt in alternatives:
# Decode and evaluate quality
text = self.tokenizer.decode(alt)
quality = quality_fn(text)
if quality > best_quality:
best_quality = quality
best_seq = alt
return best_seq, best_quality
```
### 3. Train Refinement Policy
```python
class RefinementPolicy(nn.Module):
"""Learn when and how to refine"""
def __init__(self, hidden_size=768):
super().__init__()
# Input: embeddings of generated so far
self.encoder = nn.TransformerEncoderLayer(
d_model=hidden_size,
nhead=8,
dim_feedforward=2048,
batch_first=True
)
# Output heads
self.refinement_trigger = nn.Linear(hidden_size, 1) # Binary: refine or not
self.backtrack_distance = nn.Linear(hidden_size, 100) # How far to backtrack
self.refinement_intensity = nn.Linear(hidden_size, 1) # How aggressive
def forward(self, token_embeddings: torch.Tensor) -> dict:
"""
Decide refinement strategy
Args:
token_embeddings: [seq_len, hidden_size] embeddings of generated tokens
Returns:
refinement_decision: dict with trigger, backtrack_distance, intensity
"""
# Encode sequence
context = self.encoder(token_embeddings.unsqueeze(0))
context = context[0, -1, :] # Take last token
# Predict refinement strategy
refine_logit = self.refinement_trigger(context) # [1]
refine_prob = torch.sigmoid(refine_logit) # 0-1
backtrack_logits = self.backtrack_distance(context) # [100]
backtrack_dist = torch.softmax(backtrack_logits, dim=0)
intensity = torch.sigmoid(self.refinement_intensity(context)) # [1]
return {
'should_refine': refine_prob.item() > 0.5,
'refine_probability': refine_prob.item(),
'backtrack_distance': backtrack_dist.argmax().item(),
'refinement_intensity': intensity.item()
}
def train_refinement_policy(policy, model, tokenizer, train_data, num_epochs=10):
"""Train policy with RL"""
optimizer = torch.optim.Adam(policy.parameters(), lr=1e-4)
for epoch in range(num_epochs):
for batch in train_data:
prompts = batch['prompts']
target_outputs = batch['outputs']
losses = []
for prompt, target in zip(prompts, target_outputs):
# Generate with refinement
generated_tokens = []
token_embeddings = []
refinements_applied = 0
# Autoregressive generation
tokens = tokenizer.encode(prompt)
for step in range(256): # Max generation length
# Get embeddings
embeddings = model.get_embeddings(torch.tensor([tokens]))
# Check if refinement needed
decision = policy(embeddings[0])
# Collect embeddings for policy
token_embeddings.append(embeddings[0, -1, :])
if decision['should_refine'] and step > 10:
# Apply refinement
backtrack_dist = decision['backtrack_distance']
tokens = tokens[:-backtrack_dist]
refinements_applied += 1
# Generate next token
logits = model(torch.tensor([tokens])).logits[0, -1, :]
next_token = logits.argmax().item()
tokens.append(next_token)
if next_token == tokenizer.eos_token_id:
break
# Compute loss: reward based on correctness vs efficiency
generated_text = tokenizer.decode(tokens)
similarity = compute_similarity(generated_text, target)
efficiency_bonus = (1.0 - len(tokens) / 256) # Shorter is better
reward = 0.8 * similarity + 0.2 * efficiency_bonus
loss = -torch.tensor(reward)
losses.append(loss)
# Update policy
total_loss = torch.stack(losses).mean()
optimizer.zero_grad()
total_loss.backward()
optimizer.step()
```
### 4. Inference with PASR
```python
def generate_with_pasr(model, policy, tokenizer, prompt: str,
max_length: int = 256, refinement_threshold: float = 0.5):
"""Generate with dynamic proactive self-refinement"""
tokens = tokenizer.encode(prompt)
generated = []
refinement_count = 0
quality_scores = []
for step in range(max_length):
# Get current embeddings
embeddings = model.get_embeddings(torch.tensor([tokens]))
curr_embedding = embeddings[0, -1, :]
# Get refinement decision
decision = policy(curr_embedding.unsqueeze(0))
# Compute current quality
confidence = decision['refine_probability']
quality_scores.append(confidence)
# Check if refinement triggered
if (decision['should_refine'] and
confidence < refinement_threshold and
step > 10 and len(generated) > 5):
# Backtrack
backtrack = decision['backtrack_distance']
tokens = tokens[:-min(backtrack, len(generated))]
generated = generated[:-min(backtrack, len(generated))]
refinement_count += 1
# Regenerate with higher temperature for diversity
logits = model(torch.tensor([tokens])).logits[0, -1, :]
logits = logits / 0.8 # Increase temperature
next_token = torch.multinomial(
torch.softmax(logits, dim=-1), num_samples=1
).item()
else:
# Normal generation
logits = model(torch.tensor([tokens])).logits[0, -1, :]
next_token = logits.argmax().item()
tokens.append(next_token)
generated.append(next_token)
if next_token == tokenizer.eos_token_id:
break
# Decode result
result_text = tokenizer.decode(generated)
return {
'text': result_text,
'tokens_generated': len(generated),
'refinements_applied': refinement_count,
'efficiency': 1.0 - (refinement_count / len(generated))
}
```
### 5. Evaluation
```python
def evaluate_pasr(model, policy, tokenizer, benchmark_tasks):
"""Evaluate PASR on accuracy and efficiency"""
accuracy = 0.0
token_efficiency = 0.0
num_tasks = 0
for task in benchmark_tasks:
prompt = task['prompt']
target = task['target']
# Generate with PASR
result = generate_with_pasr(model, policy, tokenizer, prompt)
generated_text = result['text']
# Check accuracy
is_correct = check_correctness(generated_text, target)
accuracy += 1.0 if is_correct else 0.0
# Track token efficiency
baseline_tokens = 100 # Estimated
token_efficiency += 1.0 - (result['tokens_generated'] / baseline_tokens)
num_tasks += 1
avg_accuracy = accuracy / num_tasks if num_tasks > 0 else 0.0
avg_efficiency = token_efficiency / num_tasks if num_tasks > 0 else 0.0
print(f"Accuracy: {avg_accuracy * 100:.1f}%")
print(f"Token Efficiency: {avg_efficiency * 100:.1f}%")
return avg_accuracy, avg_efficiency
```
## Practical Guidance
- **Refinement Threshold**: 0.4-0.6 (lower = more aggressive refinement)
- **Backtrack Distance**: 5-20 tokens (avoid over-revision)
- **Temperature**: 0.7-0.9 for alternatives (higher = more diversity)
- **Policy Training**: Mix supervised + RL (80% supervised, 20% RL)
- **Quality Function**: Use task-specific metrics (BLEU, exact match, etc.)
## Reference
A Stitch in Time (2508.12903): https://arxiv.org/abs/2508.12903
Enable dynamic, in-generation self-refinement where models decide when to backtrack and revise, achieving 41.6% token reduction and 8.2% accuracy improvement over baseline generation.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!