ModelCalls:外部推理绑定
为 embedding 等 App 自定义 I/O 绑定身份、校验、取消与统一调用回执。
构造时登记 {id,identity,invoke,assertInput?,assertOutput?}。invoke({modelId,input,timeoutMs},execution) 返回 ModelResult<Output>,正文/向量在 value,真实调用信息在 invocation。已知字面量 ID 可从登记元组推导输入输出;未知 ID 拒绝。identity 用来说明真实模型/算法版本,不从请求猜测。
timeoutMs 必须是支持范围内的正安全整数;与上层 signal 合并。输入输出 assertion 同步且必须返回 void;取消后迟到的结果不会作为成功返回。底层 I/O 应消费传入 signal,停止等待不等于能撤销外部副作用。
这是独立外部推理适配器,不能因为返回形状相同就宣称它已接入聊天 Runner 的调用次数账本。当前源码的绑定需由 App 明确承担对应业务预算;embedding 与聊天调用的计量单位不可混扣。Core 的单次多模型聊天能力仍使用 Engine/ModelRunner 的正常模型合同。
由简到繁的同业务示例
先绑定一个离线演示向量算法
入门 · Node.js
算法只演示 I/O 绑定,不提供真实语言向量质量。
ts
import { ModelCalls } from '@jangts/agent-core/kits/inference';
const models = new ModelCalls([
{ id: 'demo-vector', identity: 'length-direction-v1', invoke: (text: string) => [text.length, 1] },
] as const);
const result = await models.invoke({ modelId: 'demo-vector', input: 'Agent Core', timeoutMs: 1000 }, { signal: new AbortController().signal });
console.log(result.value, result.invocation.modelId);js
import { ModelCalls } from '@jangts/agent-core/kits/inference';
const models = new ModelCalls([
{ id: 'demo-vector', identity: 'length-direction-v1', invoke: (text) => [text.length, 1] },
]);
const result = await models.invoke({ modelId: 'demo-vector', input: 'Agent Core', timeoutMs: 1000 }, { signal: new AbortController().signal });
console.log(result.value, result.invocation.modelId);在同一 invoke 上增加输入输出检查和取消
配置 · Node.js
ts
import { ModelCalls } from '@jangts/agent-core/kits/inference';
const models = new ModelCalls([
{ id: 'demo-vector', identity: 'length-direction-v1',
assertInput(text: string) { if (!text.trim()) throw new Error('文本为空'); },
invoke(text: string, context) { context.signal.throwIfAborted(); return [text.length, 1]; },
assertOutput(vector: number[]) { if (vector.length !== 2 || vector.some(value => !Number.isFinite(value))) throw new Error('向量无效'); },
},
] as const);
const controller = new AbortController();
const result = await models.invoke({ modelId: 'demo-vector', input: 'Agent Core', timeoutMs: 1000 }, { signal: controller.signal });
console.log(models.identity('demo-vector'), result.value);js
import { ModelCalls } from '@jangts/agent-core/kits/inference';
const models = new ModelCalls([
{ id: 'demo-vector', identity: 'length-direction-v1',
assertInput(text) { if (!text.trim())
throw new Error('文本为空'); },
invoke(text, context) { context.signal.throwIfAborted(); return [text.length, 1]; },
assertOutput(vector) { if (vector.length !== 2 || vector.some(value => !Number.isFinite(value)))
throw new Error('向量无效'); },
},
]);
const controller = new AbortController();
const result = await models.invoke({ modelId: 'demo-vector', input: 'Agent Core', timeoutMs: 1000 }, { signal: controller.signal });
console.log(models.identity('demo-vector'), result.value);