featrixsphere 0.2.5566__py3-none-any.whl → 0.2.6127__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,231 @@
1
+ """
2
+ PredictionResult and PredictionFeedback classes.
3
+
4
+ These classes represent prediction results and the feedback mechanism
5
+ for improving model accuracy.
6
+ """
7
+
8
+ from dataclasses import dataclass, field
9
+ from datetime import datetime
10
+ from typing import Dict, Any, Optional, Union, TYPE_CHECKING
11
+
12
+ if TYPE_CHECKING:
13
+ from .http_client import ClientContext
14
+
15
+
16
+ @dataclass
17
+ class PredictionResult:
18
+ """
19
+ Represents a prediction result with full metadata.
20
+
21
+ Attributes:
22
+ prediction_uuid: Unique identifier for this prediction (use for feedback)
23
+ prediction: Raw prediction result (class probabilities or numeric value)
24
+ predicted_class: Predicted class name (for classification)
25
+ confidence: Confidence score (for classification)
26
+ query_record: Original input record
27
+ predictor_id: ID of predictor that made this prediction
28
+ session_id: Session ID (internal)
29
+ timestamp: When prediction was made
30
+ target_column: Target column name
31
+
32
+ Usage:
33
+ result = predictor.predict({"age": 35, "income": 50000})
34
+ print(result.predicted_class) # "churned"
35
+ print(result.confidence) # 0.87
36
+ print(result.prediction_uuid) # UUID for feedback
37
+
38
+ # Send feedback if prediction was wrong
39
+ if result.predicted_class != actual_label:
40
+ feedback = result.send_feedback(ground_truth=actual_label)
41
+ feedback.send()
42
+ """
43
+
44
+ prediction_uuid: Optional[str] = None
45
+ prediction: Optional[Union[Dict[str, float], float]] = None
46
+ predicted_class: Optional[str] = None
47
+ confidence: Optional[float] = None
48
+ query_record: Optional[Dict[str, Any]] = None
49
+ predictor_id: Optional[str] = None
50
+ session_id: Optional[str] = None
51
+ target_column: Optional[str] = None
52
+ timestamp: Optional[datetime] = None
53
+ model_version: Optional[str] = None
54
+
55
+ # Internal: client context for sending feedback
56
+ _ctx: Optional['ClientContext'] = field(default=None, repr=False)
57
+
58
+ @classmethod
59
+ def from_response(
60
+ cls,
61
+ response: Dict[str, Any],
62
+ query_record: Dict[str, Any],
63
+ ctx: Optional['ClientContext'] = None
64
+ ) -> 'PredictionResult':
65
+ """
66
+ Create PredictionResult from API response.
67
+
68
+ Args:
69
+ response: API response dictionary
70
+ query_record: Original query record
71
+ ctx: Client context for feedback
72
+
73
+ Returns:
74
+ PredictionResult instance
75
+ """
76
+ # Extract prediction data
77
+ prediction = response.get('prediction')
78
+ predicted_class = None
79
+ confidence = None
80
+
81
+ # For classification, extract class and confidence
82
+ if isinstance(prediction, dict):
83
+ # Find the class with highest probability
84
+ if prediction:
85
+ predicted_class = max(prediction.keys(), key=lambda k: prediction[k])
86
+ confidence = prediction[predicted_class]
87
+
88
+ return cls(
89
+ prediction_uuid=response.get('prediction_uuid') or response.get('prediction_id'),
90
+ prediction=prediction,
91
+ predicted_class=predicted_class,
92
+ confidence=confidence,
93
+ query_record=query_record,
94
+ predictor_id=response.get('predictor_id'),
95
+ session_id=response.get('session_id'),
96
+ target_column=response.get('target_column'),
97
+ timestamp=datetime.now(),
98
+ model_version=response.get('model_version'),
99
+ _ctx=ctx,
100
+ )
101
+
102
+ def send_feedback(self, ground_truth: Union[str, float]) -> 'PredictionFeedback':
103
+ """
104
+ Create a feedback object for this prediction.
105
+
106
+ Args:
107
+ ground_truth: The correct label/value
108
+
109
+ Returns:
110
+ PredictionFeedback object (call .send() to submit)
111
+
112
+ Raises:
113
+ ValueError: If prediction_uuid is not available
114
+ """
115
+ if not self.prediction_uuid:
116
+ raise ValueError(
117
+ "Cannot send feedback: prediction_uuid not available. "
118
+ "The server may not have returned a prediction_uuid for this prediction."
119
+ )
120
+
121
+ return PredictionFeedback(
122
+ prediction_uuid=self.prediction_uuid,
123
+ ground_truth=ground_truth,
124
+ _ctx=self._ctx,
125
+ )
126
+
127
+ def to_dict(self) -> Dict[str, Any]:
128
+ """Convert to dictionary representation."""
129
+ return {
130
+ 'prediction_uuid': self.prediction_uuid,
131
+ 'prediction': self.prediction,
132
+ 'predicted_class': self.predicted_class,
133
+ 'confidence': self.confidence,
134
+ 'query_record': self.query_record,
135
+ 'predictor_id': self.predictor_id,
136
+ 'session_id': self.session_id,
137
+ 'target_column': self.target_column,
138
+ 'timestamp': self.timestamp.isoformat() if self.timestamp else None,
139
+ 'model_version': self.model_version,
140
+ }
141
+
142
+
143
+ @dataclass
144
+ class PredictionFeedback:
145
+ """
146
+ Represents feedback (ground truth) for a prediction.
147
+
148
+ Usage:
149
+ # Method 1: From PredictionResult
150
+ result = predictor.predict(record)
151
+ feedback = result.send_feedback(ground_truth="correct_label")
152
+ feedback.send()
153
+
154
+ # Method 2: Create directly
155
+ feedback = PredictionFeedback(
156
+ prediction_uuid="123e4567-e89b-12d3-a456-426614174000",
157
+ ground_truth="correct_label"
158
+ )
159
+ feedback.send()
160
+
161
+ # Method 3: Create and send in one call
162
+ PredictionFeedback.create_and_send(
163
+ ctx=client_context,
164
+ prediction_uuid="123e4567-...",
165
+ ground_truth="correct_label"
166
+ )
167
+ """
168
+
169
+ prediction_uuid: str
170
+ ground_truth: Union[str, float]
171
+ feedback_timestamp: Optional[datetime] = None
172
+
173
+ # Internal: client context for sending
174
+ _ctx: Optional['ClientContext'] = field(default=None, repr=False)
175
+
176
+ def send(self) -> Dict[str, Any]:
177
+ """
178
+ Submit feedback to the server.
179
+
180
+ Returns:
181
+ Server response
182
+
183
+ Raises:
184
+ ValueError: If no client context available
185
+ """
186
+ if not self._ctx:
187
+ raise ValueError(
188
+ "Cannot send feedback: no client context. "
189
+ "Create feedback from a PredictionResult or use create_and_send()."
190
+ )
191
+
192
+ self.feedback_timestamp = datetime.now()
193
+
194
+ response = self._ctx.post_json(
195
+ f"/compute/prediction/{self.prediction_uuid}/update_label",
196
+ data={"user_label": str(self.ground_truth)}
197
+ )
198
+ return response
199
+
200
+ @classmethod
201
+ def create_and_send(
202
+ cls,
203
+ ctx: 'ClientContext',
204
+ prediction_uuid: str,
205
+ ground_truth: Union[str, float]
206
+ ) -> Dict[str, Any]:
207
+ """
208
+ Create and send feedback in one call.
209
+
210
+ Args:
211
+ ctx: Client context
212
+ prediction_uuid: UUID of the prediction
213
+ ground_truth: Correct label/value
214
+
215
+ Returns:
216
+ Server response
217
+ """
218
+ feedback = cls(
219
+ prediction_uuid=prediction_uuid,
220
+ ground_truth=ground_truth,
221
+ _ctx=ctx,
222
+ )
223
+ return feedback.send()
224
+
225
+ def to_dict(self) -> Dict[str, Any]:
226
+ """Convert to dictionary representation."""
227
+ return {
228
+ 'prediction_uuid': self.prediction_uuid,
229
+ 'ground_truth': self.ground_truth,
230
+ 'feedback_timestamp': self.feedback_timestamp.isoformat() if self.feedback_timestamp else None,
231
+ }