三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

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

手搓 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 annotationsimport argparse
import base64
import os
import sys
from pathlib import Path
from urllib.request import urlopenfrom openai import APIError, OpenAIDEFAULT_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_promptif args.seed is not None:parameters["seed"] = args.seedreturn parametersdef 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)continueprint(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 2client = 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.sizerequest["n"] = args.counttry:response = client.images.generate(**request)except APIError as error:print(f"SiliconFlow image generation failed: {error}", file=sys.stderr)return 1print(response.model_dump_json(indent=2))if args.output_dir:save_images(response, args.output_dir)return 0if __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,最大值可以设置为4negative_prompt:这里可以输入图像中不想出现的某些元素,消除一些影响影响因素。seed:如果想要每次都生成固定的图片,可以把seed设置为固定值。根据这个创建一个生图技能
← 返回列表