0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DifyでImagenを使用できるプラグインを開発する

Posted at

はじめに

DifyでGoogleのImagenを使用した画像生成を行おうと思ったのですが、Imagenを使用できるプラグインが無かったため開発してみました。作ったもの自体はGitHubで公開しておきましたので、興味のある方はお使いいただければと思います。
この記事では、簡単に実装内容を紹介したいと思います。

リポジトリはこちら

image.png

このプラグインで出来ること

Difyのワークフローに「Vertex AI Imagen」ツールを追加し、以下の機能を実現できます。

  • テキストからの画像生成: プロンプト(指示文)に基づいて画像を生成します
  • 豊富なパラメータ設定:
    • モデル選択: Imagen 3Imagen 4 など、用途に応じたモデルを選択可能
    • アスペクト比: 1:1, 16:9, 9:16など選択可能
    • 画像枚数: 一度に最大4枚までの画像を生成

image.png

インストールと設定

基本的な導入方法は公式ドキュメントを参照ください。

認証情報の設定

ここでVertex AIを利用するための認証情報として、以下を設定してください。

  • Google Cloud プロジェクト ID
  • Google Cloud リージョン
  • Vertex AI サービスアカウントキー

サービスアカウントのDifyへの登録方法は既存のVertex AI プラグインの方法を踏襲しています。

  1. GCPでサービスアカウントキーを発行: まず、GCPコンソールでVertex AI APIへのアクセス権を持つサービスアカウントを作成し、キー(JSONファイル)をダウンロードしておきます。

  2. サービスアカウントキーをBase64にエンコード: ダウンロードしたJSONキーは、そのままではDifyに登録できません。以下のコマンドなどを使い、JSONファイルの中身をBase64形式の文字列に変換してください。

    # macOS の場合
    base64 -i /path/to/your/service-account-key.json
    
    # Linux の場合
    base64 -w 0 /path/to/your/service-account-key.json
    
  3. Difyに認証情報を入力: ツールの設定画面にある「認証情報」セクションに、以下の通り入力します。

    • project_id: あなたのGCPプロジェクトID
    • location: Vertex AIを使用するリージョン (例: us-central1)
    • vertex_service_account_key: 先ほど生成したBase64形式の文字列を貼り付けます。
  4. 最後に「保存」をクリックします。

アプリケーションへの追加

上記設定が完了すれば他プラグインと同様、ツールとして使用できます。

技術的な解説

ここからは、このプラグインがどのような仕組みで動いているのか、開発に興味がある方向けに解説します。
基本的には以下の公式ドキュメントとDALL-Eのプラグイン実装を参考にしながら、Claude Codeで開発してみました。
Difyのプラグイン開発自体の手順は今回は割愛しますので、公式ドキュメントを参照ください。

以下、主に手を加えることになるproviderとtoolsフォルダーの中の記述について簡単に解説します。

provider

provider/vertexai-imagen.yamlにて、サービスアカウント等の認証情報で必要となる情報の記述を行なっています。

vertexai-imagen.yaml
# ...
credentials_for_provider:
  project_id:
    type: "text-input"
    required: true
    label:
      en_US: "Google Cloud Project ID"
      ja_JP: "Google Cloud プロジェクト ID"
    placeholder:
      en_US: "Enter your Google Cloud Project ID"
      ja_JP: "Google Cloud プロジェクト ID を入力してください"
  location:
    type: "text-input"
    required: true
    label:
      en_US: "Google Cloud Region"
      ja_JP: "Google Cloud リージョン"
    placeholder:
      en_US: "Enter your Google Cloud Region"
      ja_JP: "Google Cloud リージョンを入力してください"
  vertex_service_account_key:
    type: "secret-input"
    required: true
    label:
      en_US: "Vertex AI Service Account Key"
      ja_JP: "Vertex AI サービスアカウントキー"
    placeholder:
      en_US: "Enter your Google Cloud Service Account Key in base64 format"
      ja_JP: "Vertex AI サービスアカウントキーを base64 形式で入力してください"
# ...

provider/vertexai-imagen.pyでは、認証情報の設定における認証時の処理を記述しています。以下のように、入力された情報でサンプル画像生成のリクエストが成功するかを確認する処理となっています。

vertexai-imagen.py

import json
import base64
from typing import Any

from dify_plugin import ToolProvider
from dify_plugin.errors.tool import ToolProviderCredentialValidationError
from google.cloud import aiplatform
from vertexai.preview.vision_models import ImageGenerationModel
from google.oauth2 import service_account

class VertexaiImagenProvider(ToolProvider):
    
    def _validate_credentials(self, credentials: dict[str, Any]) -> None:
        try:
            """
            IMPLEMENT YOUR VALIDATION HERE
            """
            project_id = credentials.get('project_id')
            location = credentials.get('location', 'us-central1')
            service_account_key = credentials.get('vertex_service_account_key')

            service_account_info = json.loads(base64.b64decode(service_account_key))
            credentials_obj = service_account.Credentials.from_service_account_info(service_account_info)

            aiplatform.init(
                project=project_id,
                location=location,
                credentials=credentials_obj,
            )

            generation_model = ImageGenerationModel.from_pretrained("imagen-3.0-generate-002")
            response = generation_model.generate_images(
                prompt="A beautiful sunset over a calm ocean",
                number_of_images=1,
                safety_filter_level="block_low_and_above",
            )
            print("API test successful")
        except Exception as e:
            raise ToolProviderCredentialValidationError(str(e))

tools

tools/vertexai-imagen.yaml で、ユーザーが設定を操作するUIを定義します。

