开源大模型食用指南:Gemma-2-9b-it 基于 FastAPI 的本地部署调用实战
2026/9/19 11:29:35 网站建设 项目流程

开源大模型食用指南:Gemma-2-9b-it 基于 FastAPI 的本地部署调用实战

【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调(全参数/Lora)、部署国内外开源大模型(LLM)/多模态大模型(MLLM)教程项目地址: https://gitcode.com/datawhalechina/self-llm

本文是 datawhalechina/self-llm 仓库《开源大模型食用指南》中 Gemma-2-9b-it FastApi 部署调用 一文的完整技术展开,面向想在 Linux 环境(以 AutoDL 云 GPU 为例)下快速把 Google Gemma-2-9b-it 跑起来并对外提供 HTTP 服务的开发者。读完本文,你将掌握从租用 GPU 实例、配置 Python 环境、下载 9B 模型权重,到编写并启动 FastAPI 推理服务,再到用 curl 与 Python requests 两种方式调用服务的完整链路,并理解背后apply_chat_templatemodel.generate→ 解码后处理的推理实现细节。

1. 部署前的环境准备:租用 GPU 实例

Gemma-2-9b-it 是 Google 开源的 9B 参数对话模型,权重约 18GB(以 bfloat16 精度加载),推理阶段需要一张显存不低于 24GB 的显卡。在 AutoDL 平台租赁一台RTX 3090/24G 显存的机器即可满足部署要求。

创建实例时,镜像选择需要与后文依赖版本匹配,具体为:PyTorch → 2.1.0 → 3.10(ubuntu22.04) → 12.1,即 PyTorch 2.1.0、Python 3.10、Ubuntu 22.04 系统、CUDA 12.1 运行时。选择该镜像的原因在于:

  • Python 3.10 与仓库教程使用的transformers==4.42.3fastapiuvicorn等依赖兼容性良好;
  • CUDA 12.1 可被 PyTorch 2.1.0 原生支持,保证AutoModelForCausalLM能顺利将模型加载到cuda设备;
  • 镜像自带基础编译链与驱动,省去手动装 CUDA 的繁琐步骤。

创建实例后,打开终端进入命令行环境,后续的环境配置、模型下载与代码运行均在该终端内进行。

2. 环境配置:pip 换源与依赖安装

为加速依赖下载,先升级 pip 并将 pypi 源切换为清华镜像源,再安装本教程所需的三个核心依赖:

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

各依赖在本场景中的职责如下:

