AtaishNehra commited on
Commit
d402ff1
·
verified ·
1 Parent(s): c1ea19a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +82 -73
app.py CHANGED
@@ -1,91 +1,100 @@
1
  from fastapi import FastAPI, HTTPException
2
  from pydantic import BaseModel
 
3
  import joblib
 
4
  import pandas as pd
5
- from typing import Optional
 
 
 
 
 
6
  import uvicorn
7
 
8
- # Load the model and label encoder
9
- model, label_encoder = joblib.load('queue_prediction_model.joblib')
10
 
11
- app = FastAPI(title="Queue Prediction API")
 
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  class TicketInput(BaseModel):
14
  title: str
15
  description: str
16
 
17
- class TicketPrediction(BaseModel):
18
- predicted_queue: str
19
- confidence: float
20
- top_3_predictions: list
21
-
22
- # Copy your helper functions
23
- def clean_text(text):
24
- if pd.isna(text):
25
- return ""
26
- text = str(text)
27
- text = re.sub(r'\S+@\S+', 'EMAIL', text)
28
- text = re.sub(r'\b(?:\d{1,3}\.){3}\d{1,3}\b', 'IP_ADDRESS', text)
29
- text = re.sub(r'\d{1,2}/\d{1,2}/\d{4}', 'DATE', text)
30
- text = re.sub(r'\b\d+\b', 'NUM', text)
31
- text = text.lower()
32
- return text
33
-
34
- def extract_features(df):
35
- # Copy your extract_features function here
36
- # (The same function from your original code)
37
- pass
38
-
39
- @app.post("/predict", response_model=TicketPrediction)
40
- async def predict(ticket: TicketInput):
41
  try:
42
- # Create a DataFrame with the input data
43
- sample = pd.DataFrame({
44
- 'Description': [ticket.description],
45
- 'Title': [ticket.title],
46
- 'Priority': ['Normal']
47
- })
48
-
49
- # Process features
50
- sample_processed = extract_features(sample)
51
-
52
- feature_columns = [
53
- 'cleaned_description', 'cleaned_title', 'has_ups', 'has_battery',
54
- 'has_problem', 'has_ip', 'has_serial', 'is_security_related',
55
- 'is_network_related', 'is_programming_related', 'is_support_related',
56
- 'description_length', 'title_length', 'word_count', 'is_high_priority'
57
- ]
58
-
59
- X = sample_processed[feature_columns]
60
-
61
- # Make prediction
62
- prediction = model.predict(X)
63
- probabilities = model.predict_proba(X)
64
-
65
- predicted_queue = label_encoder.inverse_transform(prediction)[0]
66
- confidence = float(np.max(probabilities[0]))
67
-
68
- # Get top 3 predictions
69
- top_3_idx = np.argsort(probabilities[0])[-3:][::-1]
70
- top_3_predictions = [
71
- {
72
- "queue": queue,
73
- "probability": float(prob)
74
- }
75
- for queue, prob in zip(
76
- label_encoder.inverse_transform(top_3_idx),
77
- probabilities[0][top_3_idx]
78
- )
79
- ]
80
-
81
- return {
82
- "predicted_queue": predicted_queue,
83
- "confidence": confidence,
84
- "top_3_predictions": top_3_predictions
85
- }
86
 
87
  except Exception as e:
88
  raise HTTPException(status_code=500, detail=str(e))
89
 
90
  if __name__ == "__main__":
91
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
1
  from fastapi import FastAPI, HTTPException
2
  from pydantic import BaseModel
3
+ import torch
4
  import joblib
5
+ import json
6
  import pandas as pd
7
+ import numpy as np
8
+ import re
9
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification, BertConfig
10
+ from huggingface_hub import hf_hub_download
11
+ import os
12
+ from safetensors.torch import load_file
13
  import uvicorn
14
 
15
+ # Initialize FastAPI app
16
+ app = FastAPI(title="Ticket Field Predictor API")
17
 
18
+ # Get Hugging Face token (set via Space Secrets as HF_TOKEN)
19
+ HUGGINGFACE_TOKEN = os.getenv("HF_TOKEN")
20
 
21
+ # Model Repository on Hugging Face
22
+ REPO_ID = "AtaishNehra/ticket_field_predictor_model"
23
+
24
+ # Define features
25
+ FEATURES = [
26
+ "Company", "Contract", "Priority", "Issue Type",
27
+ "Service Level Agreement", "Sub-Issue Type", "Queue"
28
+ ]
29
+
30
+ # Load label encoders
31
+ encoder_path = hf_hub_download(repo_id=REPO_ID, filename="label_encoders.joblib", token=HUGGINGFACE_TOKEN)
32
+ label_encoders = joblib.load(encoder_path)
33
+
34
+ # Load tokenizers
35
+ tokenizers = {feature: AutoTokenizer.from_pretrained("bert-base-uncased") for feature in FEATURES}
36
+
37
+ # Function to load models
38
+ def load_model(feature):
39
+ config_filename = f"{feature}/config.json"
40
+ model_filename = f"{feature}/model.safetensors"
41
+
42
+ # Download and load the configuration
43
+ config_path = hf_hub_download(repo_id=REPO_ID, filename=config_filename, token=HUGGINGFACE_TOKEN)
44
+ with open(config_path, "r") as f:
45
+ config = json.load(f)
46
+
47
+ # Download and load the model state dict
48
+ model_path = hf_hub_download(repo_id=REPO_ID, filename=model_filename, token=HUGGINGFACE_TOKEN)
49
+ state_dict = load_file(model_path, device="cpu")
50
+
51
+ # Ensure configuration has a model_type
52
+ config.setdefault("model_type", "bert")
53
+ model_config = BertConfig.from_dict(config)
54
+ model = AutoModelForSequenceClassification.from_config(model_config)
55
+
56
+ # Load state dict without strict checking
57
+ model.load_state_dict(state_dict, strict=False)
58
+ model.eval()
59
+ return model
60
+
61
+ # Load models for each feature
62
+ models = {feature: load_model(feature) for feature in FEATURES}
63
+
64
+ # Input model for API request
65
  class TicketInput(BaseModel):
66
  title: str
67
  description: str
68
 
69
+ # Prediction function
70
+ @torch.no_grad()
71
+ def predict(title: str, description: str):
72
+ inputs = f"{title} {description}"
73
+ predictions = {}
74
+
75
+ for feature in FEATURES:
76
+ tokenizer = tokenizers[feature]
77
+ model = models[feature]
78
+ label_encoder = label_encoders[feature]
79
+
80
+ tokens = tokenizer(inputs, return_tensors="pt", padding=True, truncation=True)
81
+ output = model(**tokens).logits
82
+ pred_idx = torch.argmax(output, dim=1).item()
83
+
84
+ # Decode prediction
85
+ predictions[feature] = label_encoder.inverse_transform([pred_idx])[0]
86
+
87
+ return predictions
88
+
89
+ @app.post("/predict")
90
+ async def api_predict(ticket: TicketInput):
91
+ """API endpoint for external HTTP requests"""
 
92
  try:
93
+ predictions = predict(ticket.title, ticket.description)
94
+ return {"predictions": predictions}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
 
96
  except Exception as e:
97
  raise HTTPException(status_code=500, detail=str(e))
98
 
99
  if __name__ == "__main__":
100
+ uvicorn.run(app, host="0.0.0.0", port=7860)