SNAPKITTYWEST's picture
push from SNAPKITTYWEST/sovereign-engine-v2
9abace2 verified
Raw
History Blame Contribute Delete
14.4 kB
"""
Layer 3: Rule Evaluation
Part of SOVEREIGN PYTHON LLM ENGINE
Deterministic rules for decision-making.
All rules are pure predicates (state -> bool).
"""
from typing import Callable
import re
from ..models.state_machines import AgentState, TaskStatus, MCTSState
from ..models.entities import ActionType, MessageRole
# ==========================================
# Type Aliases
# ==========================================
Rule = Callable[[AgentState], bool]
TaskRule = Callable[[TaskStatus], bool]
MCTSRule = Callable[[MCTSState], bool]
# ==========================================
# Agent Loop Rules
# ==========================================
def should_reflect(state: AgentState) -> bool:
"""
Rule: Should agent reflect on previous step?
Triggers:
- Explicit error in state
- ERROR keyword in observation
- FAILED keyword in observation
- Code execution failure
"""
# Check for explicit error
if state.get("error") is not None:
return True
# Check observation for error indicators
observation = state.get("current_observation", "")
error_keywords = ["ERROR", "FAILED", "Exception", "Traceback"]
return any(keyword in observation for keyword in error_keywords)
def should_terminate(state: AgentState) -> bool:
"""
Rule: Should agent loop terminate?
Terminates when:
- Final answer is provided
- Error is set
- Max steps reached
- Already terminated flag is set
"""
has_answer = state.get("final_answer") is not None
has_error = state.get("error") is not None
max_steps_reached = state["step_count"] >= state["max_steps"]
already_terminated = state.get("terminated", False)
return has_answer or has_error or max_steps_reached or already_terminated
def should_route(state: AgentState) -> bool:
"""
Rule: Should query be routed to a specific source?
Routes when:
- No routing decision has been made yet
- No context has been retrieved yet
"""
no_decision = state.get("router_decision") is None
no_context = state.get("retrieved_context") is None
return no_decision and no_context
def should_retrieve(state: AgentState) -> bool:
"""
Rule: Should retrieval be executed?
Retrieves when:
- Routing decision exists
- But context hasn't been retrieved yet
"""
has_decision = state.get("router_decision") is not None
no_context = state.get("retrieved_context") is None
return has_decision and no_context
def should_use_quantum_encoding(state: AgentState) -> bool:
"""
Rule: Should quantum token encoding be used?
Uses quantum encoding when:
- Not already quantum encoded
- Step count is even (alternating pattern)
- MoE layer will be used
"""
not_encoded = not state.get("quantum_encoded", False)
even_step = state["step_count"] % 2 == 0
return not_encoded and even_step
def is_code_execution_action(state: AgentState) -> bool:
"""Rule: Is current action a code execution?"""
action = state.get("current_action")
return action == ActionType.EXECUTE_CODE.value
def is_tool_execution_action(state: AgentState) -> bool:
"""Rule: Is current action a tool execution?"""
action = state.get("current_action")
return action == ActionType.EXECUTE_TOOL.value
def is_reflection_action(state: AgentState) -> bool:
"""Rule: Is current action a reflection?"""
action = state.get("current_action")
return action == ActionType.REFLECT.value
def needs_context_compression(state: AgentState) -> bool:
"""
Rule: Does conversation context need compression?
Compresses when:
- Step count > 5 (enough history to summarize)
- Observation length > 2000 chars (long context)
"""
enough_steps = state["step_count"] > 5
observation = state.get("current_observation", "")
long_observation = len(observation) > 2000
return enough_steps and long_observation
# ==========================================
# Task Lifecycle Rules
# ==========================================
def can_start_task(status: TaskStatus) -> bool:
"""Rule: Can task be started?"""
return status == TaskStatus.PENDING
def can_complete_task(status: TaskStatus) -> bool:
"""Rule: Can task be completed?"""
return status == TaskStatus.IN_PROGRESS
def can_fail_task(status: TaskStatus) -> bool:
"""Rule: Can task fail?"""
return status in (TaskStatus.PENDING, TaskStatus.IN_PROGRESS)
def can_cancel_task(status: TaskStatus) -> bool:
"""Rule: Can task be cancelled?"""
return status in (TaskStatus.PENDING, TaskStatus.IN_PROGRESS)
def is_task_terminal(status: TaskStatus) -> bool:
"""Rule: Is task in terminal state?"""
return status in (TaskStatus.COMPLETED, TaskStatus.FAILED, TaskStatus.CANCELLED)
# ==========================================
# MCTS Search Rules
# ==========================================
def mcts_should_terminate(state: MCTSState) -> bool:
"""
Rule: Should MCTS search terminate?
Terminates when:
- Max iterations reached
- Perfect score achieved (1.0)
- Already terminated flag set
"""
max_iterations = state["iteration"] >= state["max_iterations"]
perfect_score = state["best_score"] >= 1.0
already_terminated = state.get("terminated", False)
return max_iterations or perfect_score or already_terminated
def mcts_should_expand(state: MCTSState, node_visit_count: int) -> bool:
"""
Rule: Should node be expanded?
Expands when:
- Node has been visited at least once
- OR node is the root
"""
return node_visit_count > 0 or state["current_node_id"] == state["root_node_id"]
def mcts_is_in_selection_phase(state: MCTSState) -> bool:
"""Rule: Is MCTS in selection phase?"""
return state["phase"] == "selection"
def mcts_is_in_expansion_phase(state: MCTSState) -> bool:
"""Rule: Is MCTS in expansion phase?"""
return state["phase"] == "expansion"
def mcts_is_in_evaluation_phase(state: MCTSState) -> bool:
"""Rule: Is MCTS in evaluation phase?"""
return state["phase"] == "evaluation"
def mcts_is_in_backpropagation_phase(state: MCTSState) -> bool:
"""Rule: Is MCTS in backpropagation phase?"""
return state["phase"] == "backpropagation"
# ==========================================
# Quantum MoE Rules
# ==========================================
def should_activate_moe(token_count: int, threshold: int = 10) -> bool:
"""
Rule: Should MoE layer be activated?
Activates when:
- Token count exceeds threshold
"""
return token_count >= threshold
def should_use_top_k_gating(num_experts: int, sparsity_target: float = 0.025) -> bool:
"""
Rule: Should top-K gating be used?
Always true for quantum MoE (1000 experts, 2.5% sparsity).
"""
return num_experts >= 100 # Use sparse gating for large expert counts
def expert_is_activated(expert_id: int, activated_experts: list[int]) -> bool:
"""Rule: Is expert activated?"""
return expert_id in activated_experts
def jordan_sum_is_valid(weights: list[float], tolerance: float = 1e-6) -> bool:
"""
Rule: Do Jordan softmax weights sum to -1?
Validates quantum MoE constraint.
"""
total = sum(weights)
return abs(total - (-1.0)) < tolerance
# ==========================================
# Message & Conversation Rules
# ==========================================
def is_system_message(role: MessageRole | str) -> bool:
"""Rule: Is message from system?"""
if isinstance(role, str):
return role.lower() == "system"
return role == MessageRole.SYSTEM
def is_user_message(role: MessageRole | str) -> bool:
"""Rule: Is message from user?"""
if isinstance(role, str):
return role.lower() == "user"
return role == MessageRole.USER
def is_assistant_message(role: MessageRole | str) -> bool:
"""Rule: Is message from assistant?"""
if isinstance(role, str):
return role.lower() == "assistant"
return role == MessageRole.ASSISTANT
def is_tool_message(role: MessageRole | str) -> bool:
"""Rule: Is message from tool?"""
if isinstance(role, str):
return role.lower() in ("tool", "ipython")
return role in (MessageRole.TOOL, MessageRole.IPYTHON)
def conversation_alternates_correctly(messages: list[dict[str, str]]) -> bool:
"""
Rule: Do messages alternate between user and assistant?
Checks if conversation follows proper turn-taking.
"""
if len(messages) < 2:
return True
for i in range(len(messages) - 1):
curr_role = messages[i]["role"]
next_role = messages[i + 1]["role"]
# Skip system messages
if curr_role == "system" or next_role == "system":
continue
# User should be followed by assistant, and vice versa
if curr_role == "user" and next_role != "assistant":
return False
if curr_role == "assistant" and next_role not in ("user", "tool"):
return False
return True
# ==========================================
# Content Validation Rules
# ==========================================
def contains_code_block(text: str) -> bool:
"""Rule: Does text contain markdown code block?"""
return bool(re.search(r'```\w*\n', text))
def contains_json(text: str) -> bool:
"""Rule: Does text contain JSON object/array?"""
import json
try:
json.loads(text)
return True
except:
# Try to find JSON-like structure
return bool(re.search(r'\{[^{}]*\}|\[[^\[\]]*\]', text))
def contains_error_keywords(text: str) -> bool:
"""Rule: Does text contain error keywords?"""
error_keywords = [
"error", "exception", "failed", "failure", "traceback",
"invalid", "incorrect", "wrong", "cannot", "unable"
]
text_lower = text.lower()
return any(keyword in text_lower for keyword in error_keywords)
def contains_success_keywords(text: str) -> bool:
"""Rule: Does text contain success keywords?"""
success_keywords = [
"success", "successful", "completed", "done", "finished",
"passed", "correct", "valid", "works"
]
text_lower = text.lower()
return any(keyword in text_lower for keyword in success_keywords)
def is_empty_or_whitespace(text: str) -> bool:
"""Rule: Is text empty or whitespace-only?"""
return not text.strip()
def exceeds_length_limit(text: str, limit: int) -> bool:
"""Rule: Does text exceed length limit?"""
return len(text) > limit
# ==========================================
# Numeric Validation Rules
# ==========================================
def is_in_range(value: float, min_val: float, max_val: float) -> bool:
"""Rule: Is value in range [min_val, max_val]?"""
return min_val <= value <= max_val
def is_positive(value: float) -> bool:
"""Rule: Is value positive?"""
return value > 0
def is_non_negative(value: float) -> bool:
"""Rule: Is value non-negative?"""
return value >= 0
def is_probability(value: float) -> bool:
"""Rule: Is value a valid probability [0, 1]?"""
return 0.0 <= value <= 1.0
def is_temperature(value: float) -> bool:
"""Rule: Is value a valid temperature [0, 2]?"""
return 0.0 <= value <= 2.0
# ==========================================
# Composite Rules (Logical Combinations)
# ==========================================
def all_rules(*rules: Rule) -> Rule:
"""
Combine rules with AND logic.
Returns:
Rule that passes if ALL input rules pass
"""
def combined_rule(state: AgentState) -> bool:
return all(rule(state) for rule in rules)
return combined_rule
def any_rules(*rules: Rule) -> Rule:
"""
Combine rules with OR logic.
Returns:
Rule that passes if ANY input rule passes
"""
def combined_rule(state: AgentState) -> bool:
return any(rule(state) for rule in rules)
return combined_rule
def not_rule(rule: Rule) -> Rule:
"""
Negate a rule.
Returns:
Rule that passes if input rule fails
"""
def negated_rule(state: AgentState) -> bool:
return not rule(state)
return negated_rule
# ==========================================
# Rule Registry
# ==========================================
AGENT_RULES = {
"should_reflect": should_reflect,
"should_terminate": should_terminate,
"should_route": should_route,
"should_retrieve": should_retrieve,
"should_use_quantum_encoding": should_use_quantum_encoding,
"is_code_execution": is_code_execution_action,
"is_tool_execution": is_tool_execution_action,
"is_reflection": is_reflection_action,
"needs_compression": needs_context_compression
}
TASK_RULES = {
"can_start": can_start_task,
"can_complete": can_complete_task,
"can_fail": can_fail_task,
"can_cancel": can_cancel_task,
"is_terminal": is_task_terminal
}
MCTS_RULES = {
"should_terminate": mcts_should_terminate,
"should_expand": lambda state: mcts_should_expand(state, 1),
"is_selection": mcts_is_in_selection_phase,
"is_expansion": mcts_is_in_expansion_phase,
"is_evaluation": mcts_is_in_evaluation_phase,
"is_backpropagation": mcts_is_in_backpropagation_phase
}
def get_agent_rule(name: str) -> Rule:
"""Get agent rule by name"""
if name not in AGENT_RULES:
raise ValueError(f"Unknown agent rule: {name}")
return AGENT_RULES[name]
def get_task_rule(name: str) -> TaskRule:
"""Get task rule by name"""
if name not in TASK_RULES:
raise ValueError(f"Unknown task rule: {name}")
return TASK_RULES[name]
def get_mcts_rule(name: str) -> MCTSRule:
"""Get MCTS rule by name"""
if name not in MCTS_RULES:
raise ValueError(f"Unknown MCTS rule: {name}")
return MCTS_RULES[name]