modelmix

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

ModelMix Library Skill

ModelMix库使用指南

Overview

概述

ModelMix is a Node.js library that provides a unified fluent API to interact with multiple AI LLM providers. It handles automatic fallback between models, round-robin load balancing, structured JSON output, streaming, MCP tool integration, rate limiting, and token tracking.
Use this skill when:
  • Integrating one or more AI models into a Node.js project
  • Chaining models with automatic fallback
  • Extracting structured JSON from LLMs
  • Adding MCP tools or custom tools to models
  • Working with templates and file-based prompts
Do NOT use this skill for:
  • Python or non-Node.js projects
  • Direct HTTP calls to LLM APIs (use ModelMix instead)
ModelMix是一款Node.js库,提供统一的流畅式API来与多个AI大语言模型(LLM)提供商交互。它支持模型间自动降级、轮询负载均衡、结构化JSON输出、流式传输、MCP工具集成、速率限制以及token追踪。
以下场景适合使用本指南:
  • 在Node.js项目中集成一个或多个AI模型
  • 为模型链配置自动降级机制
  • 从LLM提取结构化JSON数据
  • 为模型添加MCP工具或自定义工具
  • 使用模板和基于文件的提示词
以下场景请勿使用本指南:
  • Python或非Node.js项目
  • 直接通过HTTP调用LLM API(请使用ModelMix替代)

Common Tasks

常见任务

Installation

安装

bash
npm install modelmix
bash
npm install modelmix

Core Concepts

核心概念

Import

导入

javascript
import { ModelMix } from 'modelmix';
javascript
import { ModelMix } from 'modelmix';

Creating an Instance

创建实例

javascript
// Static factory (preferred)
const model = ModelMix.new();

// With global options
const model = ModelMix.new({
    options: { max_tokens: 4096, temperature: 0.7 },
    config: {
        system: "You are a helpful assistant.",
        max_history: 5,
        debug: 0,           // 0=silent, 1=minimal, 2=summary, 3=full (no truncate), 4=verbose
        roundRobin: false    // false=fallback, true=rotate models
    }
});
javascript
// 静态工厂方法(推荐)
const model = ModelMix.new();

// 带全局配置选项
const model = ModelMix.new({
    options: { max_tokens: 4096, temperature: 0.7 },
    config: {
        system: "你是一个乐于助人的助手。",
        max_history: 5,
        debug: 0,           // 0=静默, 1=极简, 2=摘要, 3=完整(不截断), 4=详细
        roundRobin: false    // false=降级模式, true=模型轮询
    }
});

Attaching Models (Fluent Chain)

关联模型(链式调用)

Chain shorthand methods to attach providers. First model is primary; others are fallbacks:
javascript
const model = ModelMix.new()
    .sonnet46()        // primary
    .gpt52()        // fallback 1
    .gemini3flash()    // fallback 2
    .addText("Hello!")
If
sonnet45
fails, it automatically tries
gpt5mini
, then
gemini3flash
.
通过链式简写方法关联模型提供商。第一个模型为主模型,后续为降级备选模型:
javascript
const model = ModelMix.new()
    .sonnet46()        // 主模型
    .gpt52()        // 降级备选1
    .gemini3flash()    // 降级备选2
    .addText("Hello!")
如果
sonnet45
调用失败,会自动尝试
gpt5mini
,再尝试
gemini3flash

Available Model Shorthands

可用模型简写方法

  • OpenAI:
    gpt52
    gpt51
    gpt5
    gpt5mini
    gpt5nano
    gpt41
    gpt41mini
    gpt41nano
  • Anthropic:
    opus46
    opus45
    sonnet46
    sonnet45
    haiku45
    haiku35
    (thinking variants: add
    think
    suffix)
  • Google:
    gemini3pro
    gemini3flash
    gemini25pro
    gemini25flash
  • Grok:
    grok4
    grok41
    (thinking variant available)
  • Perplexity:
    sonar
    sonarPro
  • Groq:
    scout
    maverick
  • Together:
    qwen3
    kimiK2
  • Multi-provider:
    deepseekR1
    gptOss
  • MiniMax:
    minimaxM21
  • Fireworks:
    deepseekV32
    GLM47
