基于FastAPI实现本地大模型API封装调用

server/2024/11/19 15:01:50/
  • 关于FastAPI
    • FastAPI 是一个现代、快速(高性能)的 Python Web 框架,用于构建基于标准 Python 类型提示的 API。它以简洁、直观和高效的方式提供工具,特别适合开发现代 web 服务和后端应用程序。
  • 问题:_pad() got an unexpected keyword argument ‘padding_side’
    • 解决:降级 transformers,pip install transformers==4.34.0,同时更改相关包版本以实现适配,pip install accelerate==0.25.0,pip install huggingface_hub==0.16.4
  • 问题:报错500
    • 服务器防火墙问题,只能在指定端口访问
    • post请求的参数通过request body传递,需要以 application/json 的方式 ,请求body
      • 以postman测试为例:Body中选择“raw”,则对应的Headers中的“Content-Type”“application/json”,参数形式是{"content":"有什么推荐的咖啡吗"}
        在这里插入图片描述
  • 代码实现
    • fastapi_demo.py(运行开启服务)
    • post.py(服务测试)
# fastapi_demo.py(运行开启服务)
from fastapi import FastAPI, Request, HTTPException
from transformers import AutoTokenizer, AutoModelForCausalLM, GenerationConfig
import uvicorn
import json
import datetime
import torch
import loggingprint(f"CUDA 是否可用: {torch.cuda.is_available()}")
print(f"当前 CUDA 版本: {torch.version.cuda}")
print(f"当前可用 CUDA 设备数量: {torch.cuda.device_count()}")# 设置设备参数
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():  # 检查是否可用CUDAwith 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()# 添加GET请求处理
@app.get("/")
async def read_root():return {"message": "Welcome to the API. Please use POST method to interact with the model."}@app.get('/favicon.ico')
async def favicon():return {'status': 'ok'}# 处理POST请求的端点
@app.post("/")
async def create_item(request: Request):try: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')if not prompt:raise HTTPException(status_code=400, detail="提示词不能为空")history = json_post_list.get('history', [])system_message = json_post_list.get('system_message')# 添加输入验证的日志logging.info(f"收到请求: prompt={prompt}, history={history}, system_message={system_message}")input_str = bulid_input(prompt=prompt, history=history, system_message=system_message)try:input_ids = process_input(input_str).to(CUDA_DEVICE)except Exception as e:logging.error(f"Tokenizer 错误: {str(e)}")raise HTTPException(status_code=500, detail=f"Tokenizer 处理失败: {str(e)}")try: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)except Exception as e:logging.error(f"模型生成错误: {str(e)}")raise HTTPException(status_code=500, detail=f"模型生成失败: {str(e)}")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")  # 格式化时间为字符串# 构建响应JSONanswer = {"response": response,"status": 200,"time": time}# 构建日志信息log = "[" + time + "] " + '", prompt:"' + prompt + '", response:"' + repr(response) + '"'print(log)  # 打印日志torch_gc()  # 执行GPU内存清理return answer  # 返回响应except json.JSONDecodeError:raise HTTPException(status_code=400, detail="无效的 JSON 格式")except Exception as e:logging.error(f"处理请求时发生错误: {str(e)}")raise HTTPException(status_code=500, detail=str(e))# 主函数入口
if __name__ == '__main__':# 首先检查可用的GPU数量gpu_count = torch.cuda.device_count()if int(DEVICE_ID) >= gpu_count:raise ValueError(f"指定的DEVICE_ID ({DEVICE_ID}) 无效。系统只有 {gpu_count} 个GPU设备(0-{gpu_count-1})")# 设置当前CUDA设备torch.cuda.set_device(int(DEVICE_ID))model_name_or_path = '/data/user23262833/MemoryStrategy/ChatGLM-Finetuning/chatglm3-6b(需要填写你的模型位置所在路径)'# 修改 tokenizer 初始化tokenizer = AutoTokenizer.from_pretrained(model_name_or_path,use_fast=False,trust_remote_code=True,padding_side='left'  # 直接在初始化时设置)# 更简单的 process_input 实现def process_input(text):inputs = tokenizer.encode(text, return_tensors='pt')return inputs if torch.is_tensor(inputs) else torch.tensor([inputs])model = AutoModelForCausalLM.from_pretrained(model_name_or_path, device_map={"": int(DEVICE_ID)},  # 明确指定设备映射torch_dtype=torch.float16)# 启动FastAPI应用# 用6006端口可以将autodl的端口映射到本地,从而在本地使用apiuvicorn.run(app, host='需填写你的本地或者服务器ip', port=6006, workers=1)  # 在指定端口和主机上启动应用
# post.py
import requests
import jsondef get_completion(prompt):try:headers = {'Content-Type': 'application/json'}data = {"prompt": prompt}response = requests.post(url='需填写你的本地或者服务器ip:6006', headers=headers, data=json.dumps(data))# 检查响应状态码response.raise_for_status()# 添加响应内容的打印,用于调试print("Response content:", response.text)return response.json()['response']except requests.exceptions.RequestException as e:print(f"请求错误: {e}")return Noneexcept json.JSONDecodeError as e:print(f"JSON解析错误: {e}")return Noneexcept KeyError as e:print(f"响应中缺少 'response' 键: {e}")return None# 测试代码
response = get_completion('你好')
if response is not None:print(response)
  • 测试结果
    在这里插入图片描述
  • 参考博文:https://blog.csdn.net/qq_34717531/article/details/142092636?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EOPENSEARCH%7EPaidSort-1-142092636-blog-139909949.235%5Ev43%5Epc_blog_bottom_relevance_base5&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EOPENSEARCH%7EPaidSort-1-142092636-blog-139909949.235%5Ev43%5Epc_blog_bottom_relevance_base5&utm_relevant_index=1

