Spaces:
Sleeping
Sleeping
Download app.py from kshitiz14/product_attribute: direct link, hf CLI and curl.
- Browser
- Download file 2.29 kB
-
https://huggingface.co/spaces/kshitiz14/product_attribute/resolve/main/app.py
- Command line
-
hf download hf://spaces/kshitiz14/product_attribute/app.py
-
curl -L -o app.py https://huggingface.co/spaces/kshitiz14/product_attribute/resolve/main/app.py
2.29 kB
| """ | |
| Root-level FastAPI entrypoint (Hugging Face Spaces convention expects an | |
| app.py at the repo root defining `app`). | |
| This is a thin wrapper: the actual extraction logic lives in src/ (rules | |
| extractor, trained ML model, ensemble predictor) so the core pipeline stays | |
| testable and importable on its own; this file just wires it up as the | |
| Space's entrypoint and defines the HTTP endpoints. | |
| Run locally from the repo root: | |
| uvicorn app:app --reload --port 8000 | |
| On Hugging Face Docker Spaces, the Dockerfile's CMD runs this same module | |
| on port 7860. | |
| """ | |
| import os | |
| import sys | |
| BASE_DIR = os.path.dirname(os.path.abspath(__file__)) | |
| SRC_DIR = os.path.join(BASE_DIR, "src") | |
| sys.path.insert(0, SRC_DIR) | |
| MODEL_PATH = os.path.join(SRC_DIR, "model.joblib") | |
| from fastapi import FastAPI, HTTPException | |
| from pydantic import BaseModel, Field | |
| from rules_extractor import extract_attributes_rules | |
| from predict import predict_ensemble, predict_ml | |
| app = FastAPI( | |
| title="Product Attribute Extraction API", | |
| description="Converts unstructured product/fashion descriptions into structured attributes.", | |
| version="1.0.0", | |
| ) | |
| class ExtractRequest(BaseModel): | |
| text: str = Field(..., min_length=1, description="Raw product description text") | |
| mode: str = Field( | |
| "ensemble", | |
| description="Extraction mode: 'ensemble' (default, rules+ml), 'ml', or 'rules'", | |
| ) | |
| class ExtractResponse(BaseModel): | |
| text: str | |
| attributes: dict | |
| mode: str | |
| from fastapi.responses import RedirectResponse | |
| def root(): | |
| return RedirectResponse(url="/docs") | |
| def health(): | |
| return {"status": "ok"} | |
| def extract(req: ExtractRequest): | |
| text = req.text.strip() | |
| if not text: | |
| raise HTTPException(status_code=400, detail="text must not be empty") | |
| if req.mode == "rules": | |
| attrs = extract_attributes_rules(text) | |
| elif req.mode == "ml": | |
| attrs = predict_ml(text, model_path=MODEL_PATH) | |
| elif req.mode == "ensemble": | |
| attrs = predict_ensemble(text, model_path=MODEL_PATH) | |
| else: | |
| raise HTTPException(status_code=400, detail="mode must be one of: ensemble, ml, rules") | |
| return ExtractResponse(text=text, attributes=attrs, mode=req.mode) | |