Repository navigation
Expand file tree
/
Copy pathapi.py
More file actions
125 lines (104 loc) · 4.42 KB
/
Copy pathapi.py
File metadata and controls
125 lines (104 loc) · 4.42 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
import uuid
from fastapi import FastAPI, File, UploadFile, Form, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
import uvicorn
from typing import Optional, List, Dict, Any
from agent import compiled_graph
app = FastAPI(title="AI Scholarship & Loan Engine API")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# --- IN MEMORY DATABASE ---
# In a production environment, this would be a Postgres/Mongo instance.
MOCK_DATABASE: Dict[str, Dict[str, Any]] = {}
@app.post("/api/evaluate")
async def evaluate_student(
student_name: str = Form(...),
gpa: float = Form(...),
annual_family_income: int = Form(...),
major: str = Form(...),
pan_card: Optional[UploadFile] = File(None),
college_doc: Optional[UploadFile] = File(None),
):
# Build uploaded_docs list and doc_files dict
uploaded_docs = []
doc_files = {}
if pan_card and pan_card.filename:
pan_bytes = await pan_card.read()
uploaded_docs.append(pan_card.filename)
doc_files["pan_card"] = pan_bytes
doc_files["pan_card_mime"] = pan_card.content_type or "image/png"
doc_files["pan_card_filename"] = pan_card.filename
if college_doc and college_doc.filename:
college_bytes = await college_doc.read()
uploaded_docs.append(college_doc.filename)
doc_files["college_doc"] = college_bytes
doc_files["college_doc_mime"] = college_doc.content_type or "image/png"
doc_files["college_doc_filename"] = college_doc.filename
initial_state = {
"student_profile": {
"student_name": student_name,
"gpa": gpa,
"annual_family_income": annual_family_income,
"major": major
},
"uploaded_docs": uploaded_docs,
"doc_files": doc_files,
"eligibility_score": 0.0,
"credit_score": 0,
"risk_factor": 0.0,
"credibility_score": 0.0,
"matched_scholarships": [],
"approved_loans": [],
"current_status": "System Initialized",
"gemini_analysis": {},
"agents_executed": []
}
result = compiled_graph.invoke(initial_state)
# Remove binary file data before returning JSON
response = {k: v for k, v in result.items() if k != "doc_files"}
# Generate unique ID and save to database
app_id = str(uuid.uuid4())[:8]
response["application_id"] = app_id
# Determine escalation: if status has "Partial" or "Denied", or if Human Escalation agent executed.
# We will just assume if loans are denied or it's partial, it goes to escalation.
status = response.get("current_status", "").lower()
if "partial" in status or "denied" in status or "escalated" in status or "human escalation layer" in [a.lower() for a in response.get("agents_executed", [])]:
response["is_escalated"] = True
response["admin_decision"] = "PENDING"
else:
response["is_escalated"] = False
response["admin_decision"] = "AUTO_APPROVED"
MOCK_DATABASE[app_id] = response
return response
@app.get("/api/admin/applications")
async def get_all_applications():
"""Return all applications in the database, sorted with escalated first."""
apps = list(MOCK_DATABASE.values())
apps.sort(key=lambda x: (0 if x.get("is_escalated") and x.get("admin_decision") == "PENDING" else 1))
return {"applications": apps}
class AdminAction(BaseModel):
action: str # "APPROVE" or "REJECT"
@app.post("/api/admin/applications/{app_id}/action")
async def admin_action(app_id: str, payload: AdminAction):
"""Allow admin to approve or reject an escalated loan."""
if app_id not in MOCK_DATABASE:
raise HTTPException(status_code=404, detail="Application not found")
app_data = MOCK_DATABASE[app_id]
action = payload.action.upper()
if action not in ["APPROVE", "REJECT"]:
raise HTTPException(status_code=400, detail="Invalid action")
app_data["admin_decision"] = action
if action == "APPROVE":
app_data["current_status"] = "Approved (Manual Auth)"
else:
app_data["current_status"] = "Rejected (Manual Auth)"
MOCK_DATABASE[app_id] = app_data
return {"status": "success", "application": app_data}
if __name__ == "__main__":
uvicorn.run("api:app", host="0.0.0.0", port=8000, reload=True)