Spaces:
Running on Zero
title: Physh Classification
emoji: 🏆
colorFrom: red
colorTo: purple
sdk: gradio
sdk_version: 6.28.0
python_version: '3.12'
app_file: app.py
pinned: false
license: apache-2.0
models:
- LukeFP/physh_topic_supervised_classifier
- google/embeddinggemma-300m
PhySH Topic Classifier
Paste a physics title and abstract; get back its PhySH disciplines and top-level research-area concepts.
How it works
text ──EmbeddingGemma-300m──> 768-d vector
│
├──> discipline head 768 → 1024 → 512 → 18 sigmoid
│ │
└──> concept head [768 + 18] → 1024 → 512 → 186 sigmoid
▲
discipline probabilities
Both heads are multi-label MLPs with ReLU and dropout 0.3, trained on
EmbeddingGemma vectors. The concept head is conditioned on the discipline
head's output: its 786-dimensional input is the text embedding concatenated with
the 18 discipline probabilities (the checkpoint records use_logits: False, so
probabilities rather than logits are what it expects).
Weights live in
LukeFP/physh_topic_supervised_classifier
and are downloaded at startup, so retraining only requires a push to that repo —
no change here.
| Head | micro-F1 | macro-F1 | avg labels/sample |
|---|---|---|---|
| Discipline (18) | 0.799 | 0.683 | 1.41 |
| Concept (186) | 0.641 | 0.423 | 2.12 |
Setup
google/embeddinggemma-300m is a gated repo. Accept the Gemma license on the
model page, then add a read token as a Space secret named HF_TOKEN
(Settings → Variables and secrets). Without it the Space boots but the first
classification fails.
This Space runs on ZeroGPU: infer() carries the @spaces.GPU decorator,
the models are loaded on CPU in the main process, and device placement happens
inside the decorated function. The same code runs unchanged on CPU hardware —
spaces is optional at import and torch.cuda.is_available() picks the device.
Prompt format
EmbeddingGemma prepends a task-specific prefix, and the prefix used here must
match the one used to build the training embeddings — a mismatch degrades
accuracy quietly instead of erroring. The default is the document prompt
(title: none | text: …); the Advanced panel lets you switch and compare.
Running locally
pip install -r requirements.txt
export HF_TOKEN=hf_...
python app.py
Set PHYSH_WEIGHTS_DIR=/path/to/physh_topic_supervised_classifier to load the
.pt files from a local clone instead of the Hub.
API
Gradio exposes the Space as an API, which is the practical route for batch labelling:
from gradio_client import Client
client = Client("LukeFP/Physh_Classification")
disciplines, concepts, summary = client.predict(
"Title and abstract…", 0.5, "document — title: none | text: {}", 8,
api_name="/classify",
)