[大模型]Llama-3-8B-Instruct FastApi 部署调用

环境准备

在 Autodl 平台中租赁一个 3090 等 24G 显存的显卡机器,如下图所示镜像选择 PyTorch-->2.1.0-->3.10(ubuntu22.04)-->12.1
接下来打开刚刚租用服务器的 JupyterLab,并且打开其中的终端开始环境配置、模型下载和运行演示。

在这里插入图片描述

pip 换源加速下载并安装依赖包

# 升级pip
python -m pip install --upgrade pip
# 更换 pypi 源加速库的安装
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

pip install fastapi==0.110.2
pip install uvicorn==0.29.0
pip install requests==2.31.0
pip install modelscope==1.11.0
pip install transformers==4.40.0
pip install accelerate==0.29.3

fastapi0.110.2
langchain
0.1.16
modelscope1.11.0
streamlit
1.33.0
torch2.1.2+cu121
transformers
4.40.0
uvicorn==0.29.0

考虑到部分同学配置环境可能会遇到一些问题,我们在 AutoDL 平台准备了 LLaMA3 的环境镜像,该镜像适用于该仓库的所有部署环境。点击下方链接并直接创建 Autodl 示例即可。
https://www.codewithgpu.com/i/datawhalechina/self-llm/self-llm-LLaMA3

模型下载

使用 modelscope 中的 snapshot_download 函数下载模型,第一个参数为模型名称,参数 cache_dir 为模型的下载路径。

在 /root/autodl-tmp 路径下新建 model_download.py 文件并在其中输入以下内容,粘贴代码后请及时保存文件,如下图所示。并运行 python /root/autodl-tmp/model_download.py 执行下载,模型大小为 15GB,下载模型大概需要 2 分钟。

import torch
from modelscope import snapshot_download, AutoModel, AutoTokenizer
import os
model_dir = snapshot_download('LLM-Research/Meta-Llama-3-8B-Instruct', cache_dir='/root/autodl-tmp', revision='master')

代码准备

在 /root/autodl-tmp 路径下新建 api.py 文件并在其中输入以下内容,粘贴代码后请及时保存文件。下面的代码有很详细的注释,大家如有不理解的地方,欢迎提出 issue。

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_format='<|start_header_id|>system<|end_header_id|>\n\n{content}<|eot_id|>'
    user_format='<|start_header_id|>user<|end_header_id|>\n\n{content}<|eot_id|>'
    assistant_format='<|start_header_id|>assistant<|end_header_id|>\n\n{content}<|eot_id|>\n'
    history.append({'role':'user','content':prompt})
    prompt_str = ''
    # 拼接历史对话
    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'])
    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', [])  # 获取请求中的历史记录

    messages = [
            # {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": prompt}
    ]

    # 调用模型进行对话生成
    input_str = bulid_input(prompt=prompt, history=history)
    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=512, do_sample=True,
    top_p=0.9, temperature=0.5, repetition_penalty=1.1, eos_token_id=tokenizer.encode('<|eot_id|>')[0]
    )
    outputs = generated_ids.tolist()[0][len(input_ids[0]):]
    response = tokenizer.decode(outputs)
    response = response.strip().replace('<|eot_id|>', "").replace('<|start_header_id|>assistant<|end_header_id|>\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/autodl-tmp/LLM-Research/Meta-Llama-3-8B-Instruct'
    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)  # 在指定端口和主机上启动应用

Api 部署

在终端输入以下命令启动 api 服务:

cd /root/autodl-tmp
python api.py

加载完毕后出现如下信息说明成功。

在这里插入图片描述

默认部署在 6006 端口,通过 POST 方法进行调用,可以使用 curl 调用,如下所示:

curl -X POST "http://127.0.0.1:6006" \
     -H 'Content-Type: application/json' \
     -d '{"prompt": "你好"}'

得到的返回值如下所示:

{
  "response": "😊 你好!我也很高兴见到你!有什么问题或话题想聊天吗?",
  "status": 200,
  "time": "2024-04-20 23:11:00"
}

也可以使用 python 中的 requests 库进行调用,如下所示:

import requests
import json

def get_completion(prompt):
    headers = {'Content-Type': 'application/json'}
    data = {"prompt": prompt}
    response = requests.post(url='http://127.0.0.1:6006', headers=headers, data=json.dumps(data))
    return response.json()['response']

if __name__ == '__main__':
    print(get_completion('你好'))

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/700821.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ从入门到入土

同步与异步 同步调用 优势&#xff1a; 时效性强&#xff0c;等到结果后就返回 问题&#xff1a; 扩展性差 性能下降 级联失败问题 异步调用 优势&#xff1a; 耦合度低&#xff0c;扩展性强 无需等待&#xff0c;性能好 故障隔离&#xff0c;下游服务故障不影响上游 缓…

【C语言】12.C语言内存函数

文章目录 1.memcpy使用和模拟实现2.memmove使用和模拟实现3.memset函数的使用4.memcmp函数的使用 memcpy&#xff1a;内存拷贝 memmove&#xff1a;内存移动 memset&#xff1a;内存设置 memcmp&#xff1a;内存比较 1.memcpy使用和模拟实现 memcpy&#xff1a;内存拷贝 void…

Mysql查询分析工具Explain的使用

一、前言 作为一名合格的开发人员&#xff0c;与数据库打交道是必不可少的&#xff0c;尤其是在业务规模和数据体量大规模增长的条件下&#xff0c;应用系统大部分请求读写比例在10:1左右&#xff0c;而且插入操作和一般的更新操作很少出现性能问题&#xff0c;遇到最多的&…

产品人生(12):从“产品生命周期管理”看如何做“职业规划”

