kamau1 commited on
Commit
7dd7ca0
Β·
1 Parent(s): 5aa0409

refactor(docker): apply multi-stage build, offline caching, update model loading and variable cleanup

Browse files
Files changed (2) hide show
  1. Dockerfile +40 -11
  2. sema_translation_api.py +66 -34
Dockerfile CHANGED
@@ -1,22 +1,51 @@
1
  # Dockerfile for Sema Translation API on HuggingFace Spaces
 
2
 
3
- # Use an official Python runtime as a parent image
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  FROM python:3.10-slim
5
 
6
- # Set the working directory in the container
7
- WORKDIR /code
 
 
 
8
 
9
- # Copy the requirements file into the container at /code
10
- COPY ./requirements.txt /code/requirements.txt
 
11
 
12
- # Install any needed packages specified in requirements.txt
13
- # --no-cache-dir reduces image size
14
- # --upgrade pip ensures we have the latest version
 
 
 
 
 
 
15
  RUN pip install --no-cache-dir --upgrade pip
16
- RUN pip install --no-cache-dir -r /code/requirements.txt
 
 
 
17
 
18
- # Copy the application code to the working directory
19
- COPY ./sema_translation_api.py /code/sema_translation_api.py
20
 
21
  # Expose port 7860 (HuggingFace Spaces standard)
22
  EXPOSE 7860
 
1
  # Dockerfile for Sema Translation API on HuggingFace Spaces
2
+ # Multi-stage build to handle model downloading with proper permissions
3
 
4
+ # Stage 1: Download models as root
5
+ FROM python:3.10-slim AS model-builder
6
+
7
+ # Install huggingface_hub for downloading models
8
+ RUN pip install huggingface_hub
9
+
10
+ # Download models from sematech/sema-utils
11
+ RUN python -c "\
12
+ from huggingface_hub import hf_hub_download; \
13
+ hf_hub_download('sematech/sema-utils', 'spm.model'); \
14
+ hf_hub_download('sematech/sema-utils', 'lid218e.bin'); \
15
+ hf_hub_download('sematech/sema-utils', 'translation_models/sematrans-3.3B/model.bin'); \
16
+ hf_hub_download('sematech/sema-utils', 'translation_models/sematrans-3.3B/config.json'); \
17
+ hf_hub_download('sematech/sema-utils', 'translation_models/sematrans-3.3B/shared_vocabulary.txt')"
18
+
19
+ # Stage 2: Build the application
20
  FROM python:3.10-slim
21
 
22
+ # Set up a new user named "user" with user ID 1000
23
+ RUN useradd -m -u 1000 user
24
+
25
+ # Switch to the "user" user
26
+ USER user
27
 
28
+ # Set home to the user's home directory
29
+ ENV HOME=/home/user \
30
+ PATH=/home/user/.local/bin:$PATH
31
 
32
+ # Set the working directory to the user's home directory
33
+ WORKDIR $HOME/app
34
+
35
+ # Set environment variables for HuggingFace
36
+ ENV HF_HUB_OFFLINE=1
37
+ ENV TRANSFORMERS_NO_ADVISORY_WARNINGS=1
38
+
39
+ # Copy the requirements file and install dependencies
40
+ COPY --chown=user ./requirements.txt requirements.txt
41
  RUN pip install --no-cache-dir --upgrade pip
42
+ RUN pip install --no-cache-dir --user -r requirements.txt
43
+
44
+ # Copy the downloaded models from the builder stage
45
+ COPY --chown=user --from=model-builder /root/.cache/huggingface $HOME/.cache/huggingface
46
 
47
+ # Copy the application code
48
+ COPY --chown=user ./sema_translation_api.py sema_translation_api.py
49
 
50
  # Expose port 7860 (HuggingFace Spaces standard)
51
  EXPOSE 7860
sema_translation_api.py CHANGED
@@ -69,50 +69,82 @@ def get_nairobi_time():
69
  full_date = f"{curr_day} | {curr_date} | {curr_time}"
70
  return full_date, curr_time
71
 
72
- def download_models():
73
- """Download models from HuggingFace Hub using default cache"""
74
- print("πŸ”„ Downloading models from sematech/sema-utils...")
75
 
76
  try:
77
- # Download individual files from root (using default HF cache)
78
- print("πŸ“₯ Downloading SentencePiece model...")
79
- spm_path = hf_hub_download(
80
- repo_id=REPO_ID,
81
- filename="spm.model"
82
- )
 
 
 
 
 
 
 
 
83
 
84
- print("πŸ“₯ Downloading language detection model...")
85
- ft_path = hf_hub_download(
86
- repo_id=REPO_ID,
87
- filename="lid218e.bin"
88
- )
89
 
