Enable language models to reason over extremely long contexts (128K tokens) by encoding context into lightweight LoRA adapters during test time, achieving 20% performance improvements without full model retraining.
Scanned 9/9/2026
Install to Claude Code
npx -y skills add ADu2021/skillXiv --skill perk-long-context-test-time-learning --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Perk Long Context Test Time Learning?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/adu2021-perk-long-context-test-time-learning)More formats (shields.io, HTML) on the badges page.
---
name: perk-long-context-test-time-learning
title: "PERK: Long-Context Reasoning as Parameter-Efficient Test-Time Learning"
version: 0.0.2
engine: skillxiv-v0.0.2-claude-opus-4.6
license: MIT
url: "https://arxiv.org/abs/2507.06415"
keywords: [Long-Context, Test-Time Learning, LoRA, Gradient-Based Adaptation, Parameter Efficiency]
description: "Enable language models to reason over extremely long contexts (128K tokens) by encoding context into lightweight LoRA adapters during test time, achieving 20% performance improvements without full model retraining."
---
# PERK: Long-Context Reasoning via Test-Time Parameter Adaptation
Standard approaches to long-context reasoning require expensive full model fine-tuning or suffer from position bias when information appears at different locations in lengthy documents. PERK reframes the problem: instead of treating a long context as a sequential stream, compress it into parameter updates that capture its key information. This enables the model to reason over massive contexts using only adapter parameters, not full weights.
The core insight is that context encoding and reasoning can be decoupled through bilevel optimization. An inner loop encodes context segments into a LoRA adapter, while an outer loop learns how to reason over the encoded information. Truncated gradient unrolling makes this computationally tractable on a single GPU.
## Core Concept
PERK treats long-context reasoning as a meta-learning problem solved at test time. Rather than storing contexts in memory, it learns to represent contexts as parameter updates to a lightweight adapter. This approach offers three advantages: it scales to very long sequences, reduces memory overhead dramatically, and avoids position bias by processing context as permutation-invariant batches.
The method splits a long context into chunks, encodes each chunk via gradient descent into a LoRA adapter (inner loop), then optimizes how well the adapted model answers queries over the encoded context (outer loop). Dynamic learning rates per layer and per step further refine the adaptation process.
## Architecture Overview
- **LoRA Adapter**: Lightweight parameter updates with rank 256 (or tunable lower), applied to transformer layer projections
- **Inner Loop**: Encodes context segments using causal language modeling; gradient descent compresses context into adapter parameters
- **Outer Loop**: Learns meta-parameters and per-layer learning rates to optimize reasoning performance
- **Truncated Gradient Unrolling**: Stores computational graphs only for final T steps (typically 2-3), dramatically reducing memory from O(T_inner) to O(T_truncated)
- **Batch Processing**: Context chunks processed in permutation-invariant batches with explicit indexing to preserve order information
## Implementation
### Step 1: Prepare Context and Query
Split the long document into overlapping chunks of approximately 256 tokens. Initialize a LoRA adapter with rank 256 (or lower for efficiency). This example shows preparing context for a retrieval task:
```python
import torch
import torch.nn.functional as F
from peft import get_peft_model, LoraConfig
# Assume model is a pretrained LLM
lora_config = LoraConfig(
r=256,
lora_alpha=512,
target_modules=["q_proj", "v_proj"],
lora_dropout=0.05,
bias="none",
task_type="CAUSAL_LM"
)
peft_model = get_peft_model(model, lora_config)
# Split context into chunks
context = "Your very long document..."
chunk_size = 256
chunks = [context[i:i+chunk_size]
for i in range(0, len(context), chunk_size)]
```
### Step 2: Inner Loop - Encode Context into LoRA
For each batch of context chunks, perform gradient descent to optimize LoRA parameters using a language modeling objective. This step compresses the context information into the adapter:
```python
import torch.optim as optim
def inner_loop_encode(peft_model, chunks, inner_steps=4,
inner_lr=1e-4, truncate_steps=2):
"""
Encode context chunks into LoRA parameters via gradient descent.
Uses truncated gradient unrolling to save memory.
"""
optimizer = optim.AdamW(peft_model.parameters(), lr=inner_lr)
for step in range(inner_steps):
# Randomly sample chunks to create permutation-invariant batches
batch_indices = torch.randperm(len(chunks))[:batch_size]
batch_text = " ".join([chunks[i] for i in batch_indices])
# Tokenize and get language modeling loss
inputs = tokenizer(batch_text, return_tensors="pt",
max_length=512, truncation=True)
outputs = peft_model(**inputs, labels=inputs["input_ids"])
loss = outputs.loss
# Backward pass; truncate gradients if not in final steps
if inner_steps - step > truncate_steps:
loss.backward(retain_graph=False)
else:
loss.backward(retain_graph=True)
optimizer.step()
optimizer.zero_grad()
return peft_model
```
### Step 3: Outer Loop - Optimize Reasoning
Now use the adapted model to answer queries about the encoded context. Optimize the meta-parameters to improve reasoning performance:
```python
def outer_loop_reasoning(peft_model, queries, golden_answers,
outer_steps=2, outer_lr=1e-5):
"""
Outer loop: learn to reason over encoded context.
Optimizes model parameters to answer queries correctly.
"""
meta_optimizer = optim.AdamW(peft_model.parameters(),
lr=outer_lr)
for step in range(outer_steps):
# Generate answers for queries
query_batch = queries[step * batch_size:(step+1) * batch_size]
golden_batch = golden_answers[step * batch_size:(step+1) * batch_size]
inputs = tokenizer(query_batch, return_tensors="pt",
max_length=512, truncation=True)
outputs = peft_model.generate(inputs["input_ids"],
max_length=128)
# Compute accuracy reward: higher for correct answers
predictions = tokenizer.batch_decode(outputs, skip_special_tokens=True)
accuracy = sum([pred in golden
for pred, golden in zip(predictions, golden_batch)])
reward = accuracy / len(query_batch)
# Backward pass on meta-loss
loss = -reward # Maximize accuracy
loss.backward()
meta_optimizer.step()
meta_optimizer.zero_grad()
return peft_model
```
### Step 4: Inference - Greedy Decoding
At inference time, use the adapted model to answer queries on the long context. Optionally use gradient accumulation to handle even longer contexts:
```python
def inference(peft_model, query, tokenizer, max_length=512,
gradient_accumulation_steps=4):
"""
Generate answer for query using adapted model.
Gradient accumulation trades memory for latency if needed.
"""
inputs = tokenizer(query, return_tensors="pt")
with torch.no_grad():
outputs = peft_model.generate(
inputs["input_ids"],
max_length=max_length,
do_sample=False, # Greedy decoding
temperature=0.0
)
answer = tokenizer.decode(outputs[0], skip_special_tokens=True)
return answer
```
## Practical Guidance
| Hyperparameter | Recommended Value | Notes |
|---|---|---|
| LoRA Rank | 256 | Can reduce to 16-64 for efficiency with minimal performance loss |
| Inner Loop Steps | 4 | Encodes context; 2-3 steps typically truncated for memory |
| Outer Loop Steps | 2 | Optimizes reasoning; small budget due to nested optimization |
| Inner Learning Rate | 1e-4 | Gradient descent for context encoding |
| Outer Learning Rate | 1e-5 | Meta-optimization for reasoning parameters |
| Chunk Size | ~256 tokens | Balance between granularity and memory |
| Truncate After Step | 2 | Save memory by stopping gradient tracking early |
| Max Context Length | 128K tokens | Tested up to 128K during inference |
**When to use PERK:**
- Processing documents longer than 8K-16K tokens where position matters
- Scenarios requiring strong reasoning (not just retrieval) over long contexts
- When model parameter efficiency is critical
- Multi-document QA or synthesis tasks
**When NOT to use PERK:**
- Simple retrieval or keyword matching (standard retrieval augmented generation suffices)
- Contexts under 8K tokens (standard prompting is cheaper)
- Real-time inference requirements (test-time optimization adds latency)
- Situations requiring per-token interpretability
**Common pitfalls:**
- Not truncating gradients early enough, causing out-of-memory errors
- Chunk size too small (< 128 tokens) leads to fragmented context encoding
- Outer loop learning rate too high, destabilizing meta-optimization
- Insufficient inner loop steps, leaving context under-encoded in the adapter
- Forgetting to reset LoRA parameters between different documents
## Reference
Chen, Z., Romanou, A., Weiss, G., & Bosselut, A. (2025). PERK: Long-Context Reasoning as Parameter-Efficient Test-Time Learning. arXiv:2507.06415. https://arxiv.org/abs/2507.06415
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!