標準モデル統合の実装
このドキュメントは、Pythonコードを記述してDifyのモデルサポートを追加または強化する必要がある開発者向けのもので、ディレクトリ構造の作成、モデル設定の記述、モデル呼び出しロジックの実装、プラグインのデバッグと公開までの完全なプロセスを詳細にガイドし、コアメソッドの実装とエラー処理の詳細を含んでいます。
このドキュメントは、Pythonコードを記述してDifyのモデルサポートを追加または強化する必要がある開発者向けの標準ガイドです。追加したいモデルが新しいAPI呼び出しロジック、特別なパラメータ処理、またはDifyが明示的にサポートする必要がある新機能(Vision、Tool Callingなど)を含む場合、このガイドの手順に従う必要があります。
本文を読む前に、以下のことをお勧めします:
- Pythonプログラミングの基礎とオブジェクト指向プログラミングの基本的な理解があること。
- 統合したいモデルプロバイダーが提供するAPIドキュメントと認証方法に精通していること。
- Difyプラグイン開発ツールキットをインストールし、設定済みであること(開発ツールの初期化を参照)。
- (オプション)モデルプラグインの紹介ドキュメントを読み、モデルプラグインの基本概念とアーキテクチャを理解していること。
このガイドでは、ディレクトリ構造の作成、モデル設定(YAML)の記述、モデル呼び出しロジック(Python)の実装、およびプラグインのデバッグと公開までの全プロセスを案内します。
ステップ1:ディレクトリ構造の作成
整理されたディレクトリ構造は、保守可能なプラグインを開発するための基礎です。モデルプロバイダープラグインのために特定のディレクトリとファイルを作成する必要があります。
- プロバイダーディレクトリの特定または作成: プラグインプロジェクト(通常は
dify-official-plugins
のローカルクローン)のmodels/
ディレクトリ内で、モデルプロバイダー名でフォルダを見つけるか作成します(例:models/my_new_provider
)。 models
サブディレクトリの作成: プロバイダーディレクトリ内にmodels
サブディレクトリを作成します。- モデルタイプごとのサブディレクトリ作成:
models/models/
ディレクトリ内に、サポートする必要のある各モデルタイプごとにサブディレクトリを作成します。一般的なタイプには以下が含まれます:llm
: テキスト生成モデルtext_embedding
: テキストEmbeddingモデルrerank
: Rerankモデルspeech2text
: 音声認識モデルtts
: テキスト読み上げモデルmoderation
: コンテンツ審査モデル
- 実装ファイルの準備:
- 各モデルタイプディレクトリ(例:
models/models/llm/
)に、そのタイプのモデル呼び出しロジックを実装するためのPythonファイルを作成します(例:llm.py
)。 - 同じディレクトリに、そのタイプ下の各具体的なモデルごとにYAML設定ファイルを作成します(例:
my-model-v1.yaml
)。 - (オプション)
_position.yaml
ファイルを作成して、そのタイプ下のモデルがDify UIに表示される順序を制御できます。
- 各モデルタイプディレクトリ(例:
構造例(プロバイダー my_provider
がLLMとEmbeddingをサポートすると仮定):
ステップ2:モデル設定の定義(YAML)
各具体的なモデルについて、Difyがそれを正しく理解し使用できるように、その属性、パラメータ、および機能を記述するYAMLファイルを作成する必要があります。
- YAMLファイルの作成: 対応するモデルタイプディレクトリ(例:
models/models/llm/
)に、追加するモデル用のYAMLファイルを作成します。ファイル名は通常、モデルIDと一致させるか、説明的なものにします(例:my-llm-model-v1.yaml
)。 - 設定内容の記述: AIModelEntityスキーマ定義仕様に従って内容を記述します。主要なフィールドは以下の通りです:
model
: (必須)モデルの公式API識別子。label
: (必須)Dify UIに表示される名前(多言語対応)。model_type
: (必須)所在するディレクトリタイプと一致する必要があります(例:llm
)。features
: (オプション)モデルがサポートする特殊機能(vision
、tool-call
、stream-tool-call
など)を宣言します。model_properties
: (必須)モデル固有のプロパティ(mode
(chat
またはcompletion
)、context_size
など)を定義します。parameter_rules
: (必須)ユーザーが調整可能なパラメータとそのルール(名前name
、タイプtype
、必須required
、デフォルト値default
、範囲min
/max
、オプションoptions
など)を定義します。use_template
を使用して事前定義されたテンプレートを参照し、一般的なパラメータ(temperature
、max_tokens
など)の設定を簡略化できます。pricing
: (オプション)モデルの課金情報を定義します。
例(claude-3-5-sonnet-20240620.yaml
):
ステップ3:モデル呼び出しコードの記述(Python)
これはモデル機能実装の中核となるステップです。対応するモデルタイプのPythonファイル(例:llm.py
)に、API呼び出し、パラメータ変換、結果返却を処理するコードを記述する必要があります。
-
Pythonファイルの作成/編集: モデルタイプディレクトリ(例:
models/models/llm/
)で、対応するPythonファイル(例:llm.py
)を作成または開きます。 -
実装クラスの定義:
- クラスを定義します。例:
MyProviderLargeLanguageModel
。 - このクラスは、DifyプラグインSDK内の対応するモデルタイプベースクラスを継承する必要があります。例えば、LLMの場合は
dify_plugin.provider_kits.llm.LargeLanguageModel
を継承します。
- クラスを定義します。例:
-
主要メソッドの実装:(具体的に実装が必要なメソッドは継承するベースクラスによって異なります。以下はLLMを例とします)
-
_invoke(...)
: コア呼び出しメソッド。- シグネチャ:
def _invoke(self, model: str, credentials: dict, prompt_messages: List[PromptMessage], model_parameters: dict, tools: Optional[List[PromptMessageTool]] = None, stop: Optional[List[str]] = None, stream: bool = True, user: Optional[str] = None) -> Union[LLMResult, Generator[LLMResultChunk, None, None]]:
- 責務:
credentials
とmodel_parameters
を使用してAPIリクエストを準備します。- Difyの
prompt_messages
形式をプロバイダーAPIが必要とする形式に変換します。 - Function Calling / Tool Useをサポートするために
tools
パラメータを処理します(モデルがサポートしている場合)。 stream
パラメータに基づいて、ストリーミング呼び出しを行うか同期呼び出しを行うかを決定します。- ストリーミング返却:
stream=True
の場合、このメソッドはジェネレータ(Generator
)を返す必要があり、yield
を介してLLMResultChunk
オブジェクトを逐次返却します。各チャンクには部分的な結果(テキスト、ツール呼び出しチャンクなど)とオプションの使用量情報が含まれます。 - 同期返却:
stream=False
の場合、このメソッドは完全なLLMResult
オブジェクトを返す必要があります。これには最終的なテキスト結果、完全なツール呼び出しリスト、および総使用量情報(LLMUsage
)が含まれます。
- 実装パターン: 同期ロジックとストリーミングロジックを内部ヘルパーメソッドに分割することを強く推奨します。
- シグネチャ:
-
validate_credentials(self, model: str, credentials: dict) -> None
: (必須)ユーザーが認証情報を追加または変更する際にその有効性を検証するために使用されます。通常、簡単で低コストのAPIエンドポイント(利用可能なモデルのリスト表示、残高確認など)を呼び出すことで実装されます。検証に失敗した場合は、CredentialsValidateFailedError
またはそのサブクラスをスローする必要があります。 -
get_num_tokens(self, model: str, credentials: dict, prompt_messages: List[PromptMessage], tools: Optional[List[PromptMessageTool]] = None) -> int
: (オプションだが推奨)与えられた入力のトークン数を推定するために使用されます。正確に計算できない場合やAPIがサポートしていない場合は、0を返すことができます。 -
@property _invoke_error_mapping(self) -> dict[type[InvokeError], list[type[Exception]]]
: (必須)エラーマッピング辞書を定義します。キーはDifyの標準InvokeError
サブクラスであり、値はその標準エラーにマッピングされるべきプロバイダーSDKがスローする可能性のある例外タイプのリストです。これはDifyが異なるプロバイダーのエラーを統一的に処理するために不可欠です。
-
ステップ4:プラグインのデバッグ
プラグインをコミュニティに貢献する前に、十分なテストとデバッグが不可欠です。Difyはリモートデバッグ機能を提供しており、ローカルでコードを修正し、Difyインスタンスでリアルタイムに効果をテストできます。
-
デバッグ情報の取得:
- Difyインスタンスで、「プラグイン管理」ページに移動します(管理者権限が必要な場合があります)。
- ページ右上の「プラグインのデバッグ」をクリックして、
デバッグキー
とリモートサーバーアドレス
(例:http://<your-dify-domain>:5003
)を取得します。
-
ローカル環境の設定:
- ローカルプラグインプロジェクトのルートディレクトリで、
.env
ファイルを見つけるか作成します(.env.example
からコピーできます)。 .env
ファイルを編集し、デバッグ情報を入力します:
- ローカルプラグインプロジェクトのルートディレクトリで、
-
ローカルプラグインサービスの起動:
- プラグインプロジェクトのルートディレクトリで、Python環境がアクティブになっていることを確認します(仮想環境を使用している場合)。
- メインプログラムを実行します:
- ターミナルの出力を観察し、接続が成功すると、通常、対応するログが表示されます。
-
Difyでのテスト:
- Difyの「プラグイン」または「モデルプロバイダー」ページを更新すると、ローカルプラグインインスタンスが表示され、「デバッグ中」のマークが付いている場合があります。
- 「設定」->「モデルプロバイダー」に移動し、プラグインを見つけて有効なAPI認証情報を設定します。
- Difyアプリケーションでモデルを選択して使用し、テストを行います。ローカルでのPythonコードの変更(保存後、通常はサービスが自動的に再読み込みされます)は、Difyでの呼び出し動作に直接影響します。Difyのデバッグプレビュー機能を使用すると、入出力とエラー情報を確認するのに役立ちます。
ステップ5:パッケージ化と公開
開発とデバッグが完了し、プラグインの機能に満足したら、パッケージ化してDifyコミュニティに貢献できます。
-
プラグインのパッケージ化:
- ローカルデバッグサービスを停止します(
Ctrl+C
)。 - プラグインプロジェクトのルートディレクトリでパッケージ化コマンドを実行します:
- これにより、プロジェクトのルートディレクトリに
<provider_name>.difypkg
ファイルが生成されます。
- ローカルデバッグサービスを停止します(
-
プルリクエストの送信:
- コードスタイルが良好で、Difyのプラグイン公開仕様に従っていることを確認します。
- ローカルGitのコミットをフォークした
dify-official-plugins
リポジトリにプッシュします。 - GitHub上で
langgenius/dify-official-plugins
メインリポジトリに対してプルリクエストを作成します。PRの説明には、行った変更、追加したモデルや機能、および必要なテスト手順を明確に記述します。 - Difyチームのレビューを待ちます。レビューが承認されマージされると、あなたの貢献は公式プラグインに含まれ、Difyマーケットプレイスで利用可能になります。
さらに探る
- モデルスキーマ定義 (モデルYAML仕様)
- プラグインマニフェスト構造 (
manifest.yaml
仕様) - Dify Plugin SDKリファレンス (ベースクラス、データ構造、エラータイプを検索)
- Dify公式プラグインリポジトリ (既存プラグインの実装を参照)