Agent Skills by ALSEL
汎用LLM・AI開発⭐ リポ 1品質スコア 73/100

exo:models

Exoエージェントのモデルとプロバイダーを設定する際に使用します。モデル文字列、プロバイダーの選択、APIキー、ベースURL、ModelConfig、カスタムプロバイダー、get_provider()、model_registry、コンテキストウィンドウ、トークンカウント、メディア生成ツール、マルチモーダルコンテンツ、プロバイダー固有のオプションに対応しています。model、provider、openai、anthropic、gemini、vertex、api_key、base_url、ModelConfig、get_provider、model_registry、MODEL_CONTEXT_WINDOWS、ModelResponse、StreamChunk、ModelError、custom provider、media tools、dalle、imagen、veo、context window、temperature、max_tokens、TokenCounter、count_tokensといったキーワードで自動的にトリガーします。

description の原文を見る

Use when configuring Exo agent models and providers — model strings, provider selection, API keys, base URLs, ModelConfig, custom providers, get_provider(), model_registry, context windows, token counting, media generation tools, multimodal content, provider-specific options. Triggers on: model, provider, openai, anthropic, gemini, vertex, api_key, base_url, ModelConfig, get_provider, model_registry, MODEL_CONTEXT_WINDOWS, ModelResponse, StreamChunk, ModelError, custom provider, media tools, dalle, imagen, veo, context window, temperature, max_tokens, TokenCounter, count_tokens.

SKILL.md 本文

ブランチ: これらのスキルは rename/orbiter-to-exo ブランチ用に作成されています。ここで参照する Exo API は他のブランチで異なる可能性があります。

Exo Models — プロバイダーとモデル設定

このスキルを使用する場合

開発者が以下を必要とする場合にこのスキルを使用します:

  • エージェントが使用する LLM モデルとプロバイダーを設定する
  • "provider:model" 文字列形式を理解する
  • API キー、ベース URL、タイムアウト、または再試行ポリシーを設定する
  • カスタムプロバイダーを登録する
  • プロバイダー固有オプション (Vertex AI 認証情報、OpenAI プロキシ) を使用する
  • ModelResponseStreamChunk、または ModelError 型を使用する
  • メディア生成ツール (DALL-E、Imagen、Veo) を追加する
  • コンテキストウィンドウサイズとトークン制限を理解する
  • プロバイダー間のマルチモーダルコンテンツを処理する

判断ガイド

  1. どのモデル文字列を使用するか?"provider:model_name" (例: "openai:gpt-4o""anthropic:claude-sonnet-4-20250514")
  2. モデル文字列にコロンがない? → OpenAI にデフォルト (例: "gpt-4o""openai:gpt-4o")
  3. プロバイダーインスタンスが直接必要か?get_provider("openai:gpt-4o", api_key=..., base_url=...)
  4. 再試行/タイムアウトをカスタマイズする必要があるか?max_retriestimeout の kwargs を get_provider() に渡す
  5. Vertex AI を使用するか?GOOGLE_CLOUD_PROJECT 環境変数 + ADC または google_service_account_base64 のいずれかを設定
  6. カスタムプロバイダーを構築するか?ModelProvider をサブクラス化し、complete() + stream() を実装し、model_registry に登録
  7. 画像/動画生成が必要か?dalle_generate_imageimagen_generate_image、または veo_generate_video ツールを使用
  8. コンテキストウィンドウサイズが必要か?MODEL_CONTEXT_WINDOWS 辞書をチェック
  9. 送信前にトークンをカウントする必要があるか?count_tokens(text, model="openai:gpt-4o") または一括カウント用の TokenCounter(model) を使用

リファレンス

モデル文字列形式

形式: "provider:model_name"

# 明示的なプロバイダー
agent = Agent(name="bot", model="openai:gpt-4o")
agent = Agent(name="bot", model="anthropic:claude-sonnet-4-20250514")
agent = Agent(name="bot", model="gemini:gemini-2.0-flash")
agent = Agent(name="bot", model="vertex:gemini-2.5-pro")

# 短形式 — コロンなしは OpenAI にデフォルト
agent = Agent(name="bot", model="gpt-4o")  # "openai:gpt-4o" と同等

パース (exo.config.parse_model_string):

from exo.config import parse_model_string

parse_model_string("openai:gpt-4o")       # → ("openai", "gpt-4o")
parse_model_string("gpt-4o")              # → ("openai", "gpt-4o")
parse_model_string("anthropic:claude-sonnet-4-20250514")  # → ("anthropic", "claude-sonnet-4-20250514")

