Phi-3-Mini-128K模型服务化部署:使用Docker容器化与API封装
Phi-3-Mini-128K模型服务化部署使用Docker容器化与API封装最近在折腾大模型本地部署发现微软开源的Phi-3-Mini-128K是个挺有意思的“小钢炮”。模型不大但能力不弱128K的超长上下文更是亮点。不过每次想用都得手动启动脚本调试参数实在麻烦。要是能把它封装成服务随时随地通过API调用那可就方便多了。这篇文章我就来聊聊怎么给Phi-3-Mini-128K“安个家”——用Docker把它容器化再用FastAPI做个简单的推理服务。整个过程不算复杂跟着步骤走你也能拥有一个随时待命的模型API服务。无论是想集成到自己的应用里还是为后续的微服务架构做准备这套方法都能给你打个不错的基础。1. 先理清思路我们要做什么在动手敲代码之前咱们先花两分钟把整个流程想明白。这样后面每一步做起来心里都有谱。简单来说我们的目标是把Phi-3-Mini-128K模型变成一个标准的Web服务。想象一下你有个智能助手被关在盒子里我们得做三件事给它造个“房子”用Docker容器把模型、运行环境、所有依赖都打包进去。这个房子隔离性好搬到任何支持Docker的机器上都能住。开一扇“窗户”用FastAPI或者Flask写一个Web应用。这扇窗户定义了外界如何与模型对话比如发送一个POST请求里面装着问题模型就会把答案从窗户递出来。配上“管家”和“说明书”用Docker Compose来管理这个服务比如设置环境变量、端口映射再写个Dockerfile作为构建容器的“说明书”。最终你只需要一行命令docker-compose up一个完整的模型推理服务就启动了。你可以用curl、Postman或者自己写的程序去调用它。2. 准备你的“施工场地”工欲善其事必先利其器。我们先确保手头有需要的工具。这里假设你用的是Linux或macOS系统Windows用户建议使用WSL2以获得最佳体验。2.1 基础工具检查打开你的终端依次检查并安装以下工具Python模型推理的核心环境。Phi-3系列建议使用Python 3.9或更高版本。python3 --version如果没安装可以去Python官网下载或者用系统包管理器如apt、brew安装。Docker容器化的基石。它能让我们的应用环境保持一致性。docker --version docker-compose --version如果显示“command not found”你需要去Docker官网根据你的操作系统下载并安装Docker Desktop或Docker Engine。安装后记得把当前用户加入docker用户组避免每次都要sudo。Git用来克隆模型仓库和我们的项目代码。git --version同样未安装的话请通过系统包管理器安装。2.2 获取模型文件Phi-3-Mini-128K的模型文件可以从Hugging Face Hub获取。我们创建一个项目目录并在里面下载模型。# 创建一个项目文件夹 mkdir phi3-mini-service cd phi3-mini-service # 使用Hugging Face的huggingface-cli工具下载需先安装 pip install huggingface-hub huggingface-cli download microsoft/Phi-3-mini-128k-instruct --local-dir ./model # 或者如果你更喜欢用Git注意仓库较大 # git lfs install # git clone https://huggingface.co/microsoft/Phi-3-mini-128k-instruct ./model下载可能需要一些时间毕竟模型有几个GB。完成后你的目录里会有一个model文件夹里面就是模型的所有文件。3. 编写核心服务FastAPI应用现在来造那扇“窗户”。我们选择FastAPI因为它现代、快速而且能自动生成交互式API文档特别适合这种场景。在你的项目根目录phi3-mini-service下创建一个名为app的文件夹然后开始编写应用。3.1 创建应用文件结构mkdir app cd app touch main.py requirements.txt3.2 编写依赖文件requirements.txt这个文件告诉Docker和Python需要安装哪些包。fastapi0.104.0 uvicorn[standard]0.24.0 transformers4.36.0 torch2.0.0 accelerate0.25.0 sentencepiece0.1.99 # Phi-3的分词器需要 pydantic2.0.0fastapi和uvicorn是我们的Web框架和服务器。transformers、torch、accelerate是加载和运行模型的核心。sentencepiece是Phi-3分词器必需的。3.3 编写主应用逻辑main.py这是服务的大脑定义了API接口和模型加载逻辑。from fastapi import FastAPI, HTTPException from pydantic import BaseModel from typing import Optional, List import torch from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline import logging import os # 设置日志 logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) # 定义API请求/响应格式 class ChatMessage(BaseModel): role: str # “user” or “assistant” content: str class ChatRequest(BaseModel): messages: List[ChatMessage] max_new_tokens: Optional[int] 512 temperature: Optional[float] 0.7 top_p: Optional[float] 0.9 do_sample: Optional[bool] True class ChatResponse(BaseModel): response: str model: str usage: dict # 初始化FastAPI应用 app FastAPI( titlePhi-3 Mini 128K Instruct API, description一个基于FastAPI封装的Phi-3-Mini-128K-Instruct模型推理服务。, version1.0.0 ) # 全局变量用于缓存加载的模型和分词器 _model None _tokenizer None _pipe None def load_model(): 加载模型和分词器到内存或GPU global _model, _tokenizer, _pipe if _model is not None: return model_path os.getenv(MODEL_PATH, /app/model) # 从环境变量读取路径默认为容器内路径 logger.info(f正在从 {model_path} 加载模型...) try: # 加载分词器 _tokenizer AutoTokenizer.from_pretrained(model_path, trust_remote_codeTrue) # 加载模型根据环境决定设备 device 0 if torch.cuda.is_available() else -1 # 0代表GPU-1代表CPU _model AutoModelForCausalLM.from_pretrained( model_path, torch_dtypetorch.float16 if device 0 else torch.float32, # GPU上用半精度节省显存 device_mapauto if device 0 else None, trust_remote_codeTrue ) # 创建文本生成管道方便调用 _pipe pipeline( text-generation, model_model, tokenizer_tokenizer, devicedevice ) logger.info(模型加载成功) except Exception as e: logger.error(f模型加载失败: {e}) raise app.on_event(startup) async def startup_event(): FastAPI启动时自动加载模型 load_model() app.get(/) async def root(): 健康检查端点 return {status: healthy, model: Phi-3-Mini-128K-Instruct} app.get(/health) async def health_check(): 更详细的健康检查确认模型已加载 if _model is None: raise HTTPException(status_code503, detailModel not loaded) return {status: ready, device: cuda if torch.cuda.is_available() else cpu} app.post(/v1/chat/completions, response_modelChatResponse) async def chat_completion(request: ChatRequest): 主要的聊天补全接口遵循OpenAI API部分格式 if _pipe is None: raise HTTPException(status_code503, detailService unavailable) # 将消息列表格式化为模型所需的提示文本 # Phi-3-mini-instruct 使用 |user|\n 和 |assistant|\n 格式 formatted_text for msg in request.messages: if msg.role user: formatted_text f|user|\n{msg.content}|end|\n elif msg.role assistant: formatted_text f|assistant|\n{msg.content}|end|\n formatted_text |assistant|\n # 使用管道生成文本 try: outputs _pipe( formatted_text, max_new_tokensrequest.max_new_tokens, temperaturerequest.temperature, top_prequest.top_p, do_samplerequest.do_sample, pad_token_id_tokenizer.eos_token_id, eos_token_id_tokenizer.eos_token_id, ) generated_text outputs[0][generated_text] # 只提取助理的新回复部分 response_text generated_text[len(formatted_text):].strip() # 简单计算token使用量近似 input_tokens len(_tokenizer.encode(formatted_text)) output_tokens len(_tokenizer.encode(response_text)) return ChatResponse( responseresponse_text, modelPhi-3-Mini-128K-Instruct, usage{ prompt_tokens: input_tokens, completion_tokens: output_tokens, total_tokens: input_tokens output_tokens } ) except Exception as e: logger.error(f推理过程中出错: {e}) raise HTTPException(status_code500, detailfGeneration error: {str(e)})这段代码做了几件关键事定义了标准的请求/响应数据结构模仿了OpenAI的格式方便适配。在服务启动时自动加载模型到内存或GPU。提供了根路径/和/health用于健康检查。创建了核心的/v1/chat/completions接口接收对话历史和参数返回模型生成的回复。4. 构建容器“说明书”Dockerfile有了应用代码我们需要告诉Docker如何构建镜像。在项目根目录创建Dockerfile。# 使用带有Python的官方镜像作为基础 FROM python:3.10-slim # 设置工作目录 WORKDIR /app # 安装系统依赖如果需要例如git RUN apt-get update apt-get install -y --no-install-recommends \ gcc \ g \ rm -rf /var/lib/apt/lists/* # 首先复制依赖文件利用Docker缓存层 COPY ./app/requirements.txt . # 安装Python依赖 RUN pip install --no-cache-dir --upgrade pip \ pip install --no-cache-dir -r requirements.txt # 复制模型文件假设模型已下载到项目根目录的model文件夹 # 注意由于模型文件很大这可能会使镜像体积庞大。 # 生产环境中可以考虑将模型文件放在卷(volume)或通过网络存储挂载。 COPY ./model /app/model # 复制应用代码 COPY ./app . # 声明容器运行时监听的端口 EXPOSE 8000 # 设置环境变量模型路径 ENV MODEL_PATH/app/model # 启动命令使用uvicorn运行FastAPI应用 CMD [uvicorn, main:app, --host, 0.0.0.0, --port, 8000, --reload]这个Dockerfile做了以下工作从轻量级的Python镜像开始。安装必要的系统编译工具某些Python包可能需要。安装requirements.txt里列出的所有Python包。将我们之前下载的模型文件和应用代码复制到镜像内。设置环境变量指定模型路径。最后定义启动命令在容器内的8000端口运行我们的FastAPI应用。注意将数GB的模型文件直接打包进镜像会导致镜像非常庞大。对于原型或固定环境这没问题。但在生产环境你可能需要考虑使用Docker卷Volume或网络文件系统如NFS来挂载模型文件这样镜像会更轻量更新模型也更方便。5. 使用Docker Compose编排服务单个服务用Docker run命令也能跑但用Docker Compose管理起来更优雅特别是未来需要添加数据库、缓存等其他服务时。在项目根目录创建docker-compose.yml。version: 3.8 services: phi3-api: build: . container_name: phi3-mini-api ports: - 8000:8000 # 将宿主机的8000端口映射到容器的8000端口 environment: - MODEL_PATH/app/model # 可以添加其他环境变量如日志级别 - LOG_LEVELINFO volumes: # 挂载模型目录可选如果模型文件在宿主机上可以挂载进来避免复制进镜像 # - ./model:/app/model # 挂载日志目录可选 # - ./logs:/app/logs deploy: resources: reservations: devices: - driver: nvidia count: all capabilities: [gpu] # 健康检查确保服务真正就绪 healthcheck: test: [CMD, curl, -f, http://localhost:8000/health] interval: 30s timeout: 10s retries: 3 start_period: 40s # 给模型加载留出足够时间 restart: unless-stopped networks: - phi3-network # 定义一个网络方便未来扩展其他服务 networks: phi3-network: driver: bridge这个配置文件的关键点build: .告诉Compose基于当前目录的Dockerfile构建镜像。ports端口映射让你能在宿主机通过localhost:8000访问服务。environment设置环境变量。deploy.resources这是配置GPU支持的关键。它告诉Docker Compose需要Docker with NVIDIA Container Toolkit将宿主机的GPU资源分配给容器。如果你的机器没有NVIDIA GPU可以移除这部分。healthcheck定义了健康检查策略Docker会定期调用/health接口确保服务正常运行。这对于生产环境编排和负载均衡器很重要。restart: unless-stopped确保容器在意外退出时自动重启。6. 构建、运行与测试一切就绪让我们启动这个服务。6.1 构建并启动服务在项目根目录有docker-compose.yml的目录下运行# 使用docker-compose构建镜像并启动服务-d 代表后台运行 docker-compose up -d --build第一次运行会花费较长时间因为它需要下载基础镜像、安装依赖、构建镜像。看到phi3-mini-api容器状态变为healthy就表示成功了。你可以用以下命令查看日志和状态# 查看实时日志 docker-compose logs -f phi3-api # 查看容器状态 docker-compose ps6.2 测试API接口服务运行后我们来测试一下。健康检查curl http://localhost:8000/health应该返回类似{status:ready,device:cuda}的JSON。测试聊天接口使用curlcurl -X POST http://localhost:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { messages: [ {role: user, content: 用简单的语言解释一下什么是人工智能} ], max_new_tokens: 150 }如果一切正常你会收到一个JSON响应其中response字段包含了模型生成的答案。使用交互式API文档 FastAPI自动生成了超棒的文档。打开你的浏览器访问http://localhost:8000/docs。你会看到一个Swagger UI界面里面列出了所有API端点甚至可以在这里直接点击“Try it out”进行测试非常方便。6.3 实现简单的负载均衡可选进阶如果你的服务访问量变大一个实例可能不够。你可以使用Docker Compose轻松扩展多个实例并搭配一个反向代理如Nginx做负载均衡。创建一个简单的nginx.conf配置文件upstream phi3_backend { # 指向docker-compose中定义的服务名和端口 server phi3-api-1:8000; server phi3-api-2:8000; # 可以添加更多... } server { listen 80; server_name localhost; location / { proxy_pass http://phi3_backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }修改docker-compose.yml添加Nginx服务和扩展phi3-apiversion: 3.8 services: phi3-api: build: . # ... 其他配置不变 ... networks: - phi3-network nginx: image: nginx:alpine container_name: phi3-nginx-lb ports: - 8080:80 # 通过宿主机的8080端口访问负载均衡器 volumes: - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro depends_on: - phi3-api networks: - phi3-network networks: phi3-network: driver: bridge扩展phi3-api服务实例docker-compose up -d --scale phi3-api2现在访问http://localhost:8080的请求会被Nginx分发到两个phi3-api实例上。Docker Compose会自动将服务名如phi3-api-1解析为对应的容器IP。7. 部署到生产环境的一些思考把服务跑在本地笔记本上只是第一步。要部署到真正的生产服务器比如云主机还需要考虑更多安全性API接口需要添加认证如API Key、JWT令牌。可以在FastAPI应用中使用中间件Middleware来实现。性能监控集成像Prometheus这样的监控工具收集请求延迟、错误率、GPU使用率等指标。日志管理将容器日志集中收集到ELKElasticsearch, Logstash, Kibana或Loki等系统中方便排查问题。模型更新如何在不中断服务的情况下更新模型可以考虑蓝绿部署或使用模型版本管理通过环境变量切换模型路径。资源限制在docker-compose.yml中为服务设置CPU和内存限制cpus,mem_limit防止单个容器耗尽主机资源。使用生产级服务器将uvicorn的--reload参数移除并使用更高效的ASGI服务器如gunicorn配合uvicorn工作进程。8. 写在最后走完这一趟你应该已经拥有了一个在Docker容器中运行的、可通过API调用的Phi-3-Mini-128K模型服务。从编写清晰的FastAPI应用到用Dockerfile定义环境再到用Docker Compose编排和配置健康检查这套流程是很多AI模型服务化的标准打法。最大的好处就是环境隔离和一键部署。你现在可以把整个项目文件夹打包扔到任何有Docker的机器上执行docker-compose up -d服务就能跑起来。再结合一些CI/CD工具就能实现自动化部署和更新。当然这只是一个起点。根据你的实际需求可能还需要添加批处理接口、流式响应SSE、更复杂的对话历史管理等功能。但有了这个基础框架后续的扩展都会容易很多。希望这个教程能帮你省去一些摸索的时间快去试试把你的模型服务跑起来吧获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。