手搓 Skill 之使用硅基流动 API 免费生图

SKILL 是什么

SKILL 在我看来就是可以让大模型随时看到的说明文档。文档说明了这个 SKILL 可以干什么,有什么工具可以用,应该怎么做。

开始做 SKILL

所以 Skill 的文件结构就必然有 Skill 说明(SKILL.md)以及 Skill 相关代码(Scripts)

skills-01

至于 references,其实就是一个简易化的 RAG,至于什么是 RAG,问 AI 就行。

然后先编写 SKILL.md 骨架,结构化数据 name 和 description 是描述SKILL。然后后面就可以附加这套 SKILL 怎么做,有什么约束,比如参数格式和失败处理。

---
name: siliconflow-image-generation
description: 通过 SiliconFlow API 、调用 Kwai-Kolors/Kolors 模型生成图片,另外可调整分辨率、步数、数量。
---

# SiliconFlow 生图
## 概述
## 生成图片
## 参数格式
## 结果与失败处理

编写概述

概述的话和 description 不一样,要具体说明。比如

通过 SiliconFlow 生成 1 至 4 张图片,并返回 API 响应或将图片保存到本地。具体通过 uv 运行附带脚本,并从环境变量 SILICONFLOW_API_KEY 读取密钥,避免将密钥写入命令行参数。

但是我建议直接在脚本里指定从 SILICONFLOW_API_KEY 环境变量读取,没必要再 SKILL.md 里说明,除非你有很多 KEY 要逐个使用。所以我的最终版是

通过 SiliconFlow 生成 1 至 4 张图片,并返回 API 响应或将图片保存到本地。。

生成图片说明

直接告诉大模型怎么做就可以了,比如:

通过 uv 运行脚本

uv run scripts/generate_image.py --prompt "一只坐在阳光图书馆里的电影感橘猫" --size 1024x1024 --steps 20 --count 1 --output-dir .\generated-images

编写清晰的生图提示词:主体、环境、构图、光线、媒介或风格,以及质量要求。如果这些因子会影响生图效果,请先确认用户期望的画面比例、风格、图片中的文字和不希望出现的元素。

编写参数说明

说明脚本的每个参数代表什么,其实这个主要是生图 API 支持什么参数,比如:

prompt: 提示词
size:控制参数的图像分辨率,API请求时候,可以自定义多种分辨率。
steps:控制图像生成的步长。
count:一次生成图像的个数,默认值是1,最大值可以设置为 4
output-dir:指定图片存储路径./相对路径会存放到 SKILL 目录下
seed:如果想要每次都生成固定的图片,可以把seed设置为固定值。

编写结果与失败处理

示例嘛,我就不写了,当然比如说遇到429可以等待1分钟后重试。

编写脚本

把 API 说明文档丢给 AI。

# /// script
# requires-python = ">=3.10"
# dependencies = ["openai>=1.0.0"]
# ///

"""Generate images with SiliconFlow's OpenAI-compatible API."""

from __future__ import annotations

import argparse
import base64
import os
import sys
from pathlib import Path
from urllib.request import urlopen

from openai import APIError, OpenAI


DEFAULT_BASE_URL = "https://api.siliconflow.cn/v1"
DEFAULT_MODEL = "Kwai-Kolors/Kolors"


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(
        description="Generate images with SiliconFlow's OpenAI-compatible API."
    )
    parser.add_argument("--prompt", required=True, help="Description of the desired image.")
    parser.add_argument("--model", default=DEFAULT_MODEL, help="SiliconFlow model ID.")
    parser.add_argument("--size", default="1024x1024", help="Image resolution, such as 1024x1024.")
    parser.add_argument("--steps", type=int, default=20, help="Inference steps.")
    parser.add_argument("--count", type=int, default=1, choices=range(1, 5), help="Number of images (1-4).")
    parser.add_argument("--negative-prompt", help="Elements to exclude from the image.")
    parser.add_argument("--seed", type=int, help="Seed for reproducible output when supported.")
    parser.add_argument(
        "--parameter-format",
        choices=("openai", "model"),
        default="openai",
        help="Use OpenAI-compatible names or native model parameter names.",
    )
    parser.add_argument("--base-url", default=DEFAULT_BASE_URL, help="API base URL.")
    parser.add_argument("--output-dir", type=Path, help="Directory for downloaded or base64 images.")
    return parser.parse_args()


