创见博客
invoke、stream、batch:三种调用方式到底怎么选?
七崽爱吃小饼干2026/10/13阅读 0

在 LangChain 里,模型初始化好之后,真正“提问”的动作有三种常见方式:invoke、stream、batch。它们面对的是同一类问题,但交互形态、适用场景、乃至参数和返回值都不一样。这篇文章把三者的差异讲清楚,重点说清每种方式的参数和输出。

先厘清一个容易踩的坑:JS 里没有 ainvoke / astream / abatch

如果你是从 Python 版 LangChain 过来的,可能会习惯 ainvoke、astream、abatch 这类带 a 前缀的写法。但在 LangChain JS 中并不存在这些方法。

原因很直接:JS 里的 invoke / stream / batch 本身就是异步的(返回 Promise 或异步迭代器),不需要再用 a 前缀区分同步和异步。所以:

js
// JS 正确写法
await model.invoke("...");
for await (const chunk of await model.stream("...")) {}
await model.batch(["...", "..."]);

一、invoke:一问一答

invoke 是最基础的调用方式:给一个输入,拿到一个完整回复。

参数

js
await model.invoke(input, options);

input:可以是多种形式——

  • 字符串:"用一句话介绍你自己"
  • 单条消息:new HumanMessage("...")
  • 消息数组(用于角色区分 / 多轮):[new SystemMessage(...), new HumanMessage(...)]
  • PromptValue(由 PromptTemplate 格式化而来)

options:可选的单次调用配置,会覆盖构造模型时的默认值,常用字段包括:

  • temperature、topP、maxTokens、stop —— 本次调用的生成参数;
  • callbacks —— 本次调用的回调(日志、追踪);
  • signal —— AbortSignal,用于取消请求;
  • maxRetries —— 覆盖重试次数;
  • configurable —— 配合 initChatModel 做运行时字段覆盖。

输出

返回 Promise<AIMessage>。这是一个消息对象,主要字段有:

  • content:模型回复的文本(或内容块数组);
  • tool_calls:模型请求调用的工具(若有);
  • usage_metadata:token 用量(输入 / 输出 / 总计);
  • response_metadata:厂商原始响应元信息;
  • additional_kwargs:附加参数。

示例

js
const res = await model.invoke("用一句话介绍你自己", { temperature: 0.3 });
console.log(res.content);          // 回复文本
console.log(res.usage_metadata);   // token 用量

适用场景:绝大多数“一次请求、一次完整回复”的场景,比如问答、摘要、分类。

二、stream:边生成边返回

stream 适合需要“打字机效果”或长文本输出的场景,模型每生成一小段就返回一次。

参数

签名与 invoke 一致:

js
const stream = await model.stream(input, options);

input 和 options 的含义与 invoke 相同。

输出

返回 Promise<IterableReadableStream<AIMessageChunk>>——一个异步迭代器,需要用 for await...of 逐个消费。每个元素是 AIMessageChunk,主要字段:

  • content:本批次新增的文本片段;
  • tool_call_chunks:工具调用的分片(若流式返回工具调用);
  • usage_metadata:通常只在最后一个 chunk 上携带(取决于服务端)。

提示:多个 chunk 可以用 .concat() 拼接成一个完整的 AIMessageChunk。

示例

js
const stream = await model.stream("写一首关于秋天的短诗");
for await (const chunk of stream) {
  process.stdout.write(chunk.content); // 逐块打印
}

适用场景:聊天界面、长文生成、需要实时反馈的交互。

三、batch:一次处理多个输入

batch 把多个输入打包,并发调用模型,返回一组结果,适合批量任务。

参数

js
await model.batch(inputs, options?, batchOptions?);
  • inputs:输入数组,每个元素的形式和 invoke 的 input 一样,例如 ["问题1", "问题2", "问题3"];
  • options:可以是单个配置(应用到所有输入),也可以是与 inputs 等长的数组(为每个输入单独配置);
  • batchOptions:批处理选项,字段有:
    • maxConcurrency:最大并发数,控制请求压力(注意在较新版本中更推荐通过 runnable config 传入);
    • returnExceptions:为 true 时,失败的任务不抛错,而是在结果数组对应位置返回 Error 对象。

输出

返回 Promise<结果数组>,顺序与输入一致:

  • 默认情况下每个元素是 AIMessage(遇到错误则整体抛错);
  • 当 returnExceptions: true 时,元素类型为 AIMessage | Error,需要自行判断。

示例

js
const results = await model.batch(
  ["用一句话解释 JavaScript", "用一句话解释 Python", "用一句话解释 Go"],
  { maxConcurrency: 2 }
);
results.forEach((r, i) => console.log(`[${i + 1}] ${r.content}`));

容错写法:

js
const results = await model.batch(inputs, {}, { returnExceptions: true });
results.forEach((r) =>
  r instanceof Error ? console.error("失败:", r.message) : console.log(r.content)
);

适用场景:批量翻译、批量打标、数据集预处理、对比多个提示词效果。

四、三者对比

维度invokestreambatch
输入单个输入单个输入输入数组
是否异步是(Promise)是(异步迭代器)是(Promise)
返回类型Promise<AIMessage>AsyncIterable<AIMessageChunk>Promise<AIMessage[]>
拿到结果的方式awaitfor await...ofawait
额外参数optionsoptionsoptions + batchOptions
典型场景一问一答打字机效果 / 长文本批量处理

五、怎么选

  • 只要一个完整回复 → invoke
  • 需要实时输出、提升交互体验 → stream
  • 有一批输入要一起跑、且能接受并发 → batch
  • 想要流式 + 批量 → 可以 batch 之后再对每个结果 stream,或用链式组合,但通常分开实现更清晰

另外,options 在这三种方式里含义一致,只是 batch 多了一层 batchOptions 用于控制并发和异常。理解这一点,就能在三者之间自如切换。

六、小结

invoke、stream、batch 分别对应“单次、流式、批量”三种交互形态,返回值依次是完整的 AIMessage、分片的 AIMessageChunk 流、以及结果数组。它们的调用参数基本共享同一套 options,batch 额外支持 batchOptions 控制并发与容错。最后再强调一句:在 LangChain JS 中,这些方法本身就是异步的,不存在 ainvoke / astream / abatch。

评论
0/100