組み込みプロバイダー

プロバイダー文字列クラスSDKAPI キーの環境変数
"openai"OpenAIProvideropenai (AsyncOpenAI)OPENAI_API_KEY
"anthropic"AnthropicProvideranthropic (AsyncAnthropic)ANTHROPIC_API_KEY
"gemini"GeminiProvidergoogle-genaiGEMINI_API_KEY
"vertex"VertexProvidergoogle-genai (vertexai=True)GCP ADC またはサービスアカウント

エージェントモデルパラメーター

from exo import Agent

agent = Agent(
    name="assistant",
    model="openai:gpt-4o",           # モデル文字列 (デフォルト: "openai:gpt-4o")
    temperature=0.7,                   # サンプリング温度 0.0-2.0 (デフォルト: 1.0)
    max_tokens=4096,                   # 最大出力トークン (デフォルト: None → プロバイダーのデフォルト)
    planning_model="anthropic:claude-sonnet-4-20250514",  # オプション: プランニングフェーズ用の別モデル
)

エージェントは初期化時にプロバイダーをインスタンス化せず、モデル文字列を保存し、run() 中に get_provider() 経由で遅延解決します。

get_provider() — 直接プロバイダーのインスタンス化

from exo.models import get_provider

# 基本
provider = get_provider("openai:gpt-4o")

# 明示的な API キーとカスタムベース URL (例: プロキシ)
provider = get_provider(
    "openai:gpt-4o",
    api_key="sk-...",
    base_url="https://my-proxy.com/v1",
)

# 再試行/タイムアウトのカスタマイズ
provider = get_provider(
    "anthropic:claude-sonnet-4-20250514",
    api_key="sk-ant-...",
    max_retries=5,
    timeout=60.0,
)

# Vertex AI とサービスアカウント
provider = get_provider(
    "vertex:gemini-2.5-pro",
    google_project="my-gcp-project",
    google_location="us-central1",
    google_service_account_base64="eyJ0eXBlIjoi...",
)

内部的な動作:

  1. モデル文字列をパース → (provider_name, model_name)
  2. model_registry でプロバイダークラスを検索
  3. MODEL_CONTEXT_WINDOWS からコンテキストウィンドウを検索 (オプション)
  4. 提供されたすべてのパラメーターで ModelConfig を作成
  5. プロバイダーをインスタンス化して返す

発生例外: プロバイダーが登録されていない場合 ModelError (エラーメッセージに利用可能なプロバイダーを含む)。

ModelConfig

from exo.config import ModelConfig

config = ModelConfig(
    provider="openai",                     # プロバイダー名
    model_name="gpt-4o",                  # モデル識別子
    api_key="sk-...",                      # API キー (None → SDK が環境変数を読み込む)
    base_url="https://proxy.com/v1",       # カスタムベース URL (None → プロバイダーのデフォルト)
    max_retries=3,                         # 一時的エラー時の再試行 (デフォルト: 3)
    timeout=30.0,                          # リクエストタイムアウト秒数 (デフォルト: 30.0)
    context_window_tokens=128000,          # コンテキストウィンドウオーバーライド (None → レジストリから自動)
)

ModelConfigextra = "allow" を持つ — プロバイダー固有の kwargs は属性として保存されます:

config = ModelConfig(
    provider="vertex",
    model_name="gemini-2.5-pro",
    google_project="my-project",           # Vertex 固有
    google_location="europe-west1",        # Vertex 固有
    google_service_account_base64="...",   # Vertex 固有
)

ModelProvider ABC

すべてのプロバイダーはこのインターフェースを実装します:

from exo.models.provider import ModelProvider
from exo.models.types import ModelResponse, StreamChunk
from exo.types import Message

class ModelProvider:
    def __init__(self, config: ModelConfig) -> None:
        self.config = config

    async def complete(
        self,
        messages: list[Message],
        *,
        tools: list[dict] | None = None,
        temperature: float | None = None,
        max_tokens: int | None = None,
    ) -> ModelResponse: ...

    async def stream(
        self,
        messages: list[Message],
        *,
        tools: list[dict] | None = None,
        temperature: float | None = None,
        max_tokens: int | None = None,
    ) -> AsyncIterator[StreamChunk]: ...

レスポンス型

ModelResponse (complete() から):

class ModelResponse(BaseModel):
    id: str = ""                                # プロバイダー相関 ID
    model: str = ""                             # このレスポンスを生成したモデル
    content: str = ""                           # テキスト出力
    tool_calls: list[ToolCall] = []             # リクエストされたツール呼び出し
    usage: Usage = Usage()                      # トークン使用状況 (入力、出力、合計)
    finish_reason: FinishReason = "stop"        # "stop" | "tool_calls" | "length" | "content_filter"
    reasoning_content: str = ""                 # チェーンオブソート (o1/o3、Claude 思考)

