Spaces:
Sleeping
Sleeping
kabancov_et
commited on
Commit
·
e28359e
1
Parent(s):
abe53f2
Fix API startup issues and Depends error - clean implementation
Browse files- main.py +15 -0
- start.py +18 -12
- user_manager.py +2 -2
main.py
CHANGED
|
@@ -61,9 +61,12 @@ async def detect_clothing(
|
|
| 61 |
"""
|
| 62 |
try:
|
| 63 |
# Get user ID for rate limiting
|
|
|
|
| 64 |
user_id = get_user_id(request)
|
|
|
|
| 65 |
|
| 66 |
# Check rate limit
|
|
|
|
| 67 |
if not await rate_limiter.check_rate_limit(user_id, "/clothing"):
|
| 68 |
raise HTTPException(
|
| 69 |
status_code=429,
|
|
@@ -71,6 +74,7 @@ async def detect_clothing(
|
|
| 71 |
)
|
| 72 |
|
| 73 |
# Check concurrent limit
|
|
|
|
| 74 |
if not await rate_limiter.check_concurrent_limit(user_id):
|
| 75 |
raise HTTPException(
|
| 76 |
status_code=429,
|
|
@@ -81,17 +85,24 @@ async def detect_clothing(
|
|
| 81 |
raise HTTPException(status_code=400, detail="File must be an image")
|
| 82 |
|
| 83 |
# Read file content once
|
|
|
|
| 84 |
image_bytes = await file.read()
|
|
|
|
| 85 |
|
| 86 |
# Add request to tracking after successful validation
|
|
|
|
| 87 |
await rate_limiter.add_request(user_id, "/clothing", len(image_bytes))
|
| 88 |
|
| 89 |
# Use the proper clothing detector from clothing_detector.py
|
|
|
|
| 90 |
from clothing_detector import detect_clothing_types
|
| 91 |
|
|
|
|
| 92 |
clothing_result = detect_clothing_types(image_bytes)
|
|
|
|
| 93 |
|
| 94 |
# Remove request from concurrent tracking
|
|
|
|
| 95 |
await rate_limiter.remove_request(user_id)
|
| 96 |
|
| 97 |
return JSONResponse(clothing_result)
|
|
@@ -102,8 +113,12 @@ async def detect_clothing(
|
|
| 102 |
except Exception as e:
|
| 103 |
# Remove request from concurrent tracking on error
|
| 104 |
if 'user_id' in locals():
|
|
|
|
| 105 |
await rate_limiter.remove_request(user_id)
|
| 106 |
logger.error(f"Error in clothing detection: {e}")
|
|
|
|
|
|
|
|
|
|
| 107 |
raise HTTPException(status_code=500, detail=f"Error in clothing detection: {str(e)}")
|
| 108 |
|
| 109 |
@app.post("/analyze")
|
|
|
|
| 61 |
"""
|
| 62 |
try:
|
| 63 |
# Get user ID for rate limiting
|
| 64 |
+
logger.info("Getting user ID for rate limiting...")
|
| 65 |
user_id = get_user_id(request)
|
| 66 |
+
logger.info(f"User ID obtained: {user_id}")
|
| 67 |
|
| 68 |
# Check rate limit
|
| 69 |
+
logger.info("Checking rate limit...")
|
| 70 |
if not await rate_limiter.check_rate_limit(user_id, "/clothing"):
|
| 71 |
raise HTTPException(
|
| 72 |
status_code=429,
|
|
|
|
| 74 |
)
|
| 75 |
|
| 76 |
# Check concurrent limit
|
| 77 |
+
logger.info("Checking concurrent limit...")
|
| 78 |
if not await rate_limiter.check_concurrent_limit(user_id):
|
| 79 |
raise HTTPException(
|
| 80 |
status_code=429,
|
|
|
|
| 85 |
raise HTTPException(status_code=400, detail="File must be an image")
|
| 86 |
|
| 87 |
# Read file content once
|
| 88 |
+
logger.info("Reading file content...")
|
| 89 |
image_bytes = await file.read()
|
| 90 |
+
logger.info(f"File size: {len(image_bytes)} bytes")
|
| 91 |
|
| 92 |
# Add request to tracking after successful validation
|
| 93 |
+
logger.info("Adding request to rate limiter...")
|
| 94 |
await rate_limiter.add_request(user_id, "/clothing", len(image_bytes))
|
| 95 |
|
| 96 |
# Use the proper clothing detector from clothing_detector.py
|
| 97 |
+
logger.info("Importing clothing detector...")
|
| 98 |
from clothing_detector import detect_clothing_types
|
| 99 |
|
| 100 |
+
logger.info("Starting clothing detection...")
|
| 101 |
clothing_result = detect_clothing_types(image_bytes)
|
| 102 |
+
logger.info("Clothing detection completed successfully")
|
| 103 |
|
| 104 |
# Remove request from concurrent tracking
|
| 105 |
+
logger.info("Removing request from concurrent tracking...")
|
| 106 |
await rate_limiter.remove_request(user_id)
|
| 107 |
|
| 108 |
return JSONResponse(clothing_result)
|
|
|
|
| 113 |
except Exception as e:
|
| 114 |
# Remove request from concurrent tracking on error
|
| 115 |
if 'user_id' in locals():
|
| 116 |
+
logger.info("Removing request from concurrent tracking due to error...")
|
| 117 |
await rate_limiter.remove_request(user_id)
|
| 118 |
logger.error(f"Error in clothing detection: {e}")
|
| 119 |
+
logger.error(f"Error type: {type(e)}")
|
| 120 |
+
import traceback
|
| 121 |
+
logger.error(f"Traceback: {traceback.format_exc()}")
|
| 122 |
raise HTTPException(status_code=500, detail=f"Error in clothing detection: {str(e)}")
|
| 123 |
|
| 124 |
@app.post("/analyze")
|
start.py
CHANGED
|
@@ -11,16 +11,22 @@ import uvicorn
|
|
| 11 |
from config import config
|
| 12 |
|
| 13 |
def main():
|
|
|
|
|
|
|
|
|
|
| 14 |
parser = argparse.ArgumentParser(description="Start Loomi Clothing Detection API")
|
| 15 |
-
parser.add_argument("--host", default=
|
| 16 |
-
parser.add_argument("--port", type=int, default=
|
| 17 |
-
parser.add_argument("--workers", type=int, default=
|
| 18 |
parser.add_argument("--reload", action="store_true", help="Enable auto-reload for development")
|
| 19 |
parser.add_argument("--config", help="Path to .env file")
|
| 20 |
parser.add_argument("--huggingface", action="store_true", help="Optimize for Hugging Face Spaces")
|
| 21 |
|
| 22 |
args = parser.parse_args()
|
| 23 |
|
|
|
|
|
|
|
|
|
|
| 24 |
# Load environment variables if specified
|
| 25 |
if args.config:
|
| 26 |
from dotenv import load_dotenv
|
|
@@ -29,7 +35,7 @@ def main():
|
|
| 29 |
from importlib import reload
|
| 30 |
import config
|
| 31 |
reload(config)
|
| 32 |
-
|
| 33 |
|
| 34 |
# Hugging Face Spaces optimization
|
| 35 |
if args.huggingface:
|
|
@@ -41,7 +47,7 @@ def main():
|
|
| 41 |
args.reload = False
|
| 42 |
|
| 43 |
# Validate configuration
|
| 44 |
-
warnings =
|
| 45 |
if warnings:
|
| 46 |
print("⚠️ Configuration warnings:")
|
| 47 |
for warning in warnings:
|
|
@@ -50,14 +56,14 @@ def main():
|
|
| 50 |
|
| 51 |
# Print startup information
|
| 52 |
print("🎯 Loomi Clothing Detection API")
|
| 53 |
-
print(f" Version: {
|
| 54 |
print(f" Host: {args.host}:{args.port}")
|
| 55 |
print(f" Workers: {args.workers}")
|
| 56 |
-
print(f" Background workers: {
|
| 57 |
-
print(f" Rate limit: {
|
| 58 |
-
print(f" Concurrent limit: {
|
| 59 |
-
print(f" File size limit: {
|
| 60 |
-
print(f" Hugging Face Space: {
|
| 61 |
print()
|
| 62 |
|
| 63 |
# Start the server
|
|
@@ -68,7 +74,7 @@ def main():
|
|
| 68 |
port=args.port,
|
| 69 |
workers=args.workers if not args.reload else 1,
|
| 70 |
reload=args.reload,
|
| 71 |
-
log_level=
|
| 72 |
access_log=True,
|
| 73 |
use_colors=True
|
| 74 |
)
|
|
|
|
| 11 |
from config import config
|
| 12 |
|
| 13 |
def main():
|
| 14 |
+
# Import config at the beginning
|
| 15 |
+
from config import config as api_config
|
| 16 |
+
|
| 17 |
parser = argparse.ArgumentParser(description="Start Loomi Clothing Detection API")
|
| 18 |
+
parser.add_argument("--host", default=api_config.host, help="Host to bind to")
|
| 19 |
+
parser.add_argument("--port", type=int, default=api_config.port, help="Port to bind to")
|
| 20 |
+
parser.add_argument("--workers", type=int, default=api_config.workers, help="Number of worker processes")
|
| 21 |
parser.add_argument("--reload", action="store_true", help="Enable auto-reload for development")
|
| 22 |
parser.add_argument("--config", help="Path to .env file")
|
| 23 |
parser.add_argument("--huggingface", action="store_true", help="Optimize for Hugging Face Spaces")
|
| 24 |
|
| 25 |
args = parser.parse_args()
|
| 26 |
|
| 27 |
+
# Use local config variable
|
| 28 |
+
current_config = api_config
|
| 29 |
+
|
| 30 |
# Load environment variables if specified
|
| 31 |
if args.config:
|
| 32 |
from dotenv import load_dotenv
|
|
|
|
| 35 |
from importlib import reload
|
| 36 |
import config
|
| 37 |
reload(config)
|
| 38 |
+
current_config = config.config
|
| 39 |
|
| 40 |
# Hugging Face Spaces optimization
|
| 41 |
if args.huggingface:
|
|
|
|
| 47 |
args.reload = False
|
| 48 |
|
| 49 |
# Validate configuration
|
| 50 |
+
warnings = current_config.validate()
|
| 51 |
if warnings:
|
| 52 |
print("⚠️ Configuration warnings:")
|
| 53 |
for warning in warnings:
|
|
|
|
| 56 |
|
| 57 |
# Print startup information
|
| 58 |
print("🎯 Loomi Clothing Detection API")
|
| 59 |
+
print(f" Version: {current_config.version}")
|
| 60 |
print(f" Host: {args.host}:{args.port}")
|
| 61 |
print(f" Workers: {args.workers}")
|
| 62 |
+
print(f" Background workers: {current_config.num_workers}")
|
| 63 |
+
print(f" Rate limit: {current_config.rate_limit_requests} req/min")
|
| 64 |
+
print(f" Concurrent limit: {current_config.max_concurrent_requests}")
|
| 65 |
+
print(f" File size limit: {current_config.max_upload_mb}MB")
|
| 66 |
+
print(f" Hugging Face Space: {current_config.is_huggingface_space}")
|
| 67 |
print()
|
| 68 |
|
| 69 |
# Start the server
|
|
|
|
| 74 |
port=args.port,
|
| 75 |
workers=args.workers if not args.reload else 1,
|
| 76 |
reload=args.reload,
|
| 77 |
+
log_level=current_config.log_level.lower(),
|
| 78 |
access_log=True,
|
| 79 |
use_colors=True
|
| 80 |
)
|
user_manager.py
CHANGED
|
@@ -3,13 +3,13 @@ User management and identification for the Loomi Clothing Detection API.
|
|
| 3 |
"""
|
| 4 |
import hashlib
|
| 5 |
from typing import Optional
|
| 6 |
-
from fastapi import Request
|
| 7 |
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
| 8 |
|
| 9 |
# Security
|
| 10 |
security = HTTPBearer(auto_error=False)
|
| 11 |
|
| 12 |
-
def get_user_id(request: Request, credentials: Optional[HTTPAuthorizationCredentials] =
|
| 13 |
"""
|
| 14 |
Extract user ID from request.
|
| 15 |
In production, validate JWT token.
|
|
|
|
| 3 |
"""
|
| 4 |
import hashlib
|
| 5 |
from typing import Optional
|
| 6 |
+
from fastapi import Request
|
| 7 |
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
| 8 |
|
| 9 |
# Security
|
| 10 |
security = HTTPBearer(auto_error=False)
|
| 11 |
|
| 12 |
+
def get_user_id(request: Request, credentials: Optional[HTTPAuthorizationCredentials] = None) -> str:
|
| 13 |
"""
|
| 14 |
Extract user ID from request.
|
| 15 |
In production, validate JWT token.
|