diff --git a/README.md b/README.md
index 4fa135fb9a..cd4b658283 100644
--- a/README.md
+++ b/README.md
@@ -1770,6 +1770,16 @@ Models:
**Dashboard behavior:** OpenRouter models are managed from **Available Models**. Manual add, import, and auto-sync all update the same list.
+### Baidu Qianfan / ERNIE
+
+1. Sign up: [Baidu AI Cloud Qianfan](https://cloud.baidu.com/product/wenxinworkshop)
+2. Create a Qianfan API key
+3. Dashboard → Add Provider → Baidu Qianfan
+
+**Use:** `qianfan/ernie-4.5-turbo-128k`, `qianfan/ernie-x1-turbo-32k`, or any Qianfan OpenAI-compatible model ID.
+
+**Dashboard behavior:** Qianfan is registered as an OpenAI-compatible API key provider. Built-in ERNIE models are available immediately, and passthrough model IDs are accepted for newer Qianfan deployments.
+
diff --git a/docs/ENVIRONMENT.md b/docs/ENVIRONMENT.md
index 9a9150f339..c6e20dfd73 100644
--- a/docs/ENVIRONMENT.md
+++ b/docs/ENVIRONMENT.md
@@ -404,6 +404,7 @@ Recognized pattern: `{PROVIDER_ID}_API_KEY`
| `COHERE_API_KEY` | Cohere |
| `NVIDIA_API_KEY` | NVIDIA NIM |
| `NEBIUS_API_KEY` | Nebius (embeddings) |
+| `QIANFAN_API_KEY` | Baidu Qianfan |
> [!TIP]
> Keys set via the Dashboard are stored encrypted in SQLite and take precedence over environment variables.
diff --git a/docs/USER_GUIDE.md b/docs/USER_GUIDE.md
index b1f180b531..4b076e1d00 100644
--- a/docs/USER_GUIDE.md
+++ b/docs/USER_GUIDE.md
@@ -36,6 +36,7 @@ Complete guide for configuring providers, creating combos, integrating CLI tools
| | Cerebras | Pay per use | None | Wafer-scale speed |
| | Cohere | Pay per use | None | Command R+ RAG |
| | NVIDIA NIM | Pay per use | None | Enterprise models |
+| | Baidu Qianfan | Pay per use | None | ERNIE models |
| **💰 CHEAP** | GLM-4.7 | $0.6/1M | Daily 10AM | Budget backup |
| | MiniMax M2.1 | $0.2/1M | 5-hour rolling | Cheapest option |
| | Kimi K2 | $9/mo flat | 10M tokens/mo | Predictable cost |
@@ -191,6 +192,13 @@ Models:
**Use:** `kimi/kimi-latest` — **Pro Tip:** Fixed $9/month for 10M tokens = $0.90/1M effective cost!
+#### Baidu Qianfan / ERNIE
+
+1. Sign up: [Baidu AI Cloud Qianfan](https://cloud.baidu.com/product/wenxinworkshop)
+2. Create a Qianfan API key → Dashboard → Add API Key: Provider: `qianfan`
+
+**Use:** `qianfan/ernie-4.5-turbo-128k`, `qianfan/ernie-x1-turbo-32k`, or another Qianfan OpenAI-compatible model ID.
+
### 🆓 FREE Providers
#### Qoder (8 FREE models)
@@ -590,6 +598,8 @@ For the full environment variable reference, see the [README](../README.md).
**NVIDIA NIM (`nvidia/`)**: `nvidia/nvidia/llama-3.3-70b-instruct`
+**Baidu Qianfan (`qianfan/`)**: `qianfan/ernie-4.5-turbo-128k`, `qianfan/ernie-x1-turbo-32k`
+
---
diff --git a/open-sse/config/providerRegistry.ts b/open-sse/config/providerRegistry.ts
index 657afa57e9..ab960e7790 100644
--- a/open-sse/config/providerRegistry.ts
+++ b/open-sse/config/providerRegistry.ts
@@ -864,6 +864,27 @@ export const REGISTRY: Record = {
models: [{ id: "auto", name: "Auto (Best Available)" }],
},
+ qianfan: {
+ id: "qianfan",
+ alias: "qianfan",
+ format: "openai",
+ executor: "default",
+ baseUrl: "https://qianfan.baidubce.com/v2/chat/completions",
+ modelsUrl: "https://qianfan.baidubce.com/v2/models",
+ authType: "apikey",
+ authHeader: "bearer",
+ defaultContextLength: 128000,
+ models: [
+ { id: "ernie-4.5-turbo-128k", name: "ERNIE 4.5 Turbo 128K" },
+ { id: "ernie-4.5-turbo-32k", name: "ERNIE 4.5 Turbo 32K", contextLength: 32000 },
+ { id: "ernie-4.5-turbo-8k", name: "ERNIE 4.5 Turbo 8K", contextLength: 8000 },
+ { id: "ernie-x1-turbo-32k", name: "ERNIE X1 Turbo 32K", contextLength: 32000 },
+ { id: "ernie-x1-turbo-8k", name: "ERNIE X1 Turbo 8K", contextLength: 8000 },
+ { id: "ernie-4.5-8k-preview", name: "ERNIE 4.5 8K Preview", contextLength: 8000 },
+ ],
+ passthroughModels: true,
+ },
+
glm: {
id: "glm",
alias: "glm",
diff --git a/public/providers/qianfan.svg b/public/providers/qianfan.svg
new file mode 100644
index 0000000000..19ade38113
--- /dev/null
+++ b/public/providers/qianfan.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/shared/components/ProviderIcon.tsx b/src/shared/components/ProviderIcon.tsx
index 1c070fb56c..af59c278da 100644
--- a/src/shared/components/ProviderIcon.tsx
+++ b/src/shared/components/ProviderIcon.tsx
@@ -150,6 +150,7 @@ const KNOWN_SVGS = new Set([
"opencode",
"playht",
"puter",
+ "qianfan",
"scaleway",
"sdwebui",
"synthetic",
diff --git a/src/shared/constants/providers.ts b/src/shared/constants/providers.ts
index 64169da340..084dfb23dd 100644
--- a/src/shared/constants/providers.ts
+++ b/src/shared/constants/providers.ts
@@ -151,6 +151,18 @@ export const APIKEY_PROVIDERS = {
passthroughModels: true,
website: "https://openrouter.ai",
},
+ qianfan: {
+ id: "qianfan",
+ alias: "qianfan",
+ name: "Baidu Qianfan",
+ icon: "cloud",
+ color: "#2468F2",
+ textIcon: "BD",
+ website: "https://cloud.baidu.com/product/wenxinworkshop",
+ passthroughModels: true,
+ apiHint:
+ "Use a Qianfan API key from Baidu AI Cloud. The default endpoint is OpenAI-compatible v2.",
+ },
glm: {
id: "glm",
alias: "glm",
diff --git a/tests/unit/chat-openai-compat-providers.test.ts b/tests/unit/chat-openai-compat-providers.test.ts
index 7e2c96c206..baf02ca8f6 100644
--- a/tests/unit/chat-openai-compat-providers.test.ts
+++ b/tests/unit/chat-openai-compat-providers.test.ts
@@ -8,6 +8,7 @@ import { APIKEY_PROVIDERS } from "../../src/shared/constants/providers.ts";
const CHAT_OPENAI_COMPAT_PROVIDER_IDS = [
"deepinfra",
"vercel-ai-gateway",
+ "qianfan",
"lambda-ai",
"sambanova",
"nscale",
diff --git a/tests/unit/qianfan-provider.test.ts b/tests/unit/qianfan-provider.test.ts
new file mode 100644
index 0000000000..d0eede12fc
--- /dev/null
+++ b/tests/unit/qianfan-provider.test.ts
@@ -0,0 +1,69 @@
+import test from "node:test";
+import assert from "node:assert/strict";
+import { existsSync } from "node:fs";
+import { join } from "node:path";
+
+import { REGISTRY, getRegistryEntry } from "../../open-sse/config/providerRegistry.ts";
+import { PROVIDERS } from "../../open-sse/config/constants.ts";
+import { getModelsByProviderId, isValidModel } from "../../src/shared/constants/models.ts";
+import { APIKEY_PROVIDERS } from "../../src/shared/constants/providers.ts";
+import { validateBody, createProviderSchema } from "../../src/shared/validation/schemas.ts";
+
+test("qianfan registers Baidu ERNIE as an OpenAI-compatible API key provider", () => {
+ const registryEntry = getRegistryEntry("qianfan");
+
+ assert.ok(registryEntry, "qianfan should be in the provider registry");
+ assert.equal(registryEntry, REGISTRY.qianfan);
+ assert.equal(registryEntry.id, "qianfan");
+ assert.equal(registryEntry.alias, "qianfan");
+ assert.equal(registryEntry.format, "openai");
+ assert.equal(registryEntry.executor, "default");
+ assert.equal(registryEntry.authType, "apikey");
+ assert.equal(registryEntry.authHeader, "bearer");
+ assert.equal(registryEntry.baseUrl, "https://qianfan.baidubce.com/v2/chat/completions");
+ assert.equal(registryEntry.defaultContextLength, 128000);
+ assert.equal(registryEntry.passthroughModels, true);
+
+ assert.ok(APIKEY_PROVIDERS.qianfan, "qianfan should be visible in API key providers");
+ assert.equal(APIKEY_PROVIDERS.qianfan.name, "Baidu Qianfan");
+ assert.equal(APIKEY_PROVIDERS.qianfan.website, "https://cloud.baidu.com/product/wenxinworkshop");
+ assert.equal(APIKEY_PROVIDERS.qianfan.passthroughModels, true);
+
+ assert.equal(PROVIDERS.qianfan.baseUrl, registryEntry.baseUrl);
+ assert.equal(PROVIDERS.qianfan.format, "openai");
+ assert.equal("modelsUrl" in PROVIDERS.qianfan, false);
+ assert.equal("passthroughModels" in PROVIDERS.qianfan, false);
+});
+
+test("qianfan exposes ERNIE chat models in the local model catalog", () => {
+ const models = getModelsByProviderId("qianfan");
+ const modelIds = models.map((model) => model.id);
+
+ assert.ok(modelIds.includes("ernie-4.5-turbo-128k"));
+ assert.ok(modelIds.includes("ernie-x1-turbo-32k"));
+ assert.ok(modelIds.includes("ernie-4.5-8k-preview"));
+ assert.ok(models.every((model) => typeof model.name === "string" && model.name.length > 0));
+});
+
+test("qianfan accepts known and passthrough model IDs", () => {
+ assert.equal(isValidModel("qianfan", "ernie-4.5-turbo-128k"), true);
+ assert.equal(isValidModel("qianfan", "future-qianfan-openai-compatible-model"), true);
+});
+
+test("qianfan provider creation schema accepts API-key connections", () => {
+ const validation = validateBody(createProviderSchema, {
+ provider: "qianfan",
+ apiKey: "bce-v3/test-key",
+ name: "Baidu Qianfan",
+ });
+
+ assert.equal(validation.success, true);
+ if (validation.success) {
+ assert.equal(validation.data.provider, "qianfan");
+ assert.equal(validation.data.apiKey, "bce-v3/test-key");
+ }
+});
+
+test("qianfan has a static provider icon asset", () => {
+ assert.equal(existsSync(join(process.cwd(), "public/providers/qianfan.svg")), true);
+});