Spaces:
Running
Running
| from __future__ import annotations | |
| """Refinement strategies for improving responses.""" | |
| from dataclasses import dataclass | |
| from typing import Any | |
| from src.feedback.gaps import InformationGap | |
| class RefinementAction: | |
| """An action to refine the response.""" | |
| action_type: str # "search", "verify", "expand", "clarify", "restructure" | |
| description: str | |
| parameters: dict[str, Any] | |
| priority: int # 1-5, lower is higher priority | |
| class RefinementStrategy: | |
| """Determines strategies for refining responses.""" | |
| def __init__(self, max_iterations: int = 3): | |
| """Initialize the refinement strategy. | |
| Args: | |
| max_iterations: Maximum refinement iterations allowed | |
| """ | |
| self.max_iterations = max_iterations | |
| self._current_iteration = 0 | |
| def analyze( | |
| self, | |
| query: str, | |
| answer: str, | |
| gaps: list[InformationGap], | |
| quality_score: float, | |
| ) -> list[RefinementAction]: | |
| """Analyze response and determine refinement actions. | |
| Args: | |
| query: Original query | |
| answer: Current answer | |
| gaps: Identified information gaps | |
| quality_score: Overall quality score | |
| Returns: | |
| List of refinement actions | |
| """ | |
| actions = [] | |
| # If quality is already high, minimal refinement needed | |
| if quality_score >= 0.8: | |
| return [] | |
| # Handle each gap type | |
| for gap in gaps: | |
| if gap.gap_type == "missing_fact": | |
| actions.append(RefinementAction( | |
| action_type="search", | |
| description=f"Search for missing information: {gap.description}", | |
| parameters={ | |
| "search_query": gap.suggested_search or query, | |
| "gap_description": gap.description, | |
| }, | |
| priority=1 if gap.severity == "high" else 2, | |
| )) | |
| elif gap.gap_type == "unverified": | |
| actions.append(RefinementAction( | |
| action_type="verify", | |
| description=f"Verify claim: {gap.description}", | |
| parameters={ | |
| "claim": gap.description, | |
| }, | |
| priority=2, | |
| )) | |
| elif gap.gap_type == "unclear": | |
| actions.append(RefinementAction( | |
| action_type="clarify", | |
| description=f"Clarify: {gap.description}", | |
| parameters={ | |
| "unclear_part": gap.description, | |
| }, | |
| priority=3, | |
| )) | |
| elif gap.gap_type == "outdated": | |
| actions.append(RefinementAction( | |
| action_type="search", | |
| description=f"Find recent information: {gap.description}", | |
| parameters={ | |
| "search_query": gap.suggested_search or f"{query} latest recent", | |
| "temporal": True, | |
| }, | |
| priority=1, | |
| )) | |
| # General improvements based on quality score | |
| if quality_score < 0.5: | |
| actions.append(RefinementAction( | |
| action_type="expand", | |
| description="Expand answer with more detail", | |
| parameters={"reason": "Low quality score"}, | |
| priority=2, | |
| )) | |
| # Sort by priority | |
| actions.sort(key=lambda a: a.priority) | |
| # Limit number of actions | |
| return actions[:5] | |
| def should_continue(self, quality_score: float) -> bool: | |
| """Determine if refinement should continue. | |
| Args: | |
| quality_score: Current quality score | |
| Returns: | |
| True if refinement should continue | |
| """ | |
| if self._current_iteration >= self.max_iterations: | |
| return False | |
| # Continue if quality is below threshold | |
| return quality_score < 0.7 | |
| def increment_iteration(self) -> int: | |
| """Increment the iteration counter. | |
| Returns: | |
| Current iteration number | |
| """ | |
| self._current_iteration += 1 | |
| return self._current_iteration | |
| def reset(self) -> None: | |
| """Reset the iteration counter.""" | |
| self._current_iteration = 0 | |
| def get_iteration(self) -> int: | |
| """Get current iteration number. | |
| Returns: | |
| Current iteration | |
| """ | |
| return self._current_iteration | |
| def create_refined_query( | |
| self, | |
| original_query: str, | |
| action: RefinementAction, | |
| ) -> str: | |
| """Create a refined query for additional search. | |
| Args: | |
| original_query: Original user query | |
| action: Refinement action to execute | |
| Returns: | |
| Refined search query | |
| """ | |
| if action.action_type == "search": | |
| return action.parameters.get("search_query", original_query) | |
| elif action.action_type == "verify": | |
| claim = action.parameters.get("claim", "") | |
| return f"verify {original_query} {claim}" | |
| elif action.action_type == "expand": | |
| return f"{original_query} detailed explanation" | |
| elif action.action_type == "clarify": | |
| unclear = action.parameters.get("unclear_part", "") | |
| return f"{original_query} {unclear} meaning definition" | |
| return original_query | |
| def merge_answers( | |
| self, | |
| original_answer: str, | |
| new_information: str, | |
| action: RefinementAction, | |
| ) -> str: | |
| """Merge new information into existing answer. | |
| Args: | |
| original_answer: Original answer text | |
| new_information: New information to incorporate | |
| action: The refinement action that produced this info | |
| Returns: | |
| Merged answer | |
| """ | |
| # Simple merging strategy - append with context | |
| if action.action_type == "expand": | |
| return f"{original_answer}\n\n**Additional Details:**\n{new_information}" | |
| elif action.action_type == "verify": | |
| return f"{original_answer}\n\n**Verification:**\n{new_information}" | |
| elif action.action_type == "search": | |
| return f"{original_answer}\n\n**Additional Information:**\n{new_information}" | |
| elif action.action_type == "clarify": | |
| return f"{original_answer}\n\n**Clarification:**\n{new_information}" | |
| return f"{original_answer}\n\n{new_information}" | |
| def prioritize_actions( | |
| self, | |
| actions: list[RefinementAction], | |
| time_budget: float | None = None, | |
| ) -> list[RefinementAction]: | |
| """Prioritize refinement actions within constraints. | |
| Args: | |
| actions: List of actions to prioritize | |
| time_budget: Optional time budget in seconds | |
| Returns: | |
| Prioritized list of actions | |
| """ | |
| # Estimate time per action type | |
| time_estimates = { | |
| "search": 2.0, | |
| "verify": 3.0, | |
| "expand": 1.5, | |
| "clarify": 1.0, | |
| "restructure": 0.5, | |
| } | |
| if time_budget is None: | |
| return sorted(actions, key=lambda a: a.priority) | |
| # Select actions that fit within budget | |
| prioritized = [] | |
| remaining_time = time_budget | |
| sorted_actions = sorted(actions, key=lambda a: a.priority) | |
| for action in sorted_actions: | |
| estimated_time = time_estimates.get(action.action_type, 1.0) | |
| if estimated_time <= remaining_time: | |
| prioritized.append(action) | |
| remaining_time -= estimated_time | |
| return prioritized | |