def build_extra_body(args: argparse.Namespace) -> dict[str, object]:
    if args.parameter_format == "openai":
        parameters: dict[str, object] = {"step": args.steps}
    else:
        parameters = {
            "image_size": args.size,
            "num_inference_steps": args.steps,
            "batch_size": args.count,
        }

    if args.negative_prompt:
        parameters["negative_prompt"] = args.negative_prompt
    if args.seed is not None:
        parameters["seed"] = args.seed
    return parameters


def save_images(response: object, output_dir: Path) -> None:
    output_dir.mkdir(parents=True, exist_ok=True)
    images = getattr(response, "data", [])
    for index, image in enumerate(images, start=1):
        target_path = output_dir / f"image-{index}.png"
        encoded_image = getattr(image, "b64_json", None)
        image_url = getattr(image, "url", None)
        if encoded_image:
            target_path.write_bytes(base64.b64decode(encoded_image))
        elif image_url:
            with urlopen(image_url, timeout=60) as download_response:
                target_path.write_bytes(download_response.read())
        else:
            print(f"Image {index} has no URL or base64 payload; not saved.", file=sys.stderr)
            continue
        print(f"Saved {target_path}")


def main() -> int:
    args = parse_args()
    api_key = os.environ.get("SILICONFLOW_API_KEY")
    if not api_key:
        print("Set SILICONFLOW_API_KEY before generating images.", file=sys.stderr)
        return 2

    client = OpenAI(api_key=api_key, base_url=args.base_url)
    request: dict[str, object] = {
        "model": args.model,
        "prompt": args.prompt,
        "extra_body": build_extra_body(args),
    }
    if args.parameter_format == "openai":
        request["size"] = args.size
        request["n"] = args.count

    try:
        response = client.images.generate(**request)
    except APIError as error:
        print(f"SiliconFlow image generation failed: {error}", file=sys.stderr)
        return 1

    print(response.model_dump_json(indent=2))
    if args.output_dir:
        save_images(response, args.output_dir)
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

编写元数据

元数据固定路径 agents/openai.yaml。照着改就行。

interface:
  display_name: "SiliconFlow 生图"
  short_description: "使用 SiliconFlow OpenAI 兼容接口生成图片并调整关键参数"
  default_prompt: "使用 $siliconflow-image-generation 通过 SiliconFlow 创建一张图片。"

前边实际不用管

现在大模型都很好用了,你直接丢给他 API 文档,然后编写技能就可以了,比如把下面在 AGENT 丢进去,等一会就写好了。

 client = OpenAI(api_key="Your-api_key", base_url="https://api.siliconflow.cn/v1")

  response = client.images.generate(
      model="Kwai-Kolors/Kolors",
      prompt="a cat",
      size="1024x1024",
      n=1,
      extra_body={
          "step": 20
      }
  )

  print(response)

      重点参数介绍

          image_size:控制参数的图像分辨率,API请求时候,可以自定义多种分辨率。

          num_inference_steps:控制图像生成的步长。

          batch_size:一次生成图像的个数,默认值是1,最大值可以设置为4

          negative_prompt:这里可以输入图像中不想出现的某些元素,消除一些影响影响因素。

          seed:如果想要每次都生成固定的图片,可以把seed设置为固定值。
  根据这个创建一个生图技能
posted @ 2026-08-05 22:27  电动工具  阅读(32)  评论(0)    收藏  举报