Spaces:
Sleeping
Sleeping
Commit
·
65aa0cb
0
Parent(s):
feat: First commit
Browse files- .gitattributes +77 -0
- .gitignore +3 -0
- Dockerfile +16 -0
- README.md +8 -0
- apps/create_app.py +21 -0
- apps/detection/__init__.py +28 -0
- apps/detection/controller.py +34 -0
- apps/detection/model.py +14 -0
- apps/detection/provider.py +6 -0
- apps/query/__init__.py +14 -0
- apps/recommend/__init__.py +16 -0
- apps/recommend/controller.py +42 -0
- apps/recommend/model.py +16 -0
- apps/recommend/provider.py +7 -0
- main.py +11 -0
- models/yolo.pt +3 -0
- requirements.txt +0 -0
.gitattributes
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Hugging Face's logo
|
| 2 |
+
Hugging Face
|
| 3 |
+
Search models, datasets, users...
|
| 4 |
+
Models
|
| 5 |
+
Datasets
|
| 6 |
+
Spaces
|
| 7 |
+
Posts
|
| 8 |
+
Docs
|
| 9 |
+
Pricing
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
Spaces:
|
| 14 |
+
|
| 15 |
+
MingDoan
|
| 16 |
+
/
|
| 17 |
+
gloco-backend
|
| 18 |
+
|
| 19 |
+
like
|
| 20 |
+
0
|
| 21 |
+
|
| 22 |
+
App
|
| 23 |
+
Files
|
| 24 |
+
Community
|
| 25 |
+
Settings
|
| 26 |
+
gloco-backend
|
| 27 |
+
/
|
| 28 |
+
.gitattributes
|
| 29 |
+
|
| 30 |
+
MingDoan's picture
|
| 31 |
+
MingDoan
|
| 32 |
+
initial commit
|
| 33 |
+
842aefd
|
| 34 |
+
VERIFIED
|
| 35 |
+
2 minutes ago
|
| 36 |
+
raw
|
| 37 |
+
history
|
| 38 |
+
blame
|
| 39 |
+
edit
|
| 40 |
+
delete
|
| 41 |
+
No virus
|
| 42 |
+
1.52 kB
|
| 43 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 44 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 45 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 46 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 47 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 48 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 49 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 50 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 51 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 52 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 53 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 54 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 55 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 56 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 57 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 58 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 59 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 60 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 61 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 62 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 63 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 64 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 65 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 66 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 67 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 68 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 69 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 70 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 71 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 72 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 73 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 74 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 75 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 76 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 77 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
.gitignore
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/env
|
| 2 |
+
__pycache__/
|
| 3 |
+
.env
|
Dockerfile
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.10.13-slim-bookworm
|
| 2 |
+
|
| 3 |
+
# Define the working directory
|
| 4 |
+
WORKDIR /code
|
| 5 |
+
|
| 6 |
+
# Copy the requirements file
|
| 7 |
+
COPY ./requirements.txt /code/requirements.txt
|
| 8 |
+
|
| 9 |
+
# Install the requirements
|
| 10 |
+
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
|
| 11 |
+
|
| 12 |
+
# Copy the rest of the files
|
| 13 |
+
COPY . /code
|
| 14 |
+
|
| 15 |
+
# Run the application
|
| 16 |
+
ENTRYPOINT ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
|
README.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Gloco Backend
|
| 3 |
+
emoji: 🏢
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: red
|
| 6 |
+
sdk: docker
|
| 7 |
+
pinned: false
|
| 8 |
+
---
|
apps/create_app.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI
|
| 2 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
def create_app():
|
| 6 |
+
app = FastAPI(
|
| 7 |
+
title="Trash Detection API",
|
| 8 |
+
description="GLOCO Object Detection API using FastAPI and YOLOv8",
|
| 9 |
+
docs_url="/"
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
# Add CORS middleware
|
| 13 |
+
app.add_middleware(
|
| 14 |
+
CORSMiddleware,
|
| 15 |
+
allow_origins=["*"],
|
| 16 |
+
allow_credentials=True,
|
| 17 |
+
allow_methods=["*"],
|
| 18 |
+
allow_headers=["*"],
|
| 19 |
+
)
|
| 20 |
+
|
| 21 |
+
return app
|
apps/detection/__init__.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import APIRouter, UploadFile, File, HTTPException, status
|
| 2 |
+
from fastapi.responses import JSONResponse
|
| 3 |
+
from .model import Detections
|
| 4 |
+
from .controller import detect_object
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
router = APIRouter(
|
| 8 |
+
prefix="/detection",
|
| 9 |
+
tags=["detection"],
|
| 10 |
+
default_response_class=JSONResponse
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
@router.post("/", response_model=Detections)
|
| 15 |
+
async def detection(
|
| 16 |
+
image: UploadFile = File(..., description="File to detect"),
|
| 17 |
+
):
|
| 18 |
+
if not image.content_type.startswith("image"):
|
| 19 |
+
raise HTTPException(
|
| 20 |
+
status_code=status.HTTP_400_BAD_REQUEST,
|
| 21 |
+
detail="Invalid file type. Only image files are allowed."
|
| 22 |
+
)
|
| 23 |
+
|
| 24 |
+
# Read image file
|
| 25 |
+
contents = await image.read()
|
| 26 |
+
|
| 27 |
+
detections = detect_object(contents)
|
| 28 |
+
return detections
|
apps/detection/controller.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .provider import model
|
| 2 |
+
from io import BytesIO
|
| 3 |
+
from PIL import Image
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def detect_object(image: bytes):
|
| 7 |
+
# Convert bytes to PIL image
|
| 8 |
+
image = Image.open(BytesIO(image))
|
| 9 |
+
|
| 10 |
+
detections = model.predict(image)
|
| 11 |
+
|
| 12 |
+
# Format detections
|
| 13 |
+
bboxs = detections[0].boxes.data
|
| 14 |
+
labels = detections[0].names
|
| 15 |
+
|
| 16 |
+
# Get boxs result
|
| 17 |
+
boxs_result = []
|
| 18 |
+
for box in bboxs:
|
| 19 |
+
result_conf = box[4].item()
|
| 20 |
+
if result_conf > model.conf:
|
| 21 |
+
boxs_result.append({
|
| 22 |
+
"class_name": labels[int(box[5].item())],
|
| 23 |
+
"confidence": result_conf,
|
| 24 |
+
"xmin": box[0].item(),
|
| 25 |
+
"ymin": box[1].item(),
|
| 26 |
+
"xmax": box[2].item(),
|
| 27 |
+
"ymax": box[3].item()
|
| 28 |
+
})
|
| 29 |
+
|
| 30 |
+
print(boxs_result)
|
| 31 |
+
|
| 32 |
+
return {
|
| 33 |
+
"detections": boxs_result
|
| 34 |
+
}
|
apps/detection/model.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel, Field
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class Detection(BaseModel):
|
| 5 |
+
class_name: str = Field(..., example="person")
|
| 6 |
+
confidence: float = Field(..., example=0.99)
|
| 7 |
+
xmin: float = Field(..., example=0.1)
|
| 8 |
+
ymin: float = Field(..., example=0.2)
|
| 9 |
+
xmax: float = Field(..., example=0.3)
|
| 10 |
+
ymax: float = Field(..., example=0.4)
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class Detections(BaseModel):
|
| 14 |
+
detections: list[Detection] = Field(..., description="List of detections")
|
apps/detection/provider.py
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from ultralytics import YOLO
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
model = YOLO(os.path.join(os.getcwd(), "models", "yolo.pt"))
|
| 6 |
+
model.conf = 0.5
|
apps/query/__init__.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import APIRouter
|
| 2 |
+
from fastapi.responses import JSONResponse
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
router = APIRouter(
|
| 6 |
+
prefix="/query",
|
| 7 |
+
tags=["query"],
|
| 8 |
+
default_response_class=JSONResponse
|
| 9 |
+
)
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
@router.post("/")
|
| 13 |
+
def query():
|
| 14 |
+
return {"message": "Query"}
|
apps/recommend/__init__.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import APIRouter
|
| 2 |
+
from fastapi.responses import JSONResponse
|
| 3 |
+
from .model import Recommendations, RecommendType
|
| 4 |
+
from .controller import recycle_recommendation
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
router = APIRouter(
|
| 8 |
+
prefix="/recommend",
|
| 9 |
+
tags=["recommend"],
|
| 10 |
+
default_response_class=JSONResponse,
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
@router.post("/", response_model=Recommendations)
|
| 15 |
+
async def recommend(data: RecommendType):
|
| 16 |
+
return recycle_recommendation(data.recommend_type)
|
apps/recommend/controller.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
from fastapi import HTTPException, status
|
| 3 |
+
from .provider import model
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
prompt_template = '''Think and generate content about how to recycle {type}
|
| 7 |
+
The recycle recommendation should be easy to understand and follow.
|
| 8 |
+
- For example, for the trash type "plastic bottle", provide how to use the plastic for household items.
|
| 9 |
+
- For the trash type "paper", provide how to do origami, etc.
|
| 10 |
+
|
| 11 |
+
You must answer clearly, easy to understand and step by step.
|
| 12 |
+
You must prompt professional and reliable information. No yapping.
|
| 13 |
+
|
| 14 |
+
You must provide an answer as a following JSON format:
|
| 15 |
+
{{
|
| 16 |
+
"recommendations": [
|
| 17 |
+
{{
|
| 18 |
+
"title": "Foo Bar",
|
| 19 |
+
"steps": [
|
| 20 |
+
"Foo",
|
| 21 |
+
"Bar"
|
| 22 |
+
]
|
| 23 |
+
}}
|
| 24 |
+
]
|
| 25 |
+
}}
|
| 26 |
+
'''
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def recycle_recommendation(trash_type: str):
|
| 30 |
+
prompt = prompt_template.format(type=trash_type)
|
| 31 |
+
|
| 32 |
+
answer = model.generate_content(prompt)
|
| 33 |
+
|
| 34 |
+
try:
|
| 35 |
+
parsed_data = json.loads(answer.text)
|
| 36 |
+
except json.JSONDecodeError:
|
| 37 |
+
raise HTTPException(
|
| 38 |
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
| 39 |
+
detail="Failed to parse the answer from the model"
|
| 40 |
+
)
|
| 41 |
+
|
| 42 |
+
return parsed_data
|
apps/recommend/model.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel, Field
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class Recommendation(BaseModel):
|
| 5 |
+
title: str = Field(..., title="Title of the recommendation")
|
| 6 |
+
steps: list[str] = Field(...,
|
| 7 |
+
title="Steps to follow to implement the recommendation")
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class Recommendations(BaseModel):
|
| 11 |
+
recommendations: list[Recommendation] = Field(
|
| 12 |
+
..., title="List of recommendations")
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
class RecommendType(BaseModel):
|
| 16 |
+
recommend_type: str = Field(..., title="Type of recommendation to return")
|
apps/recommend/provider.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import google.generativeai as genai
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
genai.configure(api_key=os.environ.get("GOOGLE_API_KEY"))
|
| 6 |
+
|
| 7 |
+
model = genai.GenerativeModel("gemini-pro")
|
main.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from apps.create_app import create_app
|
| 2 |
+
from apps.detection import router as detection_router
|
| 3 |
+
from apps.recommend import router as recommend_router
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
app = create_app()
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
# Register router
|
| 10 |
+
app.include_router(detection_router, prefix="/api")
|
| 11 |
+
app.include_router(recommend_router, prefix="/api")
|
models/yolo.pt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:b4292d72e8b4975e9561760e274839c18c066caa43b65c8dcea0fb37287d64eb
|
| 3 |
+
size 22557081
|
requirements.txt
ADDED
|
Binary file (2.39 kB). View file
|
|
|