vertexai-imagen.yaml
# ...
parameters:
  - name: prompt
    type: string
    required: true
    label:
      en_US: Text Prompt
      ja_JP: テキストプロンプト
    human_description:
      en_US: Describe the image you want to generate
      ja_JP: 生成したい画像を説明してください
    llm_description: A detailed text description of the image to generate. Be specific and descriptive for better results.
    form: llm
  - name: model
    type: select
    required: false
    label:
      en_US: Imagen Model
      ja_JP: Imagen モデル
    human_description:
      en_US: Choose the Imagen model to use for generation
      ja_JP: 生成に使用するImagenモデルを選択
    llm_description: The Imagen model version to use. Imagen 3 offers the highest quality, while Fast version provides quicker generation.
    options:
      - value: imagen-3.0-generate-001
        label:
          en_US: Imagen 3.0 (High Quality)
          ja_JP: Imagen 3.0(高品質)
      - value: imagen-3.0-fast-generate-001
        label:
          en_US: Imagen 3.0 Fast (Quick Generation)
          ja_JP: Imagen 3.0 Fast(高速生成)
      - value: imagen-4.0-generate-preview-06-06
        label:
          en_US: Imagen 4.0 (High Quality)
          ja_JP: Imagen 4.0(高品質)
      - value: imagen-4.0-fast-generate-preview-06-06
        label:
          en_US: Imagen 4.0 Fast (Quick Generation)
          ja_JP: Imagen 4.0 Fast(高速生成)
    default: imagen-4.0-generate-preview-06-06
    form: form
  - name: aspect_ratio
    type: select
    required: false
    label:
      en_US: Aspect Ratio
      ja_JP: アスペクト比
    human_description:
      en_US: Choose the aspect ratio for the generated image
      ja_JP: 生成される画像のアスペクト比を選択
    llm_description: The aspect ratio for the generated image. Choose based on the intended use case.
    options:
      - value: "1:1"
        label:
          en_US: Square (1:1)
          ja_JP: 正方形(1:1)
      - value: "9:16"
        label:
          en_US: Portrait (9:16)
          ja_JP: 縦向き(9:16)
      - value: "16:9"
        label:
          en_US: Landscape (16:9)
          ja_JP: 横向き(16:9)
      - value: "4:3"
        label:
          en_US: Standard (4:3)
          ja_JP: 標準(4:3)
      - value: "3:4"
        label:
          en_US: Portrait (3:4)
          ja_JP: 縦向き(3:4)
    default: "1:1"
    form: form
  - name: number_of_images
    type: number
    required: false
    label:
      en_US: Number of Images
      ja_JP: 画像の数
    human_description:
      en_US: Number of images to generate (1-4)
      ja_JP: 生成する画像の数(1-4)
    llm_description: The number of images to generate. Maximum is 4 images per request.
    default: 1
    min: 1
    max: 4
    form: form
  - name: safety_filter_level
    type: select
    required: false
    label:
      en_US: Safety Filter Level
      ja_JP: セーフティフィルターレベル
    human_description:
      en_US: Set the safety filter strictness level
      ja_JP: セーフティフィルターの厳格度レベルを設定
    llm_description: Controls how strict the safety filtering is for generated content.
    options:
      - value: block_medium_and_above
        label:
          en_US: Block Some (Recommended)
          ja_JP: 一部をブロック(推奨)
      - value: block_only_high
        label:
          en_US: Block Few
          ja_JP: 少数をブロック
      - value: block_low_and_above
        label:
          en_US: Block Most
          ja_JP: 大部分をブロック
    default: block_medium_and_above
    form: form
# ...

image.png

tools/vertexai-imagen.py がメインの処理です。処理の詳細はGitHubをみてもらえればと思いますので、ここでは流れだけ簡潔に記載します。
やっていること自体はそこまで難しいものではなく、単にVertex AIのImagenを呼び出しているだけです。

vertexai-imagen.py
# ...
class ImagenGenerateTool(Tool):
    def _invoke(self, tool_parameters: Dict[str, Any]) -> Generator[ToolInvokeMessage, None, None]:
        # 1. Difyに設定された認証情報を取得
        credentials = self.runtime.credentials
        project_id = credentials.get('project_id')
        service_account_key_b64 = credentials.get('vertex_service_account_key')

        # 2. Base64デコードしてGCPクレデンシャルを復元
        service_account_info = json.loads(base64.b64decode(service_account_key_b64))
        credentials_obj = service_account.Credentials.from_service_account_info(service_account_info)

        # 3. Vertex AIを初期化
        aiplatform.init(project=project_id, credentials=credentials_obj)

        # 4. ユーザーが入力したパラメータを取得
        prompt = tool_parameters.get('prompt')

        # 5. Imagen APIを呼び出し
        generation_model = ImageGenerationModel.from_pretrained(...)
        response = generation_model.generate_images(...)

        # 6. 結果を画像(Blob)としてDifyに返す
        for image in response.images:
            # ... (一時ファイルに保存してバイナリを読み込む処理)
            yield self.create_blob_message(blob=image_data, meta={'mime_type': 'image/png'})
# ...

特に重要なのが、Base64エンコードされたサービスアカウントキーをデコードして認証を通す部分です。設定の際にエンコードして取り込んでいるため、デコードの処理が必要となります。

おわりに

今回はDifyのプラグインを開発してみました。
思ったより手軽に作れる印象でしたので、興味のある方は試してみてもらえたらと思います。

ここまでご覧いただきありがとうございました。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?