1、环境准备
1.0、环境描述
首先查看自己的显卡为:Intel(R) Arc(TM) Graphics。
IPEX-LLM是一个由Intel开发的大模型推理加速库,它可以利用Intel的硬件(如CPU、集成显卡和独立显卡)来加速大语言模型的推理。因此为了使用xpu方案,必须是intel的显卡。
1.适用场景
- 在 Intel 笔记本/工作站运行 7B-13B 模型(如 Llama2, Mistral)。
1.1、驱动安装
1. 下载官方最新的显卡驱动
2. 下载安装 Visual Studio 以便使用其带有 C++ 工作负载的桌面开发来实现其部分包的功能
3. 安装 OneAPI Toolkit Installer(依赖第二步Visual Studio的安装)
4. 激活 OneAPI 环境
4.1 修改OneAPI安装目录下(第三步中选择的路径,例如:C:\Program Files (x86)\Intel\oneAPI)的setvars.bat文件,来配置Visual Studio环境变量
# 新增的配置
set "VS2022INSTALLDIR=C:\Program Files\Microsoft Visual Studio\2022\Community"
4.2 激活OneAPI环境
- Win + R 输入 cmd 出现命令行窗口
- 激活 OneAPI 环境
call "C:\Program Files (x86)\Intel\oneAPI\setvars.bat",如果需要强制重新激活环境需要在后方追加--force命令即可。
激活成功显示如下(出现oneAPI environment initialized):
1.2、依赖安装
1. 准备conda环境,python版本建议3.10以上
例如:
conda create -n ipex python=3.10 -y
conda activate ipex
2. 其他可能需要的依赖包安装
pip install jupyter matplotlib pandas pillow timm torcheval torchtnt tqdm -i https://pypi.mirrors.ustc.edu.cn/simple/
pip install cjm_pandas_utils cjm_psl_utils cjm_pil_utils cjm_pytorch_utils -i https://pypi.mirrors.ustc.edu.cn/simple/
conda install pkg-config libuv
# 如果是非conda环境
pip install pyuv
# 设置环境变量
set IPEX_XPU_ONEDNN_LAYOUT=1
set SYCL_CACHE_PERSISTENT=1
set BIGDL_LLM_XMX_DISABLED=1
3. 安装torch相关的包
参考下面网址进行: intel.github.io/intel-exten…
在网址中根据你的环境选择:
# 复制出来环境依赖如下
python -m pip install torch==2.5.1+cxx11.abi torchvision==0.20.1+cxx11.abi torchaudio==2.5.1+cxx11.abi intel-extension-for-pytorch==2.5.10+xpu --extra-index-url https://pytorch-extension.intel.com/release-whl/stable/xpu/cn/
# 以及ipex运行的包及相关依赖
pip install --pre --upgrade ipex-llm[xpu] --extra-index-url https://pytorch-extension.intel.com/release-whl/stable/xpu/cn/
pip install transformers==4.45.2
pip install accelerate==0.34.2
pip install peft==0.11.1
pip install trl
4. 验证torch,在conda环境里输入以下内容
import torch
import intel_extension_for_pytorch as ipex
print(f'PyTorch Version: {torch.__version__}')
print(f'Intel PyTorch Extension Version: {ipex.__version__}')
2、推理部署
2.1、代码
import torch
import os
from flask import Flask
from flask import request
from transformers import AutoTokenizer, AutoModel, Qwen2ForCausalLM, Qwen2Tokenizer, GenerationConfig
from ipex_llm.transformers import AutoModelForCausalLM
# 参数
max_new_tokens: int = 2048 # 生成响应时最大的新token数
temperature: float = 0.6 # 控制生成文本的随机性
top_p: float = 0.9 # 用于概率限制的参数,有助于控制生成文本的多样性
top_k: int = 32 # 控制生成过程中每一步考虑的最可能token的数量
repetition_penalty: float = 1.2 # 用于惩罚重复生成相同token的参数
eos_token_id = [151645, 151643]
app = Flask(__name__)
model_path = "D:\project\llm\Qwen2-7B"
tokenizer = Qwen2Tokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(model_path,
load_in_4bit=True, # 以4位精度加载
cpu_embedding=True, # 模型的嵌入层将在CPU上运行
low_cpu_mem_usage=True, # 降低CPU内存使用
use_cache=True, # 启用KV缓存(推理过程的中间层缓存)
trust_remote_code=True, # 信任远程代码
optimize_model=True,
torch_dtype=torch.float16, # 添加这行
).to('xpu').eval()
@app.route('/chat', methods=["POST"])
def chat():
req_json = request.json
messages = [
{"role": "system", "content": req_json['systemPrompt']},
{"role": "user", "content": req_json['userPrompt']}
]
generation_config = GenerationConfig(use_cache=True,
repetition_penalty=repetition_penalty,
do_sample=False, # 取消采样,使用贪心策略,输出是确定的
stop_strings="}")
# 设置停止词)
text = tokenizer.apply_chat_template(messages,
tokenize=False,
add_generation_prompt=True)
# Generate predicted tokens
input_ids = tokenizer.encode(text, return_tensors="pt").to('xpu')
print(input_ids.shape[-1])
generated_ids = model.generate(input_ids,
max_new_tokens=req_json['maxNewTokens'],
tokenizer=tokenizer,
generation_config=generation_config)
# 将输入的ids部分截掉
output_ids = generated_ids[:, input_ids.shape[-1]:]
output_str = tokenizer.batch_decode(output_ids, skip_special_tokens=True)[0]
print(output_str)
return output_str.strip()
@app.route('/chat_qwen', methods=["POST"])
def chat_qwen():
try:
# 系统设定和prompt
req_json = request.json
prompt = req_json['message']
print(prompt)
torch.xpu.empty_cache() # 清理显存
# 使用with语句确保推理完成后释放资源
with torch.inference_mode():
# 输入张量必须和模型在同一个设备中,但是张量可以在不同设备间移动
input_ids = tokenizer.encode(prompt, return_tensors="pt").to('xpu')
print(input_ids)
# 1、tokenizer的解码操作通常在CPU上进行
# 2、CPU处理文本解码更方便,且不需要占用GPU/XPU资源
# 3、最终的文本处理和返回都是在CPU上进行的
generate_ids = model.generate(
input_ids=input_ids,
# bos_token_id=151645,
# max_new_tokens=max_new_tokens,
# repetition_penalty=repetition_penalty
)
response = tokenizer.batch_decode(generate_ids, skip_special_tokens=True)[0]
response = response[len(prompt):]
return response.strip()
except Exception as e:
print(f"生成过程发生错误: {str(e)}")
return str(e), 500 # 返回错误信息和500状态码
if __name__ == '__main__':
app.run(port=8080, host="0.0.0.0")
3、问题
3.1、Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft C++ Build Tools": visualstudio.microsoft.com/visual-cpp-…
原因:缺少C++工具
解决:按照提示:安装C++ build tools,进入visual studio下载,选中C++相关的tools(使用C++的桌面开发,主要是安装C++生成工具、windows sdk等),按照默认一路下载安装。
3.2、Initializing libiomp5md.dll, but found libiomp5md.dll already initialized
解决:anaconda的环境下存在两个libiomp5md.dll文件。所以直接去虚拟环境的路径下搜索这个文件,可以看到在环境里有两个dll文件.
其中第一个是torch路径下的,第二个是虚拟环境本身路径下的,转到第二个目录下把它剪切到其他路径下备份就好(最好把路径也备份一下)。
3.3、csrc/cpu/comm/ccl.cpp(8): fatal error C1083: 无法打开包括文件: “oneapi/ccl.hpp”: No such file or directory
解决:安装oneapi base toolkit和oneapi HPC kit
3.4、generated_ids = model.generate()接口长时间不返回
解决:无须解决,第一次启动模型的时候进行预热,第一次调用接口慢可能约1-10分钟,后续的接口回归正常响应时间。