Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions examples/samples/stream_all.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""Streaming across all available adapter"""

import asyncio

import ai

MODELS: list[tuple[str, ai.Provider, str]] = [
("ai_gateway", ai.ai_gateway, "anthropic/claude-sonnet-4.6"),
("anthropic", ai.anthropic, "claude-sonnet-4-6"),
("openai", ai.openai, "gpt-5.5"),
]

messages = [
ai.system_message("Be concise."),
ai.user_message("Explain why the sky is blue in two sentences."),
]


async def _run(name: str, provider: ai.Provider, model_id: str) -> None:
print(f"\n{name} / {model_id}")

if provider.client().api_key is None:
print(f"[SKIP] {provider.api_key_env} not set")
return

model = provider(model_id)

try:
async with ai.stream(model, messages) as s:
async for event in s:
if isinstance(event, ai.TextDelta):
print(event.chunk, end="", flush=True)
print()
except Exception as exc:
print(f"[ERR] {type(exc).__name__}: {exc}")


async def main() -> None:
for name, provider, model_id in MODELS:
await _run(name, provider, model_id)


if __name__ == "__main__":
asyncio.run(main())
6 changes: 4 additions & 2 deletions src/ai/models/anthropic/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
if TYPE_CHECKING:
pass

_BASE_URL = "https://api.anthropic.com/v1"
_BASE_URL = "https://api.anthropic.com"
_API_KEY_ENV = "ANTHROPIC_API_KEY"
_ANTHROPIC_VERSION = "2023-06-01"

Expand Down Expand Up @@ -83,7 +83,9 @@ async def list(self, *, client: client_.Client | None = None) -> list[str]:
"x-api-key": c.api_key or "",
"anthropic-version": _ANTHROPIC_VERSION,
}
response = await c.http.get(f"{c.base_url.rstrip('/')}/models", headers=headers)
response = await c.http.get(
f"{c.base_url.rstrip('/')}/v1/models", headers=headers
)
response.raise_for_status()
data: list[dict[str, object]] = response.json().get("data", [])
return sorted(str(m["id"]) for m in data)
Expand Down
4 changes: 2 additions & 2 deletions src/ai/models/anthropic/check.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Anthropic connection check.

Verifies that the client's credentials are valid and that the model
exists on the Anthropic API by hitting ``GET /v1/models/{model_id}``.
exists on the Anthropic API by hitting ``GET {base_url}/v1/models/{model_id}``.

The ``anthropic-version`` header is added by the check function itself
so that :class:`~ai.models.core.client.Client` stays provider-agnostic.
Expand All @@ -24,7 +24,7 @@ async def check(client: client_.Client, model: model_.Model) -> bool:
"""Return ``True`` if *client* can reach Anthropic and *model* exists."""
if not client.api_key:
return False
url = f"{client.base_url.rstrip('/')}/models/{model.id}"
url = f"{client.base_url.rstrip('/')}/v1/models/{model.id}"
headers = {
"x-api-key": client.api_key,
"anthropic-version": _ANTHROPIC_VERSION,
Expand Down
Loading