Each method is called as
mix.methodName()
and accepts optional
{ options, config }
to override per-model settings.
  • OpenAI:
    gpt52
    gpt51
    gpt5
    gpt5mini
    gpt5nano
    gpt41
    gpt41mini
    gpt41nano
  • Anthropic:
    opus46
    opus45
    sonnet46
    sonnet45
    haiku45
    haiku35
    (带思考过程的变体:添加
    think
    后缀)
  • Google:
    gemini3pro
    gemini3flash
    gemini25pro
    gemini25flash
  • Grok:
    grok4
    grok41
    (支持带思考过程的变体)
  • Perplexity:
    sonar
    sonarPro
  • Groq:
    scout
    maverick
  • Together:
    qwen3
    kimiK2
  • 多提供商:
    deepseekR1
    gptOss
  • MiniMax:
    minimaxM21
  • Fireworks:
    deepseekV32
    GLM47
每个方法通过
mix.methodName()
调用,可传入可选的
{ options, config }
参数来覆盖模型级配置。

Common Tasks

常见任务

Get a text response

获取文本响应

javascript
const answer = await ModelMix.new()
    .gpt5mini()
    .addText("What is the capital of France?")
    .message();
javascript
const answer = await ModelMix.new()
    .gpt5mini()
    .addText("法国的首都是什么?")
    .message();

Get structured JSON

获取结构化JSON

javascript
const result = await ModelMix.new()
    .gpt5mini()
    .addText("Name and capital of 3 South American countries.")
    .json(
        { countries: [{ name: "", capital: "" }] },                    // schema example
        { countries: [{ name: "country name", capital: "in uppercase" }] }, // descriptions
        { addNote: true }                                               // options
    );
// result.countries → [{ name: "Brazil", capital: "BRASILIA" }, ...]
json()
signature:
json(schemaExample, schemaDescription?, { addSchema, addExample, addNote }?)
javascript
const result = await ModelMix.new()
    .gpt5mini()
    .addText("列出3个南美国家的名称及首都。")
    .json(
        { countries: [{ name: "", capital: "" }] },                    // 示例 schema
        { countries: [{ name: "国家名称", capital: "大写格式" }] }, // 字段描述
        { addNote: true }                                               // 选项
    );
// result.countries → [{ name: "Brazil", capital: "BRASILIA" }, ...]
json()
方法签名:
json(schemaExample, schemaDescription?, { addSchema, addExample, addNote }?)

Enhanced descriptors

增强型描述符

Descriptions can be strings or descriptor objects with metadata:
javascript
const result = await model.json(
    { name: 'martin', age: 22, sex: 'Male' },
    {
        name: { description: 'Name of the actor', required: false },
        age: 'Age of the actor',                                     // string still works
        sex: { description: 'Gender', enum: ['Male', 'Female', null] }
    }
);
Descriptor properties:
  • description
    (string) — field description
  • required
    (boolean, default
    true
    ) — if
    false
    : removed from required array, type becomes nullable
  • enum
    (array) — allowed values; if includes
    null
    , type auto-becomes nullable
  • default
    (any) — default value
字段描述可以是字符串或包含元数据的描述符对象
javascript
const result = await model.json(
    { name: 'martin', age: 22, sex: 'Male' },
    {
        name: { description: '演员姓名', required: false },
        age: '演员年龄',                                     // 字符串格式依然有效
        sex: { description: '性别', enum: ['Male', 'Female', null] }
    }
);
描述符属性:
  • description
    (字符串)—— 字段说明
  • required
    (布尔值,默认
    true
    )—— 若为
    false
    :从必填数组中移除,类型变为可空
  • enum
    (数组)—— 允许的取值;若包含
    null
    ,类型自动变为可空
  • default
    (任意类型)—— 默认值

Array auto-wrap

数组自动包装

Top-level arrays are auto-wrapped as
{ out: [...] }
for better LLM compatibility, and unwrapped on return:
javascript
const result = await model.json([{ name: 'martin' }]);
// result is an array: [{ name: "Martin" }, { name: "Carlos" }, ...]
顶级数组会自动包装为
{ out: [...] }
以提升LLM兼容性,返回时会自动解包:
javascript
const result = await model.json([{ name: 'martin' }]);
// result 为数组格式: [{ name: "Martin" }, { name: "Carlos" }, ...]

Stream a response

流式响应

javascript
await ModelMix.new()
    .gpt5mini()
    .addText("Tell me a story.")
    .stream(({ delta, message }) => {
        process.stdout.write(delta);
    });
javascript
await ModelMix.new()
    .gpt5mini()
    .addText("给我讲一个故事。")
    .stream(({ delta, message }) => {
        process.stdout.write(delta);
    });

Get raw response (tokens, thinking, tool calls)

获取原始响应(token、思考过程、工具调用)

javascript
const raw = await ModelMix.new()
    .sonnet45think()
    .addText("Solve this step by step: 2+2*3")
    .raw();
// raw.message, raw.think, raw.tokens, raw.toolCalls, raw.response
javascript
const raw = await ModelMix.new()
    .sonnet45think()
    .addText("一步步解决这个问题:2+2*3")
    .raw();
// raw.message, raw.think, raw.tokens, raw.toolCalls, raw.response

Access full response after
message()
or
json()
with
lastRaw

通过
lastRaw
获取
message()
json()
后的完整响应

After calling
message()
,
json()
,
block()
, or
stream()
, use
lastRaw
to access the complete response (tokens, thinking, tool calls, etc.). It has the same structure as
raw()
.
javascript
const model = ModelMix.new().gpt5mini().addText("Hello!");
const text = await model.message();
console.log(model.lastRaw.tokens);
// { input: 122, output: 86, total: 541, cost: 0.000319 }
console.log(model.lastRaw.think);    // reasoning content (if available)
console.log(model.lastRaw.response); // raw API response
调用
message()
json()
block()
stream()
后,可通过
lastRaw
获取完整响应数据(token、思考过程、工具调用等)。其结构与
raw()
返回结果一致。
javascript
const model = ModelMix.new().gpt5mini().addText("你好!");
const text = await model.message();
console.log(model.lastRaw.tokens);
// { input: 122, output: 86, total: 541, cost: 0.000319 }
console.log(model.lastRaw.think);    // 推理内容(若可用)
console.log(model.lastRaw.response); // 原始API响应

Add images

添加图片

javascript
const model = ModelMix.new().sonnet45();
model.addImage('./photo.jpg');                         // from file
model.addImageFromUrl('https://example.com/img.png');  // from URL
model.addText('Describe this image.');
const description = await model.message();
javascript
const model = ModelMix.new().sonnet45();
model.addImage('./photo.jpg');                         // 从本地文件添加
model.addImageFromUrl('https://example.com/img.png');  // 从URL添加
model.addText('描述这张图片。');
const description = await model.message();

Use templates with placeholders

使用带占位符的模板

javascript
const model = ModelMix.new().gpt5mini();
model.setSystemFromFile('./prompts/system.md');
model.addTextFromFile('./prompts/task.md');
model.replace({
    '{role}': 'data analyst',
    '{language}': 'Spanish'
});
model.replaceKeyFromFile('{code}', './src/utils.js');
console.log(await model.message());
javascript
const model = ModelMix.new().gpt5mini();
model.setSystemFromFile('./prompts/system.md');
model.addTextFromFile('./prompts/task.md');
model.replace({
    '{role}': '数据分析师',
    '{language}': '西班牙语'
});
model.replaceKeyFromFile('{code}', './src/utils.js');
console.log(await model.message());

Round-robin load balancing

轮询负载均衡

javascript
const pool = ModelMix.new({ config: { roundRobin: true } })
    .gpt5mini()
    .sonnet45()
    .gemini3flash();

// Each call rotates to the next model
const r1 = await pool.new().addText("Request 1").message();
const r2 = await pool.new().addText("Request 2").message();
javascript
const pool = ModelMix.new({ config: { roundRobin: true } })
    .gpt5mini()
    .sonnet45()
    .gemini3flash();

// 每次调用会切换到下一个模型
const r1 = await pool.new().addText("请求1").message();
const r2 = await pool.new().addText("请求2").message();

MCP integration (external tools)

MCP集成(外部工具)

javascript
const model = ModelMix.new({ config: { max_history: 10 } }).gpt5nano();
model.setSystem('You are an assistant. Today is ' + new Date().toISOString());
await model.addMCP('@modelcontextprotocol/server-brave-search');
model.addText('Use Internet: What is the latest news about AI?');
console.log(await model.message());
Requires
BRAVE_API_KEY
in
.env
for Brave Search MCP.
javascript
const model = ModelMix.new({ config: { max_history: 10 } }).gpt5nano();
model.setSystem('你是一个助手。今天的日期是 ' + new Date().toISOString());
await model.addMCP('@modelcontextprotocol/server-brave-search');
model.addText('使用互联网查询:AI领域的最新资讯是什么?');
console.log(await model.message());
使用Brave Search MCP需要在
.env
文件中配置
BRAVE_API_KEY

Custom local tools (addTool)

