Home »
Blog »
AI/ML Engineer সিরিজ » Series 09 » Episode 02
FastAPI দিয়ে model serving: REST API, request/response, validation
Project P9 — real inference API (Series 09, Episode 02)
🟡 INTERMEDIATE
Series 09 — Notebook থেকে Production AI
Episode 02 / 09
📑 এই পর্বে যা যা আছে
- ১. গল্প: "API দাও, notebook না"
- ২. সমস্যা: model আর বাইরের দুনিয়ার মধ্যে সেতু
- ৩. REST API আসলে কী — চায়ের দোকানের গল্পে
- ৪. কেন FastAPI (Flask/Django নয় কেন)
- ৫. তিন স্তরে: request → prediction → response
- ৬. Setup ও প্রথম endpoint
- ৭. Model load করা — startup-এ একবার
- ৮. Pydantic দিয়ে input validation
- ৯. পুরো /predict endpoint (churn model)
- ১০. চালানো ও test করা (docs, curl)
- ১১. Experiment: ভুল input পাঠিয়ে দেখো
- ১২. বাংলাদেশের বাস্তব উদাহরণ
- ১৩. AI Engineer perspective: sync, batch, health check
- ১৪. Boss Question
- ১৫. Job Requirement Decoder: "FastAPI / REST API for ML"
- ১৬. সাধারণ ভুল
- ১৭. Interview Prep
- ১৮. হাতে-কলমে
- ১৯. Project Connection: flagship V8
- ২০. সারসংক্ষেপ ও পরের পর্ব
🎬 ১. গল্প: "API দাও, notebook না"
গত পর্বে Rahim বুঝেছিল তার churn model শুধু তার laptop-এ বন্দি। আজ সে Maya-র কাছে গেল: "আপা, তাহলে
marketing team-কে কী দেব?" Maya বলল —
"ওদের একটা endpoint দাও। একটা URL, যেখানে ওরা একজন customer-এর তথ্য POST করবে, আর
সাথে সাথে ফেরত পাবে {"churn_risk": 0.82}। ওরা জানতেও চায় না ভেতরে RandomForest আছে না
XGBoost — ওরা শুধু input দেবে, output নেবে। এটাই একটা REST API, আর Python-এ এটা
বানানোর সবচেয়ে ভালো আধুনিক tool হলো FastAPI।"
আজ আমরা Rahim-এর সেই প্রথম real inference API বানাব।
❓ ২. সমস্যা: model আর বাইরের দুনিয়ার মধ্যে সেতু
আমাদের কাছে একটা saved model (model.pkl) আছে। বাইরে আছে অনেক client — mobile app, web
dashboard, অন্য backend service। এদের প্রত্যেকে ভিন্ন ভাষায় লেখা (JavaScript, Java, PHP...)। এরা কেউ
Python object সরাসরি ব্যবহার করতে পারে না।
দরকার এমন একটা common ভাষা যা সবাই বোঝে — সেটা হলো HTTP + JSON।
একটা REST API ঠিক এই সেতুটাই তৈরি করে: যেকোনো client → HTTP request → তোমার service → JSON response।
☕ ৩. REST API আসলে কী — চায়ের দোকানের গল্পে
Level 1 — সহজ intuition:
একটা চায়ের দোকান ভাবো। তুমি জানালায় গিয়ে বলো "একটা দুধ চা" (request)। ভেতরে কে চা বানাচ্ছে, কোন
পদ্ধতিতে — জানার দরকার নেই। কিছুক্ষণ পর হাতে চা পাও (response)। REST API-ও তেমন: তুমি একটা নির্দিষ্ট
"জানালায়" (endpoint/URL) নির্দিষ্ট ফরম্যাটে অর্ডার দাও, নির্দিষ্ট ফরম্যাটে ফল পাও।
Level 2 — technical:
REST API হলো HTTP-ভিত্তিক একটা interface। প্রতিটা "জানালা" একটা endpoint (যেমন
/predict)। প্রতিটা অর্ডারের একটা method থাকে — GET (তথ্য
পড়া), POST (নতুন কিছু পাঠানো/process করা)। ML prediction-এ আমরা সাধারণত POST
ব্যবহার করি, কারণ আমরা input data পাঠাচ্ছি। Data যায়-আসে JSON ফরম্যাটে।
Level 3 — AI Engineer perspective:
Engineer endpoint design করে business অনুযায়ী: POST /predict (একটা prediction),
POST /predict/batch (একসাথে অনেক), GET /health (service বেঁচে আছে কিনা)।
প্রতিটা endpoint-এর input/output contract পরিষ্কার রাখে যাতে client team সহজে integrate করতে পারে।
⚡ ৪. কেন FastAPI (Flask/Django নয় কেন)
আমরা কোনো tool "জনপ্রিয়" বলে বাছি না — কারণ দেখে বাছি:
| Tool | ML serving-এ ভূমিকা | কখন |
| FastAPI | দ্রুত, modern, Pydantic দিয়ে auto input validation, auto docs (/docs), async support | নতুন ML API — default পছন্দ |
| Flask | সহজ, হালকা, কিন্তু validation/docs নিজে যোগ করতে হয় | খুব ছোট/legacy project |
| Django | full-stack, ভারী (ORM, admin, auth) | বড় web app যেখানে ML একটা অংশমাত্র |
কেন FastAPI আমাদের পছন্দ: (১) Pydantic দিয়ে input নিজে থেকেই validate
হয় — ভুল data এলে পরিষ্কার error দেয়; (২) /docs-এ নিজে থেকে interactive
documentation তৈরি হয় — client team খুশি; (ৃৃৃ৩) দ্রুত ও async-ready, যা LLM API-এর মতো
I/O-heavy কাজে দারুণ (Series 02-এর async মনে আছে?)।
🔧 ৬. Setup ও প্রথম endpoint
প্রথমে environment (Series 02-এর uv/venv মনে করো) আর দরকারি package:
# environment তৈরি ও package install
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install fastapi uvicorn scikit-learn joblib pydantic
এবার সবচেয়ে ছোট FastAPI app — main.py:
# main.py
from fastapi import FastAPI
app = FastAPI(title="Churn Prediction API")
@app.get("/health")
def health():
# service বেঁচে আছে কিনা জানার সহজ উপায়
return {"status": "ok"}
চালাও: uvicorn main:app --reload। এখানে uvicorn হলো সেই server যে তোমার
app-কে চালু রাখে; --reload কোড বদলালে নিজে restart করে (শুধু development-এ)।
📦 ৭. Model load করা — startup-এ একবার
একটা বড় ভুল হলো প্রতিটা request-এ model joblib.load() করা — এটা প্রচণ্ড ধীর করে দেয়।
সঠিক উপায়: app চালু হওয়ার সময় একবার load করে memory-তে রেখে দেওয়া।
# main.py (model load অংশ)
import joblib
from fastapi import FastAPI
app = FastAPI(title="Churn Prediction API")
# module load হওয়ার সময় একবারই চলে -> সব request এই model share করে
model = joblib.load("model.pkl")
মনে রাখো — এখানে কোনো fit() নেই। এটাই inference: আগে train করা model
শুধু load করে ব্যবহার করছি। train আর serve সবসময় আলাদা রাখো।
🛡️ ৮. Pydantic দিয়ে input validation
Client ভুল data পাঠাতেই পারে (tenure-এ string, বা field বাদ)। Pydantic দিয়ে আমরা input-এর
একটা schema ঠিক করে দিই — FastAPI নিজে থেকেই যাচাই করে, ভুল হলে সুন্দর error দেয়।
# schemas.py
from pydantic import BaseModel, Field
class Customer(BaseModel):
tenure: int = Field(ge=0, description="কত মাস ধরে customer")
monthly_charges: float = Field(ge=0)
contract_type: str # "month-to-month" | "one-year" | "two-year"
class Prediction(BaseModel):
churn_risk: float
will_churn: bool
Field(ge=0) মানে "greater than or equal to 0" — negative tenure আসতেই পারবে না।
Output-এরও একটা schema (Prediction) রাখলে API contract স্পষ্ট থাকে।
🎯 ৯. পুরো /predict endpoint (churn model)
# main.py (সম্পূর্ণ)
import joblib
import pandas as pd
from fastapi import FastAPI
from schemas import Customer, Prediction
app = FastAPI(title="Churn Prediction API")
model = joblib.load("model.pkl")
@app.get("/health")
def health():
return {"status": "ok"}
@app.post("/predict", response_model=Prediction)
def predict(customer: Customer):
# 1) Pydantic model -> DataFrame (model যেভাবে train হয়েছিল)
row = pd.DataFrame([customer.model_dump()])
# 2) inference: probability বের করা
proba = model.predict_proba(row)[0][1] # churn=1 এর probability
# 3) business rule: 0.5-এর বেশি হলে churn ধরি
return Prediction(churn_risk=round(float(proba), 3),
will_churn=bool(proba >= 0.5))
খেয়াল করো তিনটা পরিষ্কার ধাপ: input → preprocessing → inference → response। বাস্তব
project-এ preprocessing (encoding, scaling) ঠিক এখানেই বসবে — আর সেটা train-এর সময় যা করেছিলে তার
হুবহু একই হতে হবে (নাহলে training-serving skew হবে)।
▶️ ১০. চালানো ও test করা (docs, curl)
Server চালাও: uvicorn main:app --reload। এবার তিনভাবে test করা যায়:
# 1) Browser-এ auto docs: http://127.0.0.1:8000/docs
# -> Pydantic থেকে FastAPI নিজেই interactive UI বানায়
# 2) curl দিয়ে:
curl -X POST http://127.0.0.1:8000/predict \
-H "Content-Type: application/json" \
-d '{"tenure": 3, "monthly_charges": 85.5, "contract_type": "month-to-month"}'
# উদাহরণ response:
# {"churn_risk": 0.82, "will_churn": true}
এই মুহূর্তে Rahim-এর model অবশেষে বাইরের দুনিয়ায়। marketing team-এর যেকোনো developer এই curl বা docs
দেখে integrate করতে পারবে।
🧪 ১১. Experiment: ভুল input পাঠিয়ে দেখো
"tenure": "hello" পাঠাও — FastAPI নিজে 422 error দেবে, model পর্যন্ত পৌঁছাবেই না।
tenure বাদ দিয়ে পাঠাও — "field required" error।
- negative
monthly_charges পাঠাও — validation আটকে দেবে।
এটাই FastAPI-এর শক্তি: তুমি একটা line-ও validation কোড না লিখেই তোমার API-কে ভুল data থেকে রক্ষা করছ।
🇧🇩 ১২. বাংলাদেশের বাস্তব উদাহরণ
- bKash fraud check: transaction service একটা
POST /score এ transaction
পাঠায়, milliseconds-এ fraud probability ফেরত পায় — ঠিক এই pattern।
- Daraz recommendation: app
GET /recommend?user_id=... call করে product
list পায়।
- একটা local job portal: আমাদের flagship-এর মতো — একটা JD paste করলে
/analyze endpoint দরকারি skill আর probable role ফেরত দেয়।
👷 ১৩. AI Engineer perspective: sync, batch, health check
- /health endpoint — cloud/monitoring tool এটা দিয়ে চেক করে service জীবিত কিনা।
এটা প্রায় বাধ্যতামূলক।
- Batch endpoint — marketing প্রতিদিন ১০,০০০ customer score চায়? একটা করে request
না পাঠিয়ে একটা
/predict/batch বানাও যা list নেয়।
- Sync বনাম async — CPU-তে চলা sklearn model সাধারণত sync ঠিক আছে। কিন্তু ভেতরে যদি
একটা LLM/external API call থাকে (I/O wait), তখন
async def সাহায্য করে (Series 02 recap)।
💼 ১৪. Boss Question
💼 Boss: "এই API বানিয়ে আমার কী লাভ? আগে তো notebook-এও prediction হচ্ছিল।"
উত্তর: পার্থক্যটা হলো — এখন আপনার marketing app, dashboard, বা যেকোনো team
নিজে থেকেই ২৪/৭ এই prediction ব্যবহার করতে পারবে, আমাকে ছাড়াই। আগে prediction পেতে আমাকে ডাকতে হতো, এখন
একটা URL হিট করলেই হবে। মানে model এখন একটা পুনর্ব্যবহারযোগ্য business capability —
একবার বানিয়ে বহু জায়গায় কাজে লাগবে।
🔎 ১৫. Job Requirement Decoder: "Build REST APIs for ML models (FastAPI/Flask)"
- কী বোঝায়? ML model-কে HTTP endpoint হিসেবে expose করা, যাতে অন্য software ব্যবহার করতে পারে।
- কেন চায়? প্রায় সব ML product-এই model-কে API হিসেবে serve করা হয় — এটা industry standard।
- কোন সমস্যা সমাধান করে? model আর বাকি system-এর মধ্যে integration সেতু।
- Junior-এর কী জানা লাগে? FastAPI দিয়ে
GET/POST endpoint, Pydantic
validation, model load, JSON response, /docs ব্যবহার।
- এখনই কী master লাগে না? high-throughput serving, gRPC, model server (Triton/TorchServe),
streaming response — পরে।
- GitHub-এ কীভাবে দেখাবে? একটা
app.py + schemas.py +
README-তে curl example ও /docs screenshot; সম্ভব হলে live demo link।
- Interview-তে কী জিজ্ঞেস করতে পারে? "GET vs POST কখন?", "Pydantic কেন?",
"model কোথায় load করবে — request-এ না startup-এ?", "422 error কী?"
⚠️ ১৬. সাধারণ ভুল
ভুল ১: প্রতিটা request-এ joblib.load()। → startup-এ একবার load করো।
ভুল ২: serving-এ preprocessing training-এর থেকে আলাদা। → training-serving skew, ভুল
prediction। হুবহু একই preprocessing ব্যবহার করো।
ভুল ৩: input validation না রাখা। → garbage in, crash out। Pydantic ব্যবহার করো।
ভুল ৪: --reload দিয়ে production চালানো। → এটা শুধু development-এর জন্য।
ভুল ৫: error handle না করা (model file নেই, বা unknown category)। → try/except + সঠিক
HTTP status ফেরত দাও।
🎤 ১৭. Interview Prep
প্রশ্ন ১: "একটা ML model কীভাবে API হিসেবে expose করবে?"
উত্তর: model save → FastAPI app-এ startup-এ load → Pydantic schema দিয়ে input → /predict
POST endpoint → preprocessing + inference → JSON response।
প্রশ্ন ২: "কেন FastAPI, Flask নয়?"
উত্তর: auto validation (Pydantic), auto interactive docs, async support, ও গতি — ML serving-এ কম কোডে বেশি নিরাপত্তা।
প্রশ্ন ৩: "model কি প্রতিটা request-এ load করবে?"
উত্তর: না, startup-এ একবার; নাহলে প্রতিটা request ধীর হবে।
প্রশ্ন ৪: "training-serving skew কী?"
উত্তর: train আর serve-এর সময় preprocessing আলাদা হলে model ভুল করে — একই preprocessing pipeline
দুই জায়গায় ব্যবহার করাই সমাধান।
✍️ ১৮. হাতে-কলমে
Mini exercise:
১. Series 05-এর যেকোনো model joblib.dump করে save করো।
২. উপরের কোড দিয়ে একটা FastAPI app বানাও: /health + /predict।
৩. uvicorn main:app --reload চালিয়ে /docs-এ গিয়ে একটা prediction করো।
৪. একটা POST /predict/batch যোগ করো যা list[Customer] নেয় ও list ফেরত দেয়।
৫. ভুল input পাঠিয়ে দেখো কী error আসে — বুঝে নাও validation কীভাবে রক্ষা করছে।
🚀 ১৯. Project Connection: flagship V8
এই episode-এ আমাদের flagship "Bangladesh Tech Career Assistant" V7 (RAG) থেকে
V8 (FastAPI)-এ পৌঁছাল। এখন আমরা একটা POST /analyze endpoint বানাব যা একটা
job description নেয় এবং দরকারি skill + probable role ফেরত দেয়। এটাই আমাদের Project P9
(Production AI API)-এর মূল অংশ।
তোমার কাজ: flagship-এর inference অংশটাকে একটা function-এ আলাদা করো (analyze_jd(text) -> dict),
তারপর সেটাকে FastAPI endpoint দিয়ে wrap করো। পরের episode-এ আমরা এই messy কোডকে একটা পরিষ্কার package বানাব।
📌 ২০. সারসংক্ষেপ ও পরের পর্ব
এই episode-এ আমরা শিখলাম:
✓ REST API = HTTP+JSON দিয়ে model আর বাইরের দুনিয়ার সেতু
✓ কেন FastAPI (auto validation, auto docs, async, গতি)
✓ model startup-এ একবার load করা (request-এ নয়) — এটাই সঠিক inference pattern
✓ Pydantic schema দিয়ে input/output contract ও automatic validation
✓ /predict, /health, batch endpoint — ও curl/docs দিয়ে test
পরের episode-এ আমরা এই এক-file-এর messy কোডকে একটা পরিষ্কার Python package বানাব —
config, structured logging আর secrets management সহ — যাতে এটা সত্যিকারের service-grade কোড হয়।