taxy-ml-api / serve.py
Taxy01's picture
Upload 10 files
640eb2e verified
Raw History Blame Contribute Delete
4.26 kB
"""
Taxy ML — REST API Mandiri (FastAPI)
====================================
Melayani model Deep Learning + fitur Generative AI (Gemini) pada port 5001.
Endpoints:
GET /health -> status model & GenAI
POST /predict -> prediksi risiko ketidakpatuhan (MODEL ML) + penjelasan GenAI
POST /explanation -> penjelasan hasil kalkulasi pajak (GenAI) [dipakai dashboard]
POST /chat -> chatbot Q&A pajak (GenAI) [fitur sekunder]
Menjalankan:
uvicorn serve:app --host 0.0.0.0 --port 5001
(atau) python serve.py
Backend Node (be/controllers/aiController.js) sudah menunjuk ke
http://127.0.0.1:5001 dan punya fallback bila server ini mati.
"""
import os
from typing import Optional, Dict, Any
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
# Muat .env sederhana (tanpa dependency tambahan)
def _load_dotenv():
path = os.path.join(os.path.dirname(os.path.abspath(__file__)), ".env")
if os.path.exists(path):
for line in open(path, encoding="utf-8"):
line = line.strip()
if line and not line.startswith("#") and "=" in line:
k, v = line.split("=", 1)
os.environ.setdefault(k.strip(), v.strip().strip('"').strip("'"))
_load_dotenv()
import inference
import genai
app = FastAPI(title="Taxy ML API", version="1.0.0",
description="Deep Learning Tax-Compliance Risk Profiler + Gemini GenAI")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], allow_methods=["*"], allow_headers=["*"],
)
# ----------------------------- Schemas -------------------------------------
class PredictRequest(BaseModel):
usia: float = 30
gaji_bulanan: float = 0
skor_literasi_pajak: float = 50
punya_npwp: int = 0
aktif_taxy: int = 0
status_ptkp: str = "TK/0"
pekerjaan: str = "Junior Staff"
kategori_pendapatan: Optional[str] = None
class ExplanationRequest(BaseModel):
taxData: Dict[str, Any]
category: Optional[str] = "Pajak"
class ChatRequest(BaseModel):
message: str
context: Optional[Dict[str, Any]] = None
# ----------------------------- Startup -------------------------------------
@app.on_event("startup")
def _startup():
inference.load() # muat model lebih awal
genai.init_genai() # coba aktifkan Gemini (silent jika tak ada key)
print("[Taxy ML API] Model dimuat. GenAI:", genai.status())
# ----------------------------- Endpoints -----------------------------------
@app.get("/health")
def health():
return {
"status": "ok",
"service": "Taxy ML API",
"model_loaded": inference._model is not None,
"genai": genai.status(),
}
@app.post("/predict")
def predict(req: PredictRequest):
"""Prediksi risiko ketidakpatuhan pajak dari profil pengguna (MODEL ML)
+ penjelasan natural dari Gemini (fallback lokal jika offline)."""
profile = req.model_dump()
pred = inference.predict(profile)
nice = (f"usia {profile['usia']:.0f}, gaji {profile['gaji_bulanan']:,.0f}, "
f"NPWP={'ya' if profile['punya_npwp'] else 'tidak'}, "
f"literasi {profile['skor_literasi_pajak']:.0f}/100, "
f"aktif Taxy={'ya' if profile['aktif_taxy'] else 'tidak'}")
expl = genai.explain_risk(nice, pred)
return {"success": True, "prediction": pred,
"explanation": expl["explanation"], "source": expl["source"]}
@app.post("/explanation")
def explanation(req: ExplanationRequest):
"""Penjelasan hasil kalkulasi pajak (dipakai 'Insight Pajak AI' di dashboard)."""
out = genai.explain_tax(req.taxData, req.category)
return {"success": True, "data": {"explanation": out["explanation"]},
"source": out["source"]}
@app.post("/chat")
def chat(req: ChatRequest):
"""Chatbot Q&A pajak (fitur sekunder Generative AI)."""
out = genai.chat(req.message, req.context)
return {"success": True, "reply": out["reply"], "source": out["source"]}
if __name__ == "__main__":
import uvicorn
# PORT dari environment (Hugging Face Spaces=7860, Cloud Run=8080, lokal=5001)
port = int(os.environ.get("PORT", 5001))
uvicorn.run(app, host="0.0.0.0", port=port)