This directory contains examples demonstrating how to work with Mellea's context system: inspecting per-attempt contexts produced by sampling strategies, and shrinking contexts with the Compactor protocol.
Shows how to retrieve and inspect context information when using sampling strategies and validation.
Key Features:
- Using
RejectionSamplingStrategywith requirements - Accessing
SamplingResultobjects to inspect generation attempts - Retrieving context for different generation attempts
- Examining validation contexts for each requirement
- Understanding the context tree structure
Usage:
python docs/examples/context/contexts_with_sampling.py
WindowCompactor — opt-in by passing compactor= (or the window_size= sugar). Demonstrates system-prefix pinning, pin_system_and_initial_user, pin_nothing (pure last-N), and size=0 to clear the body.
ThresholdCompactor — gate an inner compactor on the conversation's cumulative token size. The reading is taken from the most recent ModelOutputThunk's total_tokens, which for a chat backend equals prompt_tokens (full conversation history sent to the model) + completion_tokens (reply). The gate fires once the running conversation size crosses the threshold; once compaction shrinks the context, the next call produces a smaller reading and the gate closes again.
Implement the Compactor protocol with a plain class (no inheritance). Shows Pattern 1 (wired into ChatContext) and Pattern 2 (manual compact() call).
Compose the ReACT loop with a sync Compactor. Two integration points:
- Per-add — wire a
Compactoronto theChatContextso it runs every timereact()appends a Message, ToolMessage, or thunk. - Per-turn — pass
compactor=toreact(); it fires once per ReACT iteration after the tool observation.
LLMSummarizeCompactor is also a sync Compactor — it hides the async backend call internally (worker thread when called from an already-running event loop) so callers don't have to think about sync vs async.
Use pin_react_initiator (from mellea.stdlib.components.react) as the predicate so the goal and tool registration survive compaction.
- Sampling Results: Working with
SamplingResultobjects - Context Inspection: Accessing generation and validation contexts
- Multiple Attempts: Examining different generation attempts
- Context Trees: Understanding how contexts link together
- Validation Context: Inspecting how requirements were evaluated
- Compaction Protocol: Sync
Compactorfor per-add()shrinking - Pin Predicates: Auto-protect leading system messages or the user's initial prompt during compaction
# Get sampling result with full context information
res = m.instruct(
"Write a sentence.",
requirements=[...],
strategy=RejectionSamplingStrategy(loop_budget=3),
return_sampling_results=True
)
# Access different generation attempts
res.sample_generations[index]
res.sample_contexts[index]
res.sample_validations[index]
# Navigate context tree
gen_ctx.previous_node.node_data
val_ctx.node_data# Wire a compactor into a ChatContext (Pattern 1 — runs on every add())
from mellea.stdlib.context import ChatContext, WindowCompactor, ThresholdCompactor
ctx = ChatContext(compactor=WindowCompactor(size=5)) # default: pin_system
ctx = ChatContext(window_size=5) # sugar for the line above
ctx = ChatContext(
compactor=ThresholdCompactor(WindowCompactor(size=5), threshold=8000),
)
# Manual compaction (Pattern 2)
ctx = WindowCompactor(size=0).compact(ctx) # drop body, keep pinned prefix- See
mellea/stdlib/context/for context and compactor implementations - See
mellea/stdlib/sampling/for sampling strategies - See
mellea/stdlib/frameworks/react.pyfor the ReACT loop - See
docs/dev/spans.mdfor context architecture details