恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
openEuler系统部署ChatGLM2-6B:从环境配置到生产级API服务实战
首页
资讯中心
/
openEuler系统部署ChatGLM2-6B:从环境配置到生产级API服务实战
openEuler系统部署ChatGLM2-6B:从环境配置到生产级API服务实战
发布时间:2026/8/5 17:04:05
1. 项目缘起为什么要在openEuler上部署ChatGLM2最近接手了一台全新的服务器配置还不错有张能跑大模型的显卡但系统是空白的。老板给的任务很明确把这台机器变成一个能稳定提供ChatGLM2-6B模型推理服务的“生产力工具”。选型的时候我几乎没怎么犹豫就定了openEuler。很多人可能第一反应是Ubuntu或者CentOS Stream但在这个场景下openEuler有几个让我无法拒绝的优势。首先它作为面向企业级的操作系统在安全性和长期稳定性上做得相当扎实。我们部署的是要长期运行、可能对外提供API服务的大模型系统底层的稳定和安全是基石。openEuler的内核增强、等保合规指令支持对于后续可能面临的合规性检查能省不少心。其次它对ARM和x86架构的支持都很好生态也在快速完善像CANN异构计算架构这类AI加速套件在openEuler上的支持和文档都比较成熟。虽然这次我们用的是N卡但保不齐未来会换国产算力卡提前在openEuler上踩踩坑也算是技术储备。至于模型选择ChatGLM2-6B参数规模约62亿而不是更大的版本是权衡了硬件资源、响应速度和实际需求后的结果。在单张消费级显卡比如RTX 3090/4090上6B这个量级的模型可以在保证不错的中文理解和生成能力的同时实现相对流畅的交互。更大的模型当然效果更好但对显存的要求是指数级增长部署和维护成本也高得多。我们的场景主要是内部知识问答、文档摘要和代码辅助6B版本已经足够胜任性价比最高。所以这个“从0到1”的过程不仅仅是执行一遍安装命令更是一次针对特定硬件新服务器、特定系统openEuler和特定模型ChatGLM2-6B的深度定制化部署。我会把过程中每一个关键选择背后的原因、遇到的坑以及最终的解决方案都详细记录下来目标就是让你拿到另一台新服务器也能完全复现这个稳定可用的环境。2. 服务器开箱与openEuler系统安装实录新服务器到手第一步不是急着装系统而是做好规划。我这台机器配置是Intel Xeon Silver处理器128GB内存配了一张RTX 4090 24GB显卡。部署大模型尤其是要进行本地推理显卡是核心但其他部分也不能成为瓶颈。2.1 硬件检查与启动介质准备首先进BIOS确认几个关键设置确保UEFI启动模式开启这对现代操作系统和磁盘分区更友好关闭安全启动Secure Boot因为在后续安装某些驱动或库时它可能会带来不必要的麻烦。然后检查显卡是否正确安装并被识别。对于N卡可以在BIOS或服务器管理界面查看PCIe设备列表。系统镜像我选择的是openEuler 22.03 LTS SP1长期支持版本。从官网下载ISO镜像后使用Ventoy或者Rufus工具制作一个U盘启动盘。这里有个小技巧如果你预计未来会经常给不同机器装系统强烈推荐Ventoy。它可以把U盘做成一个多系统启动盘直接把ISO文件拷贝进去就行无需反复格式化烧录。2.2 系统安装过程中的关键抉择将启动盘插入服务器从U盘启动进入openEuler的图形化安装界面。安装过程大部分是常规操作但有几步需要特别注意语言和键盘建议系统语言和键盘都选择英文美国。这能避免后续在终端中可能出现的路径或字符编码问题。系统界面语言可以在安装后随时改为中文。安装目的地磁盘分区这是重中之重。对于AI服务器我推荐采用手动分区方案而不是自动。/boot/efi 300-500MBEFI系统分区格式化为vfat。/boot 1GB标准分区格式化为ext4用于存放内核和引导文件。/根分区 50-100GB格式化为xfs或ext4。openEuler默认推荐xfs性能不错。/home 根据用户数据量分配比如50GB。swap 交换分区大小通常设置为物理内存的1-2倍这里我给了256GB128GB内存的2倍。大模型加载和运行时会占用大量内存充足的swap可以在内存吃紧时提供缓冲避免进程直接被OOM内存溢出杀死。/data 这是我单独划分的一个大分区用于存放模型文件、数据集和日志。模型文件动辄几十GB单独分区便于管理和备份。我分配了剩下的所有磁盘空间格式化为xfs。软件选择在“软件选择”界面默认的“Server with GUI”就够用。但我会额外勾选“开发工具”包含GCC、Make等编译工具链和“Headless Management”方便无头管理。特别注意不要安装任何第三方软件仓库的包保持系统纯净。网络与主机名配置一个静态IP地址比DHCP动态获取更稳定方便后续远程SSH连接和端口映射。主机名可以设为有意义的比如ai-server-01。用户创建务必创建一个用于日常管理和运行服务的非root用户例如aiuser。所有后续的软件安装、模型下载和服务启动都尽量在这个用户下进行这是生产环境安全的基本要求。安装完成后重启用新创建的用户登录系统。首先运行sudo dnf update -y更新所有系统软件包到最新版本确保安全补丁都已打上。3. 基础环境与深度学习框架的深度配置系统装好了但离跑起大模型还差得远。我们需要一个完整的Python深度学习环境。很多人喜欢直接用系统自带的Python3但这很容易导致包依赖冲突。最佳实践是使用conda或miniconda来创建独立的虚拟环境。3.1 Miniconda安装与隔离环境搭建首先从清华镜像站下载Miniconda的安装脚本这样速度最快。wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/Miniconda3-latest-Linux-x86_64.sh下载后运行安装脚本bash Miniconda3-latest-Linux-x86_64.sh安装过程中会询问安装路径我一般直接安装在/home/aiuser/miniconda3。最后一步选择“yes”来初始化conda这样每次打开终端(base)环境就会自动激活。接下来为ChatGLM2创建一个专属的虚拟环境。ChatGLM2官方推荐Python 3.10我们就用这个版本。conda create -n chatglm2 python3.10 -y conda activate chatglm2现在你的命令行提示符前面应该会变成(chatglm2)这表示你已经在这个独立的环境里了。之后所有pip安装的包都只会影响这个环境。3.2 PyTorch与CUDA的精准匹配这是整个部署中最容易出错、也最关键的一步。PyTorch版本必须与你的CUDA驱动版本严格匹配。首先查看服务器NVIDIA驱动支持的CUDA版本nvidia-smi在输出结果的右上角你会看到类似“CUDA Version: 12.4”的字样。这表示你的驱动最高支持CUDA 12.4。但PyTorch需要的是CUDA Toolkit我们通常安装比驱动版本低一级或同级的稳定版。例如驱动是12.4我们可以安装CUDA 12.1的PyTorch。前往PyTorch官网https://pytorch.org/get-started/locally/使用它的安装命令生成器。选择PyTorch Build: Stable (2.3.0) Your OS: Linux Package:pip Language: Python Compute Platform:CUDA 12.1。它会生成如下命令pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121在你的(chatglm2)环境中运行这个命令。安装完成后验证是否成功python -c import torch; print(torch.__version__); print(torch.cuda.is_available())你应该能看到PyTorch版本如2.3.0和True。如果显示False说明PyTorch没有正确识别到GPU需要检查CUDA路径和驱动。3.3 其他核心依赖安装除了PyTorchChatGLM2还需要一些其他库。使用pip安装时建议指定国内镜像源加速。pip install -i https://pypi.tuna.tsinghua.edu.cn/simple transformers4.36.2 sentencepiece accelerate protobuf cpm_kernels这里固定了transformers的版本因为不同版本的API可能有细微变化固定版本能确保与ChatGLM2代码的兼容性。sentencepiece是分词器依赖accelerate用于简化分布式训练/推理cpm_kernels是ChatGLM2用到的一个高效算子库。4. ChatGLM2-6B模型部署与推理实战环境终于齐备可以请出“主角”了。部署的核心步骤分为获取模型、加载模型、启动服务。4.1 模型下载与准备ChatGLM2-6B的模型文件存放在Hugging Face Hub和国内镜像站。从国内下载速度更快。我们可以使用git lfs大文件存储来克隆仓库。# 安装git-lfs sudo dnf install git-lfs -y git lfs install # 从ModelScope魔搭社区镜像克隆速度更快 cd /data git clone https://www.modelscope.cn/ZhipuAI/chatglm2-6b.git这个过程会下载大约12GB的模型文件需要一些时间。下载完成后/data/chatglm2-6b目录下就是完整的模型。4.2 编写模型加载与推理脚本我们不直接使用官方的cli_demo.py而是自己写一个更灵活、更适合服务化的脚本。创建一个文件inference_server.pyimport torch from transformers import AutoTokenizer, AutoModelForCausalLM import argparse import time def load_model(model_path): 加载模型和分词器 print(fLoading model from {model_path}...) start_time time.time() # 使用半精度fp16加载以节省显存int4量化需要额外依赖这里先用fp16 tokenizer AutoTokenizer.from_pretrained(model_path, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained( model_path, trust_remote_codeTrue, torch_dtypetorch.float16, # 半精度 device_mapauto # 自动将模型层分配到可用的GPU上 ).eval() # 设置为评估模式 load_time time.time() - start_time print(fModel loaded in {load_time:.2f} seconds.) return model, tokenizer def generate_response(model, tokenizer, query, historyNone, max_length2048, temperature0.8): 生成回复 if history is None: history [] # 使用模型的chat接口进行对话 response, updated_history model.chat( tokenizer, query, historyhistory, max_lengthmax_length, temperaturetemperature, top_p0.8 ) return response, updated_history if __name__ __main__: parser argparse.ArgumentParser() parser.add_argument(--model_path, typestr, default/data/chatglm2-6b, helpPath to the model) parser.add_argument(--query, typestr, default你好, helpInput query) args parser.parse_args() model, tokenizer load_model(args.model_path) # 示例对话 history [] while True: try: user_input input(\n用户: ).strip() if user_input.lower() in [exit, quit]: break if not user_input: continue print(ChatGLM2: , end, flushTrue) response, history generate_response(model, tokenizer, user_input, history) print(response) except KeyboardInterrupt: print(\nExiting...) break这个脚本做了几件事1) 使用device_map’auto’让Hugging Face的accelerate库自动处理模型在GPU上的分布对于单卡它会自动全部加载上去。2) 使用torch.float16半精度能显著减少显存占用几乎不影响精度。3) 提供了一个简单的交互循环。运行脚本进行测试cd /data python inference_server.py --model_path /data/chatglm2-6b第一次运行会需要一些时间编译优化内核。输入“你好”你应该能看到模型流畅地生成回复。用nvidia-smi查看显存应该被占用了大约13-14GB模型权重激活值。4.3 显存优化与量化实战如果你的显卡显存小于24GB比如只有16GB的RTX 4080直接加载fp16模型可能会显存不足。这时就需要用到量化技术。ChatGLM2支持int4量化可以将模型显存占用压缩到6GB左右代价是轻微的精度损失。我们需要安装额外的量化库bitsandbytes。注意这个库对系统环境要求比较严格。# 先安装系统依赖 sudo dnf install gcc-c -y # 在conda环境中安装bitsandbytes指定从源码编译以兼容CUDA 12.1 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple bitsandbytes0.41.3然后修改模型加载部分的代码使用load_in_4bit参数from transformers import BitsAndBytesConfig quantization_config BitsAndBytesConfig( load_in_4bitTrue, bnb_4bit_compute_dtypetorch.float16, bnb_4bit_use_double_quantTrue, bnb_4bit_quant_typenf4 ) model AutoModelForCausalLM.from_pretrained( model_path, trust_remote_codeTrue, quantization_configquantization_config, # 使用量化配置 device_mapauto ).eval()使用int4量化后重新运行显存占用会降到6-8GB这样在RTX 4060 Ti 16GB这样的卡上也能流畅运行。生成速度会比fp16稍慢一点因为涉及反量化计算但对于大多数问答场景完全可接受。5. 构建生产级API服务与稳定性保障让模型在命令行里对话只是第一步。要真正投入使用我们需要一个常驻的、可通过网络调用的API服务。这里我选择使用FastAPI因为它轻量、异步支持好而且自动生成交互式API文档。5.1 使用FastAPI封装模型首先安装FastAPI和异步Web服务器uvicornpip install fastapi uvicorn pydantic创建一个新的文件api_server.pyfrom fastapi import FastAPI, HTTPException from pydantic import BaseModel from typing import List, Optional import uvicorn import torch from transformers import AutoTokenizer, AutoModelForCausalLM from contextlib import asynccontextmanager import logging # 配置日志 logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) # 定义请求/响应模型 class ChatRequest(BaseModel): prompt: str history: Optional[List[List[str]]] None max_length: Optional[int] 2048 temperature: Optional[float] 0.8 top_p: Optional[float] 0.8 class ChatResponse(BaseModel): response: str history: List[List[str]] status: str # 全局模型和分词器 MODEL_PATH /data/chatglm2-6b model None tokenizer None asynccontextmanager async def lifespan(app: FastAPI): # 启动时加载模型 global model, tokenizer logger.info(Loading model...) tokenizer AutoTokenizer.from_pretrained(MODEL_PATH, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained( MODEL_PATH, trust_remote_codeTrue, torch_dtypetorch.float16, device_mapauto ).eval() logger.info(Model loaded successfully.) yield # 关闭时清理如果有需要 logger.info(Shutting down...) app FastAPI(titleChatGLM2-6B API Server, lifespanlifespan) app.post(/v1/chat, response_modelChatResponse) async def chat_completion(request: ChatRequest): if model is None or tokenizer is None: raise HTTPException(status_code503, detailModel not loaded) try: response, updated_history model.chat( tokenizer, request.prompt, historyrequest.history if request.history else [], max_lengthrequest.max_length, temperaturerequest.temperature, top_prequest.top_p ) return ChatResponse( responseresponse, historyupdated_history, statussuccess ) except Exception as e: logger.error(fGeneration error: {e}) raise HTTPException(status_code500, detailstr(e)) app.get(/health) async def health_check(): return {status: healthy, model_loaded: model is not None} if __name__ __main__: # 生产环境建议用命令行启动这里仅为演示 uvicorn.run(app, host0.0.0.0, port8000)这个API提供了两个端点/v1/chat用于对话/health用于健康检查。lifespan上下文管理器确保了模型在服务启动时加载一次而不是每次请求都加载。5.2 使用Systemd管理服务进程我们不能在终端前台运行Python脚本需要用系统服务来管理。创建一个systemd服务文件sudo vim /etc/systemd/system/chatglm2-api.service内容如下[Unit] DescriptionChatGLM2-6B API Service Afternetwork.target [Service] Typesimple Useraiuser Groupaiuser WorkingDirectory/data EnvironmentPATH/home/aiuser/miniconda3/envs/chatglm2/bin ExecStart/home/aiuser/miniconda3/envs/chatglm2/bin/uvicorn api_server:app --host 0.0.0.0 --port 8000 --workers 1 Restartalways RestartSec10 StandardOutputjournal StandardErrorjournal # 限制资源防止失控 MemoryMax100G CPUQuota200% [Install] WantedBymulti-user.target这里有几个关键点1) 指定运行用户和组为aiuser安全且权限清晰。2)Environment设置了PATH确保服务能找到conda环境里的uvicorn。3)ExecStart中--workers 1是因为GPU模型通常不支持多进程并行加载一个worker进程就够了。4) 设置了MemoryMax和CPUQuota防止服务异常时吃光所有资源。5)Restartalways确保服务崩溃后能自动重启。保存后启动并启用服务sudo systemctl daemon-reload sudo systemctl start chatglm2-api sudo systemctl enable chatglm2-api sudo systemctl status chatglm2-api # 查看状态现在API服务就在后台稳定运行了。你可以用curl测试一下curl -X POST http://localhost:8000/v1/chat \ -H Content-Type: application/json \ -d {prompt: 你好请介绍一下你自己, history: []}5.3 配置Nginx反向代理与基础安全可选但推荐如果你需要从外部网络访问这个服务直接暴露8000端口是不安全的。应该用Nginx做反向代理并加上一些基础安全配置。sudo dnf install nginx -y编辑Nginx配置文件/etc/nginx/conf.d/chatglm2.confserver { listen 80; server_name your-server-domain-or-ip; # 改成你的域名或IP # 限制客户端请求体大小防止过大提示词攻击 client_max_body_size 10m; location / { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 增加超时时间大模型生成可能较慢 proxy_read_timeout 300s; proxy_connect_timeout 75s; } # 可选的静态文件服务比如提供前端页面 # location /static { # alias /data/static; # } }测试配置并重启Nginxsudo nginx -t sudo systemctl restart nginx现在你就可以通过服务器的80端口访问API了。后续还可以配置SSL证书HTTPS、设置访问权限控制等让服务更健壮。6. 性能监控、日志与日常维护指南服务上线不是终点保证其长期稳定运行更需要一套监控和维护机制。6.1 关键指标监控除了直接用nvidia-smi查看显存和GPU利用率更推荐使用nvtop一个类htop的GPU监控工具或者配置PrometheusGrafana。一个简单的脚本monitor_gpu.py可以定期记录import subprocess import time import json from datetime import datetime def get_gpu_info(): try: output subprocess.check_output([nvidia-smi, --query-gpuutilization.gpu,memory.used,memory.total,temperature.gpu, --formatcsv,noheader,nounits], textTrue) gpu_data output.strip().split(, ) return { timestamp: datetime.now().isoformat(), gpu_util_percent: int(gpu_data[0]), mem_used_mb: int(gpu_data[1]), mem_total_mb: int(gpu_data[2]), temp_c: int(gpu_data[3]) } except Exception as e: return {error: str(e)} if __name__ __main__: # 每30秒记录一次可写入文件或发送到监控系统 while True: info get_gpu_info() print(json.dumps(info)) # with open(/data/logs/gpu_monitor.log, a) as f: # f.write(json.dumps(info) \n) time.sleep(30)可以将这个脚本也配置成systemd服务或者用crontab定时运行将日志输出到文件。6.2 服务日志收集我们的API服务日志目前输出到journal。可以配置journal将其持久化到文件方便排查问题。# 创建日志目录 sudo mkdir -p /var/log/chatglm2 sudo chown aiuser:aiuser /var/log/chatglm2 # 修改service文件将StandardOutput和StandardError重定向到文件 # 在[Service]部分修改或添加 StandardOutputappend:/var/log/chatglm2/api.log StandardErrorappend:/var/log/chatglm2/api_error.log然后重启服务。这样所有服务的输出和错误信息都会记录到对应的日志文件中可以用tail -f命令实时查看。6.3 模型更新与回滚模型可能会有更新例如安全补丁、性能优化。更新时一个稳妥的做法是将新模型下载到另一个目录例如/data/chatglm2-6b-v2。编写一个新的API服务文件如api_server_v2.py指向新模型路径。创建一个新的systemd服务如chatglm2-api-v2.service并在一台测试服务器或本机另一个端口如8001上启动进行充分测试。测试无误后通过修改Nginx配置的proxy_pass指向新服务的端口实现热切换。或者直接替换原服务文件并重启原服务会有短暂中断。务必保留旧版本的模型和服务配置一旦新版本出现问题可以快速切回。整个流程走下来这台全新的服务器已经从一个裸机变成了一个承载着最新开源大模型、具备生产级API接口、有基本监控和维护能力的AI应用服务器。这其中的每一个步骤从系统分区的大小考量到PyTorch版本的精确匹配再到用systemd和Nginx构建的服务化方案都是我在多次部署中总结下来的经验。尤其是量化配置和资源限制那部分是避免线上服务雪崩的关键。下次如果再拿到一台新机器照着这个流程走一遍大概率能避开我踩过的所有坑。