Deploy Spacy Ner With Fast Api

January 28, 2021
SpaCy NER NLP SpaCy

In my previous post here: https://yudanta.github.io/posts/train-an-indonesian-ner-from-a-blank-spacy-model/, I shared about how to train simple Indonesian NER model with SpaCy. The detail of training process can be found in that article. In this post, we will focus on how to deploy the model as a REST API with FastAPI, so the users can query to our NER model via REST API. However, in this tutorial, will focus on how to create simple FastAPI project and load pre-trained NER model, if you are not familiar with FastAPI yet, please go to the FastAPI documentation site here: https://fastapi.tiangolo.com/tutorial/.

First, I already prepare the trained model here in this directory nlp_models/nlp_id_checkpoint_2021-01-12, for the example, so you don’t have to train the model, except you are have your own model previously or more datasets then use your own model.

We structured the FastAPI model as below:

├── README.md
├── app
│   ├── __init__.py
│   ├── apis
│   │   └── nlp
│   │       ├── __init__.py
│   │       └── ner.py
│   ├── core
│   │   └── __init__.py
│   ├── main.py
│   ├── routes
│   │   ├── __init__.py
│   │   └── nlp.py
│   └── tests
│       └── __init__.py
├── config.py
├── logging.conf
├── nlp_models
│   └── nlp_id_checkpoint_2021-01-12
└── requirements.txt

To load pre-trained spacy model in ```main.py``

from pathlib import Path
import spacy

model_dir = Path('nlp_models/nlp_id_checkpoint_2021-01-12')
id_nlp = spacy.load(model_dir)

I add ner.py under app/apis/nlp for handling query from users to SpaCy model

from typing import List, Dict
from ...main import id_nlp


def get_entities(sentence) -> List[Dict]:
    doc = id_nlp(sentence)
    return [(ent.text, ent.label_) for ent in doc.ents]

and for handling the http route/request, the script for http routing is in nlp.py file

from typing import Optional
from fastapi import APIRouter
from pydantic import BaseModel

class NerQuery(BaseModel):
    sentence: str


from ..apis.nlp.ner import get_entities

router = APIRouter(
    prefix='/nlp/id',
    tags=['nlp'],
    responses={
        404: {'description': 'Not Found'}
    }
)

@router.post('/ner')
async def api_ner(query: NerQuery):
    result = get_entities(query.sentence)
    return result

Lastly, we add the router to the main.py file with include_router

app = FastAPI()

from .routes import nlp

app.include_router(nlp.router)

to run the project with uvicorn:

uvicorn app.main:app --reload

wait a moments, some time required for loading SpaCy model.

You can access the generated documentation here: http://localhost:8000/docs#/nlp/api_ner_nlp_id_ner_post, try to query directly from the swagger or using curl like below

curl -X POST "http://localhost:8000/nlp/id/ner" -H  "accept: application/json" -H  "Content-Type: application/json" -d "{\"sentence\":\"Bekas Anggota BPK Rizal Djalil Didakwa Menerima Suap Rp 1 Miliar.\"}"

result

[
  [
    "Rizal Djalil",
    "PERSON"
  ]
]

the complete codes for this project can be found on this repository: https://github.com/yudanta/id-ner-spacy-fast-api, maybe, later I will add docker file for this project and maybe provide an online demo (but not promise :D)

comments powered by Disqus