模型策略:显式选择与推荐预算
从已登记的模型和推理配置中选择,以本地预算档位补全 Core 设置,并保留逐字段精确覆盖。
createModelStrategy 返回普通 ModelRunnerOptions,可直接创建 ModelRunner;不含请求 execution 的定义也可直接绑定 AgentCoreEngine。模型可以直接给定义,或用 models 中的 ID 代指。传入 ID 时找不到模型即报错,不根据名字、品牌或 URL 猜测能力。
budget 的 small、medium、large 分别适合调用较少的短任务、普通多步任务和需要更多调用空间的任务。它们规定本地准入和输出预算,不代表供应商上下文容量、真实速度或质量保证。small 为 2 次、8000 输入字符、4000 输出字符、512 输出 token 预留、15000ms 单次期限;medium 为 8 次、32000、16000、1024、30000ms;large 为 16 次、64000、32000、4096、60000ms。供应商硬上限和 Core 最终校验继续有效。
优先级由低到高:预算档位 → 已选模型配置 → 显式 reasoningOptions 中的配置 → budget 对象中的精确设置 → 顶层 Core 字段。省略 budget 使用 medium。budget 对象在 medium 上补精确值;显式 undefined 交回 Core 缺省解释,合法的 0 和 Infinity 不当作缺省。
reasoning 是 reasoningOptions 中的名称,例如 low/high/off。其内容是明确的 Core 模型配置覆盖,可指向已经按供应商推理参数构造的 Provider。Support 不推断供应商如何开启思考,不自行拼装未经声明的 wire 字段。没有匹配声明时拒绝。已有 Provider、transport、token 计数器、sink、错误端口和 execution 的合同均保留;App 服务不会被深度冻结。
由简到繁的同业务示例
短任务使用小预算,增加需求仍沿用同一 Core 构造
入门 · Node.js
import { AgentCoreEngine, ModelRunner, Support } from '@jangts/agent-core';
const provider = { async *stream() { yield '服务在线。'; } };
const config = Support.createModelStrategy({ model: { provider }, budget: 'small' });
const model = new ModelRunner(config);
console.log((await model.invoke('服务状态?')).value);
const agent = new AgentCoreEngine({ model: config });
console.log(agent.branch.agentId);import { AgentCoreEngine, ModelRunner, Support } from '@jangts/agent-core';
const provider = { async *stream() { yield '服务在线。'; } };
const config = Support.createModelStrategy({ model: { provider }, budget: 'small' });
const model = new ModelRunner(config);
console.log((await model.invoke('服务状态?')).value);
const agent = new AgentCoreEngine({ model: config });
console.log(agent.branch.agentId);已有模型用 ID 代指,推理方案显式登记
配置 · Node.js
示例 Provider 完全离线。实际供应商的推理参数由各 Provider 的显式配置实现。
import { ModelRunner, Support } from '@jangts/agent-core';
const fast = { async *stream() { yield '简短回答'; } };
const reasoned = { async *stream() { yield '经过复核的回答'; } };
const models = { fast: { provider: fast }, thorough: { provider: reasoned } };
const config = Support.createModelStrategy({ model: 'fast', models, budget: 'small',
reasoning: 'high', reasoningOptions: { high: { provider: reasoned } },
maxCalls: 1, maxOutputTokens: 1200,
});
console.log((await new ModelRunner(config).invoke('检查资料')).value);import { ModelRunner, Support } from '@jangts/agent-core';
const fast = { async *stream() { yield '简短回答'; } };
const reasoned = { async *stream() { yield '经过复核的回答'; } };
const models = { fast: { provider: fast }, thorough: { provider: reasoned } };
const config = Support.createModelStrategy({ model: 'fast', models, budget: 'small',
reasoning: 'high', reasoningOptions: { high: { provider: reasoned } },
maxCalls: 1, maxOutputTokens: 1200,
});
console.log((await new ModelRunner(config).invoke('检查资料')).value);自定义预算和原生 Core 端口保持有效
扩展 · Node.js
计数器仅为演示。生产环境注入与实际模型匹配的计数器,不用字符估算冒充真实 token 数。
import { ModelRunner, Support } from '@jangts/agent-core';
const provider = { async *stream() { yield 'done'; } };
const transport = Support.createTextTransport({ id: 'app:text' });
const config = Support.createModelStrategy({ model: { provider, transports: [transport] },
budget: { maxCalls: 3, maxInputChars: 24000, callTimeoutMs: 20000 },
tokenBudget: { counterId: 'app-counter', contextWindowTokens: 4000,
countTokens({ messages }) { return messages.reduce((sum, message) => sum + message.content.length, 0); } },
});
const result = await new ModelRunner(config).invoke({ input: 'hello', transport });
console.log(result.value);import { ModelRunner, Support } from '@jangts/agent-core';
const provider = { async *stream() { yield 'done'; } };
const transport = Support.createTextTransport({ id: 'app:text' });
const config = Support.createModelStrategy({ model: { provider, transports: [transport] },
budget: { maxCalls: 3, maxInputChars: 24000, callTimeoutMs: 20000 },
tokenBudget: { counterId: 'app-counter', contextWindowTokens: 4000,
countTokens({ messages }) { return messages.reduce((sum, message) => sum + message.content.length, 0); } },
});
const result = await new ModelRunner(config).invoke({ input: 'hello', transport });
console.log(result.value);