使用flask/fastapi封装模型,不需加载,直接推理

一、前言

LLM十分火热,各种花样封装使用,但是每次infer的时候,加载模型都需要很久,那么就需要把服务挂载在服务器上,就不用每次infer都花那么多时间加载模型了。

二、使用fastapi或者flask

笔者更喜欢flask框架,觉得他更接地气,且易于使用。

2.1 使用fastapi实现

使用了客户端和服务端的分离,使得你可以在需要的时候发送推理请求。

# start_server.py
from fastapi import FastAPI, Request
from transformers import AutoTokenizer, AutoModel
import uvicorn, json, datetime
import torch

from tqdm import tqdm
from transformers import LlamaTokenizer, AutoTokenizer, AutoModelForCausalLM, AutoConfig
from peft import  PeftModel

DEVICE = "cuda"
DEVICE_ID = "0"
CUDA_DEVICE = f"{DEVICE}:{DEVICE_ID}" if DEVICE_ID else DEVICE
print(CUDA_DEVICE)

def torch_gc():
    if torch.cuda.is_available():
        with torch.cuda.device(CUDA_DEVICE):
            torch.cuda.empty_cache()
            torch.cuda.ipc_collect()

app = FastAPI()

@app.post("/")
async def create_item(request: Request):
    global model, tokenizer
    json_post_raw = await request.json()
    json_post = json.dumps(json_post_raw)
    json_post_list = json.loads(json_post)
    prompt = json_post_list.get('prompt')  # input_text

	##### 以下为模型推理代码,替换成自己的代码  #####
    inputs = tokenizer(
        prompt,
        add_special_tokens=False,
        return_tensors="pt"
    )
    generation_output = model.generate(
        input_ids = inputs["input_ids"].to(CUDA_DEVICE), 
        **generation_config
    )  # [0]

    for i, line in enumerate(generation_output):
        generate_text = tokenizer.decode(line,skip_special_tokens=True)

    infer_result = generate_text.split('Assistant:\n')[-1].strip() + '\n'
	##### 以上为模型推理代码,替换成自己的代码 #####

    answer = {
        "response": infer_result,  # 返回的结果
    }
    

    torch_gc()
    return jsonify(answer)
    # return json.dumps({'result': result})
    # 注: 返回结果answer中如果有np.array格式,需要转成list格式,才可以返回,否则会报错TypeError: Object of type ndarray is not JSON serializable


if __name__ == '__main__':
	# 以下加载你的模型
    tokenizer = AutoTokenizer.from_pretrained('/workspace/BELLE/train/dataset/llama2_7b_chat_hf')
    tokenizer.pad_token_id = 0
    tokenizer.bos_token_id = 1
    tokenizer.eos_token_id = 2
    tokenizer.padding_side = "left"
    load_type = torch.float16 #Sometimes may need torch.float32
    model_config = AutoConfig.from_pretrained('/workspace/BELLE/train/dataset/llama2_7b_chat_hf')
    model = AutoModelForCausalLM.from_pretrained('/workspace/BELLE/train/output/saved_models/llama2_7b_chat_hf/checkpoint-67008', torch_dtype=load_type, config=model_config, device_map='auto')
    model.eval()
    # 以上加载你的模型
    uvicorn.run(app, host='0.0.0.0', port=7999, workers=1)

客户端代码如下:

# client.py
import requests

# 定义请求URL
url = "http://0.0.0.0:7999"

# 定义请求头
headers = {
    "Content-Type": "application/json"
}

# 定义请求体数据
data = {
    "prompt": "Human: \nYou are now a proficient people, \n\nAssistant:\n",
    # "history": []
}

# 发送POST请求
response = requests.post(url, headers=headers, json=data)

# 打印响应
print(response.text)
# 在shell输入下面指令,获取ip
hostname -I 

# 在终端输入下面指令调用,上述获取的ip替换下面的localhost,输入-d中数据中的引号需要进行转义,否则会报错。<p>The browser (or proxy) sent a request that this server could not understand.
curl -X POST "http://localhost:7999" -H 'Content-Type: application/json' -d '{\"prompt\": \"你好\", \"history\": []}'

2.2 使用flask实现

使用flask,记得安装相应的库pip install Flask requests
将服务启动和推理分开为两个脚本。以下是一个简单的示例,其中一个脚本 start_server.py 负责启动服务,另一个脚本 client.py 负责进行推理:

# start_server.py
from flask import Flask, request, jsonify
from transformers import GPT2LMHeadModel, GPT2Tokenizer

app = Flask(__name__)


# 以下为模型初始化,加载你的模型
model = GPT2LMHeadModel.from_pretrained("gpt2")
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
# 以上为模型初始化,加载你的模型


@app.route('/', methods=['POST'])
def infer():
    data = request.json
    input_text = data.get('input_text')

    # 处理推理请求
    result = generate_response(input_text)

    return jsonify({'result': result})
    # return json.dumps({'result': result})
    # 注: 返回结果answer中如果有np.array格式,需要转成list格式,才可以返回,否则会报错TypeError: Object of type ndarray is not JSON serializable

