PI DOCUMENTATION / 日本語
カスタムプロバイダー
プロバイダー拡張機能は、カスタム認証、モデル検出、リクエスト処理、またはストリーミングを必要とするモデルサービスに Pi を接続します。サービスがすでにサポート対象の API に対応している場合は、代わりに models.json で設定してください。
プロバイダー拡張機能は Pi 内で実行され、認証情報、プロンプト、ツール定義、モデルの応答、使用量を検査できます。信頼できるコードとして扱い、シークレットやプロバイダーのペイロードをログに記録しないでください。
最小限の統合を選択する#
| 要件 | 使用するもの |
|---|---|
| サポート対象の API を介してモデルを追加する | models.json |
| 既存のプロバイダーのエンドポイントまたはヘッダーを変更する | models.json または小規模なプロバイダー拡張機能 |
| モデルを動的に検出する | refreshModels を備えたプロバイダー |
/login フローを追加する |
ネイティブまたはレガシーの OAuth 設定を備えたプロバイダー |
| サポートされていない通信プロトコルを実装する | stream または streamSimple を備えたプロバイダー |
プロバイダー拡張機能は拡張機能であるため、読み込み、信頼、再読み込み、エラーについて同じ動作に従います。
プロバイダーを登録する#
拡張機能ファクトリーから pi.registerProvider() を呼び出します。Pi は非同期ファクトリーの完了を待ってから起動を続行するため、そこで登録されたプロバイダーは、起動時のモデル選択と pi --list-models で利用できます。
登録形式は 2 つあります。
- ネイティブ認証、フィルタリング、検出、更新、ストリーミングの動作に対応するため、
@earendil-works/pi-aiの完全なProviderを登録します。 - 既存の拡張機能で使用されるレガシー設定形式では、プロバイダー名を
ProviderConfigとともに登録します。
静的なエンドポイントとモデルのメタデータ以外も管理する新しい統合では、完全なプロバイダーを推奨します。Pi は、登録済みのネイティブプロバイダーの上に models.json のオーバーライドを合成します。
既存のプロバイダーに baseUrl または headers のみを登録した場合、その組み込みモデルは維持されます。レガシー形式で models を指定すると、チャット、画像、分類器の各処理でそのプロバイダーのモデルが置き換えられます。type を省略すると "chat" を意味します。画像モデルと分類器モデルには、明示的な判別子と、images および classifiers フィールドを通じて各 api 値に対応付けられた実装が必要です。
たとえば、複数の処理を扱うプロバイダーでは、チャット以外のモデルとその実装をまとめて登録できます。
pi.registerProvider("media-tools", {
apiKey: "$MEDIA_TOOLS_API_KEY",
models: [
{
type: "image",
id: "image-v1",
name: "Image V1",
api: "media-images",
baseUrl: "https://media.example.com/v1",
input: ["text"],
output: ["image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
},
{
type: "classifier",
id: "classifier-v1",
name: "Classifier V1",
api: "media-classifier",
baseUrl: "https://media.example.com/v1",
input: ["text"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
contextWindow: 64000,
},
],
images: {
"media-images": { generateImages: async (model, context, options) => result },
},
classifiers: {
"media-classifier": { classify: async (model, context, options) => result },
},
});モデルレベルの baseUrl 値は、プロバイダーのエンドポイントより優先されます。models リストを指定しない場合は、すべての処理の組み込みモデルが引き続き登録されます。異なる処理に同一のモデル ID があっても、モデル固有のヘッダーを含め、それぞれ別個のものとして維持されます。
拡張機能の初期読み込み後に行われた呼び出しは、直ちに反映されます。動的プロバイダーを削除し、そのプロバイダーによって置き換えられた組み込みの動作を復元するには、pi.unregisterProvider() を使用します。
ストリーミングを組み込み API 実装に委譲する完全な登録例については、検証済みの GitLab Duo プロバイダーを参照してください。
認証を提供する#
静的プロバイダーは、リテラル、環境変数の展開、またはコマンドから API キーを解決できます。これらの値では、models.json と同じ構文を使用します。
$NAMEと${NAME}は環境変数を読み取ります。- 先頭の
!commandはコマンドの出力を使用します。 $$はリテラルの$を生成します。$!は先頭に付くリテラルの!を生成します。
保存された認証情報、カスタム解決、プロバイダー固有の環境、または複数のログイン方法が統合に必要な場合は、ネイティブのプロバイダー認証を使用します。
OAuth プロバイダーは、表示名、ログインフロー、トークンの更新、アクセストークンの解決を提供します。登録後は /login に表示され、Pi は返された認証情報を ~/.pi/agent/auth.json に保存します。
OAuth コールバックは UI に依存しません。認可 URL を開く、デバイスコードを表示する、進捗を報告する、入力を要求する、またはログイン方法の選択をユーザーに求めることができます。ネットワークリクエスト中は、キャンセルと提供された中止シグナルに従ってください。
アクセストークン、更新トークン、認可ヘッダー、またはプロバイダーからの完全な応答を通常のログに書き込まないでください。
モデルを提供および更新する#
すべてのモデルには、ID、表示名、入力機能、コストのメタデータが必要です。チャットモデルと分類器モデルにはコンテキストウィンドウも必要です。チャットモデルには出力上限と推論のサポートが必要で、画像モデルは出力モダリティを宣言します。1 つのモデルだけにオーバーライドが必要な場合を除き、API 実装はプロバイダーレベルで選択してください。
Pi がアイドル状態のプロンプトキャッシュをウォーム状態に保つ必要がある場合は、promptCache.short または promptCache.long に、プロバイダーにおけるベストエフォートのキャッシュ保持期間を秒単位で設定します。その保持階層でキャッシュのウォーム状態維持を無効にするには、これらを未設定のままにします。
互換性フラグは、それ以外の点ではサポートされている API において、検証済みの相違点を示します。エンドポイントが互換性をうたっているという理由だけで有効にしないでください。
実際のサーバーに対して、リクエストフィールドと応答の動作を確認してください。
利用可能なカタログを稼働中のサービスから取得する場合は、refreshModels を使用します。呼び出し元が更新をキャンセルできるように、ブロッキング I/O に context.signal を渡してください。
2 つの登録形式では、更新の規約が異なります。
- 完全な
Providerは何も返しません。context.publish({ update })を呼び出してプロバイダーが所有するモデル状態を導入し、その後、同期的なgetModels()が最新のリストを公開します。 - レガシーの
ProviderConfig.refreshModelsは、複数処理のモデル定義を返します。Pi はその登録の稼働中モデルを返されたリストで置き換え、要求された永続化を適用します。
実行をまたいで保持すべき場合に限り、永続化されたカタログデータを公開してください。llama.cpp のような稼働中のサービスでは、永続化せずにメモリ内のリストを更新できます。リモートカタログでは、オフライン起動用にスナップショットを保持できます。
サポート対象のストリーミング API を再利用する#
プロバイダーのプロトコルが一致する場合は、常に Pi AI の API 実装のいずれかを使用してください。
サポート対象の実装には、Anthropic Messages、OpenAI Chat Completions と Responses、Google Generative AI と Vertex、Azure OpenAI Responses、Mistral Conversations、Bedrock Converse が含まれます。
プロバイダーは、リクエスト変換とストリーミングを既存の API 実装に委譲しながら、認証、ベース URL、ヘッダー、モデルのフィルタリング、検出を引き続きカスタマイズできます。
この方法では Pi のメッセージ変換、ツール処理、使用量計算、キャンセル、互換性に関する動作が維持されるため、ストリーム実装をコピーするより安全です。
カスタムストリーミングを実装する#
既存の API 実装でサービスを表現できない場合に限り、streamSimple を実装します。まず packages/ai/src/api にある実装を調べてください。
ストリームは正規化された TranscriptContext を受け取ります。システムプロンプトとツール宣言はトランスクリプトのシステムメッセージに含まれるため、context.systemPrompt または context.tools を想定せず、getCurrentSystemPrompt(context.messages) と getCurrentTools(context.messages) を使用して読み取ってください。会話途中のシステムメッセージをサポートするモデルには、そのままの位置で渡せます。サポートしない場合は、collapseSystemMessages(context) を呼び出して、後続のシステムメッセージを先頭のシステムメッセージに統合します。
カスタムストリームは、次の処理を行う必要があります。
- プロバイダー、モデル、タイムスタンプ、保留中の停止理由、コンテンツ、ゼロで初期化された使用量を含むアシスタントメッセージを作成します。
- リクエストの設定に成功したら、コンテンツイベントより前に
startイベントを 1 つ送出します。 - 対応の取れたテキスト、思考、ツール呼び出しの各イベントを送出しながら、メッセージを更新します。
- 使用量、コスト、コンテンツ、停止理由を確定します。
- 終端
doneまたはerrorイベントを正確に 1 つ送出し、ストリームを閉じます。 - キャンセルを中止済みの結果に変換します。
リクエストの設定は start より前に失敗することがあります。その場合、ストリームは error で直接終了できます。リクエストの認証情報がない場合も、ストリームが返される前に同期的に例外がスローされることがあります。
コンテンツのインデックスは、アシスタントメッセージ内のブロックを参照します。その状態を partial フィールドで公開するイベントを送出する前に、各ブロックを更新してください。toolcall_end の時点で、ツール呼び出しの引数には有効な解析済み入力が含まれている必要があります。
ストリームは、SimpleStreamOptions を通じて提供されるリクエスト計装にも従う必要があります。
- プロバイダーへのリクエストを送信する前に
options.onPayloadを呼び出し、返された代替ペイロードがあればそれを使用します。 - 応答を受信した後、その本文を使用する前に
options.onResponseを呼び出します。 - 解析された各プロバイダーイベントを正規化する前に、
options.onProviderStreamEvent?.(providerEvent, model)を待機します。 - 中止シグナルとプロバイダー固有の環境をそのまま渡します。
これらのフックは、拡張機能によるリクエストの検査、応答ヘッダーイベント、プロバイダーストリームの監視を実現します。省略すると、そのプロバイダーは Pi の組み込みプロバイダーとは異なる動作をします。
失敗と使用量を報告する#
具体的な終端停止理由を設定します。エラーおよび中止済みのメッセージには errorMessage が必要です。成功したメッセージには、正確な入力、出力、キャッシュ、合計トークン数、コストの値が必要です。
Pi は、認識されたコンテキストオーバーフローエラーの後に圧縮して再試行できます。サービスが未知のメッセージを使用する場合は、ガード付きの message_end ハンドラーで、そのプロバイダーのオーバーフロー応答だけを context_length_exceeded に正規化します。
レート制限や一時的なプロバイダー障害をコンテキストオーバーフローとして書き換えないでください。代わりに、それらの障害には Pi の通常の再試行動作が使用されます。
統合をテストする#
少なくとも以下をテストしてください。
- 通常および空のテキスト応答
- ツール呼び出しとツール結果
- サポートされている場合は、画像入力と画像ツールの結果
- 使用量とコストの計算
- 中止時の動作
- コンテキストオーバーフロー
- 不正または不完全なストリーム
- Unicode の境界
- プロバイダーをまたぐセッションの引き継ぎ
- 認証の更新とキャンセル
packages/ai/test にあるプロバイダーのテストは、組み込みプロバイダーに期待される動作を定義しています。手動プロンプトだけに頼らず、関連するテストスイートを適合させてください。
開発中は拡張機能を直接実行し、その後、検出対象の拡張機能の場所に移動するか、Pi パッケージを通じて配布します。アクティブなセッションで検出対象のプロバイダー拡張機能を変更した後は、/reload を使用してください。