Raiff1982 commited on
Commit
3dfe3ab
·
verified ·
1 Parent(s): 50b0f9a

Update src/utils/response_processor.py

Browse files
Files changed (1) hide show
  1. src/utils/response_processor.py +200 -121
src/utils/response_processor.py CHANGED
@@ -1,121 +1,200 @@
1
- from typing import Dict, Any, List, Optional
2
- from knowledge_base.grounding_truth import GroundingTruth
3
-
4
- class ResponseProcessor:
5
- """
6
- Processes and verifies AI responses using the grounding truth system
7
- """
8
-
9
- def __init__(self):
10
- self.grounding_truth = GroundingTruth()
11
- self.context_history = []
12
-
13
- def process_response(self, query: str, response: str, context: Optional[str] = None) -> str:
14
- """
15
- Process and verify a response using grounding truth
16
-
17
- Args:
18
- query: The original user query
19
- response: The generated response
20
- context: Optional context category
21
-
22
- Returns:
23
- Processed and verified response
24
- """
25
- # Split response into statements for verification
26
- statements = self._split_into_statements(response)
27
-
28
- verified_statements = []
29
- uncertain_statements = []
30
-
31
- # Verify each statement
32
- for statement in statements:
33
- verification = self.grounding_truth.verify_statement(statement, context)
34
-
35
- if verification["verified"]:
36
- verified_statements.append(statement)
37
- else:
38
- # Add confidence qualifier
39
- qualified_statement = self._add_qualifier(statement, verification["confidence"])
40
- uncertain_statements.append(qualified_statement)
41
-
42
- # Reconstruct response with proper qualifiers
43
- processed_response = self._construct_response(
44
- query, verified_statements, uncertain_statements
45
- )
46
-
47
- return processed_response
48
-
49
- def _split_into_statements(self, response: str) -> List[str]:
50
- """Split response into verifiable statements"""
51
- # Basic sentence splitting
52
- sentences = [s.strip() for s in response.split('.') if s.strip()]
53
-
54
- # Further split complex sentences with conjunctions
55
- statements = []
56
- for sentence in sentences:
57
- if any(conj in sentence.lower() for conj in ['and', 'or', 'but']):
58
- parts = sentence.split(' and ')
59
- parts.extend(sentence.split(' or '))
60
- parts.extend(sentence.split(' but '))
61
- statements.extend([p.strip() for p in parts if p.strip()])
62
- else:
63
- statements.append(sentence)
64
-
65
- return statements
66
-
67
- def _add_qualifier(self, statement: str, confidence: float) -> str:
68
- """Add appropriate qualifier based on confidence level"""
69
- if confidence >= 0.8:
70
- return f"{statement} (highly likely)"
71
- elif confidence >= 0.6:
72
- return f"{statement} (probably)"
73
- elif confidence >= 0.4:
74
- return f"{statement} (possibly)"
75
- elif confidence >= 0.2:
76
- return f"It's uncertain, but {statement.lower()}"
77
- else:
78
- return f"I'm not certain about this, but {statement.lower()}"
79
-
80
- def _construct_response(
81
- self,
82
- query: str,
83
- verified_statements: List[str],
84
- uncertain_statements: List[str]
85
- ) -> str:
86
- """Construct final response with proper structure and qualifiers"""
87
- response_parts = []
88
-
89
- # Add verified information first
90
- if verified_statements:
91
- response_parts.append("Here's what I know for certain:")
92
- response_parts.extend(verified_statements)
93
-
94
- # Add uncertain information with clear separation
95
- if uncertain_statements:
96
- if verified_statements:
97
- response_parts.append("\nAdditionally:")
98
- else:
99
- response_parts.append("Based on my current understanding:")
100
- response_parts.extend(uncertain_statements)
101
-
102
- # Add general disclaimer if there are uncertain statements
103
- if uncertain_statements:
104
- response_parts.append(
105
- "\nNote: Some parts of this response are based on my current understanding "
106
- "and might need verification. Feel free to ask for clarification on specific points."
107
- )
108
-
109
- return "\n".join(response_parts)
110
-
111
- def update_context(self, query: str, response: str):
112
- """Update context history for better response processing"""
113
- self.context_history.append({
114
- "query": query,
115
- "response": response,
116
- "timestamp": time.time()
117
- })
118
-
119
- # Keep only recent context
120
- if len(self.context_history) > 10:
121
- self.context_history.pop(0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Dict, Any, List, Optional
2
+ import time
3
+ from knowledge_base.grounding_truth import GroundingTruth
4
+
5
+ # Try to import generic responder for multi-perspective optimization
6
+ try:
7
+ from codette_responder_generic import get_generic_responder
8
+ GENERIC_RESPONDER_AVAILABLE = True
9
+ except ImportError:
10
+ GENERIC_RESPONDER_AVAILABLE = False
11
+
12
+ class ResponseProcessor:
13
+ """
14
+ Processes and verifies AI responses using the grounding truth system
15
+ and optimizes perspective selection with the generic responder
16
+ """
17
+
18
+ def __init__(self):
19
+ self.grounding_truth = GroundingTruth()
20
+ self.context_history = []
21
+ self.generic_responder = get_generic_responder() if GENERIC_RESPONDER_AVAILABLE else None
22
+ self.user_id = "anonymous" # Can be set per session
23
+
24
+ def process_response(self, query: str, response: str, context: Optional[str] = None) -> str:
25
+ """
26
+ Process and verify a response using grounding truth and multi-perspective optimization
27
+
28
+ Args:
29
+ query: The original user query
30
+ response: The generated response
31
+ context: Optional context category
32
+
33
+ Returns:
34
+ Processed and verified response
35
+ """
36
+ # Analyze query with generic responder to understand domain and select perspectives
37
+ perspective_analysis = None
38
+ if self.generic_responder:
39
+ try:
40
+ perspective_analysis = self.generic_responder.generate_response(
41
+ query, user_id=self.user_id
42
+ )
43
+ # Attach perspective information to response for later use
44
+ if perspective_analysis.get("perspectives"):
45
+ response = self._enhance_with_perspectives(response, perspective_analysis["perspectives"])
46
+ except Exception as e:
47
+ # Generic responder is optional; if it fails, continue processing
48
+ pass
49
+
50
+ # Split response into statements for verification
51
+ statements = self._split_into_statements(response)
52
+
53
+ verified_statements = []
54
+ uncertain_statements = []
55
+
56
+ # Verify each statement
57
+ for statement in statements:
58
+ verification = self.grounding_truth.verify_statement(statement, context)
59
+
60
+ if verification["verified"]:
61
+ verified_statements.append(statement)
62
+ else:
63
+ # Add confidence qualifier
64
+ qualified_statement = self._add_qualifier(statement, verification["confidence"])
65
+ uncertain_statements.append(qualified_statement)
66
+
67
+ # Reconstruct response with proper qualifiers
68
+ processed_response = self._construct_response(
69
+ query, verified_statements, uncertain_statements
70
+ )
71
+
72
+ return processed_response
73
+
74
+ def _enhance_with_perspectives(self, response: str, perspectives: List[Dict]) -> str:
75
+ """
76
+ Enhance response with multi-perspective annotations
77
+
78
+ Args:
79
+ response: The original response
80
+ perspectives: List of perspective dicts from generic responder
81
+
82
+ Returns:
83
+ Response with perspective context (optional enhancement)
84
+ """
85
+ # Optional: Add subtle perspective indicators to response
86
+ # For now, just return original response; perspectives are used for learning
87
+ return response
88
+
89
+ def _split_into_statements(self, response: str) -> List[str]:
90
+ """Split response into verifiable statements"""
91
+ # Basic sentence splitting
92
+ sentences = [s.strip() for s in response.split('.') if s.strip()]
93
+
94
+ # Further split complex sentences with conjunctions
95
+ statements = []
96
+ for sentence in sentences:
97
+ if any(conj in sentence.lower() for conj in ['and', 'or', 'but']):
98
+ parts = sentence.split(' and ')
99
+ parts.extend(sentence.split(' or '))
100
+ parts.extend(sentence.split(' but '))
101
+ statements.extend([p.strip() for p in parts if p.strip()])
102
+ else:
103
+ statements.append(sentence)
104
+
105
+ return statements
106
+
107
+ def _add_qualifier(self, statement: str, confidence: float) -> str:
108
+ """Add appropriate qualifier based on confidence level"""
109
+ if confidence >= 0.8:
110
+ return f"{statement} (highly likely)"
111
+ elif confidence >= 0.6:
112
+ return f"{statement} (probably)"
113
+ elif confidence >= 0.4:
114
+ return f"{statement} (possibly)"
115
+ elif confidence >= 0.2:
116
+ return f"It's uncertain, but {statement.lower()}"
117
+ else:
118
+ return f"I'm not certain about this, but {statement.lower()}"
119
+
120
+ def _construct_response(
121
+ self,
122
+ query: str,
123
+ verified_statements: List[str],
124
+ uncertain_statements: List[str]
125
+ ) -> str:
126
+ """Construct final response with proper structure and qualifiers"""
127
+ response_parts = []
128
+
129
+ # Add verified information first
130
+ if verified_statements:
131
+ response_parts.append("Here's what I know for certain:")
132
+ response_parts.extend(verified_statements)
133
+
134
+ # Add uncertain information with clear separation
135
+ if uncertain_statements:
136
+ if verified_statements:
137
+ response_parts.append("\nAdditionally:")
138
+ else:
139
+ response_parts.append("Based on my current understanding:")
140
+ response_parts.extend(uncertain_statements)
141
+
142
+ # Add general disclaimer if there are uncertain statements
143
+ if uncertain_statements:
144
+ response_parts.append(
145
+ "\nNote: Some parts of this response are based on my current understanding "
146
+ "and might need verification. Feel free to ask for clarification on specific points."
147
+ )
148
+
149
+ return "\n".join(response_parts)
150
+
151
+ def update_context(self, query: str, response: str):
152
+ """Update context history for better response processing"""
153
+ self.context_history.append({
154
+ "query": query,
155
+ "response": response,
156
+ "timestamp": time.time()
157
+ })
158
+
159
+ # Keep only recent context
160
+ if len(self.context_history) > 10:
161
+ self.context_history.pop(0)
162
+
163
+ def record_response_feedback(self, query: str, category: str, perspective: str, rating_value: int = 3) -> Dict[str, Any]:
164
+ """
165
+ Record user feedback on response for learning system
166
+
167
+ Args:
168
+ query: The original query
169
+ category: The detected response category
170
+ perspective: The perspective used
171
+ rating_value: User rating (0-4, where 4 is best)
172
+
173
+ Returns:
174
+ Feedback confirmation and learning status
175
+ """
176
+ if not self.generic_responder:
177
+ return {"status": "learning_disabled", "message": "Generic responder not available"}
178
+
179
+ try:
180
+ from codette_responder_generic import UserRating
181
+
182
+ # Map rating value to UserRating enum
183
+ rating_map = {0: UserRating.UNHELPFUL, 1: UserRating.SLIGHTLY_HELPFUL,
184
+ 2: UserRating.HELPFUL, 3: UserRating.VERY_HELPFUL,
185
+ 4: UserRating.EXACTLY_WHAT_NEEDED}
186
+ rating = rating_map.get(rating_value, UserRating.HELPFUL)
187
+
188
+ # Record feedback
189
+ feedback_result = self.generic_responder.record_user_feedback(
190
+ user_id=self.user_id,
191
+ response_id=f"{query[:20]}_{int(time.time())}",
192
+ category=category,
193
+ perspective=perspective,
194
+ rating=rating
195
+ )
196
+
197
+ return feedback_result
198
+
199
+ except Exception as e:
200
+ return {"status": "error", "message": str(e)}