InternLM3 开源了一个具有 80 亿参数的指令模型,名为 InternLM3-8B-Instruct,旨在用于通用任务和高级推理。该模型具有以下特点:
- 在降低成本的同时提升性能:在推理和知识密集型任务中,表现超越了像 Llama3.1-8B 和 Qwen2.5-7B 等模型。值得注意的是,InternLM3 仅在 4 万亿高质量标记上进行训练,比其他同规模的语言模型节省了超过 75% 的训练成本。
- 深度思考能力:InternLM3 支持两种模式:一种是通过长链思维解决复杂推理任务的深度思考模式,另一种是用于流畅用户交互的正常响应模式。
实验所依赖的基础开发环境如下:
----------------
ubuntu 22.04
Python 3.12.3
cuda 12.1
pytorch 2.3.0
----------------
本文默认学习者已安装好以上 Pytorch(cuda) 环境,如未安装请自行安装。
首先 pip
换源加速下载并安装依赖包:
# 升级pip
python -m pip install --upgrade pip
# 更换 pypi 源加速库的安装
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
# FastAPI 相关依赖
pip install requests==2.32.3
pip install fastapi==0.104.1
pip install uvicorn==0.24.0
# Langchain 相关依赖
pip install langchain==0.3.7
# WebDemo 相关依赖
pip install streamlit==1.41.1
# LoRA微调 相关依赖
pip install peft==0.11.1 # 用于 LoRA 微调
# 通用依赖
pip install modelscope==1.22.0 # 用于模型下载和管理
pip install transformers==4.47.1 # Hugging Face 的模型库,用于加载和训练模型
pip install sentencepiece==0.2.0 # 用于处理文本数据
pip install accelerate==0.34.2 # 用于分布式训练和混合精度训练
pip install datasets==2.20.0 # 用于加载和处理数据集
考虑到部分同学配置环境可能会遇到一些问题,我们在 AutoDL 平台准备了 InternLM3-8b-Instruct 的环境镜像,点击下方链接并直接创建 AutoDL 示例即可。 https://www.codewithgpu.com/i/datawhalechina/self-llm/self-llm-internlm3
modelscope
是一个模型管理和下载工具,支持从魔搭 (Modelscope) 等平台快速下载模型。
这里使用 modelscope
中的 snapshot_download
函数下载模型,第一个参数 model_name_or_path
为模型名称或者本地路径,第二个参数 cache_dir
为模型的下载路径,第三个参数 revision
为模型的版本号。
在 /root/autodl-tmp
路径下新建 model_download.py
文件并在其中粘贴以下代码,并保存文件。
from modelscope import snapshot_download
model_dir = snapshot_download('Shanghai_AI_Laboratory/internlm3-8b-instruct', cache_dir='./', revision='master')
注意:记得修改 cache_dir 为你的模型下载路径哦~
在终端运行 python /root/autodl-tmp/model_download.py
执行下载,模型大小为 18GB 左右,下载模型大概需要5-30分钟。
新建 api.py
文件并在其中输入以下内容,粘贴代码后请及时保存文件。记得将tokenizer和model的路径改成上面模型下载的cache_dir的路径。以下代码有很详细的注释,大家如有不理解的地方,欢迎提出 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内存碎片
# 创建FastAPI应用
app = FastAPI(
title="InternLM Chat API",
description="API for InternLM 3 chat model",
version="1.0.0"
)
# 添加GET方法的根路由
@app.get("/")
async def root():
return {
"message": "Welcome to InternLM Chat API",
"status": "healthy",
"timestamp": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
# 处理POST请求的端点
@app.post("/v1/chat")
async def create_chat(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') # 获取用户的问题
# 构建对话模板
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": prompt},
]
tokenized_chat = tokenizer.apply_chat_template(messages, tokenize=True, add_generation_prompt=True, return_tensors="pt").to("cuda")
generated_ids = model.generate(tokenized_chat, max_new_tokens=1024, temperature=1, repetition_penalty=1.005, top_k=40, top_p=0.8)
generated_ids = [
output_ids[len(input_ids):] for input_ids, output_ids in zip(tokenized_chat, generated_ids)
]
response = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
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_path = '/root/autodl-tmp/Shanghai_AI_Laboratory/internlm3-8b-instruct'
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_path, torch_dtype=torch.float16, trust_remote_code=True).cuda()
model = model.eval()
# 启动FastAPI应用
# 用6006端口可以将autodl的端口映射到本地,从而在本地使用api
uvicorn.run(app, host='0.0.0.0', port=6006, workers=1) # 在指定端口和主机上启动应用
然后在当前文件的路径下面运行:
python api.py
出现下面的信息就说明成功运行了。
默认部署在 6006 端口,通过 POST 方法进行调用。可以使用命令行curl和代码的方式来调用。
命令行:
curl -X POST "http://localhost:6006/v1/chat" \
-H 'Content-Type: application/json' \
-d '{"prompt": "你好"}'
或者使用实际IP地址:
curl -X POST "http://<your-ip>:6006/v1/chat" \
-H 'Content-Type: application/json' \
-d '{"prompt": "你好"}'
返回结果:
使用 python 中的 requests 库进行调用,创建 request.py
文件,复制下面的代码,运行 python request.py
。
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/v1/chat', headers=headers, data=json.dumps(data))
return response.json()['response']
if __name__ == '__main__':
print(get_completion('你好'))
返回结果:
同时, 这是我们部署的FastAPI的Terminal页面, 还可以看到如下信息
这里简要对上述控制台信息进行解释:
INFO: ... "GET /_stcore/health HTTP/1.1" 404 Not Found
INFO: ... "GET /_stcore/host-config HTTP/1.1" 404 Not Found
- 这些是来自 Streamlit 的健康检查请求,返回 404 是正常的,因为我们的 FastAPI 服务器没有实现这些端点
- 这表明可能有 Streamlit 应用试图连接到这个端口,但这不影响我们的 API 功能
INFO: ... "POST / HTTP/1.1" 405 Method Not Allowed
- 这是失败的API调用记录
- 显示了请求时间、用户输入和模型响应
- 405 Method Not Allowed 表示请求方法不允许
- 有请求试图向根路径 ("/") 发送 POST 请求
- 返回 405 是因为我们只在根路径定义了 GET 方法,而不是 POST
[2025-01-19 12:40:08] ", prompt:"你好", response:"'你好!很高兴见到你。有什么我可以帮助你的吗?'"
INFO: ... "POST /v1/chat HTTP/1.1" 200 OK
- 这是成功的API调用记录
- 显示了请求时间、用户输入和模型响应
- 200 OK 表示请求成功处理