http://www.ppmy.cn/server/143213.html

相关文章

2024-11-16----Android 11(全志H713)-----拉高LED灯

需求 屏背光亮起来的时候&#xff0c;LED灯 黄灯灭 绿灯亮 找到屏操作背光的驱动文件&#xff1a; longan/brandy/brandy-2.0/u-boot-2018/drivers/video/sunxi/fastlogo/fastlogo.c写下操作LED灯的方法&#xff0c;在合适的地方调用 #define setbit(x,y) x|(1<<y) …

Android Framework AMS面试题及参考答案

目录 什么是 AMS? AMS 在 Android 系统中的作用? AMS 是如何启动的? Zygote、SystemServer 与 AMS 之间的关系? AMS 如何与其他系统服务(如 PackageManagerService、WindowManagerService、WMS)交互? AMS 如何使用 Binder 完成通信? AMS 如何管理系统服务的启动…

【自学笔记】无监督学习

文章目录 简述聚类 &#xff08;Cluster learning&#xff09;K-means 异常检测密度估计一些技巧 简述 无监督学习&#xff08;Unsupervised Learning&#xff09;是机器学习的一种方法&#xff0c;其特点是不依赖于事先标记的训练数据。在无监督学习中&#xff0c;算法尝试直接…

【机器学习】从马尔可夫链到CRF:全方位解析序列建模的核心技术

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

(Ubuntu)添加用户并授予sudo权限

在 Ubuntu 中&#xff0c;可以使用 adduser 命令来新建用户。 以下是步骤和说明&#xff1a; 1.打开终端&#xff1a; 可以通过按下 Ctrl Alt T 来打开终端&#xff0c;或者在应用程序菜单中搜索并打开“终端”。 2.使用 adduser 命令&#xff1a; 在终端中输入以下命令&a…

Android OpenGL ES详解——实例化

目录 一、实例化 1、背景 2、概念 实例化、实例数量 gl_InstanceID 应用举例 二、实例化数组 1、概念 2、应用举例 三、应用举例——小行星带 1、不使用实例化 2、使用实例化 四、总结 一、实例化 1、背景 假如你有一个有许多模型的场景&#xff0c;而这些模型的…

H.265流媒体播放器EasyPlayer.js播放器出现加载视频等待画面时长过长的原因排查

在数字媒体时代&#xff0c;用户体验是衡量播放器性能的关键指标之一。EasyPlayer.js网页web无插件播放器作为一款流行的Web视频播放器&#xff0c;其加载速度和响应时间直接影响着用户的观看体验。 1、问题描述 加载视频等待画面时长过长。 2、可能的原因&#xff1a; 检查下…

将分割标签数据从JSON格式转换为YOLOv8的TXT格式

AnyLabeling是一款突破性的开源图像标注工具。 一、主要功能与特点 融合传统标注工具优点&#xff1a;AnyLabeling结合了LabelImg和Labelme等传统标注软件的优点&#xff0c;提供了多边形、矩形、圆形、线条和点等多种标注形式&#xff0c;满足不同场景的需求。强大的AI自动标…