Source code for lrs.inference.prompts
"""
Meta-cognitive prompting for LRS-Agents.
Generates precision-adaptive prompts that guide LLMs to produce
diverse policy proposals appropriate to the agent's epistemic state.
"""
from typing import Dict, List, Any
from dataclasses import dataclass
from enum import Enum
[docs]
class StrategyMode(Enum):
"""Strategic mode based on precision level"""
EXPLOITATION = "exploit" # High precision
EXPLORATION = "explore" # Low precision
BALANCED = "balanced" # Medium precision
[docs]
@dataclass
class PromptContext:
"""
Context for generating meta-cognitive prompts.
Attributes:
precision: Current precision value [0, 1]
recent_errors: List of recent prediction errors
available_tools: List of tool names
goal: Current goal description
state: Current agent state
tool_history: Recent tool executions
"""
precision: float
recent_errors: List[float]
available_tools: List[str]
goal: str
state: Dict[str, Any]
tool_history: List[Dict[str, Any]]
[docs]
class MetaCognitivePrompter:
"""
Generates precision-adaptive prompts for LLM policy generation.
The prompts adapt based on:
1. Precision level (confidence in world model)
2. Recent prediction errors (surprise events)
3. Available tools
4. Current goal
Examples:
>>> prompter = MetaCognitivePrompter()
>>>
>>> context = PromptContext(
... precision=0.3, # Low precision
... recent_errors=[0.9, 0.85, 0.7],
... available_tools=["api_fetch", "cache_fetch"],
... goal="Fetch user data",
... state={},
... tool_history=[]
... )
>>>
>>> prompt = prompter.generate_prompt(context)
>>> print("EXPLORATION MODE" in prompt)
True
"""
[docs]
def __init__(
self,
high_precision_threshold: float = 0.7,
low_precision_threshold: float = 0.4,
high_error_threshold: float = 0.7
):
"""
Initialize prompter.
Args:
high_precision_threshold: Threshold for exploitation mode
low_precision_threshold: Threshold for exploration mode
high_error_threshold: Threshold for "high surprise"
"""
self.high_precision_threshold = high_precision_threshold
self.low_precision_threshold = low_precision_threshold
self.high_error_threshold = high_error_threshold
[docs]
def generate_prompt(self, context: PromptContext) -> str:
"""
Generate precision-adaptive prompt.
Args:
context: Prompt context with precision, errors, tools, etc.
Returns:
Complete prompt string for LLM
Examples:
>>> prompt = prompter.generate_prompt(context)
>>> # Prompt includes precision value, strategy guidance, tool list
"""
# Determine strategy mode
mode = self._determine_mode(context.precision)
# Build prompt sections
header = self._build_header()
precision_info = self._build_precision_info(context.precision, mode)
strategy_guidance = self._build_strategy_guidance(mode, context)
error_analysis = self._build_error_analysis(context.recent_errors)
tool_context = self._build_tool_context(context.available_tools)
goal_description = self._build_goal_description(context.goal)
output_format = self._build_output_format()
diversity_requirements = self._build_diversity_requirements()
calibration_instructions = self._build_calibration_instructions()
# Combine all sections
prompt = "\n\n".join([
header,
precision_info,
strategy_guidance,
error_analysis,
tool_context,
goal_description,
output_format,
diversity_requirements,
calibration_instructions
])
return prompt
def _determine_mode(self, precision: float) -> StrategyMode:
"""Determine strategic mode from precision value"""
if precision >= self.high_precision_threshold:
return StrategyMode.EXPLOITATION
elif precision <= self.low_precision_threshold:
return StrategyMode.EXPLORATION
else:
return StrategyMode.BALANCED
def _build_header(self) -> str:
"""Build prompt header"""
return """You are a Bayesian policy generator for an Active Inference agent.
Your role is to PROPOSE diverse policy candidates, not to DECIDE which is best.
The agent will evaluate your proposals using Expected Free Energy (G).
Your proposals should span the exploration-exploitation spectrum based on
the agent's current precision (confidence in its world model)."""
def _build_precision_info(self, precision: float, mode: StrategyMode) -> str:
"""Build precision information section"""
confidence_level = "HIGH" if precision > 0.7 else "LOW" if precision < 0.4 else "MEDIUM"
return f"""CURRENT PRECISION (γ): {precision:.3f} ({confidence_level})
This represents the agent's confidence that its world model is correct.
- High precision (>0.7): Agent is confident → Focus on exploitation
- Low precision (<0.4): Agent is uncertain → Focus on exploration
- Medium precision: Balance both strategies
CURRENT MODE: {mode.value.upper()}"""
def _build_strategy_guidance(
self,
mode: StrategyMode,
context: PromptContext
) -> str:
"""Build strategy-specific guidance"""
if mode == StrategyMode.EXPLOITATION:
return """STRATEGIC GUIDANCE: EXPLOITATION MODE
Your proposal strategy:
1. Prioritize reward - Focus on proven, high-success approaches
2. Leverage patterns - Use tools that have worked reliably before
3. Minimize risk - Avoid experimental or untested combinations
4. Optimize efficiency - Prefer shorter, well-understood policies
Generate proposals with:
- 70% exploitation (high success probability, low information gain)
- 30% exploration (maintain some diversity)"""
elif mode == StrategyMode.EXPLORATION:
return """STRATEGIC GUIDANCE: EXPLORATION MODE
The agent's world model is unreliable. Prioritize learning over reward.
Your proposal strategy:
1. Prioritize information - Focus on reducing uncertainty
2. Test assumptions - Include diagnostic actions that reveal environment state
3. Accept risk - Exploratory policies may have lower immediate success
4. Question patterns - Previous successful strategies may be outdated
Generate proposals with:
- 70% exploration (high information gain, lower certainty)
- 30% exploitation (maintain some reliable options)"""
else: # BALANCED
return """STRATEGIC GUIDANCE: BALANCED MODE
The agent has moderate confidence. Balance exploration and exploitation.
Your proposal strategy:
1. Mix approaches - Combine proven tools with experimental ones
2. Hedge uncertainty - Include both safe and informative actions
3. Gradual adaptation - Test small variations on known patterns
4. Maintain optionality - Keep fallback plans available
Generate proposals with:
- 50% exploitation (reliable approaches)
- 50% exploration (learning opportunities)"""
def _build_error_analysis(self, recent_errors: List[float]) -> str:
"""Build error analysis section"""
if not recent_errors:
return "RECENT ERRORS: None (no execution history yet)"
avg_error = sum(recent_errors) / len(recent_errors)
high_errors = [e for e in recent_errors if e > self.high_error_threshold]
analysis = f"""RECENT PREDICTION ERRORS: {len(recent_errors)} recent executions
Average error: {avg_error:.3f}
High-surprise events: {len(high_errors)}"""
if high_errors:
analysis += f"""
⚠️ RECENT SURPRISES DETECTED
The agent has experienced {len(high_errors)} unexpected outcomes.
This suggests the environment may have changed or tools are behaving differently.
Consider:
- Alternative approaches to recent failures
- Diagnostic actions to understand what changed
- Conservative strategies that fail gracefully"""
return analysis
def _build_tool_context(self, available_tools: List[str]) -> str:
"""Build available tools section"""
tools_str = "\n".join(f" - {tool}" for tool in available_tools)
return f"""AVAILABLE TOOLS ({len(available_tools)} tools):
{tools_str}
You must only propose policies using these exact tool names.
Policies can use the same tool multiple times if needed."""
def _build_goal_description(self, goal: str) -> str:
"""Build goal description section"""
return f"""GOAL: {goal}
Your proposals should work toward this goal while respecting the
current precision level and strategic mode."""
def _build_output_format(self) -> str:
"""Build output format specification"""
return """OUTPUT FORMAT
Generate 3-7 policy proposals in JSON format:
{
"proposals": [
{
"policy_id": 1,
"tools": ["tool_name_1", "tool_name_2"],
"estimated_success_prob": 0.8,
"expected_information_gain": 0.3,
"strategy": "exploit|explore|balanced",
"rationale": "Brief explanation of why this policy makes sense",
"failure_modes": ["Potential failure scenario 1", "Scenario 2"]
},
{
"policy_id": 2,
...
}
],
"current_uncertainty": 0.6,
"known_unknowns": ["What we know we don't know"]
}
FIELD DESCRIPTIONS:
- policy_id: Unique integer ID (1, 2, 3, ...)
- tools: List of tool names in execution order
- estimated_success_prob: Your estimate of P(success) in [0, 1]
- expected_information_gain: How much we'd learn in [0, 1]
- strategy: "exploit", "explore", or "balanced"
- rationale: 1-2 sentence explanation
- failure_modes: List of ways this could fail"""
def _build_diversity_requirements(self) -> str:
"""Build diversity requirements"""
return """DIVERSITY REQUIREMENTS (CRITICAL)
Your proposal set MUST include:
1. At least 1 exploitative policy (estimated_success_prob > 0.7, low info_gain)
2. At least 1 exploratory policy (high info_gain, lower success_prob)
3. At least 1 balanced policy
Do NOT generate 5 nearly-identical proposals. The agent needs genuine alternatives
spanning different risk-reward tradeoffs.
VARIETY CHECKLIST:
☐ Different tool combinations
☐ Different policy lengths (1-5 tools)
☐ Different risk levels
☐ Different information-gathering strategies"""
def _build_calibration_instructions(self) -> str:
"""Build calibration instructions"""
return """CALIBRATION INSTRUCTIONS
⚠️ Avoid overconfidence: If you're uncertain, reflect that in lower success probabilities.
✓ Be honest: The agent's mathematical evaluation will assess your proposals objectively.
Don't inflate success probabilities to make proposals look better.
CALIBRATION TEST:
If ALL your proposals have estimated_success_prob > 0.8, you're likely overconfident.
Include riskier, more exploratory options with honest uncertainty estimates.
The agent will COMBINE your generative creativity with rigorous mathematical evaluation.
Your job is diverse proposal generation, not final decision-making."""
[docs]
def build_simple_prompt(
goal: str,
tools: List[str],
precision: float,
num_proposals: int = 5
) -> str:
"""
Build a simple prompt without full context.
Convenience function for quick prompting.
Args:
goal: Task goal
tools: Available tool names
precision: Current precision value
num_proposals: Number of proposals to generate
Returns:
Prompt string
Examples:
>>> prompt = build_simple_prompt(
... goal="Fetch data",
... tools=["api", "cache"],
... precision=0.5
... )
"""
context = PromptContext(
precision=precision,
recent_errors=[],
available_tools=tools,
goal=goal,
state={},
tool_history=[]
)
prompter = MetaCognitivePrompter()
return prompter.generate_prompt(context)