StreamChunk (stream() から):

class StreamChunk(BaseModel):
    delta: str = ""                             # 増分テキスト
    tool_call_deltas: list[ToolCallDelta] = []  # 増分ツール呼び出しフラグメント
    finish_reason: FinishReason | None = None   # 最終チャンクでのみ非 None
    usage: Usage = Usage()                      # 通常は最終チャンクのみ

ToolCallDelta:

class ToolCallDelta(BaseModel):
    index: int = 0                  # マルチツール呼び出しレスポンス内の位置
    id: str | None = None           # ツール呼び出し ID (最初のチャンクのみ)
    name: str | None = None         # ツール名 (最初のチャンクのみ)
    arguments: str = ""             # 増分 JSON フラグメント

FinishReason 正規化 — すべてのプロバイダーは以下にマップします: "stop" | "tool_calls" | "length" | "content_filter"

ModelError

from exo.models.types import ModelError

# プロバイダーが失敗時に発生させる
class ModelError(ExoError):
    def __init__(self, message: str, *, model: str = "", code: str = "") -> None:
        self.model = model     # 例: "openai:gpt-4o"
        self.code = code       # 例: "context_length"、"rate_limit"

環境変数

変数プロバイダー目的
OPENAI_API_KEYOpenAIAPI 認証 (SDK が自動読み込み)
ANTHROPIC_API_KEYAnthropicAPI 認証 (SDK が自動読み込み)
GEMINI_API_KEYGeminiAPI 認証 (api_key が渡されない場合のフォールバック)
GOOGLE_API_KEYGemini メディアツールimagen_generate_image が使用
GOOGLE_CLOUD_PROJECTVertex AIGCP プロジェクト ID (必須)
GOOGLE_CLOUD_LOCATIONVertex AIGCP リージョン (デフォルト: "us-central1")
GOOGLE_SERVICE_ACCOUNT_BASE64Vertex AIBase64 エンコードされたサービスアカウント JSON

コンテキストウィンドウ

from exo.models import MODEL_CONTEXT_WINDOWS

# 既知のモデルとそのコンテキストウィンドウサイズ (トークン):
# gpt-4o:                    128,000
# gpt-4o-mini:               128,000
# o1:                        200,000
# claude-sonnet-4-6:         200,000
# claude-opus-4-6:           200,000
# claude-haiku-4-5-20251001: 200,000
# gemini-2.0-flash:        1,048,576
# gemini-1.5-pro:          2,097,152

get_provider() によって自動的に使用され、ModelConfig.context_window_tokens を入力します。

トークンカウント

呼び出し前のトークン推定には、TokenCounter または count_tokens() 便利関数を使用します。これらは tiktoken をプロバイダー対応エンコーディング選択で使用します。

from exo import TokenCounter, count_tokens

# クイックカウント (モデル文字列ごとにカウンターをキャッシュ)
n = count_tokens("Hello, world!", model="anthropic:claude-sonnet-4-6")

# 再利用可能なカウンター
counter = TokenCounter("openai:gpt-4o")
n = counter.count("Some text to count")

# チャットメッセージをカウント (メッセージごとのオーバーヘッドを含む)
total = counter.count_messages([
    {"role": "user", "content": "Hello"},
])

# トークン ↔ 文字変換 (エンコーディング対応比率)
chars = counter.tokens_to_chars(4096)
tokens = counter.chars_to_tokens(10000)

精度: OpenAI モデルの場合は正確 (tiktoken は彼らのトークナイザー)。Anthropic の場合は ~95%、Gemini/Vertex の場合は ~85-90% (利用可能な最良のローカル近似)。

呼び出し後の使用状況: LLM 呼び出し後に実際に消費されたトークンについては、ModelResponse.usage または RunResult.usage を使用します — これらはプロバイダーが報告したものであり、常に正確です。

model_registry — プロバイダー登録

from exo.models.provider import model_registry

# 登録されたすべてのプロバイダーをリストします
model_registry.list_all()  # ["openai", "anthropic", "gemini", "vertex"]

# プロバイダークラスを取得
provider_cls = model_registry.get("openai")  # → OpenAIProvider

# カスタムプロバイダーを登録
model_registry.register("my_provider", MyProviderClass)

メディア生成ツール

画像/動画生成用の事前構築 @tool 関数:

