Rekham1110 commited on
Commit
e2483f2
·
verified ·
1 Parent(s): f2247aa

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -25
app.py CHANGED
@@ -1,26 +1,26 @@
1
  from fastapi import FastAPI, HTTPException, Header
2
  from pydantic import BaseModel
3
- from typing import Optional
4
  from datetime import datetime
5
  import logging
6
  import uvicorn
7
  import os
8
 
9
  # Set up logging
10
- logging.basicConfig(level=logging.INFO)
11
  logger = logging.getLogger(__name__)
12
 
13
  # Initialize FastAPI app
14
  app = FastAPI(title="Vendor Performance Scoring API")
15
 
16
- # Define input data model using Pydantic
17
  class VendorInput(BaseModel):
18
  Vendor_ID__c: str
19
  Vendor_Name__c: str
20
  Issue_Count__c: int
21
  Feedback_Rating__c: float
22
  Timeliness_Score__c: float
23
- Evaluation_Date__c: str # Expecting ISO format, e.g., "2025-05-14"
24
  Email__c: Optional[str] = None
25
 
26
  # Define output data model
@@ -30,8 +30,8 @@ class VendorOutput(BaseModel):
30
  Rationale__c: str
31
  Alert_Flag__c: bool
32
 
33
- # API token for security (replace with your actual token or env variable)
34
- EXPECTED_API_TOKEN = os.getenv("API_TOKEN", "hf_your_secure_token_here")
35
 
36
  # Scoring function
37
  def calculate_vendor_score(data: VendorInput) -> VendorOutput:
@@ -44,23 +44,23 @@ def calculate_vendor_score(data: VendorInput) -> VendorOutput:
44
  if not (0 <= data.Timeliness_Score__c <= 10):
45
  raise ValueError("Timeliness_Score__c must be between 0 and 10")
46
 
47
- # Parse evaluation date to ensure it's valid
48
  try:
49
  eval_date = datetime.fromisoformat(data.Evaluation_Date__c.replace("Z", "+00:00"))
50
- if eval_date > datetime.now().astimezone():
 
51
  raise ValueError("Evaluation_Date__c cannot be in the future")
52
  except ValueError as e:
53
- raise ValueError(f"Invalid Evaluation_Date__c: {str(e)}")
54
 
55
- # Rule-based scoring
56
  base_score = 100
57
- issue_deduction = data.Issue_Count__c * 5 # -5 points per issue
58
- feedback_bonus = data.Feedback_Rating__c * 2 # +2 points per rating point
59
- timeliness_bonus = data.Timeliness_Score__c * 3 # +3 points per timeliness point
60
 
61
- # Calculate composite score
62
  score = base_score - issue_deduction + feedback_bonus + timeliness_bonus
63
- score = max(0, min(100, score)) # Cap score between 0 and 100
64
 
65
  # Generate rationale
66
  rationale_parts = []
@@ -73,9 +73,8 @@ def calculate_vendor_score(data: VendorInput) -> VendorOutput:
73
  # Set alert flag
74
  alert_flag = score < 50 or data.Issue_Count__c > 5
75
 
