forked from StellarSplit/StellarSplit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfeedback.py
More file actions
135 lines (107 loc) · 3.55 KB
/
Copy pathfeedback.py
File metadata and controls
135 lines (107 loc) · 3.55 KB
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
"""Feedback endpoints for fraud detection."""
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel, Field
from typing import Optional, List
from datetime import datetime
from enum import Enum
router = APIRouter()
class FeedbackType(str, Enum):
"""Feedback type."""
TRUE_POSITIVE = "true_positive"
FALSE_POSITIVE = "false_positive"
FALSE_NEGATIVE = "false_negative"
TRUE_NEGATIVE = "true_negative"
class FeedbackRequest(BaseModel):
"""Feedback request."""
alert_id: str
is_fraud: bool
feedback_type: FeedbackType
notes: Optional[str] = None
reviewed_by: str
class FeedbackResponse(BaseModel):
"""Feedback response."""
success: bool
message: str
feedback_id: str
class FeedbackStats(BaseModel):
"""Feedback statistics."""
total_feedback: int
true_positives: int
false_positives: int
false_negatives: int
true_negatives: int
accuracy: float
precision: float
recall: float
f1_score: float
# In-memory storage (replace with database in production)
feedback_storage: List[dict] = []
@router.post("/feedback", response_model=FeedbackResponse)
async def submit_feedback(request: FeedbackRequest):
"""
Submit feedback on a fraud alert.
This helps improve the model through the feedback loop.
"""
import uuid
feedback_id = str(uuid.uuid4())
# Store feedback
feedback_entry = {
"id": feedback_id,
"alert_id": request.alert_id,
"is_fraud": request.is_fraud,
"feedback_type": request.feedback_type,
"notes": request.notes,
"reviewed_by": request.reviewed_by,
"created_at": datetime.utcnow()
}
feedback_storage.append(feedback_entry)
return FeedbackResponse(
success=True,
message="Feedback recorded successfully",
feedback_id=feedback_id
)
@router.get("/feedback/stats", response_model=FeedbackStats)
async def get_feedback_stats():
"""Get feedback statistics for model performance."""
total = len(feedback_storage)
if total == 0:
return FeedbackStats(
total_feedback=0,
true_positives=0,
false_positives=0,
false_negatives=0,
true_negatives=0,
accuracy=0.0,
precision=0.0,
recall=0.0,
f1_score=0.0
)
tp = sum(1 for f in feedback_storage if f["feedback_type"] == FeedbackType.TRUE_POSITIVE)
fp = sum(1 for f in feedback_storage if f["feedback_type"] == FeedbackType.FALSE_POSITIVE)
fn = sum(1 for f in feedback_storage if f["feedback_type"] == FeedbackType.FALSE_NEGATIVE)
tn = sum(1 for f in feedback_storage if f["feedback_type"] == FeedbackType.TRUE_NEGATIVE)
# Calculate metrics
accuracy = (tp + tn) / total if total > 0 else 0
precision = tp / (tp + fp) if (tp + fp) > 0 else 0
recall = tp / (tp + fn) if (tp + fn) > 0 else 0
f1 = 2 * (precision * recall) / (precision + recall) if (precision + recall) > 0 else 0
return FeedbackStats(
total_feedback=total,
true_positives=tp,
false_positives=fp,
false_negatives=fn,
true_negatives=tn,
accuracy=accuracy,
precision=precision,
recall=recall,
f1_score=f1
)
@router.get("/feedback/recent")
async def get_recent_feedback(limit: int = 50):
"""Get recent feedback entries."""
recent = sorted(
feedback_storage,
key=lambda x: x["created_at"],
reverse=True
)[:limit]
return {"feedback": recent}