from exo.models import dalle_generate_image, imagen_generate_image, veo_generate_video

agent = Agent(
    name="creative",
    tools=[dalle_generate_image, imagen_generate_image, veo_generate_video],
)

dalle_generate_image(prompt, size="1024x1024", quality="standard", style="vivid")

  • 必須: OPENAI_API_KEY
  • 戻り値: list[ImageURLBlock]

imagen_generate_image(prompt, aspect_ratio="1:1", number_of_images=1)

  • 必須: GOOGLE_API_KEY
  • 戻り値: list[ImageDataBlock] (base64 PNG)

veo_generate_video(prompt, duration_seconds=5, aspect_ratio="16:9")

  • 必須: GOOGLE_CLOUD_PROJECT + GCP 認証
  • 戻り値: list[VideoBlock]

マルチモーダルコンテンツサポート

Exo は、マルチモーダルメッセージに ContentBlock 型を使用します。プロバイダーのサポートは異なります:

コンテンツ型OpenAIAnthropicGemini/Vertex
TextBlockありありあり
ImageURLBlockありありあり
ImageDataBlockありありあり
AudioBlockありなし (警告)あり
VideoBlockなし (警告)なし (警告)あり
DocumentBlockなし (警告)ありあり

サポートされていない型は警告をログし、スキップされます — エラーは発生しません。

パターン

特定のモデルを持つ基本エージェント

from exo import Agent, run

agent = Agent(
    name="assistant",
    model="anthropic:claude-sonnet-4-20250514",
    temperature=0.7,
    instructions="You are a helpful assistant.",
)

result = await run(agent, "Hello!")
print(result.output)

直接プロバイダー使用 (エージェントなし)

from exo.models import get_provider
from exo.types import SystemMessage, UserMessage

provider = get_provider("openai:gpt-4o", api_key="sk-...")

response = await provider.complete([
    SystemMessage(content="You are helpful."),
    UserMessage(content="What is 2+2?"),
])
print(response.content)        # "4"
print(response.usage)          # Usage(input_tokens=..., output_tokens=..., total_tokens=...)
print(response.finish_reason)  # "stop"

直接プロバイダーでのストリーミング

from exo.models import get_provider
from exo.types import UserMessage

provider = get_provider("anthropic:claude-sonnet-4-20250514")

async for chunk in provider.stream([UserMessage(content="Tell me a story")]):
    if chunk.delta:
        print(chunk.delta, end="", flush=True)
    if chunk.finish_reason:
        print(f"\n[Finished: {chunk.finish_reason}]")

OpenAI 互換プロキシ (例: Azure、LiteLLM、vLLM)

agent = Agent(
    name="bot",
    model="openai:my-deployment",  # プロキシが期待するモデル名
)

provider = get_provider(
    "openai:my-deployment",
    api_key="your-proxy-key",
    base_url="https://your-proxy.com/v1",
)

result = await run(agent, "Hello", provider=provider)

Vertex AI とサービスアカウント

import base64, json

service_account = json.dumps({
    "type": "service_account",
    "project_id": "my-project",
    # ... サービスアカウント JSON の残り
})

provider = get_provider(
    "vertex:gemini-2.5-pro",
    google_project="my-project",
    google_location="europe-west1",
    google_service_account_base64=base64.b64encode(service_account.encode()).decode(),
)

カスタムプロバイダー登録

from exo.models.provider import ModelProvider, model_registry
from exo.models.types import ModelResponse, StreamChunk
from exo.config import ModelConfig

class MyProvider(ModelProvider):
    def __init__(self, config: ModelConfig) -> None:
        super().__init__(config)
        # ここでクライアントを初期化

    async def complete(self, messages, *, tools=None, temperature=None, max_tokens=None):
        # メッセージを変換、API を呼び出し、ModelResponse を返す
        return ModelResponse(
            content="response text",
            model=self.config.model_name,
            usage=Usage(input_tokens=10, output_tokens=5, total_tokens=15),
        )

    async def stream(self, messages, *, tools=None, temperature=None, max_tokens=None):
        # ストリーミング API を呼び出し、StreamChunk オブジェクトをイールド
        yield StreamChunk(delta="Hello ")
        yield StreamChunk(delta="world!", finish_reason="stop")

# 登録
model_registry.register("my_llm", MyProvider)

# 使用
agent = Agent(name="bot", model="my_llm:my-model-v1")

プランニングと実行で異なるモデル

agent = Agent(
    name="researcher",
    model="openai:gpt-4o",                           # メイン実行モデル
    planning_enabled=True,
    planning_model="anthropic:claude-sonnet-4-20250514",  # プランニング用の安いモデル
    planning_instructions="Create a research plan with clear steps.",
)

