H繁中版
文件開發者指南image gen provider plugin
<!-- Source: https://hermesbible.com/docs/developer-guide/image-gen-provider-plugin -->

建立圖片生成 Provider 外掛

圖片生成 provider 外掛註冊一個後端來處理每一個 image_generate 工具呼叫 — DALL·E、gpt-image、Grok、Flux、Imagen、Stable Diffusion、fal、Replicate、本地 ComfyUI 設備,或其他任何後端。內建的 provider(OpenAI、OpenAI-Codex、xAI)都以外掛形式發佈。你可以透過在 plugins/image_gen/<name>/ 中放入一個目錄來新增一個新的,或覆寫一個已有的。

提示

圖片生成是 Hermes 支援的多種後端外掛之一。其他類型(具有更專門的 ABC)包括 Memory Provider PluginsContext Engine PluginsModel Provider Plugins。通用的工具/鉤子/CLI 外掛請見 Build a Hermes Plugin

發現機制如何運作

Hermes 在三個位置掃描圖片生成後端:

  1. 內建<repo>/plugins/image_gen/<name>/(自動載入,kind: backend,始終可用)
  2. 使用者~/.hermes/plugins/image_gen/<name>/(透過 plugins.enabled 選擇性啟用)
  3. Pip — 宣告 hermes_agent.plugins 入口點的套件

每個外掛的 register(ctx) 函式呼叫 ctx.register_image_gen_provider(...) — 這會將其放入 agent/image_gen_registry.py 的 registry 中。啟用的 provider 由 config.yaml 中的 image_gen.provider 選擇;hermes tools 引導使用者進行選擇。

image_generate 工具包裝器向 registry 請求啟用的 provider 並進行分派。如果沒有已註冊的 provider,工具會顯示一個有用的錯誤,指向 hermes tools

目錄結構

plugins/image_gen/my-backend/
├── __init__.py      # ImageGenProvider 子類別 + register()
└── plugin.yaml      # 帶有 kind: backend 的 Manifest

內建外掛到此就完成了。位於 ~/.hermes/plugins/image_gen/<name>/ 的使用者外掛需要被加入 config.yamlplugins.enabled(或執行 hermes plugins enable <name>)。

ImageGenProvider ABC

繼承 agent.image_gen_provider.ImageGenProvider。唯一需要的成員是 name 屬性和 generate() 方法 — 其他都有合理的預設值:

# plugins/image_gen/my-backend/__init__.py
from typing import Any, Dict, List, Optional
import os

from agent.image_gen_provider import (
    DEFAULT_ASPECT_RATIO,
    ImageGenProvider,
    error_response,
    resolve_aspect_ratio,
    save_b64_image,
    success_response,
)

class MyBackendImageGenProvider(ImageGenProvider):
    @property
    def name(self) -> str:
        # image_gen.provider 設定中使用的穩定 ID。小寫,不含空格。
        return "my-backend"

    @property
    def display_name(self) -> str:
        # `hermes tools` 中顯示的人類標籤。省略時預設為 name.title()。
        return "My Backend"

    def is_available(self) -> bool:
        # 如果缺少認證資訊或依賴項則回傳 False。
        # 工具的可用性閘門會在分派前呼叫此方法。
        if not os.environ.get("MY_BACKEND_API_KEY"):
            return False
        try:
            import my_backend_sdk  # noqa: F401
        except ImportError:
            return False
        return True

    def list_models(self) -> List[Dict[str, Any]]:
        # `hermes tools` 模型選擇器中顯示的目錄。
        return [
            {
                "id": "my-model-fast",
                "display": "My Model (Fast)",
                "speed": "~5s",
                "strengths": "Quick iteration",
                "price": "$0.01/image",
            },
            {
                "id": "my-model-hq",
                "display": "My Model (HQ)",
                "speed": "~30s",
                "strengths": "Highest fidelity",
                "price": "$0.04/image",
            },
        ]

    def default_model(self) -> Optional[str]:
        return "my-model-fast"

    def get_setup_schema(self) -> Dict[str, Any]:
        # `hermes tools` 選擇器的中繼資料 — 設定時要提示的金鑰。
        return {
            "name": "My Backend",
            "badge": "paid",        # 選用;在選擇器中顯示為簡短標籤
            "tag": "在名稱下方顯示的一行描述",
            "env_vars": [
                {
                    "key": "MY_BACKEND_API_KEY",
                    "prompt": "My Backend API key",
                    "url": "https://my-backend.example.com/api-keys",
                },
            ],
        }

    def generate(
        self,
        prompt: str,
        aspect_ratio: str = DEFAULT_ASPECT_RATIO,
        **kwargs: Any,
    ) -> Dict[str, Any]:
        prompt = (prompt or "").strip()
        aspect_ratio = resolve_aspect_ratio(aspect_ratio)

        if not prompt:
            return error_response(
                error="Prompt is required",
                error_type="invalid_input",
                provider=self.name,
                prompt="",
                aspect_ratio=aspect_ratio,
            )

        # 模型選擇優先順序:環境變數 → 設定 → 預設值。內建 openai
        # 外掛中的輔助函式 _resolve_model() 是很好的參考。
        model_id = kwargs.get("model") or self.default_model() or "my-model-fast"

        try:
            import my_backend_sdk
            client = my_backend_sdk.Client(api_key=os.environ["MY_BACKEND_API_KEY"])
            result = client.generate(
                prompt=prompt,
                model=model_id,
                aspect_ratio=aspect_ratio,
            )

            # 支援兩種格式:
            #   - URL 字串:作為 `image` 回傳
            #   - base64 資料:透過 save_b64_image() 儲存在 $HERMES_HOME/cache/images/ 下
            if result.get("image_b64"):
                path = save_b64_image(
                    result["image_b64"],
                    prefix=self.name,
                    extension="png",
                )
                image = str(path)
            else:
                image = result["image_url"]

            return success_response(
                image=image,
                model=model_id,
                prompt=prompt,
                aspect_ratio=aspect_ratio,
                provider=self.name,
            )
        except Exception as exc:
            return error_response(
                error=str(exc),
                error_type=type(exc).__name__,
                provider=self.name,
                model=model_id,
                prompt=prompt,
                aspect_ratio=aspect_ratio,
            )

