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
54 changes: 54 additions & 0 deletions docs/src/content/docs/configuration/minimax.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
title: MiniMax
sidebar:
order: 50
---

import { FileTree } from "@astrojs/starlight/components"
import { Steps } from "@astrojs/starlight/components"
import { Tabs, TabItem } from "@astrojs/starlight/components"
import { Image } from "astro:assets"
import LLMProviderFeatures from "../../../components/LLMProviderFeatures.astro"

`minimax` is the [MiniMax AI (https://platform.minimaxi.com/)](https://platform.minimaxi.com/) chat model provider.
It uses the `MINIMAX_API_...` environment variables.

<Steps>

<ol>

<li>
Create a new API key from the [MiniMax API Keys
portal](https://platform.minimaxi.com/user-center/basic-information/interface-key).
</li>

<li>

Update the `.env` file with the API key.

```txt title=".env"
MINIMAX_API_KEY=eyJh...
```

</li>

<li>

Set the `model` field in `script` to use a MiniMax model.

```js 'model: "minimax:MiniMax-M2.7"'
script({
model: "minimax:MiniMax-M2.7",
...
})
```

Available models: `MiniMax-M2.7`, `MiniMax-M2.7-highspeed`, `MiniMax-M2.5`, `MiniMax-M2.5-highspeed`.

</li>

</ol>

</Steps>

<LLMProviderFeatures provider="minimax" />
3 changes: 3 additions & 0 deletions packages/core/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ export const ALIBABA_BASE =
"https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
export const MISTRAL_API_BASE = "https://api.mistral.ai/v1"
export const DEEPSEEK_API_BASE = "https://api.deepseek.com/v1"
export const MINIMAX_API_BASE = "https://api.minimax.io/v1"
export const WHISPERASR_API_BASE = "http://localhost:9000"
export const WINDOWS_AI_API_BASE = "http://127.0.0.1:5272/v1"
export const DOCKER_MODEL_RUNNER_API_BASE =
Expand Down Expand Up @@ -193,6 +194,7 @@ export const MODEL_PROVIDER_JAN = "jan"
export const MODEL_PROVIDER_SGLANG = "sglang"
export const MODEL_PROVIDER_VLLM = "vllm"
export const MODEL_PROVIDER_DEEPSEEK = "deepseek"
export const MODEL_PROVIDER_MINIMAX = "minimax"
export const MODEL_PROVIDER_WHISPERASR = "whisperasr"
export const MODEL_PROVIDER_WINDOWS_AI = "windows"
export const MODEL_PROVIDER_DOCKER_MODEL_RUNNER = "docker"
Expand Down Expand Up @@ -462,3 +464,4 @@ export const BOX_LEFT_AND_DOWN = "╮"
export const BOX_LEFT_AND_UP = "╯"

export const GITHUB_ASSET_URL_RX = /^https:\/\/github\.com\/.*\/assets\/.*$/i

24 changes: 24 additions & 0 deletions packages/core/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import {
MODEL_PROVIDER_ANTHROPIC_BEDROCK,
MODEL_PROVIDER_DEEPSEEK,
DEEPSEEK_API_BASE,
MODEL_PROVIDER_MINIMAX,
MINIMAX_API_BASE,
MODEL_PROVIDER_WHISPERASR,
WHISPERASR_API_BASE,
MODEL_PROVIDER_ECHO,
Expand Down Expand Up @@ -656,6 +658,27 @@ export async function parseTokenFromEnv(
}
}

if (provider === MODEL_PROVIDER_MINIMAX) {
dbg(`processing ${MODEL_PROVIDER_MINIMAX}`)
const base =
findEnvVar(env, "MINIMAX", BASE_SUFFIX)?.value || MINIMAX_API_BASE
if (!URL.canParse(base)) {
throw new Error(`${base} must be a valid URL`)
}
const token = env.MINIMAX_API_KEY
if (!token) {
throw new Error("MINIMAX_API_KEY not configured")
}
return {
provider,
model,
base,
token,
type: "openai",
source: "env: MINIMAX_API_...",
}
}

if (provider === MODEL_PROVIDER_WHISPERASR) {
dbg(`processing ${MODEL_PROVIDER_WHISPERASR}`)
const base =
Expand Down Expand Up @@ -879,3 +902,4 @@ export async function parseTokenFromEnv(
return b
}
}

40 changes: 40 additions & 0 deletions packages/core/src/llms.json
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,29 @@
}
}
},
{
"id": "minimax",
"detail": "MiniMax AI",
"url": "https://platform.minimaxi.com/",
"bearerToken": true,
"listModels": false,
"prediction": false,
"aliases": {
"large": "MiniMax-M2.7",
"small": "MiniMax-M2.7-highspeed"
},
"env": {
"MINIMAX_API_KEY": {
"description": "MiniMax API key",
"required": true,
"secret": true
},
"MINIMAX_API_BASE": {
"description": "MiniMax API base URL",
"format": "url"
}
}
},
{
"id": "lmstudio",
"detail": "LM Studio local server",
Expand Down Expand Up @@ -1340,6 +1363,23 @@
"price_per_million_input_tokens": 0.14,
"price_per_million_output_tokens": 0.28,
"input_cache_token_rebate": 0.1
},
"minimax:MiniMax-M2.7": {
"price_per_million_input_tokens": 1,
"price_per_million_output_tokens": 10
},
"minimax:MiniMax-M2.7-highspeed": {
"price_per_million_input_tokens": 1,
"price_per_million_output_tokens": 10
},
"minimax:MiniMax-M2.5": {
"price_per_million_input_tokens": 0.5,
"price_per_million_output_tokens": 5
},
"minimax:MiniMax-M2.5-highspeed": {
"price_per_million_input_tokens": 0.5,
"price_per_million_output_tokens": 5
}
}
}

