Imate težave z umetno inteligenco ali razvojem celotnega paketa? Naši strokovnjaki so vam na voljo za pomoč: prilagojeni nasveti, tehnična integracija in še več. Obrnite se na [email protected].

API za strojno učenje in obdelavo naravnega jezika za klasifikacijo s FastAPI in transformatorji, pripravljen za produkcijo

Objavljena je bila prva različica vmesnika FastAPI konec leta 2018 in od takrat se vse pogosteje uporablja v številnih aplikacijah v produkciji. (Oglejte si spletno mesto FastAPI). To je kar uporabljamo v oblaku NLP Cloud. To je odličen način za enostavno in učinkovito služenje našim stotine modelov obdelave naravnega jezika za ekstrakcijo entitet (NER), klasifikacijo besedil, analizo čustev, analizo vprašanj odgovarjanje na vprašanja, povzemanje... Ugotovili smo, da je FastAPI odličen način, da postrežemo z globokimi modeli, ki temeljijo na transformatorjih. modeli učenja.

V tem članku bi bilo zanimivo prikazati, kako izvajamo API za obdelavo naravnega jezika, ki temelji na transformatorjih Hugging Face s FastAPI.

Zakaj uporabiti FastAPI?

Pred FastAPI smo za svoje API-je v Pythonu v osnovi uporabljali Django Rest Framework, vendar smo hitro zanimal FastAPI iz naslednjih razlogov:

Zaradi teh odličnih zmogljivosti je FastAPI popolnoma primeren za API za strojno učenje. modelov, ki temeljijo na transformatorjih, kot je naš.

Namestitev FastAPI

Da bi FastAPI deloval, ga povezujemo s strežnikom Uvicorn ASGI, ki je sodoben način za nativno obdelavo asinhronih zahtevkov Python z asyncio. Lahko se odločite za FastAPI z Uvicornom namestite ročno ali pa prenesete sliko Docker, ki je pripravljena za uporabo. Pokažimo najprej ročno namestitev:

pip install fastapi[all]

Nato ga lahko začnete z:

uvicorn main:app

Sebastián Ramírez, ustvarjalec vmesnika FastAPI, ponuja več slik Docker, ki so pripravljene za uporabo in s katerimi je mogoče uporabo FastAPI v produkciji. Uvicorn + Gunicorn + FastAPI izkorišča prednosti sistema Gunicorn za vzporedno uporabo več procesov (Oglejte si sliko tukaj). Na koncu se je zahvaljujoč Uvicorn lahko upravljate več instanc FastAPI znotraj istega procesa Python, in zahvaljujoč Gunicorn lahko sprožite več procesov Python.

Vaša aplikacija FastAPI se bo samodejno zagnala ob zagonu vsebnika Docker z naslednjim: docker run.

Pomembno je, da pravilno preberete dokumentacijo teh slik Docker, saj so nekatere nastavitve, ki jih kot je na primer število vzporednih procesov, ki jih ustvari Gunicorn. Privzeto, slika ustvari toliko procesov, kolikor je procesorskih jeder v vašem računalniku. Toda v primeru zahtevnih modelov strojnega učenja, kot so pretvorniki za obdelavo naravnega jezika, lahko to hitro privede do več deset GB porabljenega pomnilnika. Ena stran strategija bi bila uporaba možnosti Gunicorn (--preload), za nalaganje model v pomnilnik naložite samo enkrat in ga delite med vse procese FastAPI Python. Druga možnost je je omejiti število procesov Gunicorn. Obe možnosti imata prednosti in slabosti, vendar to presega okvire obsega tega članka.

Enostavni vmesnik API FastAPI + Transformers za razvrščanje besedil

Klasifikacija besedila je postopek določanja, o čem govori besedilo (Prostor? O čem? Hrana?...). Več podrobnosti o besedilu razvrstitev tukaj.

Želimo ustvariti končno točko API, ki izvaja razvrščanje besedila z uporabo Facebookovega Bart Large MNLI ki je vnaprej usposobljen model, ki temelji na transformatorjih Hugging Face in je popolnoma primeren za besedilo. za razvrščanje besedil.

Naša končna točka API bo kot vhodni podatek sprejela del besedila in morebitne kategorije (imenovane oznake), in vrne oceno za vsako kategorijo (čim višja je, tem večja je verjetnost).

Končno točko bomo zahtevali z zahtevki POST, kot sledi:

curl "https://api.nlpcloud.io/v1/bart-large-mnli/classification" \
-H "Authorization: Token e7f6539e5a5d7a16e15" \
-X POST -d '{
    "text":"John Doe is a Go Developer at Google. He has been working there for 10 years and has been awarded employee of the year.",
    "labels":["job", "nature", "space"]
}'

V zameno smo dobili odgovor, kot je:

{
    "labels": [
        "job",
        "space",
        "nature"
    ],
    "scores": [
        0.9258803129196167,
        0.19384843111038208,
        0.010988432914018631
    ]
}

