feat(provider): add aimlapi.com model provider - #1
Open
Lookoff-AIMLAPI wants to merge 2 commits into
Open
Conversation
MaxKB 目前只能通过 OpenAI 供应商填写自定义 api_base 的方式访问 AI/ML API,模型需要手工输入,也没有独立的图标和渠道标识。 这里按照 regolo 的目录结构新增一个独立的供应商,支持 LLM、视觉、 向量和文生图四种模型类型。 几个和 AI/ML API 相关的实现细节: - 请求参数按“未设置就不下发”的方式构造。AI/ML API 上不同模型对 null 的容忍度不同:google/gemini-2.5-flash 可以接受,而 openai/gpt-4o-mini、 deepseek/deepseek-chat 在 temperature、top_p、seed、tools 为 null 时 直接返回 400。tools 尤其危险:Agent 第一轮成功、第二轮清空工具时失败。 已补充回归测试。 - 归因请求头按请求地址生效,只有 API URL 指向 api.aimlapi.com 时才携带, 用户改成其他服务商或中转代理时不会被带过去;合并而不是覆盖调用方的请求头。 - 向量模型直接用 openai SDK 下发字符串,而不是 langchain 的 OpenAIEmbeddings: 后者会先把文本转成 token id 数组,AI/ML API 的 /v1/embeddings 只接受字符串。 - 文生图的 size/quality 默认值为 auto,即不下发该参数。不同图片模型接受的 枚举值不同(openai/gpt-image-1 的 quality 只接受 low/medium/high, 下发 standard 会 400)。 - 文生图的凭据校验没有使用 GET /v1/models:该接口是公开的,任意 Key 都 返回 200,无法用来校验 Key。 - 输出最大 Token 数的提示文案补充说明:推理模型的思考过程可能超出该限制, 它并不能限制单次请求的费用。
供应商列表(后端 ModelProvideConstants 枚举、前端 providerList)都是 手工排序的,这里把 aimlapi.com 放到第一位。MaxKB 的供应商没有 “推荐”标记之类的机制,因此没有新增任何标记,只调整了顺序。 这个提交只在我们自己的 fork 中保留,向上游提交时应当去掉。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this PR does / why we need it?
Adds aimlapi.com (AI/ML API) as a first-class model provider.
MaxKB can already reach AI/ML API today by pointing the built-in OpenAI provider at
https://api.aimlapi.com/v1, but the operator has to type every model name by hand and theprovider shows up as "OpenAI". This PR adds a dedicated provider directory following the
regoloshape (the last externally contributed OpenAI-compatible provider, 1Panel-dev#3041), coveringfour model types: LLM, IMAGE (vision), EMBEDDING and TTI (image generation).
Summary of your change
apps/models_provider/impl/aimlapi_model_provider/— credential + model class per type,provider class, icon, plus the
ModelProvideConstantsregistration, theui/.../provider-data.tsentry and the three.pofiles (zh_CN / zh_Hant / en_US).Implementation details that are specific to this API, all of them found by probing it today:
null. Null tolerancediffers per model on this API:
google/gemini-2.5-flashacceptsnulleverywhere, whileopenai/gpt-4o-minianddeepseek/deepseek-chatreturn 400 fortemperature,top_p,seedandtoolsset tonull.tools: nullis the worst case — an agent loop that clearstools between turns succeeds on turn 1 and 400s on turn 2.
filter_optional_params()inconst.pydropsNonevalues on top of the baseMaxKBBaseModel.filter_optional_params,and
test_chat_model_omits_unset_params_instead_of_sending_nulllocks it in.HTTP-Referer/X-TitleidentifyMaxKB (the calling app);
X-AIMLAPI-*are the channel headers. They are only attached whenthe configured API URL is
api.aimlapi.com, so changing the URL to another vendor or to aproxy does not leak them, and caller-supplied headers win on a key clash. The shared constant
is never mutated. Covered by three tests, including a regex assertion on the partner id —
a malformed id is not rejected by the API, it just silently loses the attribution.
openaiSDK with plain strings (same shape asopenai_model_provider/model/embedding.py) rather than LangChain'sOpenAIEmbeddings.LangChain tokenises the input into token-id arrays first, and this API's
/v1/embeddingsonly accepts strings — it answers
400 details[].path = "input"for the array form. This isthe one thing a copy of the
regoloembedding class would have got wrong.size/qualitydefault toauto, which means "do not send the parameter". Imagemodels disagree about the allowed values:
openai/gpt-image-1accepts onlylow|medium|highforqualityand 400s onstandard, which is what the other providersin this repo send by default.
GET /v1/models. That endpoint is public on thisAPI and returns 200 for any key, including a bogus one, so it cannot validate a key. The
check posts to
/v1/images/generationswith a placeholder model name instead: an invalid keyreturns 401 and a valid one returns 404, so the key is really validated and no image is
generated (and nothing is billed). Verified both ways.
max_tokensdoes not reliably bound reasoning tokens —
zhipu/glm-5.2returned 849 tokens against a 120cap with
finish_reason: "stop". The new string is translated in zh_CN and zh_Hant.The last commit,
chore(aimlapi): fork-only placement — do not send upstream, only moves theprovider to the front of the two hand-ordered lists. It is meant to be dropped before this is
offered upstream. MaxKB has no "recommended"/featured badge for providers, so none was invented.
Model list
Model names are hardcoded per provider in this repo, so every id shipped here was checked
against
GET https://api.aimlapi.com/v1/models?include=all(id or alias — checking idsalone is not enough) and, for the ids in the list below, called live. 30 distinct ids, 0
failures on the catalog check. Users can still type any other model name by hand.
Two notes for whoever refreshes this list later:
anthropic/claude-sonnet-4.5is valid,-4-5is not.deepseek/deepseek-chatis answered bydeepseek-v4-flash(the responsemodelfield saysso). The list therefore ships
deepseek/deepseek-v4-flash, whose echo matches what was askedfor.
x-ai/grok-4-6echoesgrok-4.6, same model, different spelling.Verification
npm run build(type-check + vite build) inui/: exit 0.python apps/manage.py test <all 12 apps>:baseline on a pristine checkout 14 tests / 5 pass / 9 errors, after this change
21 tests / 12 pass / 9 errors. The 9 errors are identical before and after: the test
loader imports each app's
modelspackage as a test module and Django rejects it(
doesn't declare an explicit app_label). They are unrelated to this change.ruff checkon every added file: clean.msgfmt --checkon the three.pofiles: clean; the new strings were verified to renderunder
zh-hans,zh-hantanden.get_provider(...) .get_model(...), not a mock and not curl), plus tool calling, vision, embeddings and imagegeneration:
Credential validation was also exercised with a deliberately wrong key: LLM and TTI both
return
False(401 from the API), so a bad key is not silently accepted.Not verified
and video generation through asynchronous submit endpoints that do not match MaxKB's
synchronous STT/TTS/TTV classes, so wiring them up needs its own change.
git add -f:.gitignore:189ignoresapps/models_provider/impl/*/icon/, yet every existing provider icon is tracked.models on this API were verified against the catalog only.
Please indicate you've done the following: