ProfessorCEO commited on
Commit
9eae827
·
verified ·
1 Parent(s): 5e13f5c

Cool Shot Systems

Browse files
Files changed (5) hide show
  1. Dockerfile (1).txt +31 -0
  2. README (4).md +78 -0
  3. auth.py +61 -0
  4. main.py +77 -0
  5. requirements.txt +5 -0
Dockerfile (1).txt ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ # Set environment variables
4
+ ENV PYTHONDONTWRITEBYTECODE=1
5
+ ENV PYTHONUNBUFFERED=1
6
+
7
+ # Create non-root user for security
8
+ RUN useradd -m -u 1000 appuser
9
+
10
+ WORKDIR /app
11
+
12
+ # Install dependencies first for better caching
13
+ COPY requirements.txt .
14
+ RUN pip install --no-cache-dir --upgrade pip && \
15
+ pip install --no-cache-dir -r requirements.txt
16
+
17
+ # Copy application code
18
+ COPY --chown=appuser:appuser . .
19
+
20
+ # Switch to non-root user
21
+ USER appuser
22
+
23
+ # Hugging Face Spaces runs on port 7860 by default
24
+ EXPOSE 7860
25
+
26
+ # Health check
27
+ HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
28
+ CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:7860/health')" || exit 1
29
+
30
+ # Run the application
31
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
README (4).md ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Image Prediction API
3
+ emoji: 🖼️
4
+ colorFrom: purple
5
+ colorTo: pink
6
+ sdk: docker
7
+ pinned: false
8
+ license: mit
9
+ app_port: 7860
10
+ ---
11
+
12
+ # Image Prediction API
13
+
14
+ AI-powered image prediction service built with FastAPI.
15
+
16
+ ## Features
17
+
18
+ - 🔐 **Secure Authentication** - JWT Bearer token verification
19
+ - 🚀 **Fast Performance** - Built on FastAPI with async support
20
+ - 📊 **Health Monitoring** - Built-in health check endpoint
21
+ - 🐳 **Docker Ready** - Optimized for Hugging Face Spaces deployment
22
+
23
+ ## API Endpoints
24
+
25
+ ### Health Check
26
+ ```
27
+ GET /health
28
+ ```
29
+ Returns the service health status.
30
+
31
+ ### Prediction
32
+ ```
33
+ POST /predict
34
+ Authorization: Bearer <token>
35
+ Content-Type: application/json
36
+
37
+ {
38
+ "image_url": "https://example.com/image.jpg"
39
+ }
40
+ ```
41
+
42
+ **Response:**
43
+ ```json
44
+ {
45
+ "prediction": "Object detected",
46
+ "confidence": 0.92,
47
+ "labels": ["object", "scene", "outdoor"],
48
+ "image_url": "https://example.com/image.jpg"
49
+ }
50
+ ```
51
+
52
+ ## Environment Variables
53
+
54
+ | Variable | Description | Required |
55
+ |----------|-------------|----------|
56
+ | `JWT_SECRET` | Secret key for JWT token verification | Yes |
57
+ | `ALLOWED_ORIGINS` | Comma-separated list of allowed CORS origins | No |
58
+
59
+ ## Local Development
60
+
61
+ ```bash
62
+ # Install dependencies
63
+ pip install -r requirements.txt
64
+
65
+ # Set environment variables
66
+ export JWT_SECRET=your_secret_key
67
+
68
+ # Run the server
69
+ uvicorn main:app --reload --port 8002
70
+ ```
71
+
72
+ ## Deployment
73
+
74
+ This service is designed to run on Hugging Face Spaces with Docker SDK.
75
+
76
+ 1. Create a new Space with Docker SDK
77
+ 2. Set the `JWT_SECRET` secret in Space settings
78
+ 3. Push this code to the Space repository
auth.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from fastapi import Depends, HTTPException, status
3
+ from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
4
+ from jose import jwt, JWTError
5
+
6
+ security = HTTPBearer()
7
+
8
+ def get_jwt_secret() -> str:
9
+ """Get JWT secret from environment variable."""
10
+ secret = os.getenv("JWT_SECRET")
11
+ if not secret:
12
+ raise HTTPException(
13
+ status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
14
+ detail="JWT_SECRET not configured"
15
+ )
16
+ return secret
17
+
18
+
19
+ def verify_token(credentials: HTTPAuthorizationCredentials = Depends(security)) -> dict:
20
+ """
21
+ Verify Bearer token signature.
22
+ Returns the decoded token payload if valid.
23
+ Raises HTTPException if invalid.
24
+ """
25
+ token = credentials.credentials
26
+ jwt_secret = get_jwt_secret()
27
+
28
+ try:
29
+ # Decode and verify the JWT token
30
+ payload = jwt.decode(
31
+ token,
32
+ jwt_secret,
33
+ algorithms=["HS256"],
34
+ options={"verify_aud": False} # Clerk tokens may not have standard audience
35
+ )
36
+ return payload
37
+ except JWTError as e:
38
+ raise HTTPException(
39
+ status_code=status.HTTP_401_UNAUTHORIZED,
40
+ detail=f"Invalid token: {str(e)}",
41
+ headers={"WWW-Authenticate": "Bearer"},
42
+ )
43
+
44
+
45
+ def get_current_user(token_payload: dict = Depends(verify_token)) -> dict:
46
+ """
47
+ Extract user information from verified token.
48
+ """
49
+ user_id = token_payload.get("sub")
50
+ if not user_id:
51
+ raise HTTPException(
52
+ status_code=status.HTTP_401_UNAUTHORIZED,
53
+ detail="Invalid token: missing user ID",
54
+ headers={"WWW-Authenticate": "Bearer"},
55
+ )
56
+
57
+ return {
58
+ "user_id": user_id,
59
+ "email": token_payload.get("email"),
60
+ "claims": token_payload
61
+ }
main.py ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ from fastapi import FastAPI, Depends, HTTPException
4
+ from fastapi.middleware.cors import CORSMiddleware
5
+ from pydantic import BaseModel
6
+ from auth import get_current_user
7
+
8
+ app = FastAPI(
9
+ title="Image Prediction API",
10
+ description="AI-powered image prediction service",
11
+ version="0.1.0"
12
+ )
13
+
14
+ # Configure CORS - use environment variable for allowed origins in production
15
+ allowed_origins = os.getenv("ALLOWED_ORIGINS", "").split(",") if os.getenv("ALLOWED_ORIGINS") else ["*"]
16
+
17
+ app.add_middleware(
18
+ CORSMiddleware,
19
+ allow_origins=allowed_origins,
20
+ allow_credentials=False,
21
+ allow_methods=["*"],
22
+ allow_headers=["*"],
23
+ )
24
+
25
+
26
+ class ImagePredictRequest(BaseModel):
27
+ image_url: str
28
+
29
+
30
+ class ImagePredictResponse(BaseModel):
31
+ prediction: str
32
+ confidence: float
33
+ labels: list[str]
34
+ image_url: str
35
+
36
+
37
+ @app.get("/")
38
+ async def root():
39
+ """Health check endpoint."""
40
+ return {"status": "healthy", "service": "image-api"}
41
+
42
+
43
+ @app.get("/health")
44
+ async def health():
45
+ """Health check endpoint."""
46
+ return {"status": "healthy"}
47
+
48
+
49
+ @app.post("/predict", response_model=ImagePredictResponse)
50
+ async def predict(
51
+ request: ImagePredictRequest,
52
+ current_user: dict = Depends(get_current_user)
53
+ ):
54
+ """
55
+ Protected endpoint for image prediction.
56
+ Requires valid Bearer token.
57
+ """
58
+ # Placeholder prediction logic
59
+ # In a real application, this would call an ML model
60
+ image_url = request.image_url
61
+
62
+ # Simple mock prediction
63
+ prediction = "Object detected"
64
+ confidence = 0.92
65
+ labels = ["object", "scene", "outdoor"]
66
+
67
+ return ImagePredictResponse(
68
+ prediction=prediction,
69
+ confidence=confidence,
70
+ labels=labels,
71
+ image_url=image_url
72
+ )
73
+
74
+
75
+ if __name__ == "__main__":
76
+ import uvicorn
77
+ uvicorn.run(app, host="0.0.0.0", port=8002)
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ fastapi>=0.109.0
2
+ uvicorn>=0.27.0
3
+ python-jose[cryptography]>=3.3.0
4
+ httpx>=0.26.0
5
+ pydantic>=2.5.0