Tukaj je opisano, kako to doseči s FastAPI in transformatorji:

from fastapi import FastAPI
from pydantic import BaseModel, constr, conlist
from typing import List
from transformers import pipeline

classifier = pipeline("zero-shot-classification",
                model="facebook/bart-large-mnli")
app = FastAPI()

class UserRequestIn(BaseModel):
    text: constr(min_length=1)
    labels: conlist(str, min_items=1)

class ScoredLabelsOut(BaseModel):
    labels: List[str]
    scores: List[float]

@app.post("/classification", response_model=ScoredLabelsOut)
def read_classification(user_request_in: UserRequestIn):
    return classifier(user_request_in.text, user_request_in.labels)

Najprej: naložimo Facebookov Bart Large MNLI iz repozitorija Hugging Face in in ga pravilno inicializiramo za namene klasifikacije, zahvaljujoč transformatorskemu cevovodu:

classifier = pipeline("zero-shot-classification",
                model="facebook/bart-large-mnli")

Kasneje pa s tem uporabljamo model:

classifier(user_request_in.text, user_request_in.labels)

Druga pomembna stvar: s pomočjo programa Pydantic preverjamo podatke. Pydantic vas prisili, da vnaprej prijaviti vhodni in izhodni format za vaš API, kar je odlično z vidika dokumentacije. vidika, pa tudi zato, ker omejuje morebitne napake. V jeziku Go bi naredili skoraj enako stvar z razčlenjevanjem JSON s strukturami. Tukaj je enostaven način za izjavite, da mora polje "besedilo" vsebovati vsaj 1 znak: constr(min_length=1). V nadaljevanju pa je določeno, da mora vhodni seznam nalepk na seznamu vsebovati en element: conlist(str, min_items=1). Ta vrstica pomeni, da mora biti izhodno polje "labels" seznam nizov: List[str]. Ta pomeni, da morajo biti rezultati seznam plavajočih elementov: List[float]. Če model vrne rezultate, ki ne ustrezajo tej obliki, FastAPI samodejno sporoči napako.

class UserRequestIn(BaseModel):
    text: constr(min_length=1)
    labels: conlist(str, min_items=1)

class ScoredLabelsOut(BaseModel):
    labels: List[str]
    scores: List[float]

Nazadnje, z naslednjim dekoratorjem lahko preprosto določite, da sprejemate samo zahteve POST na določeni končni točki: @app.post("/entities", response_model=EntitiesOut).

Naprednejše preverjanje podatkov

Izvedete lahko veliko bolj zapletenih postopkov potrjevanja, kot je na primer sestavljanje. Recimo, da izvajate prepoznavanje poimenovanih entitet (NER), torej vaš model vrača seznam entitet. Vsaka entiteta ima 4 polja: text, type, start in . position. To lahko storite na naslednji način:

class EntityOut(BaseModel):
    start: int
    end: int
    type: str
    text: str

class EntitiesOut(BaseModel):
    entities: List[EntityOut]

@app.post("/entities", response_model=EntitiesOut) 
# [...]

Do zdaj smo potrjevanje prepuščali podjetju Pydantic. To v večini primerov deluje, vendar včasih želite sami dinamično sprožiti napako na podlagi zapletenih pogojev, ki jih ne obvladuje Pydantic. Če želite na primer ročno vrniti napako HTTP 400, lahko storite naslednje:

from fastapi import HTTPException

raise HTTPException(status_code=400, 
        detail="Your request is malformed")

Seveda lahko storite še veliko več!

Nastavitev korenske poti

Če FastAPI uporabljate za obrnjenim posrednikom, se boste najverjetneje morali poigrati s korensko potjo.

Težava je v tem, da za povratnim posrednikom aplikacija ne pozna celotne poti URL, zato ji moramo izrecno povedati, katera je to.

Tu na primer celoten naslov URL do naše končne točke ne sme biti preprosto /classification. Lahko pa je nekaj takega. /api/v1/classification. Tega polnega naslova URL ne želimo zakodirati, da bi da bi bila naša koda API ohlapno povezana s preostalo aplikacijo. Lahko bi naredili to:

app = FastAPI(root_path="/api/v1")

Lahko pa Uvicornu ob zagonu posredujete parameter:

uvicorn main:app --root-path /api/v1

Zaključek

Upam, da smo vam uspešno pokazali, kako priročen je lahko FastAPI za API za obdelavo naravnega jezika. Pydantic omogoča kodo zelo izrazita in manj nagnjena k napakam.

FastAPI ima odlične zmogljivosti in omogoča uporabo Python asyncio iz škatle, kar je odlično za zahtevne modele strojnega učenja, kot so modeli za obdelavo naravnega jezika, ki temeljijo na transformatorju. FastAPI uporabljamo že skoraj eno leto v NLP Cloud in do zdaj še nikoli nismo bili razočarani.

Če imate kakršno koli vprašanje, ne oklevajte in vprašajte, v veselje vam bo komentirati!

Julien Salinas
Tehnični direktor v podjetju NLP Cloud