SeFi-Image 接入现有图片生成工作流的接口适配

文章导读
如果现有图片生成工作流只兼容其他模型的 HTTP 接口,直接切到 SeFi-Image 的风险点在于字段语义、取值范围、返回结构和错误信息都不一样。建议在业务代码与 SeFi-Image 之间加一个本地适配层,把原请求转换成 SeFi-Image 的输入,再统一返回结构和错误码。这样业务侧改动最小,适配效果靠历史样本回放验证。
📋 目录
  1. 记录现有工作流的入参和出参
  2. 设计适配层统一接口
  3. 实现参数映射和默认值补齐
  4. 把报错转换成统一错误码
  5. 用历史样本回放验证
A A

如果现有图片生成工作流只兼容其他模型的 HTTP 接口,直接切到 SeFi-Image 的风险点在于字段语义、取值范围、返回结构和错误信息都不一样。建议在业务代码与 SeFi-Image 之间加一个本地适配层,把原请求转换成 SeFi-Image 的输入,再统一返回结构和错误码。这样业务侧改动最小,适配效果靠历史样本回放验证。

适用场景:本地已有图片生成服务,想用 SeFi-Image 替换原模型,且不希望大范围改动业务代码。操作动作:记录原接口字段形状,定义适配层统一 JSON 接口,做字段映射和默认值补齐,把异常转成固定错误码,再用历史请求回放对比。验证方式:跑回放请求,检查返回字段是否完整、图片是否成功生成。风险边界:适配层只保证接口形状兼容,不保证生成图风格和效果与原模型一致。

记录现有工作流的入参和出参

先别急着写代码。把当前工作流里所有调用图片生成模型的请求抓下来,逐类记录字段。每一类请求要明确:字段名、类型、取值范围、是否必填,以及返回图片的格式(比如 base64 字符串、文件 URL,还是二进制流)。

通常原系统会有两到三种典型调用:文生图、图生图、尺寸调整。实际记录时建议用 JSON Schema 或表格列出来。至少包括下面这些信息:

  • 请求路径和方式:比如 POST /generate
  • 必填字段:提示词、宽高、生成数量
  • 可选字段:采样步数、随机种子、负面提示词
  • 返回体:图片编码方式、字段名(如 imageimages)、额外信息(如耗时)

同时查看 SeFi-Image 的模型输入格式。如果它只提供本地 Python 调用,就把适配层做成本地封装服务,不假设它有 HTTP API。记录这些内容是为了明确映射边界,避免后面凭感觉猜字段。

设计适配层统一接口

适配层对外提供一套固定 JSON 接口,业务侧只认这套接口,不直接感知 SeFi-Image。这样后续替换模型时,只需要改适配层内部映射。

下面是一个统一请求示例:

{
  "prompt": "a cat on the moon",
  "negative_prompt": "blurry",
  "width": 512,
  "height": 512,
  "num_images": 1,
  "seed": 42
}

统一响应示例:

{
  "code": 0,
  "message": "success",
  "data": {
    "images": ["base64_encoded_string"],
    "seed_used": 42
  }
}

对比原系统与 SeFi-Image 默认参数时,重点看这些差异:

  • 原字段 steps 可能叫 num_inference_steps
  • 原字段 batch_size 可能对应 num_images
  • 原系统没有的字段,SeFi-Image 可能需要默认值,比如 guidance_scale
  • 图片返回格式:原系统可能是 URL,SeFi-Image 可能直接给张量,需要在适配层转成统一格式

建议先定义好这套统一接口,再动手写映射代码,避免边写边改。

实现参数映射和默认值补齐

适配层核心是一个映射函数。输入是原系统请求 JSON,输出是 SeFi-Image 需要的参数字典。对于缺失字段,补齐模型必需的默认值。

下面是一段通用 Python 代码骨架:

SeFi-Image 接入现有图片生成工作流的接口适配
def adapt_request(raw: dict) -> dict:
    # 字段映射
    mapped = {
        "prompt": raw.get("prompt", ""),
        "negative_prompt": raw.get("negative_prompt", ""),
        "width": raw.get("width", 512),
        "height": raw.get("height", 512),
        "num_images": raw.get("batch_size", 1),
        "guidance_scale": raw.get("cfg_scale", 7.5),
        "seed": raw.get("seed", -1),
    }
    # 步数映射,原字段可能叫 steps 或 num_steps
    if "steps" in raw:
        mapped["num_inference_steps"] = raw["steps"]
    elif "num_steps" in raw:
        mapped["num_inference_steps"] = raw["num_steps"]
    else:
        mapped["num_inference_steps"] = 30
    # SeFi-Image 必需但原请求没有的字段,补默认值
    mapped.setdefault("scheduler", "pndm")
    return mapped

放到哪里执行?建议把这个函数放在适配层服务的请求入口处,先解析原请求,再调用 SeFi-Image 的生成函数。执行后建议打日志,记录映射前后的完整参数,方便排查问题。

把报错转换成统一错误码

业务侧不应该直接看到模型库抛出的裸异常。适配层要捕获异常,转成固定结构,让调用方可以根据错误码做降级或重试。

可以先定义几个错误码:

  • 1001 参数错误:请求字段缺失或类型不对
  • 1002 生成超时:模型推理超过设置的时间上限
  • 1003 显存不足:推理设备内存不够
  • 1000 未知错误

异常捕获示意:

try:
    params = adapt_request(raw)
    images = sefi_generate(params)
    return build_success(images)
except ValueError as e:
    return build_error(1001, str(e))
except TimeoutError:
    return build_error(1002, "generation timeout")
except RuntimeError as e:
    if "out of memory" in str(e).lower():
        return build_error(1003, "GPU out of memory")
    return build_error(1000, str(e))

注意错误信息不要直接透传底层堆栈,只给业务侧一个可读的 message。适配层内部日志里保留完整异常,方便定位问题。

用历史样本回放验证

适配层写好后,不能只看一两个请求能通就上线。截取原系统最近一段时间内的真实请求(脱敏处理),回放到适配层,再对比结果。

做法如下:

  1. 从日志中抽取原始请求 JSON,去掉涉及隐私和内部的字段。
  2. 按调用时间顺序回放,记录每个请求的响应码、返回字段和图片是否生成成功。
  3. 比对原系统返回结构和适配层返回结构,确认业务侧需要用的字段都存在、类型一致。
  4. 抽查生成的图片,确认不是全黑或全灰,但不需要对比画质。

一个回放样本示例:

原始请求:
{
  "prompt": "a castle in the sky",
  "steps": 25,
  "cfg_scale": 7.0
}

适配层输出:
{
  "code": 0,
  "data": {
    "images": ["..."],
    "seed_used": -1
  }
}

回放时如果发现某些原字段被忽略了,要回到映射函数里补上。如果返回结构里缺少业务侧依赖的字段,也要及时调整。回放全部通过后,再让业务侧联调。这样替换成本可控,后续 SeFi-Image 自身升级也不会影响业务侧代码。