依赖作用版本说明
fastapi提供 HTTP 服务框架,定义/端点的 POST 处理逻辑默认安装最新稳定版即可
uvicornFastAPI 的 ASGI 服务器,负责真正监听端口、接收请求fastapi安装时一并带入(代码中显式import uvicorn
modelscope魔搭 ModelScope 官方 SDK,用于从国内节点下载模型权重提供snapshot_download函数
transformersHugging Face 生态的核心库,提供AutoTokenizerAutoModelForCausalLM固定为 4.42.3,该版本对 Gemma-2 系列的支持稳定,避免 API 变动

关于依赖版本的必要说明:transformers==4.42.3是本仓库该教程验证过的版本。若使用过新或过旧的 transformers,apply_chat_template对 Gemma-2 的 chat template 支持行为可能发生变化,导致生成后处理失效。

如果后续需要把该模型接入其他框架(如 LangChain、Web Demo),可参考仓库中 Gemma-2-9b-it langchain 接入 与 Gemma-2-9b-it WebDemo 部署 两篇姊妹文档,它们共用本节的环境与模型下载步骤。

3. 模型下载:基于 ModelScope 拉取权重

模型文件较大(约 18GB),如果直接从 Hugging Face 下载,在国内网络环境下通常较慢。本教程使用 ModelScope(魔搭)的snapshot_download函数从国内节点下载,速度明显更快,模型大小为 18GB 左右,按教程实测下载大约需要 5 分钟。

新建一个 Python 文件并写入以下内容,运行即可完成下载:

from modelscope import snapshot_download model_dir = snapshot_download('LLM-Research/gemma-2-9b-it', cache_dir='/root/autodl-tmp')

参数说明:

  • 第一个参数'LLM-Research/gemma-2-9b-it':模型在 ModelScope 上的仓库名称,对应官方 Gemma-2-9b-it 的镜像仓库;
  • cache_dir='/root/autodl-tmp':模型下载保存路径。AutoDL 的/root/autodl-tmp是数据盘挂载目录,容量大且实例释放后数据保留,适合存放大型权重;建议使用绝对路径,避免后续代码中路径拼接出错。

下载完成后,模型权重会保存在/root/autodl-tmp/LLM-Research/gemma-2-9b-it目录下,包含config.jsonmodel-*.safetensors分片权重、tokenizer.jsontokenizer_config.json等文件,这些文件正是后文from_pretrained加载时所需的完整目录结构。

如果后续需要使用其他模型或掌握更多下载姿势(Hugging Face、镜像站、git-lfs、Openxlab 等),可参阅仓库通用指南 模型下载。

4. 代码准备:开放端口与 api.py 服务代码

4.1 开放 AutoDL 的 6006 端口

由于模型运行在云端 AutoDL 实例上,本地无法直接访问实例内部端口,需要将实例的 6006 端口映射到本地。在 AutoDL 实例管理页面点击自定义服务,会弹出端口转发的 SSH 命令,形如:

ssh -CNg -L 6006:127.0.0.1:6006 root@connect.xxx.seetacloud.com -p <端口号>

在本机执行该命令后,访问本机http://localhost:6006即可转发到云实例的 6006 端口。AutoDL 开放端口的详细操作见仓库通用指南 AutoDL 开放端口,首次使用请先参考该文档完成映射配置。

4.2 api.py 完整代码与逐段解析

新建api.py文件,粘贴以下代码并保存。该代码以 FastAPI 为核心,对外暴露一个 POST 接口,内部加载 Gemma-2-9b-it 完成对话生成:

from fastapi import FastAPI, Request from transformers import AutoTokenizer, AutoModelForCausalLM 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内存碎片 # 创建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') # 获取请求中的提示 # 调用模型进行对话生成 chat = [ { "role": "user", "content": prompt }, ] prompt = tokenizer.apply_chat_template(chat, tokenize=False, add_generation_prompt=True) inputs = tokenizer.encode(prompt, add_special_tokens=False, return_tensors="pt") outputs = model.generate(input_ids=inputs.to(model.device), max_new_tokens=150) outputs = tokenizer.decode(outputs[0]) response = outputs.split('model')[-1].replace('<end_of_turn>\n<eos>', '') 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__': # 加载预训练的分词器和模型 path = '/root/autodl-tmp/LLM-Research/gemma-2-9b-it' print("Creat tokenizer...") tokenizer = AutoTokenizer.from_pretrained(path) print("Creat model...") model = AutoModelForCausalLM.from_pretrained( path, device_map="cuda", torch_dtype=torch.bfloat16,) # 启动FastAPI应用 # 用6006端口可以将autodl的端口映射到本地,从而在本地使用api uvicorn.run(app, host='0.0.0.0', port=6006, workers=1) # 在指定端口和主机上启动应用

下面拆解这段代码的关键设计,帮助你理解其内部原理(对应 源码文档):

(1)设备与显存管理

  • DEVICE = "cuda"DEVICE_ID = "0"通过字符串拼接得到CUDA_DEVICE = "cuda:0",用于精确定位第一块 GPU;
  • torch_gc()在每次请求处理完后调用torch.cuda.empty_cache()清空 CUDA 缓存、torch.cuda.ipc_collect()收集显存碎片。对于长驻服务而言,这一步能及时释放推理过程中产生的临时显存,避免连续请求导致显存溢出(OOM)。

(2)模型加载方式

model = AutoModelForCausalLM.from_pretrained( path, device_map="cuda", torch_dtype=torch.bfloat16,)
  • device_map="cuda"把整个模型加载到 GPU(与torch_gc中指定的cuda:0一致);
  • torch_dtype=torch.bfloat16以 bfloat16 半精度加载权重。9B 模型在 fp32 下约需 36GB 显存,bfloat16 可将显存占用压缩到约 18GB,这正是 RTX 3090/24G 可以单卡运行的直接原因,同时 bf16 的动态范围对推理精度损失很小。

(3)对话生成的后处理细节

chat = [ { "role": "user", "content": prompt }, ] prompt = tokenizer.apply_chat_template(chat, tokenize=False, add_generation_prompt=True) inputs = tokenizer.encode(prompt, add_special_tokens=False, return_tensors="pt") outputs = model.generate(input_ids=inputs.to(model.device), max_new_tokens=150) outputs = tokenizer.decode(outputs[0]) response = outputs.split('model')[-1].replace('<end_of_turn>\n<eos>', '')

这条链路是本服务的核心,逐步解释:

  1. apply_chat_template(chat, tokenize=False, add_generation_prompt=True):调用 Gemma-2 官方 chat template,将[{role: "user", content: prompt}]结构化为带<bos><start_of_turn>user<end_of_turn>等特殊标记的完整对话提示词,并追加生成提示符;
  2. tokenizer.encode(..., add_special_tokens=False, return_tensors="pt"):对模板化文本做 tokenize,add_special_tokens=False避免重复添加 BOS(chat template 已包含),返回 PyTorch 张量;
  3. model.generate(..., max_new_tokens=150):自回归生成,max_new_tokens=150控制最多生成 150 个新 token;
  4. tokenizer.decode(outputs[0]):把生成的 token 序列解码回文本;
  5. outputs.split('model')[-1].replace('<end_of_turn>\n<eos>', '')从源码结构看,这是针对 Gemma-2 模板格式的后处理——生成结果中模型的回复部分位于model标记之后,因此取split('model')[-1]截取模型回复段,再用replace清除末尾的<end_of_turn><eos>特殊标记,得到干净的回答文本。

(4)接口与启动参数

  • @app.post("/")定义根路径的 POST 接口,请求体为{"prompt": "你好"}格式的 JSON;
  • 接口返回{"response": ..., "status": 200, "time": ...}结构,其中status恒为 200 表示业务成功,time为服务端当前时间,便于日志追踪;
  • uvicorn.run(app, host='0.0.0.0', port=6006, workers=1):监听所有网卡(0.0.0.0)的 6006 端口。选择 6006 是为了与 AutoDL 端口映射保持一致,workers=1避免多进程重复加载 18GB 模型导致显存翻倍。

5. 启动与验证:FastAPI 服务运行与两种调用方式

5.1 启动服务

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

python api.py

首次启动会先执行AutoTokenizer.from_pretrainedAutoModelForCausalLM.from_pretrained,日志依次输出Creat tokenizer...Creat model...,随后加载约 18GB 权重分片。加载完毕后出现如下信息即说明服务启动成功:

成功标志包括INFO: Started server processINFO: Application startup complete.以及INFO: Uvicorn running on http://0.0.0.0:6006 (Press CTRL+C to quit)。此时服务默认部署在 6006 端口,可通过 POST 方法进行调用。

5.2 方式一:curl 调用

在本地终端(或已映射端口的机器)执行:

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

返回结果示例如下,包含模型回复、状态码与时间戳:

5.3 方式二:Python requests 调用

在应用中,更常见的是通过 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('你好'))

