Stable Diffusion 出图一张要等 30 秒?ComfyUI 跑复杂工作流 CPU 直接冒烟?别急,一块 T4 云 GPU 就能跑起生产级 AI 绘画 API,成本比你想象的还低。
为什么用云 GPU 跑 AI 绘画?
2026 年,AI 绘画已经从玩具变成了生产力工具。电商用 AI 生成商品图,设计师用 AI 出概念稿,自媒体用 AI 做封面——但本地显卡跑 SD 有几个痛点:
| 痛点 | 本地方案 | 云 GPU 方案 |
|---|---|---|
| 硬件成本 | RTX 4090 ≈ ¥15000 | T4 按需 ¥6/小时 |
| 并发能力 | 单卡串行,一张一张跑 | 多实例弹性扩容 |
| 对外服务 | 内网,无法提供 API | 公网 API,团队共享 |
| 运维复杂度 | 自己折腾 CUDA 环境 | 云厂商预装镜像,开箱即用 |
| 弹性伸缩 | 闲时吃灰,忙时不够 | 按需启停,灵活计费 |
结论: 如果你的 AI 绘画需要服务化、团队化、弹性化,云 GPU 是最佳选择。
GPU 云服务器横向对比
| 规格 | 腾讯云 GN7 | 阿里云 ecs.gn7i | 华为云 Ai1s |
|---|---|---|---|
| GPU 型号 | T4 16GB | T4 / A10 | Ascend 310 |
| 显存 | 16GB | 16GB / 24GB | – |
| vCPU | 8 核 | 8 核 | 8 核 |
| 内存 | 32GB | 32GB | 32GB |
| 按需价格 | ¥6.2/小时 | ¥7.5/小时 | ¥5.8/小时 |
| 包月价格 | ¥1800/月 | ¥2200/月 | ¥1600/月 |
| CUDA 支持 | 原生 CUDA 12 | 原生 CUDA 12 | 需适配 CANN |
| SD 兼容性 | ✅ 最佳 | ✅ 最佳 | ⚠️ 需转换 |
💡 个人推荐:跑 SD 选腾讯云 GN7 或阿里云 ecs.gn7i,原生 CUDA 生态,社区支持最完善。
5 步搭建 AI 绘画 API
第 1 步:创建 GPU 云服务器
以腾讯云为例,创建一台 GN7 实例:
# 通过腾讯云 CLI 创建(需要先安装 tccli)
tccli cvm RunInstances \
--InstanceType "GN7.2XLARGE32" \
--ImageId "img-487zeit5" \
--SystemDisk '[{"DiskType":"CLOUD_PREMIUM","DiskSize":100}]' \
--InternetAccessible '{"InternetMaxBandwidthOut":10,"PublicIpAssigned":true}' \
--InstanceChargeType "POSTPAID_BY_HOUR" \
--Placement '{"Zone":"ap-guangzhou-6"}'
第 2 步:安装 CUDA 和驱动
SSH 登录后,安装 NVIDIA 驱动:
# 更新系统
sudo apt update && sudo apt upgrade -y
# 安装 NVIDIA 驱动(腾讯云 GN7 预装了 CUDA 工具包,确认一下)
nvidia-smi
# 如果未安装,执行:
# sudo apt install -y nvidia-driver-535 nvidia-cuda-toolkit
# 确认 CUDA 可用
nvcc --version
第 3 步:部署 Stable Diffusion WebUI API
用 Docker 部署 Automatic1111 WebUI 并暴露 API:
# 创建数据目录
mkdir -p ~/stable-diffusion/{models,outputs,extensions}
# 拉取并启动(开启 API 模式)
docker run -d --name sd-webui \
--gpus all \
-p 7860:7860 \
-v ~/stable-diffusion/models:/stable-diffusion-webui/models \
-v ~/stable-diffusion/outputs:/stable-diffusion-webui/outputs \
-e COMMANDLINE_ARGS="--api --listen --no-half-vae --xformers" \
ghcr.io/ashleykleynhans/stable-diffusion-webui:latest
# 查看日志确认启动
docker logs -f sd-webui
# 看到 "Running on http://0.0.0.0:7860" 就是成功了
🔑
--api是关键参数,开启后 WebUI 暴露 RESTful API,可以用代码直接调用。
第 4 步:下载 SD 模型
# 下载 SDXL 模型(推荐 Juggernaut XL,生成质量高)
cd ~/stable-diffusion/models/Stable-diffusion
wget https://huggingface.co/RunDiffusion/Juggernaut-XL-v9/resolve/main/Juggernaut-XL-v9-RunDiffusionPhotoV2.safetensors
# 下载 LoRA(可选,提升特定风格)
cd ~/stable-diffusion/models/Lora
wget https://huggingface.co/latent-consistency/lcm-lora-sdxl/resolve/main/pytorch_lora_weights.safetensors
第 5 步:编写 API 调用代码
"""
AI 绘画 API 客户端
pip install requests pillow
"""
import requests
import base64
import json
from pathlib import Path
from datetime import datetime
class StableDiffusionAPI:
"""Stable Diffusion WebUI API 封装"""
def __init__(self, base_url: str = "http://your-gpu-server:7860"):
self.base_url = base_url.rstrip("/")
self.txt2img_url = f"{self.base_url}/sdapi/v1/txt2img"
self.img2img_url = f"{self.base_url}/sdapi/v1/img2img"
self.options_url = f"{self.base_url}/sdapi/v1/options"
def generate(
self,
prompt: str,
negative_prompt: str = "",
steps: int = 25,
cfg_scale: float = 7.5,
width: int = 1024,
height: int = 1024,
batch_size: int = 1,
seed: int = -1,
) -> list[bytes]:
"""
文生图
参数:
prompt: 正向提示词
negative_prompt: 反向提示词
steps: 采样步数(20-30 推荐)
cfg_scale: 提示词引导强度(5-12)
width/height: 出图尺寸(SDXL 推荐 1024x1024)
batch_size: 批量生成数量
seed: 随机种子(-1 随机)
返回:
list[bytes]: PNG 图片字节列表
"""
payload = {
"prompt": prompt,
"negative_prompt": negative_prompt or "lowres, bad anatomy, blurry, ugly",
"steps": steps,
"cfg_scale": cfg_scale,
"width": width,
"height": height,
"batch_size": batch_size,
"seed": seed if seed >= 0 else -1,
"sampler_name": "DPM++ 2M Karras",
"scheduler": "Karras",
}
response = requests.post(self.txt2img_url, json=payload, timeout=120)
response.raise_for_status()
result = response.json()
images = []
for img_data in result["images"]:
images.append(base64.b64decode(img_data))
return images
def save_images(self, images: list[bytes], prefix: str = "sd_output") -> list[str]:
"""保存生成图片到本地"""
output_dir = Path("./outputs")
output_dir.mkdir(exist_ok=True)
paths = []
for i, img_bytes in enumerate(images):
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"{prefix}_{timestamp}_{i}.png"
filepath = output_dir / filename
filepath.write_bytes(img_bytes)
paths.append(str(filepath))
print(f"✅ 已保存: {filepath}")
return paths
def get_current_model(self) -> str:
"""获取当前加载的模型"""
response = requests.get(f"{self.options_url}", timeout=10)
return response.json().get("sd_model_checkpoint", "unknown")
# ========== 使用示例 ==========
if __name__ == "__main__":
# 初始化 API 客户端
api = StableDiffusionAPI(base_url="http://your-gpu-server:7860")
# 查看当前模型
model = api.get_current_model()
print(f"当前模型: {model}")
# 生成图片
images = api.generate(
prompt="A futuristic cyberpunk city at night, neon lights, rain, ultra detailed, 8k resolution",
negative_prompt="lowres, bad hands, blurry, watermark, text",
steps=25,
width=1024,
height=1024,
batch_size=2,
)
# 保存到本地
api.save_images(images, prefix="cyberpunk")
print("🎨 生成完成!")
生产环境增强:用 FastAPI 封装服务
上面的 API 是 WebUI 原生的,直接暴露给外部不够安全。我们来加一层 FastAPI:
"""
生产级 AI 绘画 API 网关
pip install fastapi uvicorn python-multipart
"""
from fastapi import FastAPI, HTTPException
from fastapi.responses import Response, JSONResponse
from pydantic import BaseModel, Field
import requests
import base64
import io
app = FastAPI(title="AI 绘画 API", version="1.0.0")
SD_BACKEND = "http://127.0.0.1:7860"
class GenerateRequest(BaseModel):
prompt: str = Field(..., description="正向提示词", min_length=1, max_length=2000)
negative_prompt: str = Field(default="", max_length=2000)
steps: int = Field(default=25, ge=10, le=50)
width: int = Field(default=1024, ge=512, le=2048)
height: int = Field(default=1024, ge=512, le=2048)
batch_size: int = Field(default=1, ge=1, le=4)
class HealthResponse(BaseModel):
status: str
model: str
gpu_memory: str
@app.get("/health", response_model=HealthResponse)
def health_check():
"""健康检查 + GPU 状态"""
try:
resp = requests.get(f"{SD_BACKEND}/sdapi/v1/options", timeout=5)
model = resp.json().get("sd_model_checkpoint", "unknown")
return HealthResponse(status="healthy", model=model, gpu_memory="16GB T4")
except Exception:
raise HTTPException(status_code=503, detail="SD backend unreachable")
@app.post("/generate")
def generate_image(req: GenerateRequest):
"""生成图片(返回 PNG)"""
payload = {
"prompt": req.prompt,
"negative_prompt": req.negative_prompt or "lowres, bad anatomy, blurry",
"steps": req.steps,
"cfg_scale": 7.5,
"width": req.width,
"height": req.height,
"batch_size": req.batch_size,
"sampler_name": "DPM++ 2M Karras",
}
try:
resp = requests.post(
f"{SD_BACKEND}/sdapi/v1/txt2img",
json=payload,
timeout=180,
)
resp.raise_for_status()
except requests.RequestException as e:
raise HTTPException(status_code=502, detail=f"SD generation failed: {e}")
result = resp.json()
if not result.get("images"):
raise HTTPException(status_code=500, detail="No images generated")
# 返回第一张图片
img_bytes = base64.b64decode(result["images"][0])
return Response(content=img_bytes, media_type="image/png")
# 启动:uvicorn main:app --host 0.0.0.0 --port 8000
成本分析:跑一个月要多少钱?
| 使用场景 | GPU 实例 | 月计算 | 费用说明 |
|---|---|---|---|
| 个人尝鲜 | T4 按需,日均 2h | 30天×2h×¥6.2 = ¥372 | 周末可以不挂机 |
| 小团队服务 | T4 包月 | ¥1800 | 随时可用,24h 在线 |
| 高并发生产 | A100 包月 | ¥8000+/月 | 企业级,支持多路并发 |
| 弹性省钱方案 | 竞价实例 | ¥800-1200 | 价格低但可能被回收 |
省钱技巧:
- 竞价实例:腾讯云/阿里云竞价实例价格只有按需的 30%-50%,适合非实时任务
- 自动关机:用定时任务在凌晨 0-6 点关机,月省 25%
- 模型缓存复用:把常用模型存在云硬盘上,重启不用重新下载
- FP16 推理:使用
--no-half-vae以外的优化参数,16GB 显存能跑 SDXL
常见坑与解决方案
| 问题 | 原因 | 解决方案 |
|---|---|---|
| Out of Memory | 显存不够 | 降 resolution 或加 --medvram |
| 生成速度慢 | 未开 xformers | 加 --xformers 参数 |
| API 返回空 | 模型未加载 | 先访问 WebUI 确认模型可用 |
| 外网无法访问 | 安全组未开 7860 | 云控制台放行端口 |
| 模型下载失败 | HuggingFace 被墙 | 用国内镜像 hf-mirror.com |
# 设置 HuggingFace 国内镜像
export HF_ENDPOINT=https://hf-mirror.com
👤 作者简介
一枚在大中原腹地(河南)卖公有云的从业者,主营腾讯云/阿里云/火山云,曾踩坑无数,现专注AI大模型应用落地。关注公众号「公有云cloud」,围观AI前沿动态~
博客:y1cloud.cn
