Skip to content
Open
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
Add Atlas Cloud provider
  • Loading branch information
binyangzhu000-sudo committed Jul 7, 2026
commit c2caf9afdf37ec509d42788e1deb6a4d588ae45d
37 changes: 37 additions & 0 deletions aisuite/providers/atlascloud_provider.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import os

from aisuite.providers.openai_provider import OpenaiProvider


def _parse_base_url(config) -> str:
"""Resolve and normalize the Atlas Cloud OpenAI-compatible LLM endpoint."""
base_url = (
config.pop("base_url", None)
or config.pop("api_url", None)
or os.getenv("ATLASCLOUD_API_BASE", "https://api.atlascloud.ai/v1")
)
base_url = base_url.rstrip("/")
if not base_url.endswith("/v1"):
base_url += "/v1"
return base_url


class AtlascloudProvider(OpenaiProvider):
"""
Atlas Cloud provider for its OpenAI-compatible LLM API.

Atlas Cloud exposes chat completions through the standard OpenAI-compatible
/v1 API. Reusing the OpenAI provider keeps tool calls, tool-result
messages, streaming, and finish_reason behavior aligned with the rest of
aisuite's OpenAI-compatible providers.
"""

def __init__(self, **config):
config["base_url"] = _parse_base_url(config)
config.setdefault("api_key", os.getenv("ATLASCLOUD_API_KEY"))
if not config["api_key"]:
raise ValueError(
"Atlas Cloud API key is missing. Please provide it in the config "
"or set the ATLASCLOUD_API_KEY environment variable."
)
super().__init__(**config)
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ psycopg = { version = "^3.3.4", optional = true }
httpx = "~0.27.0"
[tool.poetry.extras]
anthropic = ["anthropic"]
atlascloud = ["openai"]
aws = ["boto3"]
azure = []
cerebras = ["cerebras_cloud_sdk"]
Expand Down
99 changes: 99 additions & 0 deletions tests/providers/test_atlascloud_provider.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
from types import SimpleNamespace
from unittest.mock import patch

import pytest

from aisuite.providers.atlascloud_provider import AtlascloudProvider


@pytest.fixture(autouse=True)
def set_api_key_env_var(monkeypatch):
monkeypatch.setenv("ATLASCLOUD_API_KEY", "test-atlascloud-api-key")
monkeypatch.delenv("ATLASCLOUD_API_BASE", raising=False)


def test_init_points_at_atlascloud_openai_compatible_endpoint():
provider = AtlascloudProvider()
assert str(provider.client.base_url) == "https://api.atlascloud.ai/v1/"
assert provider.client.api_key == "test-atlascloud-api-key"


def test_init_honors_base_url_overrides(monkeypatch):
monkeypatch.setenv("ATLASCLOUD_API_BASE", "https://proxy.example.com")
provider = AtlascloudProvider()
assert str(provider.client.base_url) == "https://proxy.example.com/v1/"

provider2 = AtlascloudProvider(api_url="https://other.example.com/v1")
assert str(provider2.client.base_url) == "https://other.example.com/v1/"


def test_init_requires_api_key(monkeypatch):
monkeypatch.delenv("ATLASCLOUD_API_KEY", raising=False)
with pytest.raises(ValueError, match="Atlas Cloud API key is missing"):
AtlascloudProvider()


def test_completion_passes_through_content():
provider = AtlascloudProvider()
messages = [{"role": "user", "content": "Howdy!"}]
mock_response = SimpleNamespace(
choices=[
SimpleNamespace(
finish_reason="stop",
message=SimpleNamespace(
role="assistant", content="hi there", tool_calls=None
),
)
]
)

with patch.object(
provider.client.chat.completions, "create", return_value=mock_response
) as mock_create:
response = provider.chat_completions_create(
model="qwen/qwen3.5-flash", messages=messages, temperature=0.7
)

assert response.choices[0].message.content == "hi there"
assert mock_create.call_args.kwargs["model"] == "qwen/qwen3.5-flash"
assert mock_create.call_args.kwargs["temperature"] == 0.7


def test_completion_surfaces_tool_calls():
provider = AtlascloudProvider()
messages = [{"role": "user", "content": "Weather in SF?"}]
tools = [
{
"type": "function",
"function": {"name": "get_weather", "parameters": {}},
}
]
tool_call = SimpleNamespace(
id="call_1",
type="function",
function=SimpleNamespace(
name="get_weather", arguments='{"city": "San Francisco"}'
),
)
mock_response = SimpleNamespace(
choices=[
SimpleNamespace(
finish_reason="tool_calls",
message=SimpleNamespace(
role="assistant", content=None, tool_calls=[tool_call]
),
)
]
)

with patch.object(
provider.client.chat.completions, "create", return_value=mock_response
) as mock_create:
response = provider.chat_completions_create(
model="qwen/qwen3.5-flash", messages=messages, tools=tools
)

assert response.choices[0].finish_reason == "tool_calls"
returned = response.choices[0].message.tool_calls
assert returned and returned[0].function.name == "get_weather"
assert mock_create.call_args.kwargs["tools"] == tools