85 changes: 85 additions & 0 deletions packages/core/src/minimax.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { describe, test, beforeEach } from "node:test"
import assert from "node:assert/strict"
import { parseModelIdentifier } from "./models"
import { MODEL_PROVIDER_MINIMAX, MINIMAX_API_BASE } from "./constants"
import { defaultModelConfigurations } from "./llms"
import { TestHost } from "./testhost"
import { resolveLanguageModel } from "./lm"

describe("MiniMax provider", () => {
beforeEach(async () => {
TestHost.install()
})

describe("parseModelIdentifier", () => {
test("minimax:MiniMax-M2.7", () => {
const { provider, model, family } =
parseModelIdentifier("minimax:MiniMax-M2.7")
assert.equal(provider, MODEL_PROVIDER_MINIMAX)
assert.equal(model, "MiniMax-M2.7")
assert.equal(family, "MiniMax-M2.7")
})

test("minimax:MiniMax-M2.7-highspeed", () => {
const { provider, model, family } = parseModelIdentifier(
"minimax:MiniMax-M2.7-highspeed"
)
assert.equal(provider, MODEL_PROVIDER_MINIMAX)
assert.equal(model, "MiniMax-M2.7-highspeed")
assert.equal(family, "MiniMax-M2.7-highspeed")
})

test("minimax:MiniMax-M2.5", () => {
const { provider, model, family } =
parseModelIdentifier("minimax:MiniMax-M2.5")
assert.equal(provider, MODEL_PROVIDER_MINIMAX)
assert.equal(model, "MiniMax-M2.5")
assert.equal(family, "MiniMax-M2.5")
})
})

describe("constants", () => {
test("MODEL_PROVIDER_MINIMAX is defined", () => {
assert.equal(MODEL_PROVIDER_MINIMAX, "minimax")
})

test("MINIMAX_API_BASE is correct", () => {
assert.equal(MINIMAX_API_BASE, "https://api.minimax.io/v1")
})
})

describe("llms.json configuration", () => {
test("minimax provider is registered", () => {
const configs = defaultModelConfigurations()
assert(configs)
// minimax should contribute aliases for large and small
const largeConfig = configs.large
assert(largeConfig)
assert(largeConfig.candidates)
const hasMinimax = largeConfig.candidates.some((c: string) =>
c.startsWith("minimax:")
)
assert(hasMinimax, "minimax should be in large candidates")
})

test("minimax small alias is registered", () => {
const configs = defaultModelConfigurations()
const smallConfig = configs.small
assert(smallConfig)
assert(smallConfig.candidates)
const hasMinimax = smallConfig.candidates.some((c: string) =>
c.startsWith("minimax:")
)
assert(hasMinimax, "minimax should be in small candidates")
})
})

describe("resolveLanguageModel", () => {
test("minimax resolves to OpenAI-compatible model", () => {
const lm = resolveLanguageModel(MODEL_PROVIDER_MINIMAX)
assert(lm)
assert(lm.completer)
assert.equal(lm.id, MODEL_PROVIDER_MINIMAX)
})
})
})
53 changes: 53 additions & 0 deletions packages/core/src/minimax_integration.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { describe, test, beforeEach } from "node:test"
import assert from "node:assert/strict"
import { parseTokenFromEnv } from "./env"
import { MODEL_PROVIDER_MINIMAX, MINIMAX_API_BASE } from "./constants"
import { TestHost } from "./testhost"

describe("MiniMax integration", () => {
beforeEach(async () => {
TestHost.install()
})

describe("parseTokenFromEnv", () => {
test("resolves MINIMAX_API_KEY and base URL", async () => {
const env: Record<string, string> = {
MINIMAX_API_KEY: "test-minimax-key",
}
const result = await parseTokenFromEnv(
env,
"minimax:MiniMax-M2.7",
{}
)
assert(result)
assert.equal(result.provider, MODEL_PROVIDER_MINIMAX)
assert.equal(result.model, "MiniMax-M2.7")
assert.equal(result.token, "test-minimax-key")
assert.equal(result.base, MINIMAX_API_BASE)
assert.equal(result.type, "openai")
assert.equal(result.source, "env: MINIMAX_API_...")
})

test("uses custom MINIMAX_API_BASE when set", async () => {
const env: Record<string, string> = {
MINIMAX_API_KEY: "test-key",
MINIMAX_API_BASE: "https://custom.minimax.io/v1",
}
const result = await parseTokenFromEnv(
env,
"minimax:MiniMax-M2.5",
{}
)
assert(result)
assert.equal(result.base, "https://custom.minimax.io/v1")
})

test("throws when MINIMAX_API_KEY is missing", async () => {
const env: Record<string, string> = {}
await assert.rejects(
() => parseTokenFromEnv(env, "minimax:MiniMax-M2.7", {}),
{ message: "MINIMAX_API_KEY not configured" }
)
})
})
})