def register(ctx) -> None:
    """外掛入口點 — 在載入時呼叫一次。"""
    ctx.register_image_gen_provider(MyBackendImageGenProvider())

plugin.yaml

name: my-backend
version: 1.0.0
description: My image backend — text-to-image via My Backend SDK
author: Your Name
kind: backend
requires_env:
  - MY_BACKEND_API_KEY

kind: backend 是將外掛路由到圖片生成註冊路徑的關鍵。requires_envhermes plugins install 時進行提示。

ABC 參考

完整契約在 agent/image_gen_provider.py 中。你通常會覆寫的方法:

成員必要預設值用途
nameimage_gen.provider 設定中使用的穩定 ID
display_namename.title()hermes tools 中顯示的標籤
is_available()True缺少認證/依賴項時的閘門
list_models()[]hermes tools 模型選擇器的目錄
default_model()list_models() 的第一個未設定模型時的後備選擇
get_setup_schema()最小化選擇器中繼資料 + 環境變數提示
generate(prompt, aspect_ratio, **kwargs)核心呼叫

回應格式

generate() 必須回傳一個透過 success_response()error_response() 建立的字典。兩者都位於 agent/image_gen_provider.py 中。

成功:

success_response(
    image=<url-or-absolute-path>,
    model=<model-id>,
    prompt=<echoed-prompt>,
    aspect_ratio="landscape" | "square" | "portrait",
    provider=<your-provider-name>,
    extra={...},  # 選用的後端特定欄位
)

錯誤:

error_response(
    error="human-readable message",
    error_type="provider_error" | "invalid_input" | "<exception class name>",
    provider=<your-provider-name>,
    model=<model-id>,
    prompt=<prompt>,
    aspect_ratio=<resolved aspect>,
)

工具包裝器將字典 JSON 序列化後交給 LLM。錯誤會作為工具結果呈現;LLM 決定如何向使用者解釋。

處理 base64 與 URL 輸出

一些後端回傳圖片 URL(fal、Replicate);其他回傳 base64 載荷(OpenAI gpt-image-2)。對於 base64 的情況,使用 save_b64_image() — 它寫入 $HERMES_HOME/cache/images/<prefix>_<timestamp>_<uuid>.<ext> 並回傳絕對 Path。將該路徑(作為 str)作為 image= 傳入 success_response()。閘道器遞送(Telegram 照片氣泡、Discord 附件)能辨識 URL 和絕對路徑。

使用者覆寫

~/.hermes/plugins/image_gen/<name>/ 放置一個使用者外掛,使用與內建外掛相同的 name 屬性,然後透過 hermes plugins enable <name> 啟用 — registry 是後寫者優先的,所以你的版本會取代內建版本。適用於將 openai 外掛指向私有代理,或替換自訂模型目錄。

測試

export HERMES_HOME=/tmp/hermes-imggen-test
mkdir -p $HERMES_HOME/plugins/image_gen/my-backend
# …copy __init__.py + plugin.yaml into that dir…

export MY_BACKEND_API_KEY=your-test-key
hermes plugins enable my-backend

# 將其選為啟用的 provider
echo "image_gen:" >> $HERMES_HOME/config.yaml
echo "  provider: my-backend" >> $HERMES_HOME/config.yaml

# 測試它
hermes -z "Generate an image of a corgi in a spacesuit"

或互動式:hermes tools → "Image Generation" → 選擇 my-backend → 如有提示則輸入 API key。

參考實作

  • plugins/image_gen/openai/__init__.py — gpt-image-2 以低/中/高三個等級作為三個虛擬模型 ID,共享一個帶有不同 quality 參數的 API 模型。單一下端下分級模型的良好範例 + config.yaml 優先順序鏈。
  • plugins/image_gen/xai/__init__.py — 透過 xAI 的 Grok Imagine。不同的格式(URL 輸出,更簡單的目錄)。
  • plugins/image_gen/openai-codex/__init__.py — Codex 風格的 Responses API 變體,重用 OpenAI SDK 但使用不同的路由基礎 URL。

透過 pip 分發

# pyproject.toml
[project.entry-points."hermes_agent.plugins"]
my-backend-imggen = "my_backend_imggen_package"

my_backend_imggen_package 必須暴露一個頂層的 register 函式。完整設定請見通用外掛指南中的 Distribute via pip

相關頁面



Memory Provider Plugins