Galle, LK--:--5/6 sites live

Deploying ML model as public API ngrok

ඔයාගෙ laptop එකේ විතරක් run වෙන API එකක්, ලෝකෙට invisible. ඒකට ඇත්තටම temporary public address එකක් දීලා, අනිත් අයට ඇත්තටම call කරන්න පුළුවන් කරන trick එකයි මේක.

An API running only on your own laptop is invisible to the rest of the world. This is the trick that gives it a real, temporary public address so others can actually call it.

20 May 20263 min readSelf Guide · Stage 17#Shipping Models to the World#ML model - as Public API#Machine learning

Lesson 58 of 64 · Part 5 · Shipping Models to the World · ML model - as Public API · bilingual notes (English + සිංහල)

Why this matters. An API running only on your own laptop is invisible to the rest of the world. This is the trick that gives it a real, temporary public address so others can actually call it.

සිංහලෙන්: ඔයාගෙ laptop එකේ විතරක් run වෙන API එකක්, ලෝකෙට invisible. ඒකට ඇත්තටම temporary public address එකක් දීලා, අනිත් අයට ඇත්තටම call කරන්න පුළුවන් කරන trick එකයි මේක.

What you'll use this for. Useful for quick demos and testing with teammates before you invest in proper cloud hosting — the next lesson (Heroku) is the permanent version of this same idea.

සිංහලෙන්: Proper cloud hosting එකකට invest කරන්නත් කලින්, quick demos වලට, teammates එක්ක test කරන්නත් ප්‍රයෝජනවත් — ඊළඟ පාඩම (Heroku) තමයි මේම අදහසේ permanent version එක.

Key principles

  • A tunnel is temporary by design — it's for demos, not production. The public URL ngrok gives you changes every time you restart it — which is exactly why real applications use proper hosting (like the next lesson) instead.
    Tunnel එකක් design එකෙන්ම temporary — demos වලට, production වලට නෙවෙයි

Walkthrough

Installing the dependencies

ExamplePython
!pip install fastapi
!pip install uvicorn
!pip install pickle5
!pip install pydantic
!pip install scikit-learn
!pip install requests
!pip install pypi-json
!pip install pyngrok
!pip install nest-asyncio

Output

Output
Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/
Collecting fastapi
  Downloading fastapi-0.78.0-py3-none-any.whl (54 kB)
     |████████████████████████████████| 54 kB 2.8 MB/s 
[?25hCollecting starlette==0.19.1
  Downloading starlette-0.19.1-py3-none-any.whl (63 kB)
     |████████████████████████████████| 63 kB 2.0 MB/s 
[?25hCollecting pydantic!=1.7,!=1.7.1,!=1.7.2,!=1.7.3,!=1.8,!=1.8.1,<2.0.0,>=1.6.2
  Downloading pydantic-1.9.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (11.1 MB)
     |████████████████████████████████| 11.1 MB 48.4 MB/s 
[?25hCollecting anyio<5,>=3.4.0
  Downloading anyio-3.6.1-py3-none-any.whl (80 kB)
     |████████████████████████████████| 80 kB 6.5 MB/s 
[?25hRequirement already satisfied: typing-extensions>=3.10.0 in /usr/local/lib/python3.7/dist-packages (from starlette==0.19.1->fastapi) (4.2.0)
Collecting sniffio>=1.1
  Downloading sniffio-1.2.0-py3-none-any.whl (10 kB)
Requirement already satisfied: idna>=2.8 in /usr/local/lib/python3.7/dist-packages (from anyio<5,>=3.4.0->starlette==0.19.1->fastapi) (2.10)
Installing collected packages: sniffio, anyio, starlette, pydantic, fastapi
… (87 more lines)
ExamplePython
from fastapi import FastAPI
from pydantic import BaseModel
import pickle
import json
import uvicorn
from pyngrok import ngrok
from fastapi.middleware.cors import CORSMiddleware
import nest_asyncio
ExamplePython
app = FastAPI()
ExamplePython
origins = ["*"]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
ExamplePython
class model_input(BaseModel):
    
    Pregnancies : int
    Glucose : int
    BloodPressure : int
    SkinThickness : int
    Insulin : int
    BMI : float
    DiabetesPedigreeFunction : float
    Age : int
ExamplePython
# loading the saved model
diabetes_model = pickle.load(open('diabetes_model.sav', 'rb'))
ExamplePython
@app.post('/diabetes_prediction')
def diabetes_predd(input_parameters : model_input):
    
    input_data = input_parameters.json()
    input_dictionary = json.loads(input_data)
    
    preg = input_dictionary['Pregnancies']
    glu = input_dictionary['Glucose']
    bp = input_dictionary['BloodPressure']
    skin = input_dictionary['SkinThickness']
    insulin = input_dictionary['Insulin']
    bmi = input_dictionary['BMI']
    dpf = input_dictionary['DiabetesPedigreeFunction']
    age = input_dictionary['Age']
    
    
    input_list = [preg, glu, bp, skin, insulin, bmi, dpf, age]
    
    prediction = diabetes_model.predict([input_list])
    
    if (prediction[0] == 0):
        return 'The person is not diabetic'
    else:
        return 'The person is diabetic'
ExamplePython
ngrok_tunnel = ngrok.connect(8000)
print('Public URL:', ngrok_tunnel.public_url)
nest_asyncio.apply()
uvicorn.run(app, port=8000)

Output

Output
INFO:     Started server process [61]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

Output

Output
Public URL: http://05ca-34-83-94-130.ngrok.io
INFO:     106.198.81.151:0 - "POST /diabetes_prediction HTTP/1.1" 200 OK

Output

Output
/usr/local/lib/python3.7/dist-packages/sklearn/base.py:451: UserWarning: X does not have valid feature names, but SVC was fitted with feature names
  "X does not have valid feature names, but"

Output

Output
INFO:     106.198.81.151:0 - "POST /diabetes_prediction HTTP/1.1" 200 OK

Output

Output
/usr/local/lib/python3.7/dist-packages/sklearn/base.py:451: UserWarning: X does not have valid feature names, but SVC was fitted with feature names
  "X does not have valid feature names, but"
INFO:     Shutting down
INFO:     Waiting for application shutdown.
INFO:     Application shutdown complete.
INFO:     Finished server process [61]

Keep going: ← Lesson 57 · Lesson 59 → · Track it in the Self Guide