大模型的api封装与本地端口调用(二)——fastapi实现
·
一、fastapi
FastAPI 是一个现代、快速(高性能)的 Python Web 框架,用于构建基于标准 Python 类型提示的 API。以下是 FastAPI 的主要特点及其入门方法的简要说明:
主要特点:
- 开发速度快:提高开发功能的速度,大约是 200% 到 300%。
- 更少的错误:减少约 40% 的人为(开发人员)引入的错误。
- 直观:出色的编辑器支持,随处都有代码补全功能,减少调试时间。
- 易用:设计易于使用和学习,减少阅读文档的时间。
- 简洁:最小化代码重复,从每个参数声明中获得多个功能。
- 健壮:生产就绪代码,具有自动交互文档。
- 基于标准:基于(并完全兼容)API 的开放标准:OpenAPI 和 JSON Schema。
二、代码封装api前端请求与后端响应
from fastapi import FastAPI, Request
from transformers import AutoTokenizer, AutoModelForCausalLM, GenerationConfig
import uvicorn
import json
import datetime
import torch
# 设置设备参数
DEVICE = "cuda" # 使用CUDA
DEVICE_ID = "0" # CUDA设备ID,如果未设置则为空
CUDA_DEVICE = f"{DEVICE}:{DEVICE_ID}" if DEVICE_ID else DEVICE # 组合CUDA设备信息
# 清理GPU内存函数
def torch_gc():
if torch.cuda.is_available(): # 检查是否可用CUDA
with torch.cuda.device(CUDA_DEVICE): # 指定CUDA设备
torch.cuda.empty_cache() # 清空CUDA缓存
torch.cuda.ipc_collect() # 收集CUDA内存碎片
# 构建 chat 模版
def bulid_input(prompt, history=[], system_message=None):
system_format = 'system\n\n{content}\n'
user_format = 'user\n\n{content}\n'
assistant_format = 'assistant\n\n{content}\n'
prompt_str = ''
# 添加system消息
if system_message:
prompt_str += system_format.format(content=system_message)
# 拼接历史对话
for item in history:
if item['role'] == 'user':
prompt_str += user_format.format(content=item['content'])
else:
prompt_str += assistant_format.format(content=item['content'])
# 添加当前用户输入
prompt_str += user_format.format(content=prompt)
return prompt_str
# 创建FastAPI应用
app = FastAPI()
# 处理POST请求的端点
@app.post("/")
async def create_item(request: Request):
global model, tokenizer # 声明全局变量以便在函数内部使用模型和分词器
json_post_raw = await request.json() # 获取POST请求的JSON数据
json_post = json.dumps(json_post_raw) # 将JSON数据转换为字符串
json_post_list = json.loads(json_post) # 将字符串转换为Python对象
prompt = json_post_list.get('prompt') # 获取请求中的提示
history = json_post_list.get('history', []) # 获取请求中的历史记录
system_message = json_post_list.get('system_message') # 获取请求中的system消息
messages = [
{"role": "user","content": prompt}
]
# 调用模型进行对话生成
input_str = bulid_input(prompt=prompt, history=history, system_message=system_message)
input_ids = tokenizer.encode(input_str, add_special_tokens=False, return_tensors='pt').cuda()
generated_ids = model.generate(
input_ids=input_ids, max_new_tokens=1024, do_sample=True,
top_p=0.5, temperature=0.95, repetition_penalty=1.1
)
outputs = generated_ids.tolist()[0][len(input_ids[0]):]
response = tokenizer.decode(outputs)
response = response.strip().replace('assistant\n\n', '').strip() # 解析 chat 模版
now = datetime.datetime.now() # 获取当前时间
time = now.strftime("%Y-%m-%d %H:%M:%S") # 格式化时间为字符串
# 构建响应JSON
answer = {
"response": response,
"status": 200,
"time": time
}
# 构建日志信息
log = "[" + time + "] " + '", prompt:"' + prompt + '", response:"' + repr(response) + '"'
print(log) # 打印日志
torch_gc() # 执行GPU内存清理
return answer # 返回响应
# 主函数入口
if __name__ == '__main__':
# 加载预训练的分词器和模型
model_name_or_path = '/root/LLaMA-Factory/models/llama3_lora_sft'
tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, use_fast=False)
model = AutoModelForCausalLM.from_pretrained(model_name_or_path, device_map="auto", torch_dtype=torch.bfloat16).cuda()
# 启动FastAPI应用
# 用6006端口可以将autodl的端口映射到本地,从而在本地使用api
uvicorn.run(app, host='0.0.0.0', port=6006, workers=1) # 在指定端口和主机上启动应用
三、代码具体解释
1. 引入库和设置设备参数
from fastapi import FastAPI, Request
from transformers import AutoTokenizer, AutoModelForCausalLM, GenerationConfig
import uvicorn
import json
import datetime
import torch
- FastAPI:一个现代、快速(高性能)的 Web 框架,用于构建 API。
- transformers:Hugging Face 提供的库,用于加载预训练模型和分词器。
- uvicorn:一个用于运行 ASGI 应用的轻量级服务器。
- json、datetime、torch:标准库和 PyTorch 库,用于 JSON 操作、时间操作和深度学习操作。
2. 设置设备参数与清理 GPU 内存函数
DEVICE = "cuda" # 使用CUDA
DEVICE_ID = "0" # CUDA设备ID,如果未设置则为空
CUDA_DEVICE = f"{DEVICE}:{DEVICE_ID}" if DEVICE_ID else DEVICE # 组合CUDA设备信息
def torch_gc():
if torch.cuda.is_available(): # 检查是否可用CUDA
with torch.cuda.device(CUDA_DEVICE): # 指定CUDA设备
torch.cuda.empty_cache() # 清空CUDA缓存
torch.cuda.ipc_collect() # 收集CUDA内存碎片
3.构建对话输入模版
def bulid_input(prompt, history=[], system_message=None):
system_format = 'system\n\n{content}\n'
user_format = 'user\n\n{content}\n'
assistant_format = 'assistant\n\n{content}\n'
prompt_str = ''
if system_message:
prompt_str += system_format.format(content=system_message)
for item in history:
if item['role'] == 'user':
prompt_str += user_format.format(content=item['content'])
else:
prompt_str += assistant_format.format(content=item['content'])
prompt_str += user_format.format(content=prompt)
return prompt_str
- system_format、user_format、assistant_format:定义不同角色的消息格式。
- bulid_input 函数将系统消息、历史对话和当前用户输入拼接成一个字符串。
4.创建 FastAPI 应用
app = FastAPI()
5.处理 POST 请求的端点
@app.post("/")
async def create_item(request: Request):
global model, tokenizer # 声明全局变量以便在函数内部使用模型和分词器
json_post_raw = await request.json() # 获取POST请求的JSON数据
json_post = json.dumps(json_post_raw) # 将JSON数据转换为字符串
json_post_list = json.loads(json_post) # 将字符串转换为Python对象
prompt = json_post_list.get('prompt') # 获取请求中的提示
history = json_post_list.get('history', []) # 获取请求中的历史记录
system_message = json_post_list.get('system_message') # 获取请求中的system消息
input_str = bulid_input(prompt=prompt, history=history, system_message=system_message)
input_ids = tokenizer.encode(input_str, add_special_tokens=False, return_tensors='pt').cuda()
generated_ids = model.generate(
input_ids=input_ids, max_new_tokens=1024, do_sample=True,
top_p=0.5, temperature=0.95, repetition_penalty=1.1
)
outputs = generated_ids.tolist()[0][len(input_ids[0]):]
response = tokenizer.decode(outputs)
response = response.strip().replace('assistant\n\n', '').strip()
now = datetime.datetime.now() # 获取当前时间
time = now.strftime("%Y-%m-%d %H:%M:%S") # 格式化时间为字符串
answer = {
"response": response,
"status": 200,
"time": time
}
log = "[" + time + "] " + '", prompt:"' + prompt + '", response:"' + repr(response) + '"'
print(log) # 打印日志
torch_gc() # 执行GPU内存清理
return answer # 返回响应
- 这个端点处理 POST 请求,接收用户输入和对话历史,调用模型生成对话响应,并返回响应结果。
- bulid_input 函数用于构建输入字符串。
- model.generate 函数用于生成模型的输出。
- torch_gc 函数用于清理 GPU 内存。
6.主函数入口
if __name__ == '__main__':
model_name_or_path = '/root/LLaMA-Factory/models/llama3_lora_sft'
tokenizer = AutoTokenizer.from_pretrained(model_name_or_path, use_fast=False)
model = AutoModelForCausalLM.from_pretrained(model_name_or_path, device_map="auto", torch_dtype=torch.bfloat16).cuda()
uvicorn.run(app, host='0.0.0.0', port=6006, workers=1)
四、postman测试
基于模型的输入json样式,向本地localhost:6006发送POST请求,发现能够正常返回模型的输出结果!

更多推荐




所有评论(0)