File size: 1,942 Bytes
896a559
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e9eb2f6
 
 
 
 
 
896a559
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
"""
FastAPI service exposing POST /extract.

Run locally:
    uvicorn api:app --reload --port 8000

Example:
    curl -X POST http://localhost:8000/extract \
         -H "Content-Type: application/json" \
         -d '{"text": "Lace mermaid wedding dress with long sleeves and scalloped hem"}'
"""
import os
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
from typing import List

from predict import predict_ensemble, predict_ml
from rules_extractor import extract_attributes_rules

MODEL_PATH = os.path.join(os.path.dirname(__file__), "model.joblib")

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

@app.get("/")
def read_root():
    return RedirectResponse(url="/docs")

@app.get("/health")
def health():
    return {"status": "ok"}


@app.post("/extract", response_model=ExtractResponse)
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)