Spaces:
Running
Running
shourya commited on
Commit ·
62a67da
1
Parent(s): 7909984
Update app docs, setup scripts, and utils
Browse files- QUICK_SETUP.md +173 -0
- README.md +20 -0
- __pycache__/utils.cpython-312.pyc +0 -0
- scripts/USING_LOCAL_MODELS.md +224 -0
- scripts/config_local.py +77 -0
- scripts/download_lightweight_models.py +69 -0
- scripts/setup.sh +0 -0
- utils.py +71 -12
QUICK_SETUP.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ⚡ Quick Setup Checklist (10 min)
|
| 2 |
+
|
| 3 |
+
Complete these steps on your laptop to prepare for your Spaces demo.
|
| 4 |
+
|
| 5 |
+
## Step 1: Download Models Locally (**~5 min**)
|
| 6 |
+
|
| 7 |
+
```bash
|
| 8 |
+
cd /Users/shouryaangrish/Documents/Work/HugginFaceInfy/infy
|
| 9 |
+
python3 scripts/download_lightweight_models.py
|
| 10 |
+
```
|
| 11 |
+
|
| 12 |
+
**What it does:**
|
| 13 |
+
- Downloads DistilBERT sentiment model (~260 MB)
|
| 14 |
+
- Downloads BERT tokenizer (~440 MB)
|
| 15 |
+
- Saves to `models/` directory
|
| 16 |
+
- **Takes ~5 minutes depending on your internet**
|
| 17 |
+
|
| 18 |
+
**What to expect:**
|
| 19 |
+
```
|
| 20 |
+
Downloading sentiment model...
|
| 21 |
+
✓ Saved to models/sentiment/
|
| 22 |
+
✓ Model: 260 MB
|
| 23 |
+
✓ Tokenizer: 5 MB
|
| 24 |
+
Total: ~265 MB
|
| 25 |
+
|
| 26 |
+
Downloading tokenizer...
|
| 27 |
+
✓ Saved to models/tokenizer/
|
| 28 |
+
✓ Model: 440 MB
|
| 29 |
+
✓ Tokenizer: 3 MB
|
| 30 |
+
Total: ~443 MB
|
| 31 |
+
|
| 32 |
+
All models ready! ✅
|
| 33 |
+
```
|
| 34 |
+
|
| 35 |
+
---
|
| 36 |
+
|
| 37 |
+
## Step 2: Test Locally (**~2 min**)
|
| 38 |
+
|
| 39 |
+
```bash
|
| 40 |
+
python3 app.py
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
- App opens at `http://localhost:7860`
|
| 44 |
+
- Click **"Analyze Sentiment"** button
|
| 45 |
+
- ✅ Should be **instant** (models load from disk, not downloading)
|
| 46 |
+
- Try another demo if you want
|
| 47 |
+
- Press `Ctrl+C` to stop
|
| 48 |
+
|
| 49 |
+
---
|
| 50 |
+
|
| 51 |
+
## Step 3: Commit Models to Git (**~2 min**)
|
| 52 |
+
|
| 53 |
+
```bash
|
| 54 |
+
git add .gitignore models/
|
| 55 |
+
git commit -m "Add pre-cached models for offline demo"
|
| 56 |
+
git push origin main
|
| 57 |
+
```
|
| 58 |
+
|
| 59 |
+
**What happens:**
|
| 60 |
+
- Git LFS automatically handles large files (`.bin`, `.safetensors` tracked in `.gitattributes`)
|
| 61 |
+
- Only pointers stored in normal git, actual files in LFS
|
| 62 |
+
- Spaces auto-pulls everything on next deploy
|
| 63 |
+
- ✅ Models available even without network
|
| 64 |
+
|
| 65 |
+
**Expected output:**
|
| 66 |
+
```
|
| 67 |
+
[main abc1234] Add pre-cached models for offline demo
|
| 68 |
+
2 files changed, 50 insertions(+)
|
| 69 |
+
create mode .gitignore
|
| 70 |
+
create mode models/sentiment/...
|
| 71 |
+
create mode models/tokenizer/...
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
---
|
| 75 |
+
|
| 76 |
+
## Step 4: Verify Spaces Updated (**~1 min**)
|
| 77 |
+
|
| 78 |
+
1. Go to your Spaces URL (check Spaces dashboard)
|
| 79 |
+
2. Wait for rebuild (usually 1-2 min)
|
| 80 |
+
3. Click **"Analyze Sentiment"**
|
| 81 |
+
4. ✅ Should work instantly (models from local storage)
|
| 82 |
+
|
| 83 |
+
---
|
| 84 |
+
|
| 85 |
+
## Result: Fully Offline Demo ✅
|
| 86 |
+
|
| 87 |
+
Now your setup:
|
| 88 |
+
- ✅ Models available **without any network calls**
|
| 89 |
+
- ✅ Demos are **instant** (no download wait)
|
| 90 |
+
- ✅ Works even if HF is down
|
| 91 |
+
- ✅ Attendees clone repo and have models immediately
|
| 92 |
+
- ✅ Perfect for company network restrictions
|
| 93 |
+
|
| 94 |
+
---
|
| 95 |
+
|
| 96 |
+
## File Sizes Reference
|
| 97 |
+
|
| 98 |
+
| File | Size |
|
| 99 |
+
|------|------|
|
| 100 |
+
| DistilBERT model | 260 MB |
|
| 101 |
+
| BERT tokenizer | 440 MB |
|
| 102 |
+
| Config files | ~10 MB |
|
| 103 |
+
| **Total size** | **~710 MB** |
|
| 104 |
+
| Git repo (with LFS) | ~1 MB (pointers) + LFS storage |
|
| 105 |
+
|
| 106 |
+
The actual large files stay in Git LFS, keeping your repo fast for cloning.
|
| 107 |
+
|
| 108 |
+
---
|
| 109 |
+
|
| 110 |
+
## Troubleshooting
|
| 111 |
+
|
| 112 |
+
### Q: Download taking too long?
|
| 113 |
+
**A:** This is normal (5-10 min on typical internet). Models are large. Go grab coffee ☕
|
| 114 |
+
|
| 115 |
+
### Q: "Permission denied" on scripts?
|
| 116 |
+
**A:** Run:
|
| 117 |
+
```bash
|
| 118 |
+
chmod +x scripts/download_lightweight_models.py
|
| 119 |
+
python3 scripts/download_lightweight_models.py
|
| 120 |
+
```
|
| 121 |
+
|
| 122 |
+
### Q: Models directory doesn't exist after download?
|
| 123 |
+
**A:** Check for errors in output. Run again:
|
| 124 |
+
```bash
|
| 125 |
+
python3 scripts/download_lightweight_models.py
|
| 126 |
+
```
|
| 127 |
+
|
| 128 |
+
### Q: Git push fails with "too large"?
|
| 129 |
+
**A:** Git LFS handles this automatically. Just:
|
| 130 |
+
```bash
|
| 131 |
+
git push origin main --force-with-lease
|
| 132 |
+
```
|
| 133 |
+
|
| 134 |
+
### Q: Models still download during demo?
|
| 135 |
+
**A:** Models didn't transfer to Spaces. Check:
|
| 136 |
+
```bash
|
| 137 |
+
ls -la models/sentimen*/
|
| 138 |
+
ls -la models/tokenizer/
|
| 139 |
+
```
|
| 140 |
+
Should show `.bin` files. If empty, re-run Step 1.
|
| 141 |
+
|
| 142 |
+
---
|
| 143 |
+
|
| 144 |
+
## Timeline for Your Session
|
| 145 |
+
|
| 146 |
+
| When | Action | Time |
|
| 147 |
+
|------|--------|------|
|
| 148 |
+
| **Day before** | Run Steps 1-4 on laptop | 10 min |
|
| 149 |
+
| **30 min before session** | Verify Spaces is ready (load app once) | 1 min |
|
| 150 |
+
| **During session** | Run demo (instant loading guaranteed) | ✅ Works! |
|
| 151 |
+
| **After session** | Attendees can clone repo + models included | Automatic |
|
| 152 |
+
|
| 153 |
+
---
|
| 154 |
+
|
| 155 |
+
## You're Ready! 🚀
|
| 156 |
+
|
| 157 |
+
Once you complete Step 4, your demo is set up perfectly:
|
| 158 |
+
- No network dependencies ✅
|
| 159 |
+
- Instant model loading ✅
|
| 160 |
+
- Reproducible for attendees ✅
|
| 161 |
+
- Spaces auto-deploys everything ✅
|
| 162 |
+
|
| 163 |
+
**Questions?** Check [USING_LOCAL_MODELS.md](./USING_LOCAL_MODELS.md) for full details.
|
| 164 |
+
|
| 165 |
+
---
|
| 166 |
+
|
| 167 |
+
## One-Liner (If you want to do it all at once)
|
| 168 |
+
|
| 169 |
+
```bash
|
| 170 |
+
cd /Users/shouryaangrish/Documents/Work/HugginFaceInfy/infy && python3 scripts/download_lightweight_models.py && git add .gitignore models/ && git commit -m "Add pre-cached models" && git push origin main && echo "✅ All done! Check Spaces in ~2 min"
|
| 171 |
+
```
|
| 172 |
+
|
| 173 |
+
Done! ✨
|
README.md
CHANGED
|
@@ -29,6 +29,26 @@ The app is hosted on HuggingFace Spaces and requires **no local installation**.
|
|
| 29 |
- **Session 2: Hands-On Developer** — Tokenizer explorer + inference playground
|
| 30 |
- **Resources & Next Steps** — Documentation links and learning resources
|
| 31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
## 📚 Session Contents
|
| 33 |
|
| 34 |
### Session 1: Introduction to HuggingFace (45 minutes)
|
|
|
|
| 29 |
- **Session 2: Hands-On Developer** — Tokenizer explorer + inference playground
|
| 30 |
- **Resources & Next Steps** — Documentation links and learning resources
|
| 31 |
|
| 32 |
+
### 🎯 Pre-Session Setup (For Presenters)
|
| 33 |
+
|
| 34 |
+
**Want instant, offline demos with zero network dependencies?**
|
| 35 |
+
|
| 36 |
+
If you're presenting and need models pre-cached (e.g., company network restrictions), follow these guides:
|
| 37 |
+
|
| 38 |
+
- **[QUICK_SETUP.md](QUICK_SETUP.md)** — 10-minute setup (recommended for demos)
|
| 39 |
+
- Download models locally
|
| 40 |
+
- Test everything works
|
| 41 |
+
- Push to Spaces for instant loading
|
| 42 |
+
|
| 43 |
+
- **[scripts/USING_LOCAL_MODELS.md](scripts/USING_LOCAL_MODELS.md)** — Deep dive guide
|
| 44 |
+
- How local model caching works
|
| 45 |
+
- Git LFS for large files
|
| 46 |
+
- Troubleshooting
|
| 47 |
+
|
| 48 |
+
**TL;DR:** `python3 scripts/download_lightweight_models.py && git add models/ && git push origin main` ✅
|
| 49 |
+
|
| 50 |
+
This ensures models are available **without any external downloads during your session**.
|
| 51 |
+
|
| 52 |
## 📚 Session Contents
|
| 53 |
|
| 54 |
### Session 1: Introduction to HuggingFace (45 minutes)
|
__pycache__/utils.cpython-312.pyc
CHANGED
|
Binary files a/__pycache__/utils.cpython-312.pyc and b/__pycache__/utils.cpython-312.pyc differ
|
|
|
scripts/USING_LOCAL_MODELS.md
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Using Local Pre-Cached Models
|
| 2 |
+
|
| 3 |
+
## Option 1: Download Models & Commit to Git (RECOMMENDED for your setup)
|
| 4 |
+
|
| 5 |
+
This approach stores models **directly in the repo**, so they're always available without any network dependency.
|
| 6 |
+
|
| 7 |
+
### Step 1: Download Lightweight Models
|
| 8 |
+
|
| 9 |
+
```bash
|
| 10 |
+
python3 scripts/download_lightweight_models.py
|
| 11 |
+
```
|
| 12 |
+
|
| 13 |
+
This downloads smaller models (~500MB total) and saves them to `models/` directory.
|
| 14 |
+
|
| 15 |
+
### Step 2: Commit Models to Git
|
| 16 |
+
|
| 17 |
+
```bash
|
| 18 |
+
cd /Users/shouryaangrish/Documents/Work/HugginFaceInfy/infy
|
| 19 |
+
git add models/
|
| 20 |
+
git commit -m "Add pre-cached models for offline use"
|
| 21 |
+
git push origin main
|
| 22 |
+
```
|
| 23 |
+
|
| 24 |
+
### Step 3: Update App to Use Local Models
|
| 25 |
+
|
| 26 |
+
Option A - Modify your app to use local models:
|
| 27 |
+
```python
|
| 28 |
+
# In app.py, change:
|
| 29 |
+
import config
|
| 30 |
+
# To:
|
| 31 |
+
from scripts.config_local import SENTIMENT_MODEL, NER_MODEL, ...
|
| 32 |
+
```
|
| 33 |
+
|
| 34 |
+
Option B - Replace config.py entirely:
|
| 35 |
+
```bash
|
| 36 |
+
cp scripts/config_local.py config.py
|
| 37 |
+
git add config.py
|
| 38 |
+
git commit -m "Switch to local model loading"
|
| 39 |
+
git push origin main
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
### Step 4: Test Locally
|
| 43 |
+
|
| 44 |
+
```bash
|
| 45 |
+
python3 app.py
|
| 46 |
+
```
|
| 47 |
+
|
| 48 |
+
Then click buttons - models will load from `models/` directory (instant, no download!)
|
| 49 |
+
|
| 50 |
+
---
|
| 51 |
+
|
| 52 |
+
## Benefits of This Approach
|
| 53 |
+
|
| 54 |
+
✅ **No network dependency** — Models stored locally in repo
|
| 55 |
+
✅ **Bypasses HF whitelist** — Company firewall won't block
|
| 56 |
+
✅ **Instant loading** — Models already on disk
|
| 57 |
+
✅ **Consistent deployments** — Same models for everyone
|
| 58 |
+
✅ **Reproducible** — Models don't change versions
|
| 59 |
+
✅ **Works on Spaces** — If you push to Spaces, models go with it
|
| 60 |
+
|
| 61 |
+
---
|
| 62 |
+
|
| 63 |
+
## What Models Are Included
|
| 64 |
+
|
| 65 |
+
| Model | Size | Task |
|
| 66 |
+
|-------|------|------|
|
| 67 |
+
| DistilBERT (Sentiment) | ~260 MB | Sentiment Analysis |
|
| 68 |
+
| BERT (Tokenizer) | ~440 MB | Tokenization |
|
| 69 |
+
| **Total** | **~500-700 MB** | |
|
| 70 |
+
|
| 71 |
+
*Note: NER, QA, Summarization still download from HF (too large for repo), but can be added if needed*
|
| 72 |
+
|
| 73 |
+
---
|
| 74 |
+
|
| 75 |
+
## How It Works
|
| 76 |
+
|
| 77 |
+
When you load models:
|
| 78 |
+
|
| 79 |
+
```python
|
| 80 |
+
# config.py checks if local models exist
|
| 81 |
+
if Path("models/sentiment").exists():
|
| 82 |
+
SENTIMENT_MODEL = "models/sentiment/model" # Load locally
|
| 83 |
+
else:
|
| 84 |
+
SENTIMENT_MODEL = "distilbert-base-uncased-..." # Download from HF
|
| 85 |
+
```
|
| 86 |
+
|
| 87 |
+
So if models are in the repo, they load instantly. If not, they download from HF as fallback.
|
| 88 |
+
|
| 89 |
+
---
|
| 90 |
+
|
| 91 |
+
## Step-by-Step Setup
|
| 92 |
+
|
| 93 |
+
### For Your Laptop (Quick Demo Prep)
|
| 94 |
+
|
| 95 |
+
```bash
|
| 96 |
+
# 1. Download lightweight models (~500MB)
|
| 97 |
+
python3 scripts/download_lightweight_models.py
|
| 98 |
+
|
| 99 |
+
# 2. Test locally
|
| 100 |
+
python3 app.py
|
| 101 |
+
# Click "Analyze Sentiment" - should be instant (models loaded from "models/" dir)
|
| 102 |
+
|
| 103 |
+
# 3. Ready for demo!
|
| 104 |
+
```
|
| 105 |
+
|
| 106 |
+
### For Spaces Deployment
|
| 107 |
+
|
| 108 |
+
```bash
|
| 109 |
+
# 1. Models already in repo from above
|
| 110 |
+
# 2. Push to Spaces
|
| 111 |
+
git push origin main
|
| 112 |
+
|
| 113 |
+
# 3. Spaces auto-deploys with pre-cached models
|
| 114 |
+
# 🎉 Demos run instantly!
|
| 115 |
+
```
|
| 116 |
+
|
| 117 |
+
---
|
| 118 |
+
|
| 119 |
+
## File Structure After Setup
|
| 120 |
+
|
| 121 |
+
```
|
| 122 |
+
infy/
|
| 123 |
+
├── models/ ← Pre-downloaded models
|
| 124 |
+
│ ├── sentiment/
|
| 125 |
+
│ │ ├── model/ ← Model files
|
| 126 |
+
│ │ └── tokenizer/ ← Tokenizer files
|
| 127 |
+
│ └── tokenizer/
|
| 128 |
+
│ ├── model/
|
| 129 |
+
│ └── tokenizer/
|
| 130 |
+
├── app.py ← Uses local models
|
| 131 |
+
├── config.py ← Loads from "models/"
|
| 132 |
+
├── utils.py
|
| 133 |
+
├── requirements.txt
|
| 134 |
+
└── scripts/
|
| 135 |
+
├── download_lightweight_models.py
|
| 136 |
+
├── config_local.py
|
| 137 |
+
└── README.md
|
| 138 |
+
```
|
| 139 |
+
|
| 140 |
+
---
|
| 141 |
+
|
| 142 |
+
## Troubleshooting
|
| 143 |
+
|
| 144 |
+
### Models directory too large for git?
|
| 145 |
+
|
| 146 |
+
Git has limits on file size. If you exceed them:
|
| 147 |
+
|
| 148 |
+
```bash
|
| 149 |
+
# Install Git LFS (Large File Storage)
|
| 150 |
+
brew install git-lfs
|
| 151 |
+
git lfs install
|
| 152 |
+
|
| 153 |
+
# Then add models to LFS
|
| 154 |
+
git lfs track "models/**/*.bin"
|
| 155 |
+
git lfs track "models/**/*.safetensors"
|
| 156 |
+
git add .gitattributes models/
|
| 157 |
+
git commit -m "Use Git LFS for large model files"
|
| 158 |
+
git push origin main
|
| 159 |
+
```
|
| 160 |
+
|
| 161 |
+
Note: *Repo already has `.gitattributes` set up for this!*
|
| 162 |
+
|
| 163 |
+
### "Models still downloading during demo"?
|
| 164 |
+
|
| 165 |
+
- Make sure `python3 scripts/download_lightweight_models.py` completed
|
| 166 |
+
- Check `models/` directory exists: `ls -la models/`
|
| 167 |
+
- Verify config.py is using local paths
|
| 168 |
+
- Restart app: `python3 app.py`
|
| 169 |
+
|
| 170 |
+
### Want offline-only (no HF fallback)?
|
| 171 |
+
|
| 172 |
+
Edit `scripts/config_local.py`:
|
| 173 |
+
```python
|
| 174 |
+
# Change this (current):
|
| 175 |
+
NER_MODEL = "dslim/bert-base-uncased-finetuned-ner"
|
| 176 |
+
|
| 177 |
+
# To this (local only):
|
| 178 |
+
NER_MODEL = str(MODELS_DIR / "ner" / "model")
|
| 179 |
+
# Then download it: python3 scripts/download_lightweight_models.py
|
| 180 |
+
```
|
| 181 |
+
|
| 182 |
+
---
|
| 183 |
+
|
| 184 |
+
## Estimated File Sizes
|
| 185 |
+
|
| 186 |
+
| Component | Size |
|
| 187 |
+
|-----------|------|
|
| 188 |
+
| DistilBERT (sentiment) | ~260 MB |
|
| 189 |
+
| BERT base (tokenizer) | ~440 MB |
|
| 190 |
+
| Config/tokenizer files | ~5 MB |
|
| 191 |
+
| **Total for 2 models** | **~700 MB** |
|
| 192 |
+
| Git repo (with models) | ~750 MB |
|
| 193 |
+
|
| 194 |
+
Git can handle this fine. For many more models, use Git LFS (already configured in `.gitattributes`)
|
| 195 |
+
|
| 196 |
+
---
|
| 197 |
+
|
| 198 |
+
## Next Steps
|
| 199 |
+
|
| 200 |
+
1. **Run:** `python3 scripts/download_lightweight_models.py`
|
| 201 |
+
2. **Test:** `python3 app.py` → click a button → instant loading ✅
|
| 202 |
+
3. **Commit:** `git add models/` → `git push origin main`
|
| 203 |
+
4. **Demo:** Perfect for your session!
|
| 204 |
+
|
| 205 |
+
---
|
| 206 |
+
|
| 207 |
+
## Why This Solves Your Problem
|
| 208 |
+
|
| 209 |
+
| Issue | Solution |
|
| 210 |
+
|-------|----------|
|
| 211 |
+
| Company firewall blocks HF | ✅ Models stored locally, no external download |
|
| 212 |
+
| Slow network during demo | ✅ Instant loading from disk |
|
| 213 |
+
| Attendees can't download | ✅ Everything in repo, cloneable |
|
| 214 |
+
| Spaces issues | ✅ Models come with Spaces push |
|
| 215 |
+
| Repeatability | ✅ Same models for everyone |
|
| 216 |
+
|
| 217 |
+
---
|
| 218 |
+
|
| 219 |
+
**Ready?** Run this on your laptop now:
|
| 220 |
+
```bash
|
| 221 |
+
python3 scripts/download_lightweight_models.py
|
| 222 |
+
```
|
| 223 |
+
|
| 224 |
+
Then let me know what the size is and we can decide if we add more models! 🚀
|
scripts/config_local.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Updated config that loads models from local repo storage
|
| 4 |
+
Falls back to HF Hub if local models not available
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import os
|
| 8 |
+
from pathlib import Path
|
| 9 |
+
|
| 10 |
+
# Models directory in repo
|
| 11 |
+
MODELS_DIR = Path(__file__).parent.parent / "models"
|
| 12 |
+
|
| 13 |
+
# Try to use local models first, fallback to HF Hub IDs
|
| 14 |
+
LOCAL_MODELS_AVAILABLE = MODELS_DIR.exists()
|
| 15 |
+
|
| 16 |
+
if LOCAL_MODELS_AVAILABLE:
|
| 17 |
+
print(f"📁 Loading models from local repo: {MODELS_DIR}")
|
| 18 |
+
# Use local paths
|
| 19 |
+
SENTIMENT_MODEL = str(MODELS_DIR / "sentiment" / "model")
|
| 20 |
+
SENTIMENT_TOKENIZER = str(MODELS_DIR / "sentiment" / "tokenizer")
|
| 21 |
+
NER_MODEL = "dslim/bert-base-uncased-finetuned-ner" # Can add locally if needed
|
| 22 |
+
QA_MODEL = "deepset/roberta-base-squad2" # Can add locally if needed
|
| 23 |
+
SUMMARIZATION_MODEL = "facebook/bart-large-cnn" # Too large for repo
|
| 24 |
+
EMBEDDINGS_MODEL = "sentence-transformers/all-MiniLM-L6-v2" # Can add locally if needed
|
| 25 |
+
else:
|
| 26 |
+
print("🌐 Local models not found, using HF Hub (will download on first use)")
|
| 27 |
+
# Fall back to HF Hub
|
| 28 |
+
SENTIMENT_MODEL = "distilbert-base-uncased-finetuned-sst-2-english"
|
| 29 |
+
SENTIMENT_TOKENIZER = "bert-base-uncased"
|
| 30 |
+
NER_MODEL = "dslim/bert-base-uncased-finetuned-ner"
|
| 31 |
+
QA_MODEL = "deepset/roberta-base-squad2"
|
| 32 |
+
SUMMARIZATION_MODEL = "facebook/bart-large-cnn"
|
| 33 |
+
EMBEDDINGS_MODEL = "sentence-transformers/all-MiniLM-L6-v2"
|
| 34 |
+
|
| 35 |
+
# Task definitions
|
| 36 |
+
TASKS = {
|
| 37 |
+
"sentiment": {
|
| 38 |
+
"name": "Sentiment Analysis",
|
| 39 |
+
"description": "Classify text sentiment (positive/negative/neutral)",
|
| 40 |
+
"model": SENTIMENT_MODEL,
|
| 41 |
+
"example": "I absolutely love this product! It's amazing and works perfectly.",
|
| 42 |
+
},
|
| 43 |
+
"ner": {
|
| 44 |
+
"name": "Named Entity Recognition",
|
| 45 |
+
"description": "Identify and classify named entities (Person, Location, Organization)",
|
| 46 |
+
"model": NER_MODEL,
|
| 47 |
+
"example": "Apple Inc. was founded by Steve Jobs in Cupertino, California.",
|
| 48 |
+
},
|
| 49 |
+
"qa": {
|
| 50 |
+
"name": "Question Answering",
|
| 51 |
+
"description": "Answer questions based on provided context",
|
| 52 |
+
"model": QA_MODEL,
|
| 53 |
+
"example_context": "The Hugging Face Hub is a platform for sharing machine learning models, datasets, and demos.",
|
| 54 |
+
"example_question": "What is the Hugging Face Hub?",
|
| 55 |
+
},
|
| 56 |
+
"summarization": {
|
| 57 |
+
"name": "Text Summarization",
|
| 58 |
+
"description": "Generate concise summaries of longer texts",
|
| 59 |
+
"model": SUMMARIZATION_MODEL,
|
| 60 |
+
"example": "The Hugging Face transformers library provides state-of-the-art pre-trained models for natural language processing tasks. It supports PyTorch and TensorFlow, making it easy to use with either framework.",
|
| 61 |
+
},
|
| 62 |
+
"similarity": {
|
| 63 |
+
"name": "Semantic Similarity",
|
| 64 |
+
"description": "Compare semantic similarity between two sentences",
|
| 65 |
+
"model": EMBEDDINGS_MODEL,
|
| 66 |
+
"example1": "The cat is sleeping on the mat",
|
| 67 |
+
"example2": "A feline is resting on the rug",
|
| 68 |
+
},
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
# Sample data paths
|
| 72 |
+
SAMPLE_DATA_CSV = "data/sample_texts.csv"
|
| 73 |
+
DEMO_SAMPLES_DIR = "data/demo_samples"
|
| 74 |
+
|
| 75 |
+
# Session timings
|
| 76 |
+
SESSION1_DURATION = 45 # minutes
|
| 77 |
+
SESSION2_DURATION = 90 # minutes
|
scripts/download_lightweight_models.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
Download lightweight/quantized models and save locally for git commit
|
| 4 |
+
Models will be stored in repo, no network needed during demos
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import os
|
| 8 |
+
import sys
|
| 9 |
+
from pathlib import Path
|
| 10 |
+
from transformers import AutoTokenizer, AutoModel, AutoModelForSequenceClassification
|
| 11 |
+
import shutil
|
| 12 |
+
|
| 13 |
+
print("=" * 70)
|
| 14 |
+
print("🤗 Downloading Lightweight Models for Local Storage")
|
| 15 |
+
print("=" * 70)
|
| 16 |
+
|
| 17 |
+
# Create models directory
|
| 18 |
+
MODELS_DIR = Path("models")
|
| 19 |
+
MODELS_DIR.mkdir(exist_ok=True)
|
| 20 |
+
|
| 21 |
+
# Use smaller/quantized models
|
| 22 |
+
MODELS = {
|
| 23 |
+
"sentiment": {
|
| 24 |
+
"model_id": "distilbert-base-uncased-finetuned-sst-2-english",
|
| 25 |
+
"desc": "Sentiment Analysis (DistilBERT - small & fast)"
|
| 26 |
+
},
|
| 27 |
+
"tokenizer": {
|
| 28 |
+
"model_id": "bert-base-uncased",
|
| 29 |
+
"desc": "Tokenizer (BERT base)"
|
| 30 |
+
},
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
print(f"\n📁 Saving models to: {MODELS_DIR.absolute()}\n")
|
| 34 |
+
|
| 35 |
+
for name, config in MODELS.items():
|
| 36 |
+
model_id = config["model_id"]
|
| 37 |
+
desc = config["desc"]
|
| 38 |
+
|
| 39 |
+
try:
|
| 40 |
+
print(f"⏳ Downloading {desc}...")
|
| 41 |
+
model_path = MODELS_DIR / name
|
| 42 |
+
|
| 43 |
+
# Download and save locally
|
| 44 |
+
tokenizer = AutoTokenizer.from_pretrained(model_id)
|
| 45 |
+
model = AutoModelForSequenceClassification.from_pretrained(model_id)
|
| 46 |
+
|
| 47 |
+
# Save to local directory
|
| 48 |
+
tokenizer.save_pretrained(model_path / "tokenizer")
|
| 49 |
+
model.save_pretrained(model_path / "model")
|
| 50 |
+
|
| 51 |
+
# Calculate size
|
| 52 |
+
size_mb = sum(f.stat().st_size for f in model_path.rglob("*")) / (1024 * 1024)
|
| 53 |
+
print(f"✅ {desc}: {size_mb:.1f} MB\n")
|
| 54 |
+
|
| 55 |
+
except Exception as e:
|
| 56 |
+
print(f"❌ Error downloading {name}: {str(e)}\n")
|
| 57 |
+
|
| 58 |
+
print("=" * 70)
|
| 59 |
+
print("✅ Models downloaded!")
|
| 60 |
+
print("=" * 70)
|
| 61 |
+
|
| 62 |
+
# Calculate total size
|
| 63 |
+
total_size = sum(f.stat().st_size for f in MODELS_DIR.rglob("*")) / (1024 * 1024)
|
| 64 |
+
print(f"\n📊 Total size: {total_size:.1f} MB")
|
| 65 |
+
print(f"📁 Location: {MODELS_DIR.absolute()}")
|
| 66 |
+
print(f"\n💡 Next: Commit these models to git")
|
| 67 |
+
print(f" git add models/")
|
| 68 |
+
print(f" git commit -m 'Add pre-downloaded models for offline use'")
|
| 69 |
+
print(f" git push origin main")
|
scripts/setup.sh
CHANGED
|
File without changes
|
utils.py
CHANGED
|
@@ -2,13 +2,23 @@
|
|
| 2 |
Utility functions for HuggingFace Enabling Sessions Spaces app
|
| 3 |
"""
|
| 4 |
import torch
|
| 5 |
-
from transformers import
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
import numpy as np
|
| 7 |
from functools import lru_cache
|
| 8 |
import config
|
| 9 |
|
| 10 |
# Lazy loading for heavy dependencies
|
| 11 |
_sbert_model = None
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
|
| 13 |
|
| 14 |
def get_sbert_model():
|
|
@@ -29,16 +39,35 @@ def load_pipeline(task_type: str):
|
|
| 29 |
return pipeline("sentiment-analysis", model=config.SENTIMENT_MODEL, device=device)
|
| 30 |
elif task_type == "ner":
|
| 31 |
return pipeline("ner", model=config.NER_MODEL, device=device, aggregation_strategy="simple")
|
| 32 |
-
elif task_type == "qa":
|
| 33 |
-
return pipeline("question-answering", model=config.QA_MODEL, device=device)
|
| 34 |
elif task_type == "summarization":
|
| 35 |
-
|
|
|
|
| 36 |
else:
|
| 37 |
raise ValueError(f"Unknown task type: {task_type}")
|
| 38 |
except Exception as e:
|
| 39 |
raise Exception(f"Error loading {task_type} pipeline: {str(e)}")
|
| 40 |
|
| 41 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
def run_sentiment_analysis(text: str):
|
| 43 |
"""Run sentiment analysis on text."""
|
| 44 |
pipe = load_pipeline("sentiment")
|
|
@@ -54,21 +83,51 @@ def run_ner(text: str):
|
|
| 54 |
|
| 55 |
|
| 56 |
def run_qa(context: str, question: str):
|
| 57 |
-
"""Run question answering on context."""
|
| 58 |
-
pipe = load_pipeline("qa")
|
| 59 |
try:
|
| 60 |
-
|
| 61 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
except Exception as e:
|
| 63 |
return {"error": str(e), "answer": "Unable to answer", "score": 0}
|
| 64 |
|
| 65 |
|
| 66 |
def run_summarization(text: str):
|
| 67 |
-
"""Generate summary of text."""
|
| 68 |
-
pipe = load_pipeline("summarization")
|
| 69 |
try:
|
| 70 |
-
|
| 71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
except Exception as e:
|
| 73 |
return f"Error: {str(e)}"
|
| 74 |
|
|
|
|
| 2 |
Utility functions for HuggingFace Enabling Sessions Spaces app
|
| 3 |
"""
|
| 4 |
import torch
|
| 5 |
+
from transformers import (
|
| 6 |
+
pipeline,
|
| 7 |
+
AutoTokenizer,
|
| 8 |
+
AutoModelForSequenceClassification,
|
| 9 |
+
AutoModelForQuestionAnswering,
|
| 10 |
+
AutoModelForSeq2SeqLM
|
| 11 |
+
)
|
| 12 |
import numpy as np
|
| 13 |
from functools import lru_cache
|
| 14 |
import config
|
| 15 |
|
| 16 |
# Lazy loading for heavy dependencies
|
| 17 |
_sbert_model = None
|
| 18 |
+
_qa_model = None
|
| 19 |
+
_qa_tokenizer = None
|
| 20 |
+
_summarization_model = None
|
| 21 |
+
_summarization_tokenizer = None
|
| 22 |
|
| 23 |
|
| 24 |
def get_sbert_model():
|
|
|
|
| 39 |
return pipeline("sentiment-analysis", model=config.SENTIMENT_MODEL, device=device)
|
| 40 |
elif task_type == "ner":
|
| 41 |
return pipeline("ner", model=config.NER_MODEL, device=device, aggregation_strategy="simple")
|
|
|
|
|
|
|
| 42 |
elif task_type == "summarization":
|
| 43 |
+
# `summarization` alias is not present in some transformers builds.
|
| 44 |
+
return pipeline("text2text-generation", model=config.SUMMARIZATION_MODEL, device=device)
|
| 45 |
else:
|
| 46 |
raise ValueError(f"Unknown task type: {task_type}")
|
| 47 |
except Exception as e:
|
| 48 |
raise Exception(f"Error loading {task_type} pipeline: {str(e)}")
|
| 49 |
|
| 50 |
|
| 51 |
+
def get_qa_model():
|
| 52 |
+
"""Lazy load QA model and tokenizer."""
|
| 53 |
+
global _qa_model, _qa_tokenizer
|
| 54 |
+
if _qa_model is None:
|
| 55 |
+
_qa_tokenizer = AutoTokenizer.from_pretrained(config.QA_MODEL)
|
| 56 |
+
_qa_model = AutoModelForQuestionAnswering.from_pretrained(config.QA_MODEL)
|
| 57 |
+
_qa_model.eval()
|
| 58 |
+
return _qa_model, _qa_tokenizer
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def get_summarization_model():
|
| 62 |
+
"""Lazy load Summarization model and tokenizer."""
|
| 63 |
+
global _summarization_model, _summarization_tokenizer
|
| 64 |
+
if _summarization_model is None:
|
| 65 |
+
_summarization_tokenizer = AutoTokenizer.from_pretrained(config.SUMMARIZATION_MODEL)
|
| 66 |
+
_summarization_model = AutoModelForSeq2SeqLM.from_pretrained(config.SUMMARIZATION_MODEL)
|
| 67 |
+
_summarization_model.eval()
|
| 68 |
+
return _summarization_model, _summarization_tokenizer
|
| 69 |
+
|
| 70 |
+
|
| 71 |
def run_sentiment_analysis(text: str):
|
| 72 |
"""Run sentiment analysis on text."""
|
| 73 |
pipe = load_pipeline("sentiment")
|
|
|
|
| 83 |
|
| 84 |
|
| 85 |
def run_qa(context: str, question: str):
|
| 86 |
+
"""Run question answering on context using direct model inference."""
|
|
|
|
| 87 |
try:
|
| 88 |
+
model, tokenizer = get_qa_model()
|
| 89 |
+
inputs = tokenizer(question, context, return_tensors="pt", truncation=True, max_length=512)
|
| 90 |
+
|
| 91 |
+
with torch.no_grad():
|
| 92 |
+
outputs = model(**inputs)
|
| 93 |
+
|
| 94 |
+
answer_start_idx = outputs.start_logits.argmax(dim=1).item()
|
| 95 |
+
answer_end_idx = outputs.end_logits.argmax(dim=1).item() + 1
|
| 96 |
+
|
| 97 |
+
answer = tokenizer.convert_tokens_to_string(
|
| 98 |
+
tokenizer.convert_ids_to_tokens(inputs["input_ids"][0][answer_start_idx:answer_end_idx])
|
| 99 |
+
)
|
| 100 |
+
|
| 101 |
+
score = (outputs.start_logits.max().item() + outputs.end_logits.max().item()) / 2
|
| 102 |
+
|
| 103 |
+
return {
|
| 104 |
+
"answer": answer.strip(),
|
| 105 |
+
"score": float(score),
|
| 106 |
+
"start": int(answer_start_idx),
|
| 107 |
+
"end": int(answer_end_idx)
|
| 108 |
+
}
|
| 109 |
except Exception as e:
|
| 110 |
return {"error": str(e), "answer": "Unable to answer", "score": 0}
|
| 111 |
|
| 112 |
|
| 113 |
def run_summarization(text: str):
|
| 114 |
+
"""Generate summary of text using direct model inference."""
|
|
|
|
| 115 |
try:
|
| 116 |
+
model, tokenizer = get_summarization_model()
|
| 117 |
+
inputs = tokenizer(text[:1024], return_tensors="pt", max_length=1024, truncation=True)
|
| 118 |
+
|
| 119 |
+
with torch.no_grad():
|
| 120 |
+
summary_ids = model.generate(
|
| 121 |
+
inputs["input_ids"],
|
| 122 |
+
max_length=150,
|
| 123 |
+
min_length=30,
|
| 124 |
+
num_beams=4,
|
| 125 |
+
length_penalty=2.0,
|
| 126 |
+
early_stopping=True
|
| 127 |
+
)
|
| 128 |
+
|
| 129 |
+
summary = tokenizer.batch_decode(summary_ids, skip_special_tokens=True)[0]
|
| 130 |
+
return summary.strip()
|
| 131 |
except Exception as e:
|
| 132 |
return f"Error: {str(e)}"
|
| 133 |
|