Spaces:
Sleeping
Sleeping
Commit ·
0cc2bd2
1
Parent(s): 3480927
Fix deployment: add startup script, env config, routing fixes, and reorganize classifier service
Browse files- DEPLOYMENT.md +110 -0
- Dockerfile +11 -3
- README.md +8 -87
- bacterial-classifier/api.py +0 -80
- {bacterial-classifier → classifier_service}/.gitignore +0 -0
- {bacterial-classifier → classifier_service}/README.txt +0 -0
- classifier_service/api.py +6 -4
- {bacterial-classifier → classifier_service}/app.py +0 -0
- {bacterial-classifier → classifier_service}/requirements.txt +0 -0
- {bacterial-classifier → classifier_service}/run_backend.ps1 +0 -0
- push2.txt +12 -0
- push_final.txt +14 -0
- push_log.txt +12 -0
- requirements.txt +4 -4
- start.sh +15 -0
- upload_to_hf.py +43 -0
DEPLOYMENT.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 🦠 BacSense v2 - Hugging Face Deployment Guide
|
| 2 |
+
|
| 3 |
+
## Current Status
|
| 4 |
+
- **Frontend**: Deployed on Vercel ✅
|
| 5 |
+
- **Backend**: Deployed on Hugging Face Spaces (Docker) ⚠️
|
| 6 |
+
|
| 7 |
+
## Issue Diagnosis
|
| 8 |
+
|
| 9 |
+
The "Not Found" error on Hugging Face typically means:
|
| 10 |
+
1. The server isn't starting properly
|
| 11 |
+
2. The port configuration is incorrect
|
| 12 |
+
3. Model files aren't being found during initialization
|
| 13 |
+
|
| 14 |
+
## Solution Implemented
|
| 15 |
+
|
| 16 |
+
### 1. Updated Dockerfile
|
| 17 |
+
- Added better debugging with startup script
|
| 18 |
+
- Configured proper environment variables for Hugging Face
|
| 19 |
+
- Added curl for health checks
|
| 20 |
+
|
| 21 |
+
### 2. Added Startup Script (`start.sh`)
|
| 22 |
+
- Shows directory contents on startup
|
| 23 |
+
- Verifies model files are present
|
| 24 |
+
- Starts uvicorn server with proper configuration
|
| 25 |
+
|
| 26 |
+
### 3. API Configuration
|
| 27 |
+
- Root endpoint (`/`) now shows a welcome page
|
| 28 |
+
- Health check available at `/health`
|
| 29 |
+
- Debug endpoint at `/debug_model` to diagnose issues
|
| 30 |
+
- API documentation at `/docs`
|
| 31 |
+
|
| 32 |
+
## How to Deploy
|
| 33 |
+
|
| 34 |
+
### Step 1: Push to Hugging Face
|
| 35 |
+
```bash
|
| 36 |
+
cd "e:\1-Antigravity Python\Bacsense 2.0\BacSense-API"
|
| 37 |
+
git add .
|
| 38 |
+
git commit -m "Fix deployment: add startup script and debugging"
|
| 39 |
+
git push origin main
|
| 40 |
+
```
|
| 41 |
+
|
| 42 |
+
### Step 2: Check Deployment Logs
|
| 43 |
+
1. Go to your Hugging Face Space: https://huggingface.co/spaces/joytheslothh/BacSense-API
|
| 44 |
+
2. Click on "Logs" tab
|
| 45 |
+
3. Watch the startup logs to see if:
|
| 46 |
+
- All dependencies install successfully
|
| 47 |
+
- Model files are found
|
| 48 |
+
- Server starts on port 7860
|
| 49 |
+
|
| 50 |
+
### Step 3: Test Endpoints
|
| 51 |
+
Once deployed, test these endpoints:
|
| 52 |
+
|
| 53 |
+
**Health Check:**
|
| 54 |
+
```
|
| 55 |
+
https://joytheslothh-bacsense-api.hf.space/health
|
| 56 |
+
```
|
| 57 |
+
|
| 58 |
+
**API Documentation:**
|
| 59 |
+
```
|
| 60 |
+
https://joytheslothh-bacsense-api.hf.space/docs
|
| 61 |
+
```
|
| 62 |
+
|
| 63 |
+
**Debug Model:**
|
| 64 |
+
```
|
| 65 |
+
https://joytheslothh-bacsense-api.hf.space/debug_model
|
| 66 |
+
```
|
| 67 |
+
|
| 68 |
+
## Frontend Configuration (Vercel)
|
| 69 |
+
|
| 70 |
+
Update your frontend API URL in Vercel to point to:
|
| 71 |
+
```
|
| 72 |
+
https://joytheslothh-bacsense-api.hf.space
|
| 73 |
+
```
|
| 74 |
+
|
| 75 |
+
Or in your frontend code, update the API base URL:
|
| 76 |
+
```typescript
|
| 77 |
+
// In your React code
|
| 78 |
+
const API_URL = "https://joytheslothh-bacsense-api.hf.space";
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
## Troubleshooting
|
| 82 |
+
|
| 83 |
+
### If you still see "Not Found":
|
| 84 |
+
|
| 85 |
+
1. **Check the logs** - Look for import errors or missing files
|
| 86 |
+
2. **Verify model loading** - Visit `/debug_model` endpoint
|
| 87 |
+
3. **Test locally** - Run `docker build -t bacsense .` and `docker run -p 7860:7860 bacsense`
|
| 88 |
+
|
| 89 |
+
### Common Issues:
|
| 90 |
+
|
| 91 |
+
**TensorFlow Import Error:**
|
| 92 |
+
- Ensure all requirements are installed
|
| 93 |
+
- Check if TensorFlow CPU version is compatible
|
| 94 |
+
|
| 95 |
+
**Model Files Not Found:**
|
| 96 |
+
- Verify `bacsense_v2_package` folder exists in the repo
|
| 97 |
+
- Check that `.keras` and `.pkl` files are tracked by Git LFS
|
| 98 |
+
|
| 99 |
+
**Port Binding Issue:**
|
| 100 |
+
- Hugging Face expects port 7860
|
| 101 |
+
- Server must bind to `0.0.0.0` not `localhost`
|
| 102 |
+
|
| 103 |
+
## Alternative: Streamlit-Only Deployment
|
| 104 |
+
|
| 105 |
+
If FastAPI continues to have issues, you can deploy as a pure Streamlit app:
|
| 106 |
+
|
| 107 |
+
1. Rename `app.py` to `streamlit_app.py`
|
| 108 |
+
2. Update Dockerfile CMD to: `CMD ["streamlit", "run", "streamlit_app.py"]`
|
| 109 |
+
|
| 110 |
+
This gives you the dashboard without the separate API backend.
|
Dockerfile
CHANGED
|
@@ -7,6 +7,7 @@ RUN apt-get update && apt-get install -y \
|
|
| 7 |
libsm6 \
|
| 8 |
libxrender1 \
|
| 9 |
libxext6 \
|
|
|
|
| 10 |
&& rm -rf /var/lib/apt/lists/*
|
| 11 |
|
| 12 |
# Set up user
|
|
@@ -23,8 +24,15 @@ RUN pip install --no-cache-dir -r requirements.txt
|
|
| 23 |
# Copy source code
|
| 24 |
COPY --chown=user . .
|
| 25 |
|
| 26 |
-
# Hugging Face
|
| 27 |
EXPOSE 7860
|
| 28 |
|
| 29 |
-
#
|
| 30 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
libsm6 \
|
| 8 |
libxrender1 \
|
| 9 |
libxext6 \
|
| 10 |
+
curl \
|
| 11 |
&& rm -rf /var/lib/apt/lists/*
|
| 12 |
|
| 13 |
# Set up user
|
|
|
|
| 24 |
# Copy source code
|
| 25 |
COPY --chown=user . .
|
| 26 |
|
| 27 |
+
# Hugging Face Spaces typically expects port 7860
|
| 28 |
EXPOSE 7860
|
| 29 |
|
| 30 |
+
# Environment variable for Hugging Face
|
| 31 |
+
ENV GRADIO_SERVER_NAME="0.0.0.0"
|
| 32 |
+
ENV GRADIO_SERVER_PORT="7860"
|
| 33 |
+
|
| 34 |
+
# Make startup script executable
|
| 35 |
+
RUN chmod +x start.sh
|
| 36 |
+
|
| 37 |
+
# Run the startup script for better debugging
|
| 38 |
+
CMD ["./start.sh"]
|
README.md
CHANGED
|
@@ -1,90 +1,11 @@
|
|
| 1 |
-
|
| 2 |
-
title: BacSense API
|
| 3 |
emoji: 🦠
|
| 4 |
colorFrom: blue
|
| 5 |
-
colorTo:
|
| 6 |
-
sdk:
|
| 7 |
-
sdk_version: "1.32.0"
|
| 8 |
-
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
**Bacsense 2.0** is an open-access visual platform for clinical microbiology research. Our mission is to accelerate pathogen identification through advanced hybrid neural networks and machine learning.
|
| 17 |
-
|
| 18 |
-
This project integrates a robust **VGG16 + SVM** hybrid classification architecture with a modern, high-performance web interface to quickly and accurately identify microscopic bacterial species from uploaded culture images.
|
| 19 |
-
|
| 20 |
-
## ✨ Key Features
|
| 21 |
-
|
| 22 |
-
- **🔬 High-Accuracy Classification:** Leverages a pre-trained VGG16 backbone for deep feature extraction, paired with a Support Vector Machine (SVM) classifier for pinpoint taxa identification.
|
| 23 |
-
- **⚡ Real-time API:** Fast and lightweight inference backend powered by FastAPI.
|
| 24 |
-
- **🌌 Premium Scientific UI:** A stunning, fully responsive dark-theme design featuring highly interactive GSAP spring cursors, meteor shower effects, and beautifully animated petri-dish data components.
|
| 25 |
-
- **📊 Detailed Analysis Metrics:** Get immediate clinical insights on morphological traits, probability distribution thresholds, and gram stains for tested pathogens natively in the browser.
|
| 26 |
-
|
| 27 |
-
## 🛠️ Tech Stack
|
| 28 |
-
|
| 29 |
-
### Frontend
|
| 30 |
-
- **Framework:** React + Vite (TypeScript)
|
| 31 |
-
- **Styling:** Tailwind CSS
|
| 32 |
-
- **Animations:** GSAP (GreenSock) & Framer Motion
|
| 33 |
-
- **UI Architecture:** MagicUI
|
| 34 |
-
|
| 35 |
-
### Backend / ML Engine
|
| 36 |
-
- **REST API Runtime:** FastAPI & Uvicorn
|
| 37 |
-
- **Machine Learning Pipelines:** TensorFlow / Keras (VGG16), Scikit-Learn (SVM, PCA)
|
| 38 |
-
- **Image Processing Computation:** Pillow (PIL), NumPy, SciPy
|
| 39 |
-
|
| 40 |
-
---
|
| 41 |
-
|
| 42 |
-
## 🚀 Getting Started
|
| 43 |
-
|
| 44 |
-
### Prerequisites
|
| 45 |
-
- [Node.js](https://nodejs.org/) (v16+)
|
| 46 |
-
- [Python](https://python.org/) (3.9+)
|
| 47 |
-
|
| 48 |
-
### 1. Boot the ML Backend
|
| 49 |
-
|
| 50 |
-
Open a terminal in the project root and navigate to the backend service to spin up the prediction API:
|
| 51 |
-
|
| 52 |
-
```bash
|
| 53 |
-
cd bacterial-classifier
|
| 54 |
-
python -m venv venv
|
| 55 |
-
|
| 56 |
-
# Windows Activation
|
| 57 |
-
venv\Scripts\activate
|
| 58 |
-
# Mac/Linux Activation
|
| 59 |
-
# source venv/bin/activate
|
| 60 |
-
|
| 61 |
-
pip install -r requirements.txt
|
| 62 |
-
pip install fastapi uvicorn python-multipart
|
| 63 |
-
|
| 64 |
-
# Start the FastAPI uvicorn server
|
| 65 |
-
uvicorn api:app --host 0.0.0.0 --port 5000 --reload
|
| 66 |
-
```
|
| 67 |
-
The ML API will successfully bind to `http://localhost:5000`.
|
| 68 |
-
|
| 69 |
-
### 2. Start the React Frontend
|
| 70 |
-
|
| 71 |
-
Open a new terminal tab, navigate to the frontend folder, install dependencies, and launch the Vite dev server:
|
| 72 |
-
|
| 73 |
-
```bash
|
| 74 |
-
cd frontend
|
| 75 |
-
npm install
|
| 76 |
-
npm run dev
|
| 77 |
-
```
|
| 78 |
-
|
| 79 |
-
The user interface will be live at `http://localhost:5173`. 🥳 Drag and drop a microscopic image into the Upload Zone to test the prediction model!
|
| 80 |
-
|
| 81 |
-
## 🔬 Supported Species
|
| 82 |
-
The engine spans multiple common pathogenic datasets and correctly identifies critical bacteria including:
|
| 83 |
-
- *Escherichia coli* (Gram-negative)
|
| 84 |
-
- *Staphylococcus aureus* (Gram-positive)
|
| 85 |
-
- *Clostridium perfringens* (Anaerobic)
|
| 86 |
-
- *Bacillus cereus* (Spore-forming)
|
| 87 |
-
- *Listeria monocytogenes*
|
| 88 |
-
|
| 89 |
-
---
|
| 90 |
-
*© 2026 Bacsense Scientific Systems. Built for Next-Gen Bioinformatics.*
|
|
|
|
| 1 |
+
title: BacSense v2 API
|
|
|
|
| 2 |
emoji: 🦠
|
| 3 |
colorFrom: blue
|
| 4 |
+
colorTo: purple
|
| 5 |
+
sdk: docker
|
|
|
|
|
|
|
| 6 |
pinned: false
|
| 7 |
+
license: mit
|
| 8 |
+
tags:
|
| 9 |
+
- water-quality
|
| 10 |
+
- bacteria-classification
|
| 11 |
+
- machine-learning
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bacterial-classifier/api.py
DELETED
|
@@ -1,80 +0,0 @@
|
|
| 1 |
-
import io
|
| 2 |
-
import os
|
| 3 |
-
import sys
|
| 4 |
-
import tempfile
|
| 5 |
-
from typing import List
|
| 6 |
-
from fastapi import FastAPI, UploadFile, File, HTTPException
|
| 7 |
-
from fastapi.middleware.cors import CORSMiddleware
|
| 8 |
-
|
| 9 |
-
# Add the parent directory to sys.path to import bacsense_v2_package
|
| 10 |
-
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
| 11 |
-
from bacsense_v2_package.inference import BacSense
|
| 12 |
-
|
| 13 |
-
app = FastAPI(title="Bacsense 2.0 API")
|
| 14 |
-
|
| 15 |
-
# Setup CORS to allow requests from the React frontend
|
| 16 |
-
app.add_middleware(
|
| 17 |
-
CORSMiddleware,
|
| 18 |
-
allow_origins=["*"], # Adjust this in production, e.g., ["http://localhost:5173"]
|
| 19 |
-
allow_credentials=True,
|
| 20 |
-
allow_methods=["*"],
|
| 21 |
-
allow_headers=["*"],
|
| 22 |
-
)
|
| 23 |
-
|
| 24 |
-
# Load the model upon startup
|
| 25 |
-
# The model files are located in the bacsense_v2_package directory
|
| 26 |
-
model_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', 'bacsense_v2_package'))
|
| 27 |
-
classifier = BacSense(model_dir=model_dir)
|
| 28 |
-
classifier.warmup()
|
| 29 |
-
|
| 30 |
-
@app.post("/predict_batch")
|
| 31 |
-
async def predict_batch(files: List[UploadFile] = File(...)):
|
| 32 |
-
if not files or len(files) == 0:
|
| 33 |
-
raise HTTPException(status_code=400, detail="No files uploaded")
|
| 34 |
-
|
| 35 |
-
results = []
|
| 36 |
-
|
| 37 |
-
for file in files:
|
| 38 |
-
temp_path = None
|
| 39 |
-
try:
|
| 40 |
-
# Read the uploaded file into an IO stream
|
| 41 |
-
contents = await file.read()
|
| 42 |
-
|
| 43 |
-
# BacSense uses cv2.imread and PIL.Image.open with a file path, so we save it to disk temporarily
|
| 44 |
-
fd, temp_path = tempfile.mkstemp(suffix=".png")
|
| 45 |
-
with os.fdopen(fd, 'wb') as f:
|
| 46 |
-
f.write(contents)
|
| 47 |
-
|
| 48 |
-
# Process the image
|
| 49 |
-
result = classifier.predict(temp_path)
|
| 50 |
-
|
| 51 |
-
# Format probabilities for the frontend
|
| 52 |
-
# UI expects 0-100 for confidence
|
| 53 |
-
confidence_pct = result["confidence"] * 100 if result["confidence"] <= 1.0 else result["confidence"]
|
| 54 |
-
|
| 55 |
-
results.append({
|
| 56 |
-
"filename": file.filename,
|
| 57 |
-
"success": True,
|
| 58 |
-
"prediction": result['prediction'],
|
| 59 |
-
"confidence": confidence_pct,
|
| 60 |
-
"probabilities": [
|
| 61 |
-
{"name": result['prediction'], "probability": confidence_pct}
|
| 62 |
-
],
|
| 63 |
-
"details": {
|
| 64 |
-
"gram_stain": result.get("gram", "Unknown"),
|
| 65 |
-
"shape": result.get("shape", "Unknown"),
|
| 66 |
-
"pathogenicity": result.get("risk", "Unknown")
|
| 67 |
-
}
|
| 68 |
-
})
|
| 69 |
-
except Exception as e:
|
| 70 |
-
results.append({
|
| 71 |
-
"filename": file.filename,
|
| 72 |
-
"success": False,
|
| 73 |
-
"error": str(e)
|
| 74 |
-
})
|
| 75 |
-
finally:
|
| 76 |
-
# Clean up the temporary file
|
| 77 |
-
if temp_path and os.path.exists(temp_path):
|
| 78 |
-
os.remove(temp_path)
|
| 79 |
-
|
| 80 |
-
return {"results": results}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{bacterial-classifier → classifier_service}/.gitignore
RENAMED
|
File without changes
|
{bacterial-classifier → classifier_service}/README.txt
RENAMED
|
File without changes
|
classifier_service/api.py
CHANGED
|
@@ -49,12 +49,14 @@ async def root():
|
|
| 49 |
</html>
|
| 50 |
"""
|
| 51 |
|
| 52 |
-
# Catch-all route
|
| 53 |
@app.get("/{path_name:path}", response_class=HTMLResponse)
|
| 54 |
async def catch_all(path_name: str):
|
| 55 |
-
#
|
| 56 |
-
|
| 57 |
-
|
|
|
|
|
|
|
| 58 |
return await root()
|
| 59 |
|
| 60 |
# Global classifier instance
|
|
|
|
| 49 |
</html>
|
| 50 |
"""
|
| 51 |
|
| 52 |
+
# Catch-all route for SPA support (but exclude API endpoints)
|
| 53 |
@app.get("/{path_name:path}", response_class=HTMLResponse)
|
| 54 |
async def catch_all(path_name: str):
|
| 55 |
+
# Don't catch API endpoints - they should return 404 if not found
|
| 56 |
+
api_endpoints = ["docs", "redoc", "openapi.json", "health", "debug_model", "predict_batch", "api"]
|
| 57 |
+
if any(path_name.startswith(endpoint) for endpoint in api_endpoints):
|
| 58 |
+
raise HTTPException(status_code=404)
|
| 59 |
+
# For everything else, return the root page (useful for SPA routing)
|
| 60 |
return await root()
|
| 61 |
|
| 62 |
# Global classifier instance
|
{bacterial-classifier → classifier_service}/app.py
RENAMED
|
File without changes
|
{bacterial-classifier → classifier_service}/requirements.txt
RENAMED
|
File without changes
|
{bacterial-classifier → classifier_service}/run_backend.ps1
RENAMED
|
File without changes
|
push2.txt
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Uploading LFS objects: 100% (7/7), 61 MB | 0 B/s, done.
|
| 2 |
+
remote: -------------------------------------------------------------------------
|
| 3 |
+
remote: Your push was rejected because it contains files larger than 10 MiB.
|
| 4 |
+
remote: Please use https://git-lfs.github.com/ to store large files.
|
| 5 |
+
remote: See also: https://hf.co/docs/hub/repositories-getting-started#terminal
|
| 6 |
+
remote:
|
| 7 |
+
remote: Offending files:
|
| 8 |
+
remote: - bacsense_v2_package/vgg16_feature_extractor.keras (ref: refs/heads/main)
|
| 9 |
+
remote: -------------------------------------------------------------------------
|
| 10 |
+
To https://huggingface.co/spaces/joytheslothh/BacSense-API
|
| 11 |
+
! [remote rejected] main -> main (pre-receive hook declined)
|
| 12 |
+
error: failed to push some refs to 'https://huggingface.co/spaces/joytheslothh/BacSense-API'
|
push_final.txt
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Pushing to https://huggingface.co/spaces/joytheslothh/BacSense-API
|
| 2 |
+
Uploading LFS objects: 100% (7/7), 61 MB | 0 B/s, done.
|
| 3 |
+
POST git-receive-pack (60176516 bytes)
|
| 4 |
+
remote: -------------------------------------------------------------------------
|
| 5 |
+
remote: Your push was rejected because it contains files larger than 10 MiB.
|
| 6 |
+
remote: Please use https://git-lfs.github.com/ to store large files.
|
| 7 |
+
remote: See also: https://hf.co/docs/hub/repositories-getting-started#terminal
|
| 8 |
+
remote:
|
| 9 |
+
remote: Offending files:
|
| 10 |
+
remote: - bacsense_v2_package/vgg16_feature_extractor.keras (ref: refs/heads/main)
|
| 11 |
+
remote: -------------------------------------------------------------------------
|
| 12 |
+
To https://huggingface.co/spaces/joytheslothh/BacSense-API
|
| 13 |
+
! [remote rejected] main -> main (pre-receive hook declined)
|
| 14 |
+
error: failed to push some refs to 'https://huggingface.co/spaces/joytheslothh/BacSense-API'
|
push_log.txt
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Uploading LFS objects: 100% (7/7), 61 MB | 0 B/s, done.
|
| 2 |
+
remote: -------------------------------------------------------------------------
|
| 3 |
+
remote: Your push was rejected because it contains files larger than 10 MiB.
|
| 4 |
+
remote: Please use https://git-lfs.github.com/ to store large files.
|
| 5 |
+
remote: See also: https://hf.co/docs/hub/repositories-getting-started#terminal
|
| 6 |
+
remote:
|
| 7 |
+
remote: Offending files:
|
| 8 |
+
remote: - bacsense_v2_package/vgg16_feature_extractor.keras (ref: refs/heads/main)
|
| 9 |
+
remote: -------------------------------------------------------------------------
|
| 10 |
+
To https://huggingface.co/spaces/joytheslothh/BacSense-API
|
| 11 |
+
! [remote rejected] main -> main (pre-receive hook declined)
|
| 12 |
+
error: failed to push some refs to 'https://huggingface.co/spaces/joytheslothh/BacSense-API'
|
requirements.txt
CHANGED
|
@@ -1,11 +1,11 @@
|
|
| 1 |
-
tensorflow>=2.
|
| 2 |
scikit-learn>=1.3.0
|
| 3 |
scikit-image>=0.21.0
|
| 4 |
opencv-python-headless>=4.8.0
|
| 5 |
-
numpy>=1.24.0
|
| 6 |
-
Pillow>=
|
| 7 |
scipy>=1.11.0
|
| 8 |
-
streamlit>=1.
|
| 9 |
pandas>=2.0.0
|
| 10 |
fastapi
|
| 11 |
uvicorn
|
|
|
|
| 1 |
+
tensorflow-cpu>=2.15.0,<2.16.0
|
| 2 |
scikit-learn>=1.3.0
|
| 3 |
scikit-image>=0.21.0
|
| 4 |
opencv-python-headless>=4.8.0
|
| 5 |
+
numpy>=1.24.0,<2.0.0
|
| 6 |
+
Pillow>=10.0.0
|
| 7 |
scipy>=1.11.0
|
| 8 |
+
streamlit>=1.41.0
|
| 9 |
pandas>=2.0.0
|
| 10 |
fastapi
|
| 11 |
uvicorn
|
start.sh
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
# Startup script for Hugging Face Spaces
|
| 3 |
+
|
| 4 |
+
echo "🦠 Starting BacSense v2 API..."
|
| 5 |
+
echo "Current directory: $(pwd)"
|
| 6 |
+
echo "Contents:"
|
| 7 |
+
ls -la
|
| 8 |
+
|
| 9 |
+
echo ""
|
| 10 |
+
echo "Checking bacsense_v2_package:"
|
| 11 |
+
ls -la bacsense_v2_package/ || echo "Directory not found!"
|
| 12 |
+
|
| 13 |
+
echo ""
|
| 14 |
+
echo "Starting uvicorn server..."
|
| 15 |
+
exec uvicorn classifier_service.api:app --host 0.0.0.0 --port 7860
|
upload_to_hf.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from huggingface_hub import HfApi
|
| 2 |
+
import os
|
| 3 |
+
|
| 4 |
+
TOKEN = "REDACTED"
|
| 5 |
+
REPO_ID = "joytheslothh/BacSense-API"
|
| 6 |
+
REPO_TYPE = "space"
|
| 7 |
+
|
| 8 |
+
# Files/dirs to skip (frontend, docs, git artifacts)
|
| 9 |
+
SKIP_DIRS = {"frontend", ".git", "__pycache__", ".gitignore"}
|
| 10 |
+
SKIP_FILES = {"push_log.txt", "push2.txt", "push_final.txt", "upload_to_hf.py",
|
| 11 |
+
"render.yaml", "BacSense_v2_Technical_Documentation.docx",
|
| 12 |
+
"BacSense_v2_Technical_Documentation.docx-1.pdf",
|
| 13 |
+
"BacSense_v2_Technical_Documentation.docx.txt"}
|
| 14 |
+
SKIP_EXTS = {".ps1"}
|
| 15 |
+
|
| 16 |
+
api = HfApi(token=TOKEN)
|
| 17 |
+
base = os.path.abspath(os.path.dirname(__file__))
|
| 18 |
+
|
| 19 |
+
files_to_upload = []
|
| 20 |
+
for root, dirs, files in os.walk(base):
|
| 21 |
+
# Prune skip dirs in-place
|
| 22 |
+
dirs[:] = [d for d in dirs if d not in SKIP_DIRS and not d.startswith('.')]
|
| 23 |
+
for fname in files:
|
| 24 |
+
if fname in SKIP_FILES:
|
| 25 |
+
continue
|
| 26 |
+
if any(fname.endswith(ext) for ext in SKIP_EXTS):
|
| 27 |
+
continue
|
| 28 |
+
full_path = os.path.join(root, fname)
|
| 29 |
+
rel_path = os.path.relpath(full_path, base).replace("\\", "/")
|
| 30 |
+
files_to_upload.append((full_path, rel_path))
|
| 31 |
+
|
| 32 |
+
print(f"Uploading {len(files_to_upload)} files to {REPO_ID}...\n")
|
| 33 |
+
for i, (local, remote) in enumerate(files_to_upload, 1):
|
| 34 |
+
size_mb = os.path.getsize(local) / (1024*1024)
|
| 35 |
+
print(f"[{i}/{len(files_to_upload)}] {remote} ({size_mb:.2f} MB)")
|
| 36 |
+
api.upload_file(
|
| 37 |
+
path_or_fileobj=local,
|
| 38 |
+
path_in_repo=remote,
|
| 39 |
+
repo_id=REPO_ID,
|
| 40 |
+
repo_type=REPO_TYPE,
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
print("\n✅ All files uploaded successfully!")
|