Skip to content

feat: add aimlapi.com as an OpenAI-compatible LLM provider - #1

Open
Lookoff-AIMLAPI wants to merge 3 commits into
mainfrom
feat/aimlapi-provider
Open

feat: add aimlapi.com as an OpenAI-compatible LLM provider#1
Lookoff-AIMLAPI wants to merge 3 commits into
mainfrom
feat/aimlapi-provider

Conversation

@Lookoff-AIMLAPI

Copy link
Copy Markdown
Member

What

Adds aimlapi as an API provider: one OpenAI-compatible endpoint
(https://api.aimlapi.com/v1) in front of 350+ chat models from many vendors,
so a user can move between Deepseek-, Anthropic- and OpenAI-class models by
editing provider_model alone.

Shape copied from the existing gateway/API providers (openrouter_fn,
minimax_fn, litellm_fn — the litellm PR is the closest template):

  • sources/llm_provider.pyaimlapi_fn, one entry in available_providers,
    one entry in unsafe_providers. The env var name falls out of the existing
    get_api_key() convention as AIMLAPI_API_KEY, no extra code.
  • tests/test_aimlapi_provider.py — 16 tests, matching the one-module-per-provider
    convention of test_litellm_provider.py / test_minimax_provider.py.
  • .env.example, README.md — key placeholder and a provider table row.

Base URL is overridable with AIMLAPI_BASE_URL, same as MiniMax.

Privacy

docs/CONTRIBUTING.md requires that cloud services be "optional alternatives,
clearly defined with a warning message". aimlapi is therefore in
unsafe_providers, so the existing "Warning: you are using an API provider.
You data will be sent to the cloud." fires, and is_local = True is refused.
Nothing about the default local path changes.

Two things that would have been bugs

  1. Unset parameters are omitted, never sent as None. aimlapi.com answers
    400 for an explicit null on temperature, top_p, seed, tools,
    tool_choice, response_format, stream and max_tokens — but only on
    some models, and the OpenAI SDK serialises an unset optional as literal
    null. A provider copied verbatim from a working OpenAI-compatible one can
    therefore fail on every real call with a fully green mocked test suite.
    There is a regression test asserting no request parameter is None.
  2. Attribution headers are keyed on the request origin, not the provider
    name.
    If AIMLAPI_BASE_URL is pointed at a proxy or a self-hosted gateway,
    aimlapi_attribution_headers() returns {} so nothing rides to a third
    party, and it returns a fresh dict every call so the module-level constant
    cannot be mutated. Both are covered by tests, as is the
    ^part_[A-Za-z0-9]{1,64}$ shape of the partner id — a malformed id is
    dropped silently at the gateway, so only a test catches a typo.

Verification

Environment: macOS arm64, Python 3.12 venv from requirements.txt. vosk==0.3.45
publishes no macOS arm64 wheel, so it was omitted from the local install; it is
unrelated to this change and nothing in the test suite imports it.

Tests — python -m pytest tests/ -q

passed failed subtests
baseline (main, pristine) 154 9 12
with this branch 170 9 12

The 9 failures are identical in both runs and pre-existing: 8 in
tests/test_litellm_provider.py (litellm's current API surface) and
tests/test_memory.py::test_save_and_load_memory. The 16 added passes are the
new provider module.

Live inference through Provider("aimlapi", ...).respond() — not a mock,
not a raw curl. Both models shipped in the README row were called:

catalog check deepseek/deepseek-v4-flash: id=True alias=False
catalog check anthropic/claude-sonnet-4.6: id=True alias=False

=== deepseek/deepseek-v4-flash ===
base_url        : https://api.aimlapi.com/v1
default_headers : {
  "HTTP-Referer": "https://github.com/Fosowl/agenticSeek",
  "X-AIMLAPI-Partner-ID": "part_agenticseek",
  "X-AIMLAPI-Source": "agent/agenticseek",
  "X-Title": "AgenticSeek"
}
response        : 'AIMLAPI OK'

=== anthropic/claude-sonnet-4.6 ===
base_url        : https://api.aimlapi.com/v1
default_headers : { ...same four headers... }
response        : 'AIMLAPI OK'

Model ids were checked against both id and aliases in
GET /v1/models?include=all filtered to type == "openai/chat-completions",
and then actually called — that catalog both omits ids that work and lists
at least one that does not, so membership alone is not proof.

Two-turn tool loopCoderAgent driven end to end on
deepseek/deepseek-v4-flash: turn 1 the model emits a bash block, the framework
executes it and pushes the output back as a user message, turn 2 the model
answers from that output. Final memory:

[0] system: ...coder_agent.txt...
[1] user:   Using a single bash block, run exactly `echo AIMLAPI_TOOL_TURN_1`. ...
[2] assistant: ```bash / echo AIMLAPI_TOOL_TURN_1 / ```
[3] user:   [success] Execution success, code output: ... AIMLAPI_TOOL_TURN_1
[4] assistant: It printed AIMLAPI_TOOL_TURN_1.

Final answer: It printed AIMLAPI_TOOL_TURN_1.

Not verified / caveats

  • max_tokens does not reliably bound reasoning tokens on this API — some
    reasoning models return several times the cap with finish_reason: "stop".
    AgenticSeek exposes no max-tokens control, so nothing here depends on it, but
    it is worth knowing before one is added.
  • Only README.md was updated. The 7 translated READMEs and the stale
    "API Providers (Cloud-Based)" table further down README.md were left alone —
    neither lists openrouter, minimax or litellm either, and PR Upgrade MiniMax provider: add M3 as default, drop M2.5 variants Fosowl/agenticSeek#511
    (MiniMax) touched only README.md + README_CHS.md, so full fan-out is not
    the convention here.
  • vosk could not be installed locally (no macOS arm64 wheel), so any test that
    would need it was never exercised — none appear to exist.

Commits

  • feat: add aimlapi.com as an OpenAI-compatible LLM provider
  • chore(aimlapi): fork-only placement — do not send upstream — moves the
    provider row to the top of the hand-ordered README table. Drop this commit
    before any upstream PR; the provider is complete without it. No badge was
    invented: this repo has no featured/recommended concept.

aimlapi and others added 3 commits September 3, 2026 07:53
AgenticSeek's prompts are tuned for Deepseek-class models, but reaching one
today means holding a separate key per vendor. aimlapi.com is a single
OpenAI-compatible endpoint in front of 350+ chat models, so a user can switch
between Deepseek, Anthropic and others by editing provider_model alone. This
follows the precedent already set by the litellm gateway provider.

The provider is registered in unsafe_providers so the existing "your data will
be sent to the cloud" warning fires, as docs/CONTRIBUTING.md requires of any
cloud service, and get_api_key derives AIMLAPI_API_KEY with no extra code.

Request parameters are built by omitting unset keys instead of passing None:
aimlapi.com answers 400 for an explicit null on temperature/top_p/tools and
others on some of its models, which a mock-based test cannot catch.

Attribution headers identifying AgenticSeek are keyed on the request origin
rather than on the provider name, so overriding AIMLAPI_BASE_URL to a proxy
sends none of them, and each call builds a fresh dict.
Moves the aimlapi.com row to the top of the API provider table. The table is
hand-ordered (roughly by age, not alphabetically), so reordering touches no
generation machinery. The repo has no "recommended"/featured badge concept and
none is invented here.

This commit exists only so it can be dropped before any upstream PR; the
provider itself is complete without it.
The placeholder part_agenticseek was a readable stand-in chosen before the
partner was registered. Registration mints the id server-side, so the
real value is part_l9PWfCWCyHgneiq7GLfDHUsf. A wrong or unknown partner id is accepted with a
200 and silently not attributed, so this would not have surfaced at runtime.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant