modelmix
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseModelMix 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
常见任务
- Get a text response
- Get structured JSON
- Stream a response
- Get raw response (tokens, thinking, tool calls)
- Access full response after or
message()withjson()lastRaw - Add images
- Use templates with placeholders
- Round-robin load balancing
- MCP integration (external tools)
- Custom local tools (addTool)
- Rate limiting (Bottleneck)
- Debug mode
- Use free-tier models
- Conversation history
Installation
安装
bash
npm install modelmixbash
npm install modelmixCore 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 fails, it automatically tries , then .
sonnet45gpt5minigemini3flash通过链式简写方法关联模型提供商。第一个模型为主模型,后续为降级备选模型:
javascript
const model = ModelMix.new()
.sonnet46() // 主模型
.gpt52() // 降级备选1
.gemini3flash() // 降级备选2
.addText("Hello!")如果调用失败,会自动尝试,再尝试。
sonnet45gpt5minigemini3flashAvailable Model Shorthands
可用模型简写方法
- OpenAI:
gpt52gpt51gpt5gpt5minigpt5nanogpt41gpt41minigpt41nano - Anthropic:
opus46opus45sonnet46sonnet45haiku45(thinking variants: addhaiku35suffix)think - Google:
gemini3progemini3flashgemini25progemini25flash - Grok:
grok4(thinking variant available)grok41 - Perplexity:
sonarsonarPro - Groq:
scoutmaverick - Together:
qwen3kimiK2 - Multi-provider:
deepseekR1gptOss - MiniMax:
minimaxM21 - Fireworks:
deepseekV32GLM47
Each method is called as and accepts optional to override per-model settings.
mix.methodName(){ options, config }- OpenAI:
gpt52gpt51gpt5gpt5minigpt5nanogpt41gpt41minigpt41nano - Anthropic:
opus46opus45sonnet46sonnet45haiku45(带思考过程的变体:添加haiku35后缀)think - Google:
gemini3progemini3flashgemini25progemini25flash - Grok:
grok4(支持带思考过程的变体)grok41 - Perplexity:
sonarsonarPro - Groq:
scoutmaverick - Together:
qwen3kimiK2 - 多提供商:
deepseekR1gptOss - MiniMax:
minimaxM21 - Fireworks:
deepseekV32GLM47
每个方法通过调用,可传入可选的参数来覆盖模型级配置。
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()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:
- (string) — field description
description - (boolean, default
required) — iftrue: removed from required array, type becomes nullablefalse - (array) — allowed values; if includes
enum, type auto-becomes nullablenull - (any) — default value
default
字段描述可以是字符串或包含元数据的描述符对象:
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 for better LLM compatibility, and unwrapped on return:
{ out: [...] }javascript
const result = await model.json([{ name: 'martin' }]);
// result is an array: [{ name: "Martin" }, { name: "Carlos" }, ...]顶级数组会自动包装为以提升LLM兼容性,返回时会自动解包:
{ out: [...] }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.responsejavascript
const raw = await ModelMix.new()
.sonnet45think()
.addText("一步步解决这个问题:2+2*3")
.raw();
// raw.message, raw.think, raw.tokens, raw.toolCalls, raw.responseAccess full response after message()
or json()
with lastRaw
message()json()lastRaw通过lastRaw
获取message()
或json()
后的完整响应
lastRawmessage()json()After calling , , , or , use to access the complete response (tokens, thinking, tool calls, etc.). It has the same structure as .
message()json()block()stream()lastRawraw()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调用、、或后,可通过获取完整响应数据(token、思考过程、工具调用等)。其结构与返回结果一致。
message()json()block()stream()lastRawraw()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 in for Brave Search MCP.
BRAVE_API_KEY.envjavascript
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需要在文件中配置。
.envBRAVE_API_KEYCustom 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.jsjavascript
const model = ModelMix.new({
config: { debug: 2 } // 0=静默, 1=极简, 2=摘要, 3=完整(不截断), 4=详细
}).gpt5mini();若要获取完整调试输出,还需设置环境变量:
DEBUG=ModelMix* node script.jsUse 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 for
package.jsonbefore runningmodelmix.npm install - Use static factory to create instances (not
ModelMix.new()).new ModelMix() - Store API keys in and load with
.envordotenv/config. Never hardcode keys.process.loadEnvFile() - Chain models for resilience: primary model first, fallbacks after.
- When using MCP tools or , set
addTool()to at least 3.max_history - Use for structured output instead of parsing text manually. Use descriptor objects
.json()in descriptions for richer schema control.{ description, required, enum, default } - Use for simple text,
.message()when you need tokens/thinking/toolCalls..raw() - For thinking models, append to the method name (e.g.
think).sonnet45think() - Template placeholders use syntax in both system prompts and user messages.
{key} - The library uses CommonJS internally () but supports ESM import via
require.{ 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()设置为至少3。max_history - 如需结构化输出,请使用方法而非手动解析文本。在描述中使用描述符对象
.json()来实现更精细的schema控制。{ description, required, enum, default } - 简单文本响应使用,需要token/思考过程/工具调用数据时使用
.message()。.raw() - 对于支持思考过程的模型,在方法名后追加后缀(例如
think)。sonnet45think() - 模板占位符在系统提示词和用户消息中均使用语法。
{key} - 该库内部使用CommonJS(),但支持通过
require进行ESM导入。{ ModelMix } - 自定义配置可用的提供商Mix类:,
MixOpenAI,MixAnthropic,MixGoogle,MixPerplexity,MixGroq,MixTogether,MixGrok,MixOpenRouter,MixOllama,MixLMStudio,MixCustom,MixCerebras,MixFireworks。MixMiniMax
API Quick Reference
API速查
| Method | Returns | Description |
|---|---|---|
| | Add user message |
| | Add user message from file |
| | Set system prompt |
| | Set system prompt from file |
| | Add image from file |
| | Add image from URL or data URI |
| | Set placeholder replacements |
| | Replace placeholder with file content |
| | Get text response |
| | Get structured JSON. Descriptions support descriptor objects |
| | Full response |
| | Full response from last |
| | Stream response |
| | Extract code block from response |
| | Add MCP server tools |
| | Register custom local tool |
| | Register multiple tools |
| | Remove a tool |
| | List registered tools |
| | Clone instance sharing models |
| | Attach custom provider |
| 方法 | 返回值 | 描述 |
|---|---|---|
| | 添加用户消息 |
| | 从文件添加用户消息 |
| | 设置系统提示词 |
| | 从文件设置系统提示词 |
| | 从文件添加图片 |
| | 从URL或数据URI添加图片 |
| | 设置占位符替换规则 |
| | 用文件内容替换指定占位符 |
| | 获取文本响应 |
| | 获取结构化JSON。描述支持使用 |
| | 获取完整原始响应 |
| | 最近一次 |
| | 实现流式响应 |
| | 从响应中提取代码块 |
| | 添加MCP服务工具 |
| | 注册自定义本地工具 |
| | 批量注册工具 |
| | 移除指定工具 |
| | 列出已注册的工具 |
| | 克隆实例并共享已关联的模型 |
| | 关联自定义提供商 |