エラーハンドリング

from exo.models.types import ModelError

try:
    result = await run(agent, "Hello", provider=provider)
except ModelError as e:
    print(f"Model: {e.model}")    # "openai:gpt-4o"
    print(f"Code: {e.code}")      # "rate_limit"、"context_length" など
    print(f"Message: {e}")        # "[openai:gpt-4o] Rate limit exceeded"

プロバイダー固有の注釈

OpenAI

  • デフォルト max_tokens: None (OpenAI が独自のデフォルトを適用)
  • ストリーミングは stream_options={"include_usage": True} 経由で使用状況を含める
  • model_extra 経由で o1/o3 モデルレスポンスから reasoning_content を抽出
  • base_url はプロキシ、Azure OpenAI、vLLM、LiteLLM などを有効にする

Anthropic

  • デフォルト max_tokens: 4096 (ハードコード — Anthropic はこのフィールドを要求)
  • システムメッセージを system= kwarg に抽出 (メッセージリストにはない)
  • 連続した ToolResult メッセージは単一のユーザーメッセージにマージ (Anthropic API 要件)
  • thinking ブロックから reasoning_content を抽出
  • ツール形式は OpenAI の parameters ではなく input_schema を使用

Gemini

  • api_key が提供されない場合 GEMINI_API_KEY 環境変数にフォールバック
  • API が省略した場合、合成ツール呼び出し ID (call_0call_1) を生成
  • システムメッセージは system_instruction 設定経由で渡される、メッセージ内にはない
  • セーフティフィルター理由は "content_filter" finish reason にマップ

Vertex AI

  • Gemini と同じメッセージ/ツール形式 (共有 Google SDK)
  • GOOGLE_CLOUD_PROJECT 環境変数または google_project kwarg が必須
  • 位置のデフォルトは "us-central1"GOOGLE_CLOUD_LOCATION または google_location でオーバーライド
  • 認証情報: サービスアカウント base64 → google.oauth2.service_account.Credentials、または GCP ADC フォールバック

落とし穴

  • モデル文字列にコロンがない → OpenAI と想定"gpt-4o" は動作しますが、"anthropic:" プレフィックスなしの "claude-sonnet-4-20250514" は OpenAI モデルとして見つけようとし、失敗します
  • API キーはデフォルトで環境変数api_key=None の場合、各プロバイダーの SDK は自動的に独自の環境変数を読み込みます。明示的にオーバーライドする場合にのみ api_key を渡します。
  • Anthropic は max_tokens=4096 をハードコード — OpenAI/Gemini と異なり、Anthropic は max_tokens を要求します。指定しない場合、プロバイダーは 4096 にデフォルト設定します。max_tokens を Agent または complete()/stream() で渡してオーバーライドします。
  • Vertex AI は GCP 認証が必要 — ADC を設定 (gcloud auth application-default login) するか、google_service_account_base64 を渡す
  • ModelConfig.extra = "allow" — プロバイダー固有の kwargs (google_project など) は静かに保存されます。タイプミスはエラーを発生させません。
  • コンテキストウィンドウは参考情報MODEL_CONTEXT_WINDOWS はコンテキスト管理 (要約、ウィンドウイング) で使用されますが、プロバイダーは適用しません。それを超過するとプロバイダー側エラーが発生します。
  • プロバイダーのインスタンス化は遅延Agent(model="openai:gpt-4o")run() が呼ばれるまでプロバイダーを作成しません。無効なモデル文字列は初期化時に失敗しません。
  • エージェントの温度デフォルトは 1.0 — しかし complete()/stream() を直接呼び出すときプロバイダーに None が渡され、プロバイダー独自のデフォルトを使用
  • メディアツールはスタンドアロン — 内部的に独自の SDK クライアントを作成し、エージェントのプロバイダーを使用しません。環境変数を直接読み込みます。
  • サポートされていないコンテンツ型はエラーを発生させないAudioBlock を Anthropic に送信すると、警告をログし、ブロックを静かにスキップ
  • FinishReason は正規化される — すべてのプロバイダーは 4 つの値にマップします: "stop""tool_calls""length""content_filter"。プロバイダー固有の理由は失われます。

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
midsphere-ai
リポジトリ
midsphere-ai/exo
ライセンス
MIT
最終更新
2026/4/13

Source: https://github.com/midsphere-ai/exo / ライセンス: MIT

本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: midsphere-ai · midsphere-ai/exo · ライセンス: MIT