产品生命周期管理是产品人常接触的一个概念&#xff0c;它是一种全面管理产品从概念构想、设计开发、生产制造、市场推广、销售使用&#xff0c;直至最终退役的全生命周期过程的方法论和一系列业务流程。下面我们来简单介绍下产品生命周期管理&#xff1a; 概念阶段&#xff1a…

MybatisPlus代码生成器使用案例

针对数据库中的实体类表&#xff0c;自动生成相关的pojo类&#xff0c;mapper&#xff0c;service等 1. Get-Started 基于mybatisplus&#xff0c;idea下载mybatisplus插件 sql文件 /*!40101 SET OLD_CHARACTER_SET_CLIENTCHARACTER_SET_CLIENT */; /*!40101 SET NAMES utf8 …

面试官:MySQL也可以实现分布式锁吗?

首先说结论&#xff0c;可以做&#xff0c;但不推荐做。 我们并不推荐使用数据库实现分布式锁。 如果非要这么做&#xff0c;实现大概有两种。 1、锁住Java的方法&#xff0c;借助insert实现 如何用数据库实现分布式锁呢&#xff0c;简单来说就是创建一张锁表&#xff0c;比…

PB案例学习笔记-19制作一个图片按钮

写在前面 这是PB案例学习笔记系列文章的第19篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

MAC认证

简介 MAC认证是一种基于接口和MAC地址对用户的网络访问权限进行控制的认证方法&#xff0c;它不需要用户安装任何客户端软件。设备在启动了MAC认证的接口上首次检测到用户的MAC地址以后&#xff0c;即启动对该用户的认证操作。认证过程中&#xff0c;不需要用户手动输入用户名…

Leetcode3174. 清除数字

Every day a Leetcode 题目来源&#xff1a;3174. 清除数字 解法1&#xff1a;栈 用栈模拟&#xff0c;遇到数字就弹出栈顶&#xff0c;遇到字母就插入栈。 最后留在栈里的就是答案。 代码&#xff1a; /** lc appleetcode.cn id3174 langcpp** [3174] 清除数字*/// lc c…

如何做好期货投资?

期货&#xff0c;这个词对于很多人来说可能还是个陌生的词汇&#xff0c;但是&#xff0c;随着经济的发展和人们对金融投资的需求增加&#xff0c;期货投资也变得越来越受到关注。那么&#xff0c;如何才能做好期货投资呢&#xff1f; 首先&#xff0c;了解期货的基本知识是非…

现货黄金交易多少克一手?国内外情况大不同

如果大家想参与国际市场上的现货黄金交易&#xff0c;就应该从它交易细则的入手&#xff0c;先彻底认识这个品种&#xff0c;因为它是来自欧美市场的投资方式&#xff0c;所以无论是从合约的计的单位&#xff0c;计价的货币&#xff0c;交易的具体时间&#xff0c;以及买卖过程…

word空白页删除不了怎么办?

上方菜单栏点击“视图”&#xff0c;下方点击“大纲视图”。找到文档分页符的位置。将光标放在要删除的分节符前&#xff0c;按下键盘上的“Delet”键删除分页符。

Filament 【表单操作】修改密码

场景描述&#xff1a; 新增管理员信息时需要填写密码&#xff0c;修改管理员信息时密码可以为空&#xff08;不修改密码&#xff09;&#xff0c;此时表单中密码输入有冲突&#xff0c;需要对表单中密码字段进项条件性的判断&#xff0c;使字段在 create 操作时为必需填写&…

服务器部署spring项目jar包使用bat文件,省略每次输入java -jar了

echo off set pathC:\Program Files\Java\jre1.8.0_191\bin START "YiXiangZhengHe-8516" "%path%/java" -Xdebug -jar -Dspring.profiles.activeprod -Dserver.port8516 YiXiangZhengHe-0.0.1-SNAPSHOT.jar 将set path后面改成jre的bin文件夹 START 后…

在微信小程序中安装和使用vant框架

目录 1、初始化项目2、安装vant相关依赖3、修改 app.json4、修改 project.config.json5、构建npm6、使用示例 本文将详细介绍如何在微信小程序中安装并使用vant框架&#xff5e; 开发工具&#xff1a;微信开发者工具 1、初始化项目 从终端进入小程序项目目录&#xff0c;执行…

一个数据查询导出工具

数据查询导出工具 安装说明 安装完成后在桌面会创建“数据查询导出工具”的查询工具。 程序初始化 配置数据库连接 首次运行&#xff0c;请先配置数据库连接 点击“数据库连接”后&#xff0c;会出现下面的窗体&#xff0c;要求输入维护工程师密码。&#xff08;维护工程师密码…

VScode如何调试

调试 1.打断点 1.点击调试按钮 3.点击下拉选择环境node&#xff0c;点击绿三角选择输入调试的命令&#xff08;具体命令查看package.json中scripts中的哪一个命令和运行的文件&#xff09;&#xff0c;点击右边的设置&#xff08;可以直接跳下面第八步&#xff01;&#xff…

实体类status属性使用枚举类型的步骤

1. 问题引出 当实体类的状态属性为Integer类型时&#xff0c;容易写错 2. 初步修改 把状态属性强制为某个类型&#xff0c;并且自定义一些可供选择的常量。 public class LessonStatus {public static final LessonStatus NOT_LEARNED new LessonStatus(0,"未学习"…

SQL 数据库学习 Part 1

数据和信息 信息 信息是客观存在的&#xff0c;是关于现实世界事物的存在方式或运动状态 数据 数据是用来记录信息的可识别的符号&#xff0c;是信息的具体表现形式 数据和信息的联系 数据是信息的符号表示或载体信息则是数据的内涵&#xff0c;是对数据的语义解释 数据…

牛客热题:设计LRU缓存结构

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 牛客热题&#xff1a;设计LRU缓存结构题目链接方法一…