Zenaight commited on
Commit
25d2492
·
verified ·
1 Parent(s): 71015aa

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -5
app.py CHANGED
@@ -1,7 +1,60 @@
1
- from fastapi import FastAPI
 
 
 
 
 
2
 
3
- app = FastAPI()
4
 
5
- @app.get("/")
6
- def greet_json():
7
- return {"Hello": "World!"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py
2
+ from fastapi import FastAPI, HTTPException
3
+ from pydantic import BaseModel
4
+ from typing import List, Literal
5
+ import joblib
6
+ import numpy as np
7
 
8
+ app = FastAPI(title="Transaction Categorizer")
9
 
10
+ # Load models once at startup
11
+ shop_model = joblib.load("shop_classifier.pkl")
12
+ category_model = joblib.load("category_classifier.pkl")
13
+
14
+ def predict_or_na(pipeline, text: str, threshold: float = 0.3) -> str:
15
+ """
16
+ Returns the top class if its probability ≥ threshold, else "N/A"
17
+ """
18
+ probs = pipeline.predict_proba([text])[0]
19
+ top_idx = int(np.argmax(probs))
20
+ return str(pipeline.classes_[top_idx]) if probs[top_idx] >= threshold else "N/A"
21
+
22
+ class TransactionIn(BaseModel):
23
+ id: str
24
+ description: str
25
+
26
+ class TransactionOut(BaseModel):
27
+ id: str
28
+ description: str
29
+ shop: str
30
+ category: str
31
+
32
+ @app.post("/predict", response_model=List[TransactionOut])
33
+ def predict_transactions(
34
+ items: List[TransactionIn],
35
+ threshold: float = 0.3
36
+ ):
37
+ """
38
+ Predict shop and category for each transaction.
39
+ - **items**: list of `{ id, description }`
40
+ - **threshold**: optional override for probability cutoff
41
+ """
42
+ results = []
43
+ for item in items:
44
+ desc_norm = item.description.lower().strip()
45
+ shop_pred = predict_or_na(shop_model, desc_norm, threshold)
46
+ category_pred = predict_or_na(category_model, desc_norm, threshold)
47
+ results.append(
48
+ TransactionOut(
49
+ id=item.id,
50
+ description=item.description,
51
+ shop=shop_pred,
52
+ category=category_pred
53
+ )
54
+ )
55
+ return results
56
+
57
+ # Optional healthcheck
58
+ @app.get("/health")
59
+ def health():
60
+ return {"status": "ok"}