Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/baklib-tools_skills.json
T

1 line
34 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "baklib-tools/skills", "files": {"examples/requirements-to-published-content-health-cms/artifacts/images/README.md": {"f0df7b92f1a53c54a6bfb7cd8320cc2fc03db76c": {"t": 1785596113.6021707, "n": 903, "h": "196ee6f38605e6bd", "c": "# 示例配图(三镜头)\n\n与 [image-plan-from-content.md](../image-plan-from-content.md) 及 [prompts/](prompts/) 中提示词对应:\n\n| 文件 | 镜头 |\n|------|------|\n| `rtc-demo-shot1.png` | 痛点:内容分散、多屏混乱 |\n| `rtc-demo-shot2.png` | 方案:统一内容枢纽 |\n| `rtc-demo-shot3.png` | 结果/CTA:分期路径 |\n\n[06-wechat-article.html](../06-wechat-article.html) 使用相对路径 `images/rtc-demo-shot*.png` 引用;本地用浏览器打开该 HTML 即可预览。\n\n## 重新生成(维护者)\n\n在仓库根目录 `skills`(含 `.config/UCLOUD_API_KEY`)下执行:\n\n```bash\npython3 skills/image-generation-ucloud/scripts/generate_ucloud_image.py \\\n --prompt examples/requirements-to-published-content-health-cms/artifacts/images/prompts/shot1-pain.txt \\\n --output examples/requirements-to-published-content-health-cms/artifacts/images/rtc-demo-shot1.png \\\n --size 4:3 --image-size 1K\n```\n\n将 `shot1-pain` / `shot2-solution` / `shot3-cta` 与输出文件名轮换执行三次。模型与密钥说明见 [image-generation-ucloud](../../../../skills/image-generation-ucloud/SKILL.md)。\n"}}, "skills/image-generation/SKILL.md": {"f0df7b92f1a53c54a6bfb7cd8320cc2fc03db76c": {"t": 1785596113.791131, "n": 3524, "h": "6aef566ba6b21018", "c": "---\nname: image-generation\ndescription: >-\n 图像生成工作流总览:何时出图、如何选用后端子技能、与提示词技能配合。\n 在用户需要配图/示意图、选择 UCloud 或 OpenRouter 等 API 出图、或询问本仓库「出图技能怎么组合」时使用。\n---\n\n# 图像生成(总技能)\n\n## 执行前提:须配合服务商子技能\n\n本总技能**不能**单独完成「调 API、运行脚本、产出图像」;只说明工作流、组合方式与密钥检查原则,**不包含**任一服务商的完整端点、请求体与可执行命令。\n\n- **必须**与至少一个 **`image-generation-<服务商>`** 子技能同时使用(当前为 **`image-generation-ucloud`**、**`image-generation-openrouter`**;以后仓库若增加其它供应商,命名约定见下表)。实际出图时以**对应子技能**的 `SKILL.md` 与目录内脚本为准。\n- 若环境中**仅有**本总技能、**没有**任一端子技能,代理应**先**请用户选定或说明打算使用的后端(或根据已有密钥推断),再打开该子技能;**不要**仅凭本文件自行拼凑 HTTP 调用。\n- **提示词类技能**(如 `nano-banana-pro-prompting`)可与总技能、服务商子技能组合,但**不能**替代服务商子技能完成鉴权与请求。\n\n## 命名与组合规则(开源场景)\n\n本仓库将「出图」拆成 **1 个总技能 + 若干后端子技能**,避免把某一云厂商或某一账号流程写死为唯一路径。\n\n| 类型 | 目录名(`name`) | 何时阅读 |\n|------|------------------|----------|\n| 总览 | `image-generation` | 工作流、授权、与提示词技能配合、选哪个后端 |\n| UCloud ModelVerse | `image-generation-ucloud` | 使用 UCloud 文档中的 ModelVerse 图像 API |\n| OpenRouter | `image-generation-openrouter` | 使用 OpenRouter 调用 Gemini 等图像能力 |\n\n**约定**:以后若增加其他供应商,使用同一前缀 `image-generation-` + 短后缀(如 `image-generation-xxx`),并在本文件表格中补充一行。\n\n## 本技能做什么\n\n- 说明 **何时** 适合调用出图能力(含与正文/营销文案的配合方式)。\n- 指引 **下一步** 应打开哪个子技能(按用户实际使用的接口)。\n- 指向本仓库已有的 **提示词专项技能**(见下文),与「如何调 HTTP」解耦。\n\n## 本技能不做什么\n\n- **不**作为可独立执行的出图技能:端点、模型 ID、脚本路径与参数以各 **`image-generation-*` 服务商子技能**为准,本文件不重复罗列以免与子技能脱节。\n- **不**代替用户保管或填写密钥、**不**承诺计费与配额;密钥与费用以各平台控制台为准。\n- **不**把某一项目的私有目录、内部规范文件名写死为唯一路径;你应在**自己的项目**里维护风格说明与占位约定。\n- 提示词撰写原则见 `nano-banana-pro-prompting`;**单次 API 请求的提示词须自包含**,勿假设模型能「记住上一张图」(见该技能与 [AGENTS.md](https://github.com/baklib-tools/skills/blob/main/AGENTS.md))。\n\n## 与提示词技能的关系\n\n- **撰写/优化** Nano Banana(Gemini 3 Pro Image)类提示词:使用 **[nano-banana-pro-prompting](https://github.com/baklib-tools/skills/blob/main/skills/nano-banana-pro-prompting/SKILL.md)**。\n- **调用哪个 HTTP 接口**:按后端阅读 **`image-generation-ucloud`** 或 **`image-generation-openrouter`**;二者与提示词技能正交,可任意组合。\n\n## 执行前检查 API 密钥(代理必读)\n\n在运行各服务商脚本或替用户发起出图请求之前,**先确认**对应密钥是否已配置;若未配置,**不要静默失败**,应提示用户**优先**在**项目根目录**下创建 **`.config/`** 内密钥文件(再备选环境变量):\n\n| 后端 | 优先(项目根) | 备选(环境变量) |\n|------|----------------|------------------|\n| UCloud | `.config/UCLOUD_API_KEY` | `UCLOUD_API_KEY` |\n| OpenRouter | `.config/OPENROUTER_API_KEY` | `OPENROUTER_API_KEY` |\n\n文件内容为**单行**密钥文本,UTF-8 编码;**勿**将密钥写入仓库或技能正文。脚本会从项目根向上查找含 `.config` 的目录(详见各子技能说明)。\n\n## 工作流建议(通用)\n\n1. **先定模型与风格**(是否用 Gemini 3 Pro Image、是否需图内文字等),再写提示词文件(UTF-8)。\n2. **再选后端**:有 UCloud ModelVerse 密钥则读 `image-generation-ucloud`;若使用 OpenRouter 则读 `image-generation-openrouter`。\n3. **再执行**:由用户或 CI 在本地运行其脚本/工具发起请求;代理可协助检查命令行参数与错误信息含义,但**不**默认代跑生产密钥请求(除非你明确授权且环境已配置)。\n\n### 与「文章成稿」类任务的配合\n\n- 若正文中仅有配图占位,**不要默认自动出图**;在用户**明确**要求生成配图或等价指令后再执行出图与替换占位。\n- 若任务本身已包含「生成配图」「成片」等授权,可按该任务技能执行,仍建议 **Nano Banana + 选定后端** 与项目规范一致。\n\n## 参考脚本(按服务商拆分)\n\n各云厂商的 **模型 ID、参数、请求体** 差异大,本仓库将 **Python 示例脚本放在对应子技能目录**,避免一个脚本里堆满互斥逻辑:\n\n| 服务商 | 脚本路径 | 依赖 |\n|--------|----------|------|\n| UCloud ModelVerse | [`generate_ucloud_image.py`](https://github.com/baklib-tools/skills/blob/main/skills/image-generation-ucloud/scripts/generate_ucloud_image.py) | `requests` |\n| OpenRouter | [`generate_openrouter_image.py`](https://github.com/baklib-tools/skills/blob/main/skills/image-generation-openrouter/scripts/generate_openrouter_image.py) | `requests` |\n\n将对应技能目录安装到你项目中的**技能路径**(以所用工具文档为准)后,在项目根执行;脚本通过向上查找含 **`.config`** 的目录定位密钥文件,详见各脚本 `--help`。本仓库**不提供**本地离线出图示例脚本(能力因环境差异大,由用户自行选用工具链)。\n\n**总技能目录不再提供**「三合一」聚合脚本;换后端时换目录与脚本即可。\n\n## 失败时\n\n- 优先根据 **stderr 与各平台返回** 判断是鉴权、模型名、尺寸还是限流。\n- 可在 **不泄露密钥** 的前提下,切换到另一后端子技能中的流程(例如 UCloud 不可用时改用 OpenRouter),并相应调整模型与尺寸参数。\n"}}, "skills/image-generation-ucloud/scripts/generate_ucloud_image.py": {"f0df7b92f1a53c54a6bfb7cd8320cc2fc03db76c": {"t": 1785596113.8233624, "n": 14602, "h": "6d6f4629f44b014a", "c": "#!/usr/bin/env python3\n\"\"\"\nUCloud ModelVerse 图像生成(参考实现)\n\n仅处理 UCloud 文档中的模型与参数;模型 ID、尺寸别名以 UCloud 当前文档为准。\n依赖:requests。将本技能目录安装到项目的技能路径(以所用工具文档为准)后,在项目根执行。\n\n密钥(读取顺序):优先项目根 .config/UCLOUD_API_KEY,其次环境变量 UCLOUD_API_KEY。\n\"\"\"\n\nfrom __future__ import annotations\n\nimport argparse\nimport base64\nimport json\nimport os\nimport sys\nfrom pathlib import Path\nfrom typing import Literal, TypedDict\n\nimport requests\n\n# 官方模型列表(无需密钥即可查询,用于核对 baseModelId)\nUCLOUD_V1BETA_MODELS_URL = \"https://api.modelverse.cn/v1beta/models\"\nUCLOUD_V1_MODELS_URL = \"https://api.modelverse.cn/v1/models\"\n\n\nclass _ModelImagesGenerations(TypedDict):\n kind: Literal[\"images_generations\"]\n sizes: dict[str, str]\n\n\nclass _ModelGenerateContent(TypedDict):\n kind: Literal[\"generate_content\"]\n sizes: None # 无像素别名表;--size 直接作 aspectRatio\n\n\nModelConfig = _ModelImagesGenerations | _ModelGenerateContent\n\n# 仅保留:豆包文生图(images/generations)+ Gemini 图像(generateContent)。\n# Gemini 模型 ID 请与 GET v1beta/models 返回的 baseModelId 对齐(例如 Flash 图像为 gemini-3.1-flash-image)。\nUCLOUD_MODELS: dict[str, ModelConfig] = {\n \"doubao-seedream-4.5\": {\n \"kind\": \"images_generations\",\n \"sizes\": {\n \"4:3\": \"2304x1728\",\n \"3:4\": \"1728x2304\",\n \"16:9\": \"2560x1440\",\n \"9:16\": \"1440x2560\",\n },\n },\n \"gemini-3-pro-image\": {\n \"kind\": \"generate_content\",\n \"sizes\": None,\n },\n \"gemini-3.1-flash-image\": {\n \"kind\": \"generate_content\",\n \"sizes\": None,\n },\n}\n\nDEFAULT_MODEL = \"gemini-3-pro-image\"\n\n\ndef find_project_root() -> Path:\n script = Path(__file__).resolve()\n home = Path.home()\n p = script.parent\n for _ in range(10):\n if (p / \".config\").is_dir() and p != home:\n return p\n if p == p.parent:\n break\n p = p.parent\n for depth in (4, 3):\n if len(script.parents) > depth:\n return script.parents[depth]\n return script.parents[-1]\n\n\ndef get_api_key(env_name: str, config_filename: str) -> str | None:\n project_root = find_project_root()\n config_file = project_root / \".config\" / config_filename\n if config_file.exists():\n try:\n with open(config_file, \"r\", encoding=\"utf-8\") as f:\n key = f.read().strip()\n if key:\n return key\n except OSError as e:\n print(f\"⚠️ 读取配置文件失败: {e}\", file=sys.stderr)\n api_key = os.getenv(env_name)\n if api_key:\n return api_key.strip()\n return None\n\n\ndef get_ucloud_api_key() -> str | None:\n return get_api_key(\"UCLOUD_API_KEY\", \"UCLOUD_API_KEY\")\n\n\ndef print_ucloud_api_key_help() -> None:\n print(\"\", file=sys.stderr)\n print(\"📌 未检测到 UCloud API 密钥,请任选其一:\", file=sys.stderr)\n print(\n \" • 优先:在项目根目录创建 .config/UCLOUD_API_KEY(单行密钥,UTF-8)\",\n file=sys.stderr,\n )\n print(\n \" • 备选:环境变量 UCLOUD_API_KEY\",\n file=sys.stderr,\n )\n print(\n \" • 换后端:OpenRouter 技能目录下脚本(image-generation-openrouter)\",\n file=sys.stderr,\n )\n print(\n \" 技能说明:image-generation-ucloud(本仓库 skills/ 下)\",\n file=sys.stderr,\n )\n\n\ndef resolve_canonical_model_id(user_arg: str) -> str | None:\n \"\"\"将 CLI 传入的模型名解析为 UCLOUD_MODELS 的键(兼容旧名与 API 长 ID)。\"\"\"\n u = user_arg.strip()\n if u in UCLOUD_MODELS:\n return u\n if \"doubao-seedream\" in u:\n return \"doubao-seedream-4.5\"\n # API 长名 -> 本脚本使用的短名\n if u == \"publishers/google/models/gemini-3-pro-image-preview\":\n return \"gemini-3-pro-image\"\n if u == \"publishers/google/models/gemini-3-pro-image\":\n return \"gemini-3-pro-image\"\n # 含 gemini-3.1-flash-image 即视为 Flash 图像(兼容 -preview 后缀)\n if \"gemini-3.1-flash-image\" in u:\n return \"gemini-3.1-flash-image\"\n if \"gemini-3-pro-image\" in u:\n return \"gemini-3-pro-image\"\n return None\n\n\ndef fetch_v1beta_models() -> list[dict[str, object]]:\n r = requests.get(UCLOUD_V1BETA_MODELS_URL, timeout=30)\n r.raise_for_status()\n data = r.json()\n return list(data.get(\"models\") or [])\n\n\ndef print_official_model_lists() -> None:\n \"\"\"打印官方 API 返回的模型 ID(走 stdout,便于重定向)。\"\"\"\n print(\"—— GET v1beta/models(Gemini 协议,含 generateContent,节选 id 含 image)——\")\n try:\n models = fetch_v1beta_models()\n except requests.RequestException as e:\n print(f\"❌ 请求失败: {e}\", file=sys.stderr)\n return\n for m in models:\n bid = str(m.get(\"baseModelId\", \"\"))\n actions = m.get(\"supportedActions\") or []\n if \"generateContent\" not in actions:\n continue\n if \"image\" not in bid.lower():\n continue\n print(f\" {bid}\")\n\n print()\n print(\"—— GET v1/models(OpenAI 兼容列表,节选 id 含 image)——\")\n try:\n r = requests.get(UCLOUD_V1_MODELS_URL, timeout=30)\n r.raise_for_status()\n data = r.json()\n for row in data.get(\"data\") or []:\n mid = str(row.get(\"id\", \"\"))\n if \"image\" in mid.lower():\n print(f\" {mid}\")\n except requests.RequestException as e:\n print(f\"❌ v1/models 请求失败: {e}\", file=sys.stderr)\n\n print()\n print(\n \"本脚本内置文生图模型(见 UCLOUD_MODELS):\"\n f\" {', '.join(UCLOUD_MODELS)}。\"\n \" 豆包走 v1/images/generations,通常不在 v1beta 列表中,以 UCloud 图像 API 文档为准。\"\n )\n\n\ndef resolve_api_size(sizes: dict[str, str] | None, size: str | None) -> str | None:\n \"\"\"根据该模型的别名表解析 --size;无表则原样返回(或 None)。\"\"\"\n if not size:\n return None\n if sizes is None:\n return size\n resolved = sizes.get(size, size)\n if size in sizes:\n print(f\" 尺寸别名 {size!r} → {resolved}\", file=sys.stderr)\n return resolved\n\n\ndef _save_image_from_response(image_data: dict, output_path: Path) -> bool:\n if \"url\" in image_data:\n img_response = requests.get(image_data[\"url\"], timeout=30)\n if img_response.status_code != 200:\n print(f\"❌ 下载图像失败: HTTP {img_response.status_code}\", file=sys.stderr)\n return False\n output_path.write_bytes(img_response.content)\n print(f\"✅ 图像已保存: {output_path}\", file=sys.stderr)\n return True\n if \"b64_json\" in image_data:\n image_bytes = base64.b64decode(image_data[\"b64_json\"])\n output_path.write_bytes(image_bytes)\n print(f\"✅ 图像已保存: {output_path}\", file=sys.stderr)\n return True\n print(\"❌ 错误: 响应中未找到图像数据\", file=sys.stderr)\n return False\n\n\ndef _request_images_generations(\n api_key: str,\n payload: dict,\n output_file: str,\n model_id: str,\n prompt: str,\n size_hint: str | None = None,\n) -> bool:\n url = \"https://api.modelverse.cn/v1/images/generations\"\n headers = {\"Authorization\": api_key, \"Content-Type\": \"application/json\"}\n print(\"🎨 正在生成图像...\", file=sys.stderr)\n print(f\" 模型: {model_id}\", file=sys.stderr)\n print(f\" 提示词: {prompt}\", file=sys.stderr)\n if size_hint:\n print(f\" 尺寸: {size_hint}\", file=sys.stderr)\n try:\n response = requests.post(url, json=payload, headers=headers, timeout=60)\n except requests.exceptions.RequestException as e:\n print(f\"❌ 网络请求失败: {e}\", file=sys.stderr)\n return False\n if response.status_code != 200:\n print(f\"❌ API 请求失败: HTTP {response.status_code}\", file=sys.stderr)\n print(f\" 响应: {response.text}\", file=sys.stderr)\n print_ucloud_api_key_help()\n return False\n result = response.json()\n if \"data\" not in result or not result[\"data\"]:\n print(\"❌ 错误: API 响应格式不正确\", file=sys.stderr)\n print(f\" 响应: {result}\", file=sys.stderr)\n return False\n output_path = Path(output_file)\n output_path.parent.mkdir(parents=True, exist_ok=True)\n return _save_image_from_response(result[\"data\"][0], output_path)\n\n\ndef generate_via_images_generations(\n model_id: str,\n prompt: str,\n output_file: str,\n size: str | None = None,\n n: int = 1,\n image_url: str | None = None,\n) -> bool:\n cfg = UCLOUD_MODELS.get(model_id)\n if not cfg or cfg[\"kind\"] != \"images_generations\":\n return False\n sizes = cfg[\"sizes\"]\n api_key = get_ucloud_api_key()\n if not api_key:\n print(\"❌ 错误: 未找到 UCloud API 密钥\", file=sys.stderr)\n print_ucloud_api_key_help()\n return False\n api_size = resolve_api_size(sizes, size)\n payload = {\n \"model\": model_id,\n \"prompt\": prompt,\n \"n\": n,\n \"watermark\": False,\n }\n if api_size:\n payload[\"size\"] = api_size\n if image_url:\n payload[\"image\"] = image_url\n return _request_images_generations(\n api_key, payload, output_file, model_id, prompt, api_size\n )\n\n\ndef generate_gemini_generate_content(\n prompt: str,\n output_file: str,\n model_id: str,\n size: str | None = None,\n image_size: str = \"1K\",\n) -> bool:\n \"\"\"v1beta generateContent,适用于文档中的 Gemini 图像模型 ID。\"\"\"\n api_key = get_ucloud_api_key()\n if not api_key:\n print(\"❌ 错误: 未找到 UCloud API 密钥\", file=sys.stderr)\n print_ucloud_api_key_help()\n return False\n\n aspect_ratio = \"4:3\"\n if size:\n aspect_ratio = size\n\n url = f\"https://api.modelverse.cn/v1beta/models/{model_id}:generateContent\"\n headers = {\n \"x-goog-api-key\": api_key,\n \"Content-Type\": \"application/json\",\n }\n payload = {\n \"contents\": [{\"role\": \"user\", \"parts\": [{\"text\": prompt}]}],\n \"generationConfig\": {\n \"responseModalities\": [\"IMAGE\"],\n \"imageConfig\": {\n \"aspectRatio\": aspect_ratio,\n \"imageSize\": image_size,\n },\n },\n }\n\n label = \"Gemini 图像\"\n if \"flash\" in model_id.lower():\n label = \"Gemini 3.1 Flash Image\"\n elif \"pro-image\" in model_id.lower():\n label = \"Gemini 3 Pro Image\"\n\n print(f\"🎨 正在使用 UCloud {label} 生成图像...\", file=sys.stderr)\n print(f\" 模型: {model_id}\", file=sys.stderr)\n print(f\" 提示词: {prompt}\", file=sys.stderr)\n print(f\" 宽高比: {aspect_ratio}, 分辨率: {image_size}\", file=sys.stderr)\n\n try:\n response = requests.post(url, json=payload, headers=headers, timeout=300)\n except requests.exceptions.RequestException as e:\n print(f\"❌ 网络请求失败: {e}\", file=sys.stderr)\n return False\n\n if response.status_code != 200:\n print(f\"❌ API 请求失败: HTTP {response.status_code}\", file=sys.stderr)\n try:\n error_data = response.json()\n print(\n f\" 错误详情: {json.dumps(error_data, indent=2, ensure_ascii=False)}\",\n file=sys.stderr,\n )\n except Exception:\n print(f\" 响应: {response.text}\", file=sys.stderr)\n print_ucloud_api_key_help()\n return False\n\n result = response.json()\n candidates = result.get(\"candidates\") or []\n if not candidates:\n print(\"❌ 错误: 响应中未找到 candidates\", file=sys.stderr)\n print(\n f\" 响应: {json.dumps(result, indent=2, ensure_ascii=False)}\",\n file=sys.stderr,\n )\n return False\n\n content = candidates[0].get(\"content\") or {}\n parts = content.get(\"parts\") or []\n\n inline_data = None\n mime_type = \"image/png\"\n for part in parts:\n if not isinstance(part, dict):\n continue\n data_block = part.get(\"inlineData\")\n if isinstance(data_block, dict) and \"data\" in data_block:\n inline_data = data_block[\"data\"]\n mime_type = data_block.get(\"mimeType\", mime_type)\n break\n\n if not inline_data:\n print(\"❌ 错误: 响应中未找到 inlineData 图像数据\", file=sys.stderr)\n print(\n f\" 响应: {json.dumps(result, indent=2, ensure_ascii=False)}\",\n file=sys.stderr,\n )\n return False\n\n try:\n image_bytes = base64.b64decode(inline_data)\n output_path = Path(output_file)\n output_path.parent.mkdir(parents=True, exist_ok=True)\n output_path.write_bytes(image_bytes)\n print(f\"✅ 图像已保存: {output_path}\", file=sys.stderr)\n print(f\" 格式: {mime_type}\", file=sys.stderr)\n return True\n except OSError as e:\n print(f\"❌ 保存图像失败: {e}\", file=sys.stderr)\n return False\n\n\ndef main() -> None:\n parser = argparse.ArgumentParser(\n description=\"UCloud ModelVerse 图像生成\",\n formatter_class=argparse.RawDescriptionHelpFormatter,\n epilog=\"\"\"\n示例:\n %(prog)s --list-models\n %(prog)s --prompt prompt.txt --output out.png --size 4:3\n %(prog)s --prompt prompt.txt --output out.png --model gemini-3.1-flash-image --size 16:9\n %(prog)s --prompt prompt.txt --output out.jpg --model doubao-seedream-4.5 --size 4:3\n \"\"\",\n )\n parser.add_argument(\n \"--list-models\",\n action=\"store_true\",\n help=\"调用 GET v1beta/models 与 GET v1/models,列出官方返回的图像相关模型 ID(无需密钥)\",\n )\n parser.add_argument(\"--prompt\", help=\"提示词文件路径(UTF-8)\")\n parser.add_argument(\"--output\", help=\"输出图像路径\")\n parser.add_argument(\n \"--model\",\n default=DEFAULT_MODEL,\n help=(\n f\"模型 ID。默认 {DEFAULT_MODEL};\"\n \"可选 gemini-3.1-flash-image、doubao-seedream-4.5;\"\n \"与官方不一致时请运行 --list-models 核对\"\n ),\n )\n parser.add_argument(\n \"--size\",\n default=None,\n metavar=\"比例或像素\",\n help=\"宽高比(如 4:3)或文档要求的像素串;Gemini 类为 aspectRatio\",\n )\n parser.add_argument(\n \"--image-size\",\n default=\"1K\",\n metavar=\"1K|2K|…\",\n help=\"仅 Gemini generateContent:generationConfig.imageConfig.imageSize(默认 1K)\",\n )\n\n args = parser.parse_args()\n\n if args.list_models:\n print_official_model_lists()\n sys.exit(0)\n\n if not args.prompt or not args.output:\n parser.error(\"请提供 --prompt 与 --output,或使用 --list-models\")\n\n if not get_ucloud_api_key():\n print(\"❌ 错误: 未找到 UCloud API 密钥\", file=sys.stderr)\n print_ucloud_api_key_help()\n sys.exit(1)\n\n try:\n prompt = Path(args.prompt).read_text(encoding=\"utf-8\")\n except OSError as e:\n print(f\"❌ 无法读取提示词文件 {args.prompt}: {e}\", file=sys.stderr)\n sys.exit(1)\n\n mid = resolve_canonical_model_id(args.model)\n if not mid:\n print(\n f\"❌ 不支持的模型: {args.model}。内置:{', '.join(UCLOUD_MODELS)}\",\n file=sys.stderr,\n )\n sys.exit(1)\n\n cfg = UCLOUD_MODELS[mid]\n if cfg[\"kind\"] == \"images_generations\":\n ok = generate_via_images_generations(\n mid, prompt, args.output, size=args.size, n=1\n )\n else:\n ok = generate_gemini_generate_content(\n prompt,\n args.output,\n mid,\n size=args.size,\n image_size=args.image_size,\n )\n\n sys.exit(0 if ok else 1)\n\n\nif __name__ == \"__main__\":\n main()\n"}}, "skills/image-generation-ucloud/SKILL.md": {"f0df7b92f1a53c54a6bfb7cd8320cc2fc03db76c": {"t": 1785596114.3689318, "n": 4120, "h": "acc8d1464fcc9bb7", "c": "---\nname: image-generation-ucloud\ndescription: >-\n 通过 UCloud ModelVerse 图像 API 出图:鉴权、端点、模型与尺寸约定。\n 在用户指定 UCloud、ModelVerse、api.modelverse.cn 或需 doubao-seedream / gemini-3-pro-image / gemini-3.1-flash-image 时使用。\n---\n\n# 图像生成 · UCloud(ModelVerse)\n\n## 技能范围\n\n- **本技能只解决**:如何按 UCloud 公开文档调用 **ModelVerse** 图像相关接口(鉴权位置、端点形态、模型与参数要点)。\n- **不包含**:替代用户执行扣费请求、保证 SLA;亦不重复 **提示词写法**(见 [nano-banana-pro-prompting](https://github.com/baklib-tools/skills/blob/main/skills/nano-banana-pro-prompting/SKILL.md))。\n\n## 执行前检查 API 密钥\n\n在运行 `generate_ucloud_image.py` 或代用户发起请求前,**先确认**已具备 UCloud 密钥;若缺失,提示用户**优先**在**项目根**创建 **`.config/UCLOUD_API_KEY`**(单行文本,UTF-8),其次再考虑环境变量 **`UCLOUD_API_KEY`**。本仓库示例脚本在读取提示词前会校验密钥,缺失时按上述顺序提示。\n\n## 官方文档与模型列表 API\n\n- 产品与接口说明以 UCloud 文档为准,例如文档中心内 **ModelVerse** 各模型「图像 API」章节(路径可能随版本调整,请站内搜索模型名)。\n- **Gemini 3.1 Flash Image**:[gemini-3.1-flash-image](https://docs.ucloud.cn/modelverse/api_doc/image_api/gemini-3.1-flash-image)(文档路径名可能与 **API 返回的 `baseModelId`** 不完全一致,以接口为准。)\n- **Gemini 3 Pro Image(示例)**:[gemini-3-pro-image](https://docs.ucloud.cn/modelverse/api_doc/image_api/gemini-3-pro-image)\n- **核对模型 ID(无需密钥)**:\n - `GET https://api.modelverse.cn/v1beta/models` — Gemini 协议,`models[].baseModelId`(如 `gemini-3.1-flash-image`)。\n - `GET https://api.modelverse.cn/v1/models` — OpenAI 兼容列表,`data[].id`。\n- 本仓库脚本支持 **`--list-models`**,会请求上述接口并节选名称中含 `image` 的条目,便于与脚本内置 ID 对照。\n\n## 鉴权与配置\n\n- **密钥**:使用你在 UCloud 控制台获得的 **ModelVerse API Key**。**推荐**:项目根 **`.config/UCLOUD_API_KEY`**(单行文本,UTF-8);**备选**:环境变量 **`UCLOUD_API_KEY`**。本仓库示例脚本的读取顺序为 **`.config` 文件优先于环境变量**。\n- **勿**在技能或仓库中写入真实密钥。\n\n## 两种 HTTP 形态(需按模型选用)\n\n### 1)通用图像生成(`images/generations`)\n\n- **典型用途**:`doubao-seedream-4.5` 等文档中约定走该路径的模型(豆包文生图;**模型 ID 以文档/控制台为准**,不一定出现在 `v1beta/models` 列表中)。\n- **端点(示例)**:`POST https://api.modelverse.cn/v1/images/generations`\n- **请求头**:`Authorization` 为 API Key;`Content-Type: application/json`。\n- **响应**:常见为 JSON,`data[0]` 中含 `url` 或 `b64_json`;下载或解码后写入文件即可。\n- **水印**:若文档支持 `watermark` 字段,按文档与合规要求设置。\n\n### 2)Gemini 系列图像 · `generateContent`(v1beta)\n\n- **典型模型 ID(示例)**:`gemini-3-pro-image`、`gemini-3.1-flash-image`(与 `GET v1beta/models` 的 `baseModelId` 对齐;亦可能出现 `publishers/google/models/gemini-3-pro-image` 等长名,以接口为准)。\n- **端点形态(示例)**:`POST https://api.modelverse.cn/v1beta/models/<model-id>:generateContent`\n- **请求头**:文档若要求使用 **`x-goog-api-key`** 传递密钥,则与上一种 `Authorization` 方式区分,**不得混用**;以官方示例为准。\n- **请求体要点**:`contents` 承载用户文本;`generationConfig` 内配置 **`responseModalities`**(如含 `IMAGE`)、**`imageConfig`**(如 **`aspectRatio`**、**`imageSize`** 等)。常见 **1K** 配图可在 `imageSize` 中使用 **`1K`**,具体以文档为准。\n- **响应**:从 `candidates[].content.parts[]` 中解析 **`inlineData`**(base64)与 `mimeType`,再写入二进制文件。\n\n## 模型与尺寸(摘要)\n\n| 类型 | 说明 |\n|------|------|\n| `gemini-3-pro-image` | 宽高比多由 `imageConfig.aspectRatio` 表达;分辨率档见 `imageSize`(如 1K)。 |\n| `gemini-3.1-flash-image` | 同上(`generateContent`);名称以 `v1beta/models` 为准。 |\n| `doubao-seedream-4.5` | 尺寸常为具体像素串或文档给定别名;总像素区间以文档为准。 |\n\n**尺寸与别名** 以 UCloud 当前文档为准;本技能内示例脚本若含别名表,仅为方便使用,**上线前请对照文档校验**。\n\n## 本技能内参考脚本\n\n- **路径**:[`scripts/generate_ucloud_image.py`](scripts/generate_ucloud_image.py)(仅 UCloud ModelVerse:`images/generations` 与 `v1beta` `generateContent`)。\n- **依赖**:Python 3、`requests`。\n- **密钥**:`UCLOUD_API_KEY` 或项目根 `.config/UCLOUD_API_KEY`。\n\n```bash\npython path/to/image-generation-ucloud/scripts/generate_ucloud_image.py --list-models\npython path/to/image-generation-ucloud/scripts/generate_ucloud_image.py \\\n --prompt prompt.txt --output out.png --size 4:3\npython path/to/image-generation-ucloud/scripts/generate_ucloud_image.py \\\n --prompt prompt.txt --output out.png --model gemini-3.1-flash-image --size 16:9 --image-size 1K\n```\n\nOpenRouter 出图请使用 **`image-generation-openrouter`** 目录下脚本,勿与本脚本混用。\n\n## 与总技能、OpenRouter 的关系\n\n- 总览与工作流:**[image-generation](https://github.com/baklib-tools/skills/blob/main/skills/image-generation/SKILL.md)**。\n- 若 UCloud 不可用或需使用 OpenRouter 路由的 Gemini 图像能力:**[image-generation-openrouter](https://github.com/baklib-tools/skills/blob/main/skills/image-generation-openrouter/SKILL.md)**。\n\n## 不做什么\n\n- 不绑定某一私有仓库目录或内部文件名(如「某营销目录下的唯一规范」);公开读者应能在自己的项目中复现「密钥 + 端点 + 请求体」。\n"}}, "examples/requirements-to-published-content-health-cms/artifacts/image-plan-from-content.md": {"f0df7b92f1a53c54a6bfb7cd8320cc2fc03db76c": {"t": 1785596116.2797935, "n": 1597, "h": "1e5a31267a4703e3", "c": "# 配图推导说明(F 阶段示例):由文案到三镜头\n\n> **原则**:用户**不**逐张指定「画什么、用什么色」;模型在加载 **image-generation** 与 **nano-banana-pro-prompting** 等技能后,根据已定稿的 [05-wechat-article.md](05-wechat-article.md) / [04-public-article.md](04-public-article.md) **自行推导**镜头叙事与提示词要点。\n\n---\n\n## 1. 叙事抽取\n\n| 文稿段落 | 核心信息 | 情绪 / 视觉隐喻 |\n|----------|----------|-----------------|\n| 导语 +「散、乱、难追溯」 | 多端分散、版本不一 | **压迫感、碎片化** |\n| 「一个库」「统一存储」 | 收敛、结构化 | **由乱到治、秩序感** |\n| 「分期」「同源发布」「路线图」 | 渐进、可落地 | **由暗到亮、路径清晰** |\n\n---\n\n## 2. 三镜头结构(与公众号运营常见节奏一致)\n\n| 镜头 | 用途 | 推导依据 |\n|------|------|----------|\n| **Shot 1 · 痛点** | 篇首图 | 导语中「网盘、旧后台、公众号各一版」→ 多终端混乱、文档堆叠意象 |\n| **Shot 2 · 方案** | 中段 | 「知识库 + 资源库」「角色与审核」→ 仪表盘式整洁界面或抽象「单一枢纽」 |\n| **Shot 3 · 结果 / CTA** | 篇尾 | 「分期路线图」「同源发布」→ 向上台阶、路径展开或团队协作明亮场景 |\n\n---\n\n## 3. 提示词要点(示例级,非最终出图指令)\n\n模型在撰写**分步英文/中文提示词**时,可参考 **nano-banana-pro-prompting** 的 Step 1–9 结构;以下为**要点级**摘要:\n\n- **Shot 1**:医疗内容运营向场景,多屏幕/多文件夹隐喻分散;冷色或对比强调混乱;避免具体真实产品界面与可辨识商标。 \n- **Shot 2**:抽象「统一内容枢纽」:单一路径汇聚文档与媒体;青绿色系(与品牌示例一致时可弱化为中性医疗蓝绿);扁平插画或等距视角。 \n- **Shot 3**:三阶段阶梯或时间轴「统一 → 治理 → 集成」;暖色高光、留白充足;可加一句**图内短标题**(须与 Step 7 文案逐字一致,若采用文内字)。\n\n**自检**:图内中文是否正确、是否误画 HEX/口令;系列三图是否在**同一条提示词内自洽**(无「与上一张一致」类跨请求依赖)。\n\n---\n\n## 4. 与技能链的关系\n\n```text\n05-wechat-article.md(定稿)\n ↓\n本文件(推导镜头与约束)\n ↓\nimage-generation / nano-banana-pro-prompting(生成提示词与可选脚本出图)\n ↓\nwechat-mp-html(将成图插入 HTML 的 img src,再发布)\n```\n\n本示例已在仓库内生成 **三帧 PNG**(`artifacts/images/rtc-demo-shot1.png` 等),由 **`image-generation-ucloud`** 脚本调用 UCloud Gemini 图像模型产出;提示词见 `artifacts/images/prompts/`。重新生成或更换模型时请在仓库根目录执行(需配置 `.config/UCLOUD_API_KEY`),详见 [artifacts/images/README.md](images/README.md)。\n"}}}}