90
- # Download translation model files individually
91
- print("πŸ“₯ Downloading translation model (3.3B)...")
 
 
 
 
92
 
93
- # Download all necessary CTranslate2 files
94
- model_bin_path = hf_hub_download(
95
- repo_id=REPO_ID,
96
- filename="translation_models/sematrans-3.3B/model.bin"
97
- )
98
 
99
- hf_hub_download(
100
- repo_id=REPO_ID,
101
- filename="translation_models/sematrans-3.3B/config.json"
102
- )
 
 
 
103
 
104
- hf_hub_download(
105
- repo_id=REPO_ID,
106
- filename="translation_models/sematrans-3.3B/shared_vocabulary.txt"
107
- )
108
 
109
- # The model directory is the parent of the model.bin file
110
- ct_model_full_path = os.path.dirname(model_bin_path)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
 
112
  return spm_path, ft_path, ct_model_full_path
113
 
114
  except Exception as e:
115
- print(f"❌ Error downloading models: {e}")
116
  raise e
117
 
118
  def load_models():
@@ -121,8 +153,8 @@ def load_models():
121
 
122
  print("πŸš€ Loading models into memory...")
123
 
124
- # Download models first
125
- spm_path, ft_path, ct_model_path = download_models()
126
 
127
  # Suppress fasttext warnings
128
  fasttext.FastText.eprint = lambda x: None
 
69
  full_date = f"{curr_day} | {curr_date} | {curr_time}"
70
  return full_date, curr_time
71
 
72
+ def get_model_paths():
73
+ """Get model paths from HuggingFace cache (models pre-downloaded in Docker)"""
74
+ print("πŸ”„ Loading models from cache...")
75
 
76
  try:
77
+ # Check if we're in offline mode (Docker environment)
78
+ offline_mode = os.environ.get("HF_HUB_OFFLINE", "0") == "1"
79
+
80
+ if offline_mode:
81
+ print("πŸ“¦ Running in offline mode - using cached models")
82
+ # In offline mode, models are already downloaded and cached
83
+ # We need to find them in the cache directory
84
+
85
+ # Get paths from cache using hf_hub_download with local_files_only=True
86
+ spm_path = hf_hub_download(
87
+ repo_id=REPO_ID,
88
+ filename="spm.model",
89
+ local_files_only=True
90
+ )
91
 
92
+ ft_path = hf_hub_download(
93
+ repo_id=REPO_ID,
94
+ filename="lid218e.bin",
95
+ local_files_only=True
96
+ )
97
 
98
+ # Get the translation model path
99
+ model_bin_path = hf_hub_download(
100
+ repo_id=REPO_ID,
101
+ filename="translation_models/sematrans-3.3B/model.bin",
102
+ local_files_only=True
103
+ )
104
 
105
+ # The model directory is the parent of the model.bin file
106
+ ct_model_full_path = os.path.dirname(model_bin_path)
 
 
 
107
 
108
+ else:
109
+ print("🌐 Running in online mode - downloading models")
110
+ # Online mode - download models (for local development)
111
+ spm_path = hf_hub_download(
112
+ repo_id=REPO_ID,
113
+ filename="spm.model"
114
+ )
115
 
116
+ ft_path = hf_hub_download(
117
+ repo_id=REPO_ID,
118
+ filename="lid218e.bin"
119
+ )
120
 
121
+ # Download all necessary CTranslate2 files
122
+ model_bin_path = hf_hub_download(
123
+ repo_id=REPO_ID,
124
+ filename="translation_models/sematrans-3.3B/model.bin"
125
+ )
126
+
127
+ hf_hub_download(
128
+ repo_id=REPO_ID,
129
+ filename="translation_models/sematrans-3.3B/config.json"
130
+ )
131
+
132
+ hf_hub_download(
133
+ repo_id=REPO_ID,
134
+ filename="translation_models/sematrans-3.3B/shared_vocabulary.txt"
135
+ )
136
+
137
+ ct_model_full_path = os.path.dirname(model_bin_path)
138
+
139
+ print(f"πŸ“ Model paths:")
140
+ print(f" SentencePiece: {spm_path}")
141
+ print(f" Language detection: {ft_path}")
142
+ print(f" Translation model: {ct_model_full_path}")
143
 
144
  return spm_path, ft_path, ct_model_full_path
145
 
146
  except Exception as e:
147
+ print(f"❌ Error loading models: {e}")
148
  raise e
149
 
150
  def load_models():
 
153
 
154
  print("πŸš€ Loading models into memory...")
155
 
156
+ # Get model paths (from cache or download)
157
+ spm_path, ft_path, ct_model_path = get_model_paths()
158
 
159
  # Suppress fasttext warnings
160
  fasttext.FastText.eprint = lambda x: None