1

我第一次尝试部署 NLP ML 模型。为此,建议我使用 FastAPI 和 uvicorn。我在让 FastAPI 做出响应方面取得了一些成功;但是,我无法成功传递数据帧并让它处理它。我尝试过使用字典,甚至尝试将传递的 json 转换为数据帧。

我得到data_dict = data.dict()ValueError: Iterable over raw text documents expected, string object received.

我得到data_dict = pd.DataFrame(data.dict())ValueError: If using all scalar values, you must pass an index

我相信我理解这个问题,我的 Data 类需要一个字符串,这不是;但是,我无法确定如何设置和/或传递预期数据,以便 fit_transform() 起作用。最终,我将根据提交的消息值返回预测。如果我可以传递 1 行或更多行的数据帧并为每一行做出并返回预测,则奖励。响应将包括 id、项目和预测,以便我们将来能够利用此响应将预测发布回原始(请求)系统。

test_connection.py

#%%
import requests
import pandas as pd
import json
import os
from pprint import pprint

url = 'http://127.0.0.1:8000/predict'
print(os.getcwd())
#%%
df = pd.DataFrame(
    {
        'id': ['ab410483801c38', 'cd34148639180'],
        'project': ['project1', 'project2'], 
        'messages': ['This is message 1', 'This is message 2']
    }
)
to_predict_dict = df.iloc[0].to_dict()
#%%
r = requests.post(url, json=to_predict_dict)

主文件

#!/usr/bin/env python
# coding: utf-8

import pickle
import pandas as pd
import numpy as np
from pydantic import BaseModel
from sklearn.feature_extraction.text import TfidfVectorizer

# Server
import uvicorn
from fastapi import FastAPI
# Model
import xgboost as xgb


app = FastAPI()

clf = pickle.load(open('data/xgbmodel.pickle', 'rb'))

class Data(BaseModel):
    # id: str
    project: str
    messages: str

@app.get("/ping")
async def test():
    return {"ping": "pong"}

@app.post("/predict")
async def predict(data: Data):
#    data_dict = data.dict()
    data_dict = pd.DataFrame(data.dict())
    tfidf_vect = TfidfVectorizer(stop_words="english", analyzer='word', token_pattern=r'\w{1,}')
    tfidf_vect.fit_transform(data_dict['messages'])
#   to_predict = tfidf_vect.transform(data_dict['messages'])
#   prediction = clf.predict(to_predict)

    return {"response": "Success"}
4

3 回答 3

0

可能不是最优雅的解决方案,但我使用以下方法取得了进展:

def predict(data: Data):
    data_dict = pd.DataFrame(
        {
            'id': [data.id],
            'project': [data.project],
            'messages': [data.messages]
        }
    )
于 2020-07-30T23:03:38.640 回答
0

首先,将您的数据帧编码df为面向 JSON 记录的格式:

r = requests.post(url, json=df.to_json(orient='records')).

然后,使用以下命令解码/predict/端点内的数据:

df = pd.DataFrame(jsonable_encoder(data))

记得导入模块from fastapi.encoders import jsonable_encoder

于 2022-02-22T20:43:18.590 回答
0

data.messages我可以通过简单地转换成一个列表来解决这个问题。我还必须进行一些不相关的更改,我未能腌制我的矢量化器(字符串标记器)。

import pickle
import pandas as pd
import numpy as np
import json
import time
from pydantic import BaseModel
from sklearn.feature_extraction.text import TfidfVectorizer

# Server / endpoint
import uvicorn
from fastapi import FastAPI
# Model
import xgboost as xgb


app = FastAPI(debug=True)

clf = pickle.load(open('data/xgbmodel.pickle', 'rb'))
vect = pickle.load(open('data/tfidfvect.pickle', 'rb'))

class Data(BaseModel):
    id: str = None
    project: str
    messages: str

@app.get("/ping")
async def ping():
    return {"ping": "pong"}

@app.post("/predict/")
def predict(data: Data):
    start = time.time()
    data_l = [data.messages] # make messages iterable.
    to_predict = vect.transform(data_l)
    prediction = clf.predict(to_predict)

    exec_time = round((time.time() - start), 3)
    return {
        "id": data.id,
        "project": data.project,
        "prediction": prediction[0], 
        "execution_time": exec_time
        }

if __name__ == "__main__":
    uvicorn.run(app, host="127.0.0.1", port=8000)
于 2020-08-03T14:09:34.610 回答