自定义本地工具(addTool)

javascript
const model = ModelMix.new({ config: { max_history: 10 } }).gpt5mini();

model.addTool({
    name: "get_weather",
    description: "Get weather for a city",
    inputSchema: {
        type: "object",
        properties: { city: { type: "string" } },
        required: ["city"]
    }
}, async ({ city }) => {
    return `The weather in ${city} is sunny, 25C`;
});

model.addText("What's the weather in Tokyo?");
console.log(await model.message());
javascript
const model = ModelMix.new({ config: { max_history: 10 } }).gpt5mini();

model.addTool({
    name: "get_weather",
    description: "获取城市天气",
    inputSchema: {
        type: "object",
        properties: { city: { type: "string" } },
        required: ["city"]
    }
}, async ({ city }) => {
    return `${city}的天气是晴天,气温25摄氏度`;
});

model.addText("东京的天气怎么样?");
console.log(await model.message());

Rate limiting (Bottleneck)

速率限制(Bottleneck)

javascript
const model = ModelMix.new({
    config: {
        bottleneck: {
            maxConcurrent: 4,
            minTime: 1000
        }
    }
}).gpt5mini();
javascript
const model = ModelMix.new({
    config: {
        bottleneck: {
            maxConcurrent: 4,
            minTime: 1000
        }
    }
}).gpt5mini();

Debug mode

调试模式

javascript
const model = ModelMix.new({
    config: { debug: 2 }  // 0=silent, 1=minimal, 2=summary, 3=full (no truncate), 4=verbose
}).gpt5mini();
For full debug output, also set the env:
DEBUG=ModelMix* node script.js
javascript
const model = ModelMix.new({
    config: { debug: 2 }  // 0=静默, 1=极简, 2=摘要, 3=完整(不截断), 4=详细
}).gpt5mini();
若要获取完整调试输出,还需设置环境变量:
DEBUG=ModelMix* node script.js

Use free-tier models

使用免费层模型

javascript
// These use providers with free quotas (OpenRouter, Groq, Cerebras)
const model = ModelMix.new()
    .gptOss()
    .kimiK2()
    .deepseekR1()
    .hermes3()
    .addText("What is the capital of France?");
console.log(await model.message());
javascript
// 这些模型使用提供免费额度的提供商(OpenRouter、Groq、Cerebras)
const model = ModelMix.new()
    .gptOss()
    .kimiK2()
    .deepseekR1()
    .hermes3()
    .addText("法国的首都是什么?");
console.log(await model.message());

Conversation history

对话历史

javascript
const chat = ModelMix.new({ config: { max_history: 10 } }).gpt5mini();
chat.addText("My name is Martin.");
await chat.message();
chat.addText("What's my name?");
const reply = await chat.message();  // "Martin"
javascript
const chat = ModelMix.new({ config: { max_history: 10 } }).gpt5mini();
chat.addText("我的名字是Martin。");
await chat.message();
chat.addText("我叫什么名字?");
const reply = await chat.message();  // "Martin"

Agent Usage Rules

