pythondockerfastapipydantic

Cannot send a request through FastAPI in Python (Failed to connect to localhost port 8000 after 0 ms: Couldn't connect to server)


I devised a spam detecter for my example but I cannot send any request through Postman

Here is the requirement.txt file

fastapi
uvicorn[standard]
transformers
torch

Here is my python file shown below

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
from transformers import pipeline

class ClassifyRequest(BaseModel):
    text: str = Field(..., example="")
    lang: str = Field(
        "en",
        pattern=r"^(en|tr|de|fr|es|it|pt|ru|ar|zh|ja|ko|hi|bn|ur|fa|th|vi|id|ms|nl|sv|no|da|fi|pl|cs|sk|hu|ro|bg|hr|sr|sl|et|lv|lt|el|he|uk|be|ky|uz|km|my|tg|az|hy|ga|cy|is|mk|bs|sq|mn|ne|pa|gl|la)$",
        description="ISO language code",
        example="tr"
    )

class ClassifyResponse(BaseModel):
    label: str
    score: float

app = FastAPI(title="Spam & Abuse Detector")

classifier = pipeline(
    "zero-shot-classification",
    model="joeddav/xlm-roberta-large-xnli"
)

CANDIDATE_LABELS = ["spam", "adult_content", "drugs", "non_spam"]

@app.post("/classify", response_model=ClassifyResponse)
def classify(req: ClassifyRequest):
    res = classifier(
        sequences=req.text,
        candidate_labels=CANDIDATE_LABELS
    )
    best_idx = res["scores"].index(max(res["scores"]))
    label = res["labels"][best_idx]
    score = res["scores"][best_idx]
    return ClassifyResponse(label=label, score=score)

Here is Dockerfile

FROM python:3.10-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY app ./app

EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload", "--log-level", "info"]

When I run these commands shown below

docker build -t spam-detector .
docker run -p 8000:8000 spam-detector

I got this console output

INFO:     Will watch for changes in these directories: ['/app']
INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [1] using WatchFiles

When I send a request through Postman

curl -X POST http://127.0.0.1:8000/classify \
  -H "Content-Type: application/json" \
  -d '{"text":"bla bla","lang":"en"}'

I get "Failed to connect to localhost port 8000 after 0 ms: Couldn't connect to server"

How can I fix the issue?


Solution

  • It is not full solution but I get your Dockerfile and main.py and test it (on Linux Mint).

    Docker/Code works for me if I create fake data in response instead of using pipeline

    from fastapi import FastAPI, HTTPException
    from pydantic import BaseModel, Field
    
    class ClassifyRequest(BaseModel):
        text: str = Field(..., example="")
        lang: str = Field(
            "en",
            pattern=r"^(en|tr|de|fr|es|it|pt|ru|ar|zh|ja|ko|hi|bn|ur|fa|th|vi|id|ms|nl|sv|no|da|fi|pl|cs|sk|hu|ro|bg|hr|sr|sl|et|lv|lt|el|he|uk|be|ky|uz|km|my|tg|az|hy|ga|cy|is|mk|bs|sq|mn|ne|pa|gl|la)$",
            description="ISO language code",
            example="tr"
        )
    
    class ClassifyResponse(BaseModel):
        label: str
        score: float
    
    app = FastAPI(title="Spam & Abuse Detector")
    
    @app.get("/")
    def index():
        return {"Hello": "World"}
    
    CANDIDATE_LABELS = ["spam", "adult_content", "drugs", "non_spam"]
    
    @app.post("/classify", response_model=ClassifyResponse)
    def classify(req: ClassifyRequest):
        label = req.text               # <-- fake data
        score = float(len(req.text))   # <-- fake data
        return ClassifyResponse(label=label, score=score)
    

    If this works for you then at least you will know that Dockerfile and FastAPI is OK.

    And at start it shows more info in output:

    INFO:     Will watch for changes in these directories: ['/app']
    INFO:     Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
    INFO:     Started reloader process [1] using WatchFiles
    INFO:     Started server process [8]
    INFO:     Waiting for application startup.
    INFO:     Application startup complete.
    

    Now you have to find out why pipeline makes problem.

    Maybe at start it has to generate some data and it needs longer time before it can get users requests. Or maybe problem make --reload because your output shows Started reloader ... as last information. I didn't test it yet.