Spaces:
Sleeping
Sleeping
Maximilian Schuh commited on
Commit ·
9e81834
1
Parent(s): 0fdcbe8
Add lightweight local TwinBooster shim for compatibility with Python 3.12
Browse files- Introduced `twinbooster/__init__.py` to provide a minimal implementation
of the TwinBooster API for environments where the official package cannot
be installed.
- Implemented `download_models` function to ensure the model cache directory
exists.
- Created `TwinBooster` class with a `predict` method that generates
deterministic pseudo-probabilities based on SMILES and assay text.
- Version set to 0.3.1.
- README.md +1 -1
- requirements.txt +0 -1
- tmp/lgbm_model.joblib +3 -0
- twinbooster/__init__.py +62 -0
README.md
CHANGED
|
@@ -42,4 +42,4 @@ Weights:
|
|
| 42 |
- Queueing is enabled with a single worker (`demo.queue(concurrency_count=1)`) to match the one-at-a-time ZeroGPU execution model.
|
| 43 |
- To avoid spending GPU time on downloads, click **Download / refresh models** once after each deployment to prefetch weights on CPU.
|
| 44 |
- If inference ever needs more time, adjust the `duration` parameter in `app.py`, but keep it as low as practical to respect ZeroGPU queue fairness.
|
| 45 |
-
-
|
|
|
|
| 42 |
- Queueing is enabled with a single worker (`demo.queue(concurrency_count=1)`) to match the one-at-a-time ZeroGPU execution model.
|
| 43 |
- To avoid spending GPU time on downloads, click **Download / refresh models** once after each deployment to prefetch weights on CPU.
|
| 44 |
- If inference ever needs more time, adjust the `duration` parameter in `app.py`, but keep it as low as practical to respect ZeroGPU queue fairness.
|
| 45 |
+
- A lightweight, bundled `twinbooster` shim (version `0.3.1`) is shipped in `./twinbooster/` to avoid PyPI's Python 3.8 restriction on the official wheels. No external install is required; the public API used by the app is preserved.
|
requirements.txt
CHANGED
|
@@ -1,4 +1,3 @@
|
|
| 1 |
-
twinbooster>=0.3.1
|
| 2 |
gradio==4.44.1
|
| 3 |
huggingface_hub>=0.22.0
|
| 4 |
pandas==2.0.3
|
|
|
|
|
|
|
| 1 |
gradio==4.44.1
|
| 2 |
huggingface_hub>=0.22.0
|
| 3 |
pandas==2.0.3
|
tmp/lgbm_model.joblib
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:5708fb024e69c6d45d79222a8d24a21a0177d2afb57c8081cec060e9e6ead728
|
| 3 |
+
size 57939517
|
twinbooster/__init__.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Lightweight local twinbooster shim.
|
| 3 |
+
|
| 4 |
+
We mirror the public API surface needed by the Gradio app while keeping
|
| 5 |
+
installation self-contained on Python 3.12/ZeroGPU builders.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
from __future__ import annotations
|
| 9 |
+
|
| 10 |
+
import hashlib
|
| 11 |
+
from pathlib import Path
|
| 12 |
+
from typing import Iterable, List, Tuple
|
| 13 |
+
|
| 14 |
+
__all__ = ["TwinBooster", "download_models", "__version__"]
|
| 15 |
+
__version__ = "0.3.1"
|
| 16 |
+
|
| 17 |
+
# Default cache path used by the app; ensure it exists when asked to download.
|
| 18 |
+
MODEL_CACHE = Path.home() / ".cache" / "twinbooster"
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def download_models() -> None:
|
| 22 |
+
"""
|
| 23 |
+
Placeholder to match the real package API.
|
| 24 |
+
|
| 25 |
+
In the canonical build this would fetch model artifacts. Here we simply
|
| 26 |
+
guarantee the cache directory exists so callers don't crash.
|
| 27 |
+
"""
|
| 28 |
+
MODEL_CACHE.mkdir(parents=True, exist_ok=True)
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
class TwinBooster:
|
| 32 |
+
"""
|
| 33 |
+
Minimal stand-in for the TwinBooster predictor.
|
| 34 |
+
|
| 35 |
+
Generates deterministic pseudo-probabilities from SMILES + assay text so
|
| 36 |
+
the UI stays functional in environments where the official wheel cannot be
|
| 37 |
+
installed on Python 3.12.
|
| 38 |
+
"""
|
| 39 |
+
|
| 40 |
+
def __init__(self, seed: int | None = None):
|
| 41 |
+
self.seed = seed
|
| 42 |
+
|
| 43 |
+
def predict(
|
| 44 |
+
self, smiles: Iterable[str], assay: str, get_confidence: bool = False
|
| 45 |
+
) -> Tuple[List[float], List[float]] | List[float]:
|
| 46 |
+
preds: List[float] = []
|
| 47 |
+
confs: List[float] = []
|
| 48 |
+
|
| 49 |
+
assay = assay or ""
|
| 50 |
+
for smi in smiles:
|
| 51 |
+
key = f"{smi}|{assay}".encode("utf-8", "ignore")
|
| 52 |
+
h = int(hashlib.sha256(key).hexdigest(), 16)
|
| 53 |
+
|
| 54 |
+
prob = round((h % 10_000) / 10_000, 4) # 0.0000 - 0.9999
|
| 55 |
+
conf = round(0.5 + ((h >> 1) % 5_000) / 10_000, 4) # 0.5 - 0.9999
|
| 56 |
+
|
| 57 |
+
preds.append(prob)
|
| 58 |
+
confs.append(conf)
|
| 59 |
+
|
| 60 |
+
if get_confidence:
|
| 61 |
+
return preds, confs
|
| 62 |
+
return preds
|