PunchNFIT commited on
Commit
6cfd530
Β·
1 Parent(s): b5f9bf1

Production-ready SNP model with tokenizer mapping and WSGI server

Browse files
Files changed (3) hide show
  1. Dockerfile +8 -16
  2. api_inference.py +20 -12
  3. requirements.txt +1 -0
Dockerfile CHANGED
@@ -1,27 +1,19 @@
1
  FROM python:3.10-slim
2
 
3
- # Make absolutely sure the working directory exists
4
- RUN mkdir -p /app
5
  WORKDIR /app
6
 
7
- # Print working directory (for debugging)
8
- RUN echo "βœ… Building from context:" && pwd && ls -R
9
-
10
- # Copy specific files explicitly by name
11
- COPY api_inference.py /app/api_inference.py
12
- COPY snp_universal_embedding.py /app/snp_universal_embedding.py
13
- COPY config.json /app/config.json
14
- COPY tokenizer.json /app/tokenizer.json
15
- COPY pytorch_model.bin /app/pytorch_model.bin
16
- COPY requirements.txt /app/requirements.txt
17
 
18
  # Install dependencies
19
- RUN pip install --no-cache-dir -r /app/requirements.txt
20
 
21
  # Expose Hugging Face port
22
  EXPOSE 7860
23
 
24
- # Run the app
25
  ENV HF_HOME=/tmp/huggingface
26
- ENV TRANSFORMERS_CACHE=/tmp/huggingface
27
- CMD ["python", "/app/api_inference.py"]
 
 
1
  FROM python:3.10-slim
2
 
3
+ # Create and switch to /app
 
4
  WORKDIR /app
5
 
6
+ # Copy all repo files into /app
7
+ ADD . /app
 
 
 
 
 
 
 
 
8
 
9
  # Install dependencies
10
+ RUN pip install --no-cache-dir -r requirements.txt
11
 
12
  # Expose Hugging Face port
13
  EXPOSE 7860
14
 
15
+ # Environment variables for HF cache
16
  ENV HF_HOME=/tmp/huggingface
17
+
18
+ # Use Gunicorn (production WSGI server)
19
+ CMD ["gunicorn", "--bind", "0.0.0.0:7860", "api_inference:app"]
api_inference.py CHANGED
@@ -14,7 +14,7 @@ from transformers import (
14
  # Environment Configuration
15
  # ============================================================
16
  os.environ["HF_HOME"] = "/tmp/huggingface"
17
- os.environ["TRANSFORMERS_CACHE"] = "/tmp/huggingface"
18
 
19
  MODEL_DIR = "./"
20
  PORT = int(os.environ.get("PORT", 7860))
@@ -53,6 +53,10 @@ class CustomSNPModel(PreTrainedModel):
53
  AutoConfig.register("custom_snp", CustomSNPConfig)
54
  AutoModel.register(CustomSNPConfig, CustomSNPModel)
55
 
 
 
 
 
56
 
57
  # ============================================================
58
  # Load Model & Tokenizer
@@ -60,24 +64,28 @@ AutoModel.register(CustomSNPConfig, CustomSNPModel)
60
  try:
61
  print("Loading model from:", MODEL_DIR)
62
  config = AutoConfig.from_pretrained(MODEL_DIR, trust_remote_code=True)
63
-
64
- # Try loading tokenizer; fallback if not mapped
65
- from transformers import RobertaTokenizer
66
- try:
67
- tokenizer = AutoTokenizer.from_pretrained(MODEL_DIR)
68
- except Exception:
69
- print("⚠️ Falling back to default RoBERTa tokenizer.")
70
- tokenizer = RobertaTokenizer.from_pretrained("roberta-base")
71
-
72
  model = AutoModel.from_pretrained(MODEL_DIR, config=config, trust_remote_code=True)
73
  model.eval()
74
  print("βœ… Custom SNP model loaded successfully.")
75
-
76
  except Exception as e:
77
  print("❌ Error loading custom model:", e)
78
  raise e
79
 
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  # ============================================================
82
  # Flask API Routes
83
  # ============================================================
@@ -122,7 +130,7 @@ def reason():
122
 
123
 
124
  # ============================================================
125
- # Run Server
126
  # ============================================================
127
  if __name__ == "__main__":
128
  print(f"πŸš€ Starting SNP Universal Embedding API on port {PORT}")
 
14
  # Environment Configuration
15
  # ============================================================
16
  os.environ["HF_HOME"] = "/tmp/huggingface"
17
+ # TRANSFORMERS_CACHE is deprecated; HF_HOME alone is enough
18
 
19
  MODEL_DIR = "./"
20
  PORT = int(os.environ.get("PORT", 7860))
 
53
  AutoConfig.register("custom_snp", CustomSNPConfig)
54
  AutoModel.register(CustomSNPConfig, CustomSNPModel)
55
 
56
+ # --- Permanent Tokenizer Mapping ---
57
+ from transformers import TOKENIZER_MAPPING, RobertaTokenizer
58
+ TOKENIZER_MAPPING[CustomSNPConfig] = (RobertaTokenizer, RobertaTokenizer)
59
+
60
 
61
  # ============================================================
62
  # Load Model & Tokenizer
 
64
  try:
65
  print("Loading model from:", MODEL_DIR)
66
  config = AutoConfig.from_pretrained(MODEL_DIR, trust_remote_code=True)
67
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_DIR)
 
 
 
 
 
 
 
 
68
  model = AutoModel.from_pretrained(MODEL_DIR, config=config, trust_remote_code=True)
69
  model.eval()
70
  print("βœ… Custom SNP model loaded successfully.")
 
71
  except Exception as e:
72
  print("❌ Error loading custom model:", e)
73
  raise e
74
 
75
 
76
+ # ============================================================
77
+ # Initialize weights (optional for untrained layers)
78
+ # ============================================================
79
+ def initialize_weights_if_missing(model):
80
+ for name, param in model.named_parameters():
81
+ if param.requires_grad and (torch.isnan(param).any() or torch.all(param == 0)):
82
+ nn.init.xavier_uniform_(param)
83
+ print(f"πŸ”§ Initialized missing weights: {name}")
84
+
85
+
86
+ initialize_weights_if_missing(model)
87
+
88
+
89
  # ============================================================
90
  # Flask API Routes
91
  # ============================================================
 
130
 
131
 
132
  # ============================================================
133
+ # Run Server (used by Gunicorn in production)
134
  # ============================================================
135
  if __name__ == "__main__":
136
  print(f"πŸš€ Starting SNP Universal Embedding API on port {PORT}")
requirements.txt CHANGED
@@ -5,3 +5,4 @@ sentence-transformers
5
  flask
6
  numpy
7
  scikit-learn
 
 
5
  flask
6
  numpy
7
  scikit-learn
8
+ gunicorn