AgentSkillsCN

modelmix

介绍如何使用 ModelMix Node.js 库,通过统一的接口与多家 AI 大模型提供商进行交互。适用于集成各类 AI 模型(如 OpenAI、Anthropic、Google、Groq、Perplexity、Grok 等)、实现模型链式调用并配置回退机制、从大模型中获取结构化 JSON 数据、添加 MCP 工具、实现流式响应,或在 Node.js 中管理多供应商 AI 工作流等场景。

SKILL.md
--- frontmatter
name: modelmix
description: Instructions for using the ModelMix Node.js library to interact with multiple AI LLM providers through a unified interface. Use when integrating AI models (OpenAI, Anthropic, Google, Groq, Perplexity, Grok, etc.), chaining models with fallback, getting structured JSON from LLMs, adding MCP tools, streaming responses, or managing multi-provider AI workflows in Node.js.

ModelMix Library Skill

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)

Installation

bash
npm install modelmix

Core Concepts

Import

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
        roundRobin: false    // false=fallback, true=rotate models
    }
});

Attaching Models (Fluent Chain)

Chain shorthand methods to attach providers. First model is primary; others are fallbacks:

javascript
const model = ModelMix.new()
    .sonnet45()        // primary
    .gpt5mini()        // fallback 1
    .gemini3flash()    // fallback 2
    .addText("Hello!")

If sonnet45 fails, it automatically tries gpt5mini, then gemini3flash.

Available Model Shorthands

  • OpenAI: gpt52 gpt51 gpt5 gpt5mini gpt5nano gpt41 gpt41mini gpt41nano
  • Anthropic: opus46 opus45 sonnet45 sonnet4 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.

Common Tasks

Get a text response

javascript
const answer = await ModelMix.new()
    .gpt5mini()
    .addText("What is the capital of France?")
    .message();

Get structured 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 }?)

Stream a response

javascript
await ModelMix.new()
    .gpt5mini()
    .addText("Tell me a story.")
    .stream(({ delta, message }) => {
        process.stdout.write(delta);
    });

Get raw response (tokens, thinking, tool calls)

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

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

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

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();

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());

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();

MCP integration (external tools)

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.

Custom local tools (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());

Rate limiting (Bottleneck)

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
}).gpt5mini();

For full debug output, also set the env: 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());

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"

Agent Usage Rules

  • 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 .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.

API Quick Reference

MethodReturnsDescription
.addText(text)thisAdd user message
.addTextFromFile(path)thisAdd user message from file
.setSystem(text)thisSet system prompt
.setSystemFromFile(path)thisSet system prompt from file
.addImage(path)thisAdd image from file
.addImageFromUrl(url)thisAdd image from URL or data URI
.replace({})thisSet placeholder replacements
.replaceKeyFromFile(key, path)thisReplace placeholder with file content
.message()Promise<string>Get text response
.json(example, desc?, opts?)Promise<object>Get structured JSON
.raw()Promise<{message, think, toolCalls, tokens, response}>Full response
.lastRawobject | nullFull response from last message()/json()/block()/stream() call
.stream(callback)PromiseStream response
.block()Promise<string>Extract code block from response
.addMCP(package)PromiseAdd MCP server tools
.addTool(def, callback)thisRegister custom local tool
.addTools([{tool, callback}])thisRegister multiple tools
.removeTool(name)thisRemove a tool
.listTools(){local, mcp}List registered tools
.new()ModelMixClone instance sharing models
.attach(key, provider)thisAttach custom provider

References