CUDA 版本
经过测试,Llama-3只有在CUDA新版下才可以运行,CUDA Version: 12.4
验证通过。
代理
在公司内网环境,往往需要代理才能下载模型文件。我这里使用session模式下全局。~/.bash.rc
export HTTP_PROXY="http://*.*.*.*:*"export HTTPS_PROXY="http://*.*.*.*:*"
安装依赖
pip install fastapi==0.110.2pip install uvicorn==0.29.0pip install requests==2.31.0pip install transformers==4.40.0pip install accelerate==0.29.3
llama3-8B 是基本模型,基本上只完成输入提示,但 llama3-8B Instruct 针对指令跟随和多轮对话模板进行了微调,用于助理完成作为聊天响应。
如果你的特定目的是为了聊天完成,那么指令是最好的选择,否则如果它是为了简单的输入完成,那么基本模型就可以了
from fastapi import FastAPI, Requestfrom transformers import AutoTokenizer, AutoModelForCausalLM, GenerationConfigimport uvicornimport jsonimport datetimeimport torch# 设置设备参数DEVICE = "cuda" # 使用CUDADEVICE_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_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,pad_token_id=tokenizer.encode('<|eot_id|>')[0], 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") # 格式化时间为字符串# 构建响应JSONanswer = {"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 = 'meta-llama/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的端口映射到本地,从而在本地使用apiuvicorn.run(app, host='0.0.0.0', port=6006, workers=1) # 在指定端口和主机上启动应用
测试
POST http://127.0.0.1:6006{"prompt": "你是谁?"}