运行后可直接打印出模型的文本回复,与 curl 方式等价,适合嵌入到业务代码中作为统一的大模型调用入口。

6. 深入原理与仓库联动

6.1 推理链路小结

从上面的代码可以提炼出 Gemma-2 系模型在 Transformers 框架下的标准推理范式:

HTTP 请求(prompt) → 构造 chat 消息列表 → apply_chat_template 模板化 → tokenizer.encode 转 token → model.generate 自回归生成 → tokenizer.decode 还原文本 → 去除特殊标记 → HTTP 响应

这一范式同样被仓库内 Gemma-2-9b-it langchain 接入 一文的Gemma2_LLM._call函数完整复用——它将同一套apply_chat_template+generate+ 后处理逻辑封装进自定义 LLM 类,从而让 Gemma-2-9b-it 无缝接入 LangChain 生态,进一步印证了本文代码的通用性与可迁移性。

6.2 常见问题与调优方向

  • 显存不足(OOM):确认torch_dtype=torch.bfloat16生效;RTX 3090 24G 在 150 token 输出下通常够用,若增大max_new_tokens导致 OOM,可适当调低该值。
  • 响应速度workers=1与常驻模型保证单请求延迟稳定;如需更高并发吞吐,可考虑换用 vLLM 等推理框架,但这超出本文 FastAPI 直调方案的范畴。
  • 端口访问不通:检查 AutoDL 自定义服务的 SSH 端口转发命令是否在本地保持运行,详见 AutoDL 开放端口。
  • 模型路径问题path必须与第 3 节snapshot_downloadcache_dir+ 仓库名拼接结果一致(即/root/autodl-tmp/LLM-Research/gemma-2-9b-it),否则from_pretrained会报目录不存在。

6.3 仓库中的后续进阶路线

本文属于 Gemma-2-9b-it 系列教程的部署篇,仓库 models/Gemma2 目录还提供了完整的进阶链路(均已登记在 support_model.md 的 Gemma-2-9b-it 条目下):

  • Gemma-2-9b-it langchain 接入:将本地模型封装为 LangChain 自定义 LLM,用于搭建 Agent / RAG 应用;
  • Gemma-2-9b-it WebDemo 部署:基于 Streamlit 构建可交互的聊天页面;
  • Gemma-2-9b-it peft lora微调:使用 PEFT + LoRA 对 9B 模型进行高效微调(含配套 IPython Notebook)。

至此,你已经完成了从零到一将 Gemma-2-9b-it 部署为可调用的 FastAPI 服务,掌握了依赖环境配置、国内模型下载、GPU 显存管理以及 HTTP 接口封装的全套技能,可在此基础上继续向 LangChain 应用开发与 LoRA 微调方向深入。

【免费下载链接】self-llm《开源大模型食用指南》针对中国宝宝量身打造的基于Linux环境快速微调(全参数/Lora)、部署国内外开源大模型(LLM)/多模态大模型(MLLM)教程项目地址: https://gitcode.com/datawhalechina/self-llm

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询