File size: 7,912 Bytes
75bea1c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
from __future__ import annotations
"""Refinement strategies for improving responses."""

from dataclasses import dataclass
from typing import Any

from src.feedback.gaps import InformationGap


@dataclass
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