def generate_response(input_text):
    # 以下实现模型推理逻辑
    # 例如,使用预训练的 GPT-2 模型进行文本生成
    input_ids = tokenizer.encode(input_text, return_tensors='pt')
    output = model.generate(input_ids, max_length=100, num_return_sequences=1)
    generated_text = tokenizer.decode(output[0], skip_special_tokens=True)
    return generated_text
	# 以上实现模型推理逻辑
	
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

客户端代码如下:

# client.py
import requests

def run_client(input_text):
    url = 'http://localhost:5000'
    data = {'input_text': input_text}
    response = requests.post(url, json=data)
    
    if response.status_code == 200:  # 200 表示请求成功
        result = response.json()
        print(result['result'])
    else:
        print('Error:', response.status_code)

if __name__ == '__main__':
    input_text = "Human: \nYou are now a proficient people, \n\nAssistant:\n"
    run_client(input_text)
# 也可以直接在终端输入下面指令调用
curl -X POST "http://localhost:7999" -H 'Content-Type: application/json' -d '{\"prompt\": \"你好\", \"history\": []}'

小结

笔者最近也是遇到类似的问题,做个小结,后续还会继续优化相关代码,持续更新。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Flask是一个基于Python的轻量级Web开发框架,可用于将yolo图像识别模型封装为Restful API。 首先,需要安装Flask框架和相关依赖项,包括numpy、opencv和yolo模型本身。接着,可以根据自己的需求编写一个Flask app,其中包括以下主要功能: 1. 获得图像的URL或二进制数据 2. 调用预先加载的yolo模型 3. 处理yolo模型的输出结果 4. 将结果返回到客户端 为了优化API的性能,可以考虑以异步的方式调用yolo模型。可以使用Python的协程库(例如asyncio),或使用基于消息传递的工具(例如RabbitMQ),以异步方式处理多个模型调用请求。 最后,为方便客户端开发者使用API,可以提供文档和示例代码。可以使用Swagger或YAML等工具编写API文档,并提供基于不同编程语言的示例代码(例如Python、Java、JavaScript和C#等)。 综上所述,使用Flask将yolo图像识别模型封装为Restful API是一项相对容易实现的任务,但需要深入了解Flask框架、yolo模型API设计。 ### 回答2: Flask是一个基于Python的web应用程序框架,适用于快速开发Python web应用程序。Yolo是一种对象检测的算法,可以在一张图像中检测出对象的位置和所属类别。将Yolo图像识别模型封装为Restful API意味着可以通过网络API进行远程调用,将图像输入模型进行识别,并获得相应的识别结果。 在将Yolo模型封装为Restful API时,需要先写一个Flask应用程序。然后,将已经训练好的Yolo模型导入到应用程序中。接下来,根据需要定义一个或多个RESTful API端点,并使其可以响应来自客户端的HTTP请求。在这些API端点中,使用图像识别模型对输入图片进行识别,然后把输出结果返回给客户端。 具体来说,为了能够在Flask应用程序中使用Yolo模型进行图像识别,需要将模型导入至Python的代码中,并使用OpenCV或其他图像处理库对输入图片进行预处理。同时,要配置好Flask路由,定义API端点路径,并访问到模型去进行识别操作。 总结而言,将Yolo图像识别模型封装为Restful API的过程需要深入掌握Python语言Flask框架的开发,同时也需要对图像识别领域有一定的了解。此外,在实现过程中,需要保证模型能够高效地进行识别,并考虑到Python和Flask的性能问题。 ### 回答3: 在使用Flask将YOLO图像识别模型封装为RESTful API之前,需要进行以下步骤: 1.准备YOLO模型:首先,需要准备好YOLO模型。可以使用现有的预训练模型或根据自己的需要训练模型。 2.安装Flask和相关库:在使用Flask构建RESTful API之前,需要安装Flask和与之相关的库,例如flask-restful,flask-cors等。 3.编写Flask应用程序:编写Flask应用程序包括定义API端点,配置数据传输格式,处理请求和返回结果等。 具体步骤如下: 1.定义API端点:在Flask应用程序中定义API端点是相当简单的,只需使用Flask的route装饰器和HTTP方法即可定义RESTful API。例如,可以使用POST方法将图像上传到服务器。 @app.route('/predict', methods=['POST']) def predict(): # 接收传输的图像 file = request.files['image'] image = Image.open(file.stream) # 调用模型进行预测 result = yolo_model.predict(image) # 返回预测结果 return jsonify(result) 2.配置数据传输格式:为了方便客户端和服务器端之间的数据传输,需要配置数据传输格式。使用json格式是比较常见的,可以使用Flask的jsonify函数轻松地将结果转换为json格式。 3.处理请求和返回结果:可以使用Flask的request对象获取传输的数据,使用jsonify函数返回结果。 通过以上步骤,可以将YOLO图像识别模型封装为RESTful API并实现图像识别功能。客户端可以通过发送Post请求并传输图像数据,服务器端进行预测,并返回结果。这种方式可以很方便地实现模型的部署和使用,提高应用程序的可扩展性和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值