File size: 3,163 Bytes
6cc8da8
 
d402ff1
6cc8da8
d402ff1
6cc8da8
d402ff1
 
 
 
 
 
6cc8da8
 
d402ff1
 
6cc8da8
d402ff1
 
6cc8da8
d402ff1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6cc8da8
 
 
 
d402ff1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6cc8da8
d402ff1
 
6cc8da8
 
 
 
 
d402ff1
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
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import torch
import joblib
import json
import pandas as pd
import numpy as np
import re
from transformers import AutoTokenizer, AutoModelForSequenceClassification, BertConfig
from huggingface_hub import hf_hub_download
import os
from safetensors.torch import load_file
import uvicorn

# Initialize FastAPI app
app = FastAPI(title="Ticket Field Predictor API")

# Get Hugging Face token (set via Space Secrets as HF_TOKEN)
HUGGINGFACE_TOKEN = os.getenv("HF_TOKEN")

# Model Repository on Hugging Face
REPO_ID = "AtaishNehra/ticket_field_predictor_model"

# Define features
FEATURES = [
    "Company", "Contract", "Priority", "Issue Type",
    "Service Level Agreement", "Sub-Issue Type", "Queue"
]

# Load label encoders
encoder_path = hf_hub_download(repo_id=REPO_ID, filename="label_encoders.joblib", token=HUGGINGFACE_TOKEN)
label_encoders = joblib.load(encoder_path)

# Load tokenizers
tokenizers = {feature: AutoTokenizer.from_pretrained("bert-base-uncased") for feature in FEATURES}

# Function to load models
def load_model(feature):
    config_filename = f"{feature}/config.json"
    model_filename = f"{feature}/model.safetensors"

    # Download and load the configuration
    config_path = hf_hub_download(repo_id=REPO_ID, filename=config_filename, token=HUGGINGFACE_TOKEN)
    with open(config_path, "r") as f:
        config = json.load(f)

    # Download and load the model state dict
    model_path = hf_hub_download(repo_id=REPO_ID, filename=model_filename, token=HUGGINGFACE_TOKEN)
    state_dict = load_file(model_path, device="cpu")

    # Ensure configuration has a model_type
    config.setdefault("model_type", "bert")
    model_config = BertConfig.from_dict(config)
    model = AutoModelForSequenceClassification.from_config(model_config)

    # Load state dict without strict checking
    model.load_state_dict(state_dict, strict=False)
    model.eval()
    return model

# Load models for each feature
models = {feature: load_model(feature) for feature in FEATURES}

# Input model for API request
class TicketInput(BaseModel):
    title: str
    description: str

# Prediction function
@torch.no_grad()
def predict(title: str, description: str):
    inputs = f"{title} {description}"
    predictions = {}

    for feature in FEATURES:
        tokenizer = tokenizers[feature]
        model = models[feature]
        label_encoder = label_encoders[feature]

        tokens = tokenizer(inputs, return_tensors="pt", padding=True, truncation=True)
        output = model(**tokens).logits
        pred_idx = torch.argmax(output, dim=1).item()

        # Decode prediction
        predictions[feature] = label_encoder.inverse_transform([pred_idx])[0]

    return predictions

@app.post("/predict")
async def api_predict(ticket: TicketInput):
    """API endpoint for external HTTP requests"""
    try:
        predictions = predict(ticket.title, ticket.description)
        return {"predictions": predictions}

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=7860)