文章目录
- Stable Diffusion 3.5 FP8 文生图实战:我做了一个“可复用 AI 镜像”(Docker + FastAPI),把部署从“装环境”变成“一条命令起服务”
- 0. 我这次想解决的到底是什么问题
- 1. 为什么我盯上 SD3.5 + FP8(而不是只做 FP16)
- 2. 我做的“AI 镜像”长什么样:一张图说清组件关系
- 3. 我选择的两条推理路线
- 3.1 路线 A:Diffusers Pipeline(先跑通、再优化)
- 3.2 路线 B:TensorRT + FP8(把“能用”推进到“能打”)
- 4. 我镜像里的目录结构(我习惯这样摆)
- 5. Dockerfile:我怎么把“环境地狱”封进镜像
- 6. FastAPI:我怎么把“文生图脚本”变成“可用服务”
- 7. 推理封装:Diffusers 版本(先跑通)
- 8. 我怎么跑起来:构建、启动、请求一气呵成
- 9. FP8 / TensorRT 我怎么接(我把它当“第二阶段强化”)
- 10. 我最后的总结
- 参考链接(方便我贴到 CSDN 参考区)
- (可选)我给自己留的“技术自测题”
Stable Diffusion 3.5 FP8 文生图实战:我做了一个“可复用 AI 镜像”(Docker + FastAPI),把部署从“装环境”变成“一条命令起服务”
这篇是我参加「AI 镜像开发实战征文活动」的实战总结:围绕Stable Diffusion 3.5 FP8做一个可复用、可移植、可上线的镜像(容器镜像 / 环境镜像都算),目标是把“文生图服务”变成标准化组件。
0. 我这次想解决的到底是什么问题
我在做文生图项目时,反复踩到三个坑:
- 环境不一致:显卡驱动、CUDA、PyTorch、Diffusers、各种依赖一变就炸
- 资源不可控:显存不够、加载太慢、启动时间不可预期
- 上线不标准:脚本能跑 ≠ 服务可用(API、日志、缓存、复现都缺)
所以我给自己的要求是三句话:
- 能在“干净机器”上复现(可复用)
- 能跑 FP8 / TensorRT 路线(可优化)
- 能提供 API(可集成 / 可上线)
1. 为什么我盯上 SD3.5 + FP8(而不是只做 FP16)
SD3 系列在 Diffusers 侧的一个关键特征是:pipeline 会用到三个文本编码器,并且官方文档明确提到:为了在大多数“常规硬件”上跑起来,经常需要做 offload(比如 CPU/GPU 卸载)。(huggingface.co)
而 SD3.5 的“FP8 + TensorRT”路线,给了我一个非常工程化的收益点:更快 + 更省显存。Stability AI 与 NVIDIA 的公开信息提到,SD3.5 家族在 TensorRT + FP8 优化后可以带来显著性能提升与显存下降。(Stability AI)
另外,Hugging Face 上也提供了TensorRT 优化版本的 SD3.5 Large,并说明其中包含 FP8 精度的 MMDiT(核心 transformer)导出与量化产物,同时给了示例脚本与性能表。(huggingface.co)
2. 我做的“AI 镜像”长什么样:一张图说清组件关系
我把它拆成 6 块:请求入口、API、队列(可选)、GPU Worker、模型缓存、产物存储。
这个结构的重点不是“多复杂”,而是每一块都能单独替换:
- 我可以把 FastAPI 换成 Gradio / Streamlit
- 我可以把 Worker 换成 TensorRT 路线 / Diffusers 路线
- 我可以把存储换成本地磁盘 / 对象存储
3. 我选择的两条推理路线
3.1 路线 A:Diffusers Pipeline(先跑通、再优化)
我用StableDiffusion3Pipeline这条线的原因很朴素:工程集成成本低,而且 SD3 pipeline 的关键特性(3 个文本编码器、offload 建议)在官方文档里写得很清楚。(huggingface.co)
如果我只是要“跑起来 + API 化”,路线 A 最快落地。
3.2 路线 B:TensorRT + FP8(把“能用”推进到“能打”)
如果我追求更稳定的线上吞吐和显存占用,我会直接对齐官方提供的 TensorRT 优化仓库:
- HF 的
stable-diffusion-3.5-large-tensorrt说明了ONNX 导出(BF16)+ FP8 的 MMDiT,并给出示例推理命令与引擎构建参数。(huggingface.co) - 这条路线的核心价值就是:把“PyTorch 生态的不确定性”收敛到“推理引擎的确定性”
我把官方公开收益画成了一张概念图(不是我实测数据,而是对公开信息的可视化):
4. 我镜像里的目录结构(我习惯这样摆)
sd35-fp8-mirror/ ├── Dockerfile ├── requirements.txt ├── app.py # FastAPI ├── sd_infer.py # 推理封装(Diffusers / TRT 可二选一) └── README.md5. Dockerfile:我怎么把“环境地狱”封进镜像
我用 CUDA Runtime 基础镜像是为了减少和宿主机 CUDA 的扯皮;同时把 HF 缓存挂载出来,避免每次重启都重新拉权重。
FROM nvidia/cuda:12.4.1-cudnn-runtime-ubuntu22.04 ENV DEBIAN_FRONTEND=noninteractive \ PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ HF_HOME=/cache/huggingface \ TRANSFORMERS_CACHE=/cache/huggingface \ HF_HUB_ENABLE_HF_TRANSFER=1 RUN apt-get update && apt-get install -y --no-install-recommends \ python3 python3-pip git curl \ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY requirements.txt /app/requirements.txt RUN python3 -m pip install --upgrade pip && pip install -r requirements.txt COPY app.py sd_infer.py /app/ EXPOSE 8000 CMD ["uvicorn", "app:api", "--host", "0.0.0.0", "--port", "8000"]requirements.txt(我会把版本锁住,减少漂移):
fastapi==0.115.0 uvicorn[standard]==0.30.6 pydantic==2.8.2 pillow==10.4.0 torch transformers diffusers accelerate safetensors huggingface_hub6. FastAPI:我怎么把“文生图脚本”变成“可用服务”
我把推理封装成一个generate(),API 只负责:入参校验、seed 控制、返回图片字节流。
# app.pyfromfastapiimportFastAPIfrompydanticimportBaseModel,Fieldfromfastapi.responsesimportResponsefromsd_inferimportget_engine api=FastAPI(title="SD3.5 FP8 Mirror API")classT2I(BaseModel):prompt:str=Field(...,min_length=1)negative_prompt:str|None=Nonewidth:int=1024height:int=1024steps:int=30guidance_scale:float=3.5seed:int|None=Noneengine=get_engine()# 懒加载/单例@api.post("/v1/txt2img")deftxt2img(req:T2I):img_bytes=engine.generate(prompt=req.prompt,negative_prompt=req.negative_prompt,width=req.width,height=req.height,steps=req.steps,guidance_scale=req.guidance_scale,seed=req.seed,)returnResponse(content=img_bytes,media_type="image/png")我把“工程可用性”放在第一位:
- 参数都可控(steps / seed / guidance 等)
- 输出格式固定(PNG)
- 结构清晰,后续接队列、加鉴权、加日志都不会拆大梁
7. 推理封装:Diffusers 版本(先跑通)
下面这个sd_infer.py我写得很“朴素”:
- 默认 FP16/BF16
- 显存紧张时可以做 offload(SD3 文档明确提到 offloading 的必要性倾向)(huggingface.co)
# sd_infer.py(Diffusers 路线示例)importioimporttorchfromPILimportImagefromdiffusersimportStableDiffusion3Pipeline _MODEL_ID="stabilityai/stable-diffusion-3.5-large"# 需要在 HF 同意协议后可拉取 :contentReference[oaicite:6]{index=6}classDiffusersEngine:def__init__(self):dtype=torch.bfloat16iftorch.cuda.is_available()elsetorch.float32 self.pipe=StableDiffusion3Pipeline.from_pretrained(_MODEL_ID,torch_dtype=dtype)iftorch.cuda.is_available():self.pipe.to("cuda")# 机器显存不宽裕时,可以考虑:# self.pipe.enable_model_cpu_offload()@torch.inference_mode()defgenerate(self,prompt,negative_prompt=None,width=1024,height=1024,steps=30,guidance_scale=3.5,seed=None):g=NoneifseedisnotNoneandtorch.cuda.is_available():g=torch.Generator(device="cuda").manual_seed(seed)out=self.pipe(prompt=prompt,negative_prompt=negative_prompt,width=width,height=height,num_inference_steps=steps,guidance_scale=guidance_scale,generator=g,).images[0]buf=io.BytesIO()out.save(buf,format="PNG")returnbuf.getvalue()_engine=Nonedefget_engine():global_engineif_engineisNone:_engine=DiffusersEngine()return_engine8. 我怎么跑起来:构建、启动、请求一气呵成
# 构建镜像docker build -t sd35-fp8-mirror:0.1.# 启动(把 HF 缓存挂出来,避免重复下载)docker run --gpus all --rm\-p8000:8000\-v$PWD/cache:/cache\sd35-fp8-mirror:0.1调用:
curl-X POST"http://localhost:8000/v1/txt2img"\-H"Content-Type: application/json"\-d'{ "prompt": "A cinematic photo of a rainy neon street, ultra-detailed, 35mm", "negative_prompt": "blurry, low quality, watermark", "width": 1024, "height": 1024, "steps": 30, "guidance_scale": 3.5, "seed": 42 }'--output out.png9. FP8 / TensorRT 我怎么接(我把它当“第二阶段强化”)
如果我把镜像推到生产环境,我会优先对齐官方 TensorRT 路线,因为 HF 的 TensorRT 仓库已经把关键步骤(容器、脚本、引擎参数、HF Token)写清楚了,并明确存在--fp8这条推理分支。(huggingface.co)
我通常会这么做取舍:
- 先用 Diffusers 版把业务链路跑通(API、鉴权、队列、监控)
- 再把 Worker 替换成 TensorRT FP8 引擎(吞吐、显存、稳定性)
- 镜像层保持不变,只替换推理后端实现
10. 我最后的总结
这次“AI 镜像开发”的核心,不是堆参数、也不是追榜单,而是把 SD3.5 FP8 这件事做成一个可以复用的工程模块:
- 镜像解决“环境一致性”
- FP8/TensorRT 解决“性能与显存”(Stability AI)
- API 化解决“可集成与可上线”
参考链接(方便我贴到 CSDN 参考区)
Stability AI:Introducing Stable Diffusion 3.5 https://stability.ai/news/introducing-stable-diffusion-3-5 Hugging Face:stabilityai/stable-diffusion-3.5-large https://huggingface.co/stabilityai/stable-diffusion-3.5-large Hugging Face:stabilityai/stable-diffusion-3.5-large-tensorrt https://huggingface.co/stabilityai/stable-diffusion-3.5-large-tensorrt Diffusers 文档:Stable Diffusion 3 Pipeline(3 encoders / offloading) https://huggingface.co/docs/diffusers/main/en/api/pipelines/stable_diffusion/stable_diffusion_3 Stability AI:SD3.5 TensorRT + FP8 官方公告 https://stability.ai/news/stable-diffusion-35-models-optimized-with-tensorrt-deliver-2x-faster-performance-and-40-less-memory-on-nvidia-rtx-gpus(可选)我给自己留的“技术自测题”
- SD3 pipeline 为什么会用三个文本编码器?这对显存与加载时间意味着什么?(huggingface.co)
- 我把 Diffusers Worker 切到 TensorRT FP8 Worker 时,镜像层和服务层分别应该改哪里、哪些不该动?(huggingface.co)
- 公开信息里提到的“更快 + 更省显存”,在工程上应该如何量化(吞吐、p95 延迟、显存峰值、冷启动时间)?(Stability AI)