Agent使用规则

  • Always check
    package.json
    for
    modelmix
    before running
    npm install
    .
  • Use
    ModelMix.new()
    static factory to create instances (not
    new ModelMix()
    ).
  • Store API keys in
    .env
    and load with
    dotenv/config
    or
    process.loadEnvFile()
    . Never hardcode keys.
  • Chain models for resilience: primary model first, fallbacks after.
  • When using MCP tools or
    addTool()
    , set
    max_history
    to at least 3.
  • Use
    .json()
    for structured output instead of parsing text manually. Use descriptor objects
    { description, required, enum, default }
    in descriptions for richer schema control.
  • Use
    .message()
    for simple text,
    .raw()
    when you need tokens/thinking/toolCalls.
  • For thinking models, append
    think
    to the method name (e.g.
    sonnet45think()
    ).
  • Template placeholders use
    {key}
    syntax in both system prompts and user messages.
  • The library uses CommonJS internally (
    require
    ) but supports ESM import via
    { ModelMix }
    .
  • Available provider Mix classes for custom setups:
    MixOpenAI
    ,
    MixAnthropic
    ,
    MixGoogle
    ,
    MixPerplexity
    ,
    MixGroq
    ,
    MixTogether
    ,
    MixGrok
    ,
    MixOpenRouter
    ,
    MixOllama
    ,
    MixLMStudio
    ,
    MixCustom
    ,
    MixCerebras
    ,
    MixFireworks
    ,
    MixMiniMax
    .
  • 运行
    npm install
    前,请先检查
    package.json
    中是否已存在
    modelmix
    依赖。
  • 使用
    ModelMix.new()
    静态工厂方法创建实例(而非
    new ModelMix()
    )。
  • 将API密钥存储在
    .env
    文件中,通过
    dotenv/config
    process.loadEnvFile()
    加载。切勿硬编码密钥。
  • 通过链式调用模型来提升可靠性:主模型在前,降级备选模型在后。
  • 使用MCP工具或
    addTool()
    时,需将
    max_history
    设置为至少3。
  • 如需结构化输出,请使用
    .json()
    方法而非手动解析文本。在描述中使用描述符对象
    { description, required, enum, default }
    来实现更精细的schema控制。
  • 简单文本响应使用
    .message()
    ,需要token/思考过程/工具调用数据时使用
    .raw()
  • 对于支持思考过程的模型,在方法名后追加
    think
    后缀(例如
    sonnet45think()
    )。
  • 模板占位符在系统提示词和用户消息中均使用
    {key}
    语法。
  • 该库内部使用CommonJS(
    require
    ),但支持通过
    { ModelMix }
    进行ESM导入。
  • 自定义配置可用的提供商Mix类:
    MixOpenAI
    ,
    MixAnthropic
    ,
    MixGoogle
    ,
    MixPerplexity
    ,
    MixGroq
    ,
    MixTogether
    ,
    MixGrok
    ,
    MixOpenRouter
    ,
    MixOllama
    ,
    MixLMStudio
    ,
    MixCustom
    ,
    MixCerebras
    ,
    MixFireworks
    ,
    MixMiniMax

API Quick Reference

API速查

MethodReturnsDescription
.addText(text)
this
Add user message
.addTextFromFile(path)
this
Add user message from file
.setSystem(text)
this
Set system prompt
.setSystemFromFile(path)
this
Set system prompt from file
.addImage(path)
this
Add image from file
.addImageFromUrl(url)
this
Add image from URL or data URI
.replace({})
this
Set placeholder replacements
.replaceKeyFromFile(key, path)
this
Replace placeholder with file content
.message()
Promise<string>
Get text response
.json(example, desc?, opts?)
Promise<object|array>
Get structured JSON. Descriptions support descriptor objects
{ description, required, enum, default }
. Top-level arrays auto-wrapped
.raw()
Promise<{message, think, toolCalls, tokens, response}>
Full response
.lastRaw
object | null
Full response from last
message()
/
json()
/
block()
/
stream()
call
.stream(callback)
Promise
Stream response
.block()
Promise<string>
Extract code block from response
.addMCP(package)
Promise
Add MCP server tools
.addTool(def, callback)
this
Register custom local tool
.addTools([{tool, callback}])
this
Register multiple tools
.removeTool(name)
this
Remove a tool
.listTools()
{local, mcp}
List registered tools
.new()
ModelMix
Clone instance sharing models
.attach(key, provider)
this
Attach custom provider
方法返回值描述
.addText(text)
this
添加用户消息
.addTextFromFile(path)
this
从文件添加用户消息
.setSystem(text)
this
设置系统提示词
.setSystemFromFile(path)
this
从文件设置系统提示词
.addImage(path)
this
从文件添加图片
.addImageFromUrl(url)
this
从URL或数据URI添加图片
.replace({})
this
设置占位符替换规则
.replaceKeyFromFile(key, path)
this
用文件内容替换指定占位符
.message()
Promise<string>
获取文本响应
.json(example, desc?, opts?)
Promise<object|array>
获取结构化JSON。描述支持使用
{ description, required, enum, default }
格式的描述符对象。顶级数组会自动包装
.raw()
Promise<{message, think, toolCalls, tokens, response}>
获取完整原始响应
.lastRaw
object | null
最近一次
message()
/
json()
/
block()
/
stream()
调用的完整响应
.stream(callback)
Promise
实现流式响应
.block()
Promise<string>
从响应中提取代码块
.addMCP(package)
Promise
添加MCP服务工具
.addTool(def, callback)
this
注册自定义本地工具
.addTools([{tool, callback}])
this
批量注册工具
.removeTool(name)
this
移除指定工具
.listTools()
{local, mcp}
列出已注册的工具
.new()
ModelMix
克隆实例并共享已关联的模型
.attach(key, provider)
this
关联自定义提供商

References

参考链接