76
- # Log the result
77
- logger.info(f"Scored Vendor {data.Vendor_ID__c}: Score={score}, Alert={alert_flag}")
78
-
79
  return VendorOutput(
80
  Vendor_ID__c=data.Vendor_ID__c,
81
  Score__c=score,
@@ -86,22 +85,45 @@ def calculate_vendor_score(data: VendorInput) -> VendorOutput:
86
  logger.error(f"Error scoring vendor {data.Vendor_ID__c}: {str(e)}")
87
  raise HTTPException(status_code=400, detail=f"Scoring error: {str(e)}")
88
 
89
- # API endpoint for scoring
90
  @app.post("/score-vendor", response_model=VendorOutput)
91
  async def score_vendor(data: VendorInput, authorization: Optional[str] = Header(None)):
92
- # Validate API token
93
  if not authorization or authorization != f"Bearer {EXPECTED_API_TOKEN}":
 
94
  raise HTTPException(status_code=401, detail="Invalid or missing API token")
95
 
96
- # Calculate score and return result
97
  return calculate_vendor_score(data)
98
 
99
- # Root endpoint for health check
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  @app.get("/")
101
  async def root():
 
102
  return {"message": "Vendor Scoring API is running"}
103
 
104
- # Start Uvicorn server when running directly
105
  if __name__ == "__main__":
106
- port = int(os.getenv("PORT", 7860)) # Default to 7860 for Hugging Face Spaces
107
- uvicorn.run(app, host="0.0.0.0", port=port)
 
 
1
  from fastapi import FastAPI, HTTPException, Header
2
  from pydantic import BaseModel
3
+ from typing import Optional, List
4
  from datetime import datetime
5
  import logging
6
  import uvicorn
7
  import os
8
 
9
  # Set up logging
10
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
11
  logger = logging.getLogger(__name__)
12
 
13
  # Initialize FastAPI app
14
  app = FastAPI(title="Vendor Performance Scoring API")
15
 
16
+ # Define input data model
17
  class VendorInput(BaseModel):
18
  Vendor_ID__c: str
19
  Vendor_Name__c: str
20
  Issue_Count__c: int
21
  Feedback_Rating__c: float
22
  Timeliness_Score__c: float
23
+ Evaluation_Date__c: str # ISO format, e.g., "2025-05-14"
24
  Email__c: Optional[str] = None
25
 
26
  # Define output data model
 
30
  Rationale__c: str
31
  Alert_Flag__c: bool
32
 
33
+ # API token from environment variable
34
+ EXPECTED_API_TOKEN = os.getenv("API_TOKEN", "hf_default_token_for_testing")
35
 
36
  # Scoring function
37
  def calculate_vendor_score(data: VendorInput) -> VendorOutput:
 
44
  if not (0 <= data.Timeliness_Score__c <= 10):
45
  raise ValueError("Timeliness_Score__c must be between 0 and 10")
46
 
47
+ # Parse and validate evaluation date
48
  try:
49
  eval_date = datetime.fromisoformat(data.Evaluation_Date__c.replace("Z", "+00:00"))
50
+ current_date = datetime.now().astimezone()
51
+ if eval_date > current_date:
52
  raise ValueError("Evaluation_Date__c cannot be in the future")
53
  except ValueError as e:
54
+ raise ValueError(f"Invalid Evaluation_Date__c format or value: {str(e)}")
55
 
56
+ # Calculate score
57
  base_score = 100
58
+ issue_deduction = data.Issue_Count__c * 5
59
+ feedback_bonus = data.Feedback_Rating__c * 2
60
+ timeliness_bonus = data.Timeliness_Score__c * 3
61
 
 
62
  score = base_score - issue_deduction + feedback_bonus + timeliness_bonus
63
+ score = max(0, min(100, score))
64
 
65
  # Generate rationale
66
  rationale_parts = []
 
73
  # Set alert flag
74
  alert_flag = score < 50 or data.Issue_Count__c > 5
75
 
76
+ logger.info(f"Scored Vendor {data.Vendor_ID__c}: Score={score:.1f}, Alert={alert_flag}")
77
+
 
78
  return VendorOutput(
79
  Vendor_ID__c=data.Vendor_ID__c,
80
  Score__c=score,
 
85
  logger.error(f"Error scoring vendor {data.Vendor_ID__c}: {str(e)}")
86
  raise HTTPException(status_code=400, detail=f"Scoring error: {str(e)}")
87
 
88
+ # Single vendor scoring endpoint
89
  @app.post("/score-vendor", response_model=VendorOutput)
90
  async def score_vendor(data: VendorInput, authorization: Optional[str] = Header(None)):
 
91
  if not authorization or authorization != f"Bearer {EXPECTED_API_TOKEN}":
92
+ logger.warning("Invalid or missing API token")
93
  raise HTTPException(status_code=401, detail="Invalid or missing API token")
94
 
 
95
  return calculate_vendor_score(data)
96
 
97
+ # Batch vendor scoring endpoint
98
+ @app.post("/score-vendors", response_model=List[VendorOutput])
99
+ async def score_vendors(data: List[VendorInput], authorization: Optional[str] = Header(None)):
100
+ if not authorization or authorization != f"Bearer {EXPECTED_API_TOKEN}":
101
+ logger.warning("Invalid or missing API token")
102
+ raise HTTPException(status_code=401, detail="Invalid or missing API token")
103
+
104
+ results = []
105
+ for vendor in data:
106
+ try:
107
+ result = calculate_vendor_score(vendor)
108
+ results.append(result)
109
+ except Exception as e:
110
+ logger.error(f"Skipping vendor {vendor.Vendor_ID__c}: {str(e)}")
111
+ results.append(VendorOutput(
112
+ Vendor_ID__c=vendor.Vendor_ID__c,
113
+ Score__c=0,
114
+ Rationale__c=f"Error: {str(e)}",
115
+ Alert_Flag__c=True
116
+ ))
117
+ return results
118
+
119
+ # Health check endpoint
120
  @app.get("/")
121
  async def root():
122
+ logger.info("Root endpoint accessed")
123
  return {"message": "Vendor Scoring API is running"}
124
 
125
+ # Start Uvicorn server
126
  if __name__ == "__main__":
127
+ port = int(os.getenv("PORT", 7860))
128
+ logger.info(f"Starting server on port {port}")
129
+ uvicorn.run(app, host="0.0.0.0", port=port, log_level="info")