GPU 云服务器实战:用腾讯云/阿里云 GPU 实例搭建 AI 绘画 API 服务

阿里云上云采购季 2核2G云服务器99元/年 续费同价

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 价格低但可能被回收

省钱技巧:

  1. 竞价实例:腾讯云/阿里云竞价实例价格只有按需的 30%-50%,适合非实时任务
  2. 自动关机:用定时任务在凌晨 0-6 点关机,月省 25%
  3. 模型缓存复用:把常用模型存在云硬盘上,重启不用重新下载
  4. 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

发表评论