| """
|
| 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
|
|
|
|
|
|
|
|
|
|
|
|
|
| Rule = Callable[[AgentState], bool]
|
| TaskRule = Callable[[TaskStatus], bool]
|
| MCTSRule = Callable[[MCTSState], bool]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| """
|
|
|
| if state.get("error") is not None:
|
| return True
|
|
|
|
|
| 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
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
|
|
|
|
| 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
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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"]
|
|
|
|
|
| if curr_role == "system" or next_role == "system":
|
| continue
|
|
|
|
|
| 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
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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:
|
|
|
| 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
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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]
|
|
|