Files
ragflow/web/src/services/llm-service.ts
Eugene 6b11f62391 feat: add AIMLAPI (aimlapi.com) as a model provider (#17311)
### Summary

This PR adds **aimlapi.com** as a model provider, so a RAGFlow user can
enter one API key in the model settings and use AIMLAPI's models across
the app. AIMLAPI ([aimlapi.com](https://aimlapi.com)) is an
OpenAI-compatible aggregator that serves 700+ models (LLM, embedding,
vision, TTS, ASR) from many providers behind a single API.

The change mirrors the repo's existing "add provider" pattern (e.g.
FuturMix / OpenRouter): provider logic lives in the same files those
providers use, and shared / UI files get only registration entries.

**Backend**
- `conf/llm_factories.json` — the `aimlapi.com` factory entry.
- `rag/llm/__init__.py`, `rag/llm/{chat,embedding,cv}_model.py` —
LiteLLM adapters (chat, embedding, image2text) with a production base
URL, overridable via `AIMLAPI_API_URL`.
- `rag/llm/model_meta.py` — an `AIMLAPI` model-meta so the provider
lists its full `/v1/models` catalog dynamically (classified by the
endpoint `type`), the same way OpenRouter does.
- `api/apps/restful_apis/aimlapi_api.py` — an optional "Get API key"
flow using AIMLAPI's agent-authorization (OAuth 2.0 Device Authorization
Grant, RFC 8628). The device code is kept server-side (Redis); only the
issued key reaches the browser.

**Frontend (`web/`)**
- Provider registration (constant, icon allowlist, brand logo), the
model picker (`LIST_MODEL_PROVIDERS` + a `buildLocalConfig` entry), and
the "Get API key" button in the provider dialog. Locales added to `en`
and `zh`.

**Configuration** — production defaults are compiled in; endpoints and
the partner id are overridable through `AIMLAPI_*` environment
variables, so the same build works across environments.

**Testing** — the `web` build passes; chat, embedding and dynamic model
listing were smoke-tested against the live API.
2026-07-24 22:50:14 +08:00

112 lines
2.2 KiB
TypeScript

import api from '@/utils/api';
import { registerNextServer } from '@/utils/register-server';
const {
listAllAddedModels,
defaultModel,
listProviders,
addProvider,
addProviderInstance,
verifyProviderConnection,
listProviderModels,
listProviderInstances,
listInstanceModels,
showProviderInstance,
addInstanceModel,
editInstanceModel,
deleteProviderInstance,
updateModelStatus,
patchInstanceModel,
deleteInstanceModels,
updateProviderInstance,
aimlapiAuthorizeStart,
aimlapiAuthorizePoll,
} = api;
const methods = {
listAllAddedModels: {
url: listAllAddedModels,
method: 'get',
},
listDefaultModels: {
url: defaultModel,
method: 'get',
},
setDefaultModel: {
url: defaultModel,
method: 'patch',
},
listProviders: {
url: listProviders,
method: 'get',
},
addProvider: {
url: addProvider,
method: 'put',
},
addProviderInstance: {
url: addProviderInstance,
method: 'post',
},
verifyProviderConnection: {
url: verifyProviderConnection,
method: 'post',
},
listProviderModels: {
url: listProviderModels,
method: 'get',
},
listProviderInstances: {
url: listProviderInstances,
method: 'get',
},
listInstanceModels: {
url: listInstanceModels,
method: 'get',
},
showProviderInstance: {
url: showProviderInstance,
method: 'get',
},
addInstanceModel: {
url: addInstanceModel,
method: 'post',
},
editInstanceModel: {
url: editInstanceModel,
method: 'put',
},
deleteProviderInstance: {
url: deleteProviderInstance,
method: 'delete',
},
updateModelStatus: {
url: updateModelStatus,
method: 'patch',
},
patchInstanceModel: {
url: patchInstanceModel,
method: 'patch',
},
deleteInstanceModels: {
url: deleteInstanceModels,
method: 'delete',
},
updateProviderInstance: {
url: updateProviderInstance,
method: 'put',
},
aimlapiAuthorizeStart: {
url: aimlapiAuthorizeStart,
method: 'post',
},
aimlapiAuthorizePoll: {
url: aimlapiAuthorizePoll,
method: 'post',
},
} as const;
const llmService = registerNextServer<keyof typeof methods>(methods);
export default llmService;