Inayatgaming commited on
Commit
6e1f6f6
·
verified ·
1 Parent(s): 166fc22

Upload 4 files

Browse files
Files changed (4) hide show
  1. .gitignore +7 -0
  2. Dockerfile +21 -0
  3. app.py +182 -0
  4. requirements.txt +4 -0
.gitignore ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ .venv/
2
+ __pycache__/
3
+ *.pyc
4
+ .env
5
+ *.log
6
+ data/
7
+ .cache/
Dockerfile ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.12-slim
2
+
3
+ WORKDIR /app
4
+
5
+ ENV PYTHONUNBUFFERED=1 \
6
+ PIP_NO_CACHE_DIR=1 \
7
+ HF_HOME=/data/.cache/huggingface \
8
+ ICMR_DATA_DIR=/data \
9
+ PORT=7860
10
+
11
+ # The bootstrapper uses Hugging Face Hub to download the data/code.
12
+ RUN pip install --no-cache-dir --upgrade pip \
13
+ && pip install --no-cache-dir huggingface_hub
14
+
15
+ RUN mkdir -p /data
16
+
17
+ COPY app.py /app/app.py
18
+
19
+ EXPOSE 7860
20
+
21
+ CMD ["python", "/app/app.py"]
app.py ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Hugging Face Docker Space bootstrapper for the ICMR + HITEK demo API.
4
+
5
+ This is the Python equivalent of the supplied Linux/VPS setup script:
6
+ - Downloads the parquet data files from the source dataset repo.
7
+ - Downloads the prebuilt index parts from the full-db repo.
8
+ - Downloads main.py, build_index.py and requirements.txt.
9
+ - Installs the downloaded Python requirements.
10
+ - Starts main:app with Uvicorn on the Hugging Face $PORT.
11
+
12
+ Environment variables:
13
+ DATA_REPO Default: Kzr0xx/Icmr-and-hitek
14
+ FULL_REPO Default: Kzr0xx/icrm-hitek-full-db-mixed
15
+ HF_TOKEN Optional token for private/gated repositories.
16
+ ICMR_DATA_DIR Default: /data
17
+ PORT Default: 7860
18
+ SKIP_DOWNLOAD Set to 1/true/yes to skip downloads.
19
+ """
20
+
21
+ import os
22
+ import sys
23
+ import subprocess
24
+ from pathlib import Path
25
+
26
+ from huggingface_hub import hf_hub_download
27
+
28
+
29
+ DATA_REPO = os.getenv("DATA_REPO", "Kzr0xx/Icmr-and-hitek")
30
+ FULL_REPO = os.getenv("FULL_REPO", "Kzr0xx/icrm-hitek-full-db-mixed")
31
+ DATA_DIR = Path(os.getenv("ICMR_DATA_DIR", "/data"))
32
+ PORT = int(os.getenv("PORT", "7860"))
33
+
34
+ FILES = [
35
+ "part1.parquet",
36
+ "part2a.parquet",
37
+ "part2b_new.parquet",
38
+ ]
39
+
40
+ IDX = [
41
+ "idx_phone.0.parquet",
42
+ "idx_phone.1.parquet",
43
+ "idx_phone.2.parquet",
44
+ "idx_phone.3.parquet",
45
+ "idx_phone.4.parquet",
46
+ "idx_phone.5.parquet",
47
+ "idx_phone.6.parquet",
48
+ "idx_aadhar.0.parquet",
49
+ "idx_aadhar.1.parquet",
50
+ "idx_aadhar.2.parquet",
51
+ "idx_aadhar.3.parquet",
52
+ "idx_aadhar.4.parquet",
53
+ "idx_aadhar.5.parquet",
54
+ "idx_aadhar.6.parquet",
55
+ ]
56
+
57
+ CODE = [
58
+ "main.py",
59
+ "build_index.py",
60
+ "requirements.txt",
61
+ ]
62
+
63
+
64
+ def download(repo: str, filename: str, destination: Path):
65
+ """Download a file from a Hugging Face dataset repository."""
66
+ destination.parent.mkdir(parents=True, exist_ok=True)
67
+
68
+ if destination.exists() and destination.stat().st_size > 0:
69
+ print(f"[SKIP] {destination} already exists", flush=True)
70
+ return
71
+
72
+ print(f"[DOWNLOAD] {repo}/{filename}", flush=True)
73
+
74
+ token = os.getenv("HF_TOKEN") or None
75
+
76
+ cached = hf_hub_download(
77
+ repo_id=repo,
78
+ filename=filename,
79
+ repo_type="dataset",
80
+ token=token,
81
+ local_dir=str(destination.parent),
82
+ local_dir_use_symlinks=False,
83
+ )
84
+
85
+ cached_path = Path(cached)
86
+
87
+ # hf_hub_download normally places it directly in local_dir.
88
+ # This fallback handles cases where the returned path differs.
89
+ if cached_path.resolve() != destination.resolve():
90
+ destination.parent.mkdir(parents=True, exist_ok=True)
91
+ if not destination.exists():
92
+ cached_path.replace(destination)
93
+
94
+ print(f"[OK] {destination}", flush=True)
95
+
96
+
97
+ def install_requirements(requirements_file: Path):
98
+ print("[SETUP] Installing API requirements...", flush=True)
99
+
100
+ subprocess.check_call([
101
+ sys.executable,
102
+ "-m",
103
+ "pip",
104
+ "install",
105
+ "--no-cache-dir",
106
+ "-r",
107
+ str(requirements_file),
108
+ ])
109
+
110
+
111
+ def start_api():
112
+ print("=" * 60, flush=True)
113
+ print(" ICMR + HITEK Hugging Face Docker Space", flush=True)
114
+ print("=" * 60, flush=True)
115
+ print(f"Data directory: {DATA_DIR}", flush=True)
116
+ print(f"Port: {PORT}", flush=True)
117
+
118
+ env = os.environ.copy()
119
+ env["ICMR_DATA_DIR"] = str(DATA_DIR)
120
+
121
+ print(f"Starting API on 0.0.0.0:{PORT}", flush=True)
122
+
123
+ os.execvpe(
124
+ sys.executable,
125
+ [
126
+ sys.executable,
127
+ "-m",
128
+ "uvicorn",
129
+ "main:app",
130
+ "--host",
131
+ "0.0.0.0",
132
+ "--port",
133
+ str(PORT),
134
+ "--workers",
135
+ "1",
136
+ ],
137
+ env,
138
+ )
139
+
140
+
141
+ def main():
142
+ DATA_DIR.mkdir(parents=True, exist_ok=True)
143
+
144
+ skip = os.getenv("SKIP_DOWNLOAD", "").lower() in {
145
+ "1", "true", "yes", "on"
146
+ }
147
+
148
+ if not skip:
149
+ print("[1/3] Downloading data files...", flush=True)
150
+ for filename in FILES:
151
+ download(DATA_REPO, filename, DATA_DIR / filename)
152
+
153
+ print("[2/3] Downloading index parts...", flush=True)
154
+ for filename in IDX:
155
+ download(FULL_REPO, filename, DATA_DIR / filename)
156
+
157
+ print("[3/3] Downloading API code...", flush=True)
158
+ for filename in CODE:
159
+ download(FULL_REPO, filename, Path("/app") / filename)
160
+ else:
161
+ print("[SKIP_DOWNLOAD] Using files already present in /app and /data", flush=True)
162
+
163
+ requirements = Path("/app/requirements.txt")
164
+
165
+ if requirements.exists():
166
+ install_requirements(requirements)
167
+ else:
168
+ raise FileNotFoundError(
169
+ "requirements.txt was not downloaded. "
170
+ "Check FULL_REPO/HF_TOKEN and repository contents."
171
+ )
172
+
173
+ if not Path("/app/main.py").exists():
174
+ raise FileNotFoundError(
175
+ "/app/main.py was not downloaded from the configured FULL_REPO."
176
+ )
177
+
178
+ start_api()
179
+
180
+
181
+ if __name__ == "__main__":
182
+ main()
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ # Bootstrap dependency.
2
+ # app.py downloads the actual API requirements.txt from FULL_REPO
3
+ # and installs it at Space startup.
4
+ huggingface_hub>=0.30.0