subbunanepalli commited on
Commit
ac75f49
·
verified ·
1 Parent(s): 1b79cf5

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +175 -0
app.py ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException
2
+ from pydantic import BaseModel, Field, validator
3
+ from typing import Optional
4
+ import pandas as pd
5
+ import joblib
6
+
7
+ app = FastAPI()
8
+
9
+ # === Paths ===
10
+ TFIDF_PATH = "models/tfidf_vectorizer.pkl"
11
+ MODEL_PATH = "models/logreg_model.pkl"
12
+ ENCODER_PATH = "models/label_encoders.pkl"
13
+
14
+ # === Load artifacts ===
15
+ tfidf_vectorizer = joblib.load(TFIDF_PATH)
16
+ models = joblib.load(MODEL_PATH)
17
+ label_encoders = joblib.load(ENCODER_PATH)
18
+
19
+ # === Input Schema ===
20
+ class TransactionData(BaseModel):
21
+ Transaction_Id: str
22
+ Hit_Seq: int
23
+ Hit_Id_List: str
24
+ Origin: str
25
+ Designation: str
26
+ Keywords: str
27
+ Name: str
28
+ SWIFT_Tag: str
29
+ Currency: str
30
+ Entity: str
31
+ Message: str
32
+ City: str
33
+ Country: str
34
+ State: str
35
+ Hit_Type: str
36
+ Record_Matching_String: str
37
+ WatchList_Match_String: str
38
+ Payment_Sender_Name: Optional[str] = ""
39
+ Payment_Reciever_Name: Optional[str] = ""
40
+ Swift_Message_Type: str
41
+ Text_Sanction_Data: str
42
+ Matched_Sanctioned_Entity: str
43
+ Is_Match: int
44
+ Red_Flag_Reason: str
45
+ Risk_Level: str
46
+ Risk_Score: float
47
+ Risk_Score_Description: str
48
+ CDD_Level: str
49
+ PEP_Status: str
50
+ Value_Date: str
51
+ Last_Review_Date: str
52
+ Next_Review_Date: str
53
+ Sanction_Description: str
54
+ Checker_Notes: str
55
+ Sanction_Context: str = Field(..., min_length=5)
56
+ Maker_Action: str
57
+ Customer_ID: int
58
+ Customer_Type: str
59
+ Industry: str
60
+ Transaction_Date_Time: str
61
+ Transaction_Type: str
62
+ Transaction_Channel: str
63
+ Originating_Bank: str
64
+ Beneficiary_Bank: str
65
+ Geographic_Origin: str
66
+ Geographic_Destination: str
67
+ Match_Score: float
68
+ Match_Type: str
69
+ Sanctions_List_Version: str
70
+ Screening_Date_Time: str
71
+ Risk_Category: str
72
+ Risk_Drivers: str
73
+ Alert_Status: str
74
+ Investigation_Outcome: str
75
+ Case_Owner_Analyst: str
76
+ Escalation_Level: str
77
+ Escalation_Date: str
78
+ Regulatory_Reporting_Flags: bool
79
+ Audit_Trail_Timestamp: str
80
+ Source_Of_Funds: str
81
+ Purpose_Of_Transaction: str
82
+ Beneficial_Owner: str
83
+ Sanctions_Exposure_History: bool
84
+
85
+ @validator("Sanction_Context")
86
+ def context_not_blank(cls, v):
87
+ if not v.strip():
88
+ raise ValueError("Sanction_Context must not be blank.")
89
+ return v
90
+
91
+ class PredictionRequest(BaseModel):
92
+ transaction_data: TransactionData
93
+
94
+ @app.get("/")
95
+ def root():
96
+ return {"status": "healthy", "message": "LogReg TF-IDF API is running"}
97
+
98
+ @app.post("/validate")
99
+ def validate_input(request: PredictionRequest):
100
+ try:
101
+ _ = request.transaction_data
102
+ return {"status": "success", "message": "Input schema is valid."}
103
+ except Exception as e:
104
+ raise HTTPException(status_code=400, detail=str(e))
105
+
106
+ @app.post("/predict")
107
+ def predict(request: PredictionRequest):
108
+ try:
109
+ input_data = pd.DataFrame([request.transaction_data.dict()])
110
+
111
+ text_input = f"""
112
+ Transaction ID: {input_data['Transaction_Id'].iloc[0]}
113
+ Origin: {input_data['Origin'].iloc[0]}
114
+ Designation: {input_data['Designation'].iloc[0]}
115
+ Keywords: {input_data['Keywords'].iloc[0]}
116
+ Name: {input_data['Name'].iloc[0]}
117
+ SWIFT Tag: {input_data['SWIFT_Tag'].iloc[0]}
118
+ Currency: {input_data['Currency'].iloc[0]}
119
+ Entity: {input_data['Entity'].iloc[0]}
120
+ Message: {input_data['Message'].iloc[0]}
121
+ City: {input_data['City'].iloc[0]}
122
+ Country: {input_data['Country'].iloc[0]}
123
+ State: {input_data['State'].iloc[0]}
124
+ Hit Type: {input_data['Hit_Type'].iloc[0]}
125
+ Record Matching String: {input_data['Record_Matching_String'].iloc[0]}
126
+ WatchList Match String: {input_data['WatchList_Match_String'].iloc[0]}
127
+ Payment Sender: {input_data['Payment_Sender_Name'].iloc[0]}
128
+ Payment Receiver: {input_data['Payment_Reciever_Name'].iloc[0]}
129
+ Swift Message Type: {input_data['Swift_Message_Type'].iloc[0]}
130
+ Text Sanction Data: {input_data['Text_Sanction_Data'].iloc[0]}
131
+ Matched Sanctioned Entity: {input_data['Matched_Sanctioned_Entity'].iloc[0]}
132
+ Red Flag Reason: {input_data['Red_Flag_Reason'].iloc[0]}
133
+ Risk Level: {input_data['Risk_Level'].iloc[0]}
134
+ Risk Score: {input_data['Risk_Score'].iloc[0]}
135
+ CDD Level: {input_data['CDD_Level'].iloc[0]}
136
+ PEP Status: {input_data['PEP_Status'].iloc[0]}
137
+ Sanction Description: {input_data['Sanction_Description'].iloc[0]}
138
+ Checker Notes: {input_data['Checker_Notes'].iloc[0]}
139
+ Sanction Context: {input_data['Sanction_Context'].iloc[0]}
140
+ Maker Action: {input_data['Maker_Action'].iloc[0]}
141
+ Customer Type: {input_data['Customer_Type'].iloc[0]}
142
+ Industry: {input_data['Industry'].iloc[0]}
143
+ Transaction Type: {input_data['Transaction_Type'].iloc[0]}
144
+ Transaction Channel: {input_data['Transaction_Channel'].iloc[0]}
145
+ Geographic Origin: {input_data['Geographic_Origin'].iloc[0]}
146
+ Geographic Destination: {input_data['Geographic_Destination'].iloc[0]}
147
+ Risk Category: {input_data['Risk_Category'].iloc[0]}
148
+ Risk Drivers: {input_data['Risk_Drivers'].iloc[0]}
149
+ Alert Status: {input_data['Alert_Status'].iloc[0]}
150
+ Investigation Outcome: {input_data['Investigation_Outcome'].iloc[0]}
151
+ Source of Funds: {input_data['Source_Of_Funds'].iloc[0]}
152
+ Purpose of Transaction: {input_data['Purpose_Of_Transaction'].iloc[0]}
153
+ Beneficial Owner: {input_data['Beneficial_Owner'].iloc[0]}
154
+ """
155
+
156
+ X_tfidf = tfidf_vectorizer.transform([text_input])
157
+ response = {}
158
+
159
+ for label, model in models.items():
160
+ proba = model.predict_proba(X_tfidf)[0]
161
+ pred_idx = proba.argmax()
162
+ decoded = label_encoders[label].inverse_transform([pred_idx])[0]
163
+
164
+ response[label] = {
165
+ "prediction": decoded,
166
+ "probabilities": {
167
+ label_encoders[label].classes_[i]: float(p)
168
+ for i, p in enumerate(proba)
169
+ }
170
+ }
171
+
172
+ return response
173
+
174
+ except Exception as e:
175
+ raise HTTPException(status_code=500, detail=str(e))