@langchain/groq 版本演进深度解读:从 0.2.4 到 1.3.1 的关键能力升级与源码实现
【免费下载链接】langchainjsThe agent engineering platform项目地址: https://gitcode.com/GitHub_Trending/la/langchainjs
本文以@langchain/groq官方 CHANGELOG.md 为线索,结合仓库内ChatGroq的源码实现,系统梳理 Groq 集成包从 v0.2.4 到 v1.3.1 的完整演进脉络。你将了解到:结构化输出(structured output)三种实现方式的底层差异、streamEvents原生 OpenAI 兼容事件流、中止(abort)信号处理机制、reasoning_effort推理强度控制,以及 peer dependency 约束背后的真实原因——读完可直接把这些能力落地到基于 LangChain.js 与 Groq 的 LLM 应用中。
一、包概况:@langchain/groq在 LangChain.js 中的定位
@langchain/groq是 LangChain.js 官方发布的 Groq 集成包,位于仓库 libs/providers/langchain-groq,通过官方groq-sdk提供完整的 Groq 聊天模型推理能力。其核心入口在 src/index.ts,对外导出唯一的ChatGroq类;当前版本 1.3.1 的依赖约束见 package.json:
- 运行时依赖:
groq-sdk^1.6.0 - peer 依赖:
@langchain/core^1.1.30(这是 1.3.1 版本收紧后的下限,原因见下文) - Node.js 要求:>=20
- 同时提供 ESM(
dist/index.js)与 CJS(dist/index.cjs)双构建产物
从 CHANGELOG 的演进记录可以看出,这个包经历了三个阶段:早期(0.2.x)解决基础消息转换问题 → 中期(1.0.x)对齐 LangChain v1.0 与新核心能力(profile、abort、结构化输出)→ 当前(1.1.x–1.3.x)持续强化推理模型支持与流式事件能力。
二、v1.3.x:peer 依赖收紧与原生 streamEvents
2.1 为什么必须要求@langchain/core>= 1.1.30(1.3.1)
1.3.1 是一个看似简单却极具代表性的修复版本:将 peer dependency 从^1.0.0收紧为^1.1.30。CHANGELOG 明确给出了根因——ChatGroq的源码直接导入了两个从@langchain/core@1.1.30起才引入的导出子路径:
@langchain/core/utils/standard_schema(对应 chat_models.ts 中的isSerializableSchema导入)@langchain/core/language_models/structured_output(对应assembleStructuredOutputPipeline、createContentParser、createFunctionCallingParser导入)
旧的^1.0.0范围允许安装缺少这些导出子路径的旧版 core,导致构建/运行期出现模块解析失败(module-not-found)。这是 npm 生态中典型的"peer 依赖范围过宽"问题:peer 依赖的下限必须等于代码实际使用到的最老 API 的引入版本。对使用者而言,这一变更意味着升级@langchain/groq时需要同步检查@langchain/core版本,否则会在打包或启动阶段立即报错。
2.2 原生 OpenAI 兼容 streamEvents(1.3.0)
1.3.0 引入了对streamEvents事件的原生支持。所谓"原生 OpenAI 兼容",在源码层面的体现是 _streamChatModelEvents 方法:
- 通过
invocationParams(options, { streaming: true })构造带stream: true的请求参数; - 调用
completionWithRetry拿到ChatCompletionChunk的异步迭代流; - 外层包一个
abortableStream,在signal.aborted时提前终止; - 最终交由
@langchain/core/language_models/openai_completions_stream的convertOpenAICompletionsStream统一转换,并显式传入{ streamUsage: true, provider: "groq" }。
这意味着 Groq 的 SSE 流会被统一归一化为带类型的事件流,可区分文本增量、推理(reasoning)文本、工具调用(tool call)增量以及 token 用量(usage)。仓库中的单元测试 chat_models_stream_events.test.ts 直接验证了这四类场景:
describe("ChatGroq.streamEvents", () => { test("streams text", async () => { await expect( mockGroq(openAITextOnlyChunks()).streamEvents("Hello") ).toHaveStreamText("Hello world"); }); test("streams reasoning", async () => { await expect( mockGroq(openAIReasoningTextChunks()).streamEvents("Hello") ).toHaveStreamReasoning("Let me reason..."); }); test("streams tool calls", async () => { await expect( mockGroq(openAIToolCallChunks()).streamEvents("Hello") ).toHaveStreamToolCalls([ { name: "web_search", args: { query: "weather" } }, ]); }); test("streams usage", async () => { await expect( mockGroq(openAITextWithUsage()).streamEvents("Hello") ).toHaveStreamUsage({ input_tokens: 10, output_tokens: 2, total_tokens: 12, }); }); });测试用vi.spyOn(model, "completionWithRetry")以 fake chunk 数据模拟 Groq 响应,验证事件流能正确输出文本、推理内容、工具调用与 usage——这说明streamEvents适合作为构建 Agent 流式 UI、实时展示思考过程与 token 消耗的统一入口。
三、v1.1.x:推理模型与结构化输出的能力跃升
3.1reasoning_effort推理强度控制(1.1.5)
1.1.5 为ChatGroq增加了reasoning_effort支持。在 ChatGroqInput 接口 中,该参数被约束为联合类型:
reasoningEffort?: "none" | "default" | "low" | "medium" | "high" | null;从源码注释看,该能力针对推理类模型(如openai/gpt-oss-20b、openai/gpt-oss-120b、qwen/qwen3-32b),允许应用在"快速低推理"与"深度高推理"之间权衡。它在 invocationParams 中通过options?.reasoning_effort ?? this.reasoningEffort传递给 Groq API,既可作为构造参数全局设定,也可在单次invoke调用时覆盖。
3.2 标准 Schema 支持的结构化输出(1.1.4)与 gpt-oss 原生 JSON Schema(1.1.0)
1.1.4 实现"standard schema support for structured output"——即withStructuredOutput不再只接受 zod 或裸对象,也接受符合@langchain/core/utils/standard_schema规范的SerializableSchema。这一点从 withStructuredOutput 的签名重载 可以确认:outputSchema参数的类型为InteropZodType<RunOutput> | SerializableSchema<RunOutput> | Record<string, any>三者的联合。
1.1.0 则进一步为gpt-oss系列模型引入原生 JSON Schema 结构化输出。其底层决策逻辑在 groq-schema.ts 中,关键函数是getGroqStructuredOutputMethod与groqStrictifySchema:
function supportsJsonSchema(model: string): boolean { return model.startsWith("openai/gpt-oss"); } export const SUPPORTED_STRUCTURED_OUTPUT_METHODS = [ "jsonSchema", "functionCalling", "jsonMode", ] as const;决策规则(与 groq-schema.test.ts 中的断言一一对应):
| 模型 / 指定 method | 默认/结果 | 说明 |
|---|---|---|
openai/gpt-oss-*且未指定 | jsonSchema | 前缀匹配,新 gpt-oss 模型自动支持 |
| 其它模型且未指定 | functionCalling | 退化为工具调用方式 |
任意模型显式指定jsonMode | jsonMode | 使用response_format: { type: "json_object" } |
指定jsonSchema但模型不支持 | 抛出异常 | 提示改用functionCalling或jsonMode |
| 指定非法 method | 抛出异常 | 仅允许三种方法 |
三种方法对应 withStructuredOutput 实现 中的三条分支:
- jsonSchema:将 schema 经
toJsonSchema转换后再经groqStrictifySchema严格化,写入response_format: { type: "json_schema", json_schema: { strict: true, ... } },配合createContentParser解析; - jsonMode:使用
response_format: { type: "json_object" }+createContentParser; - functionCalling:把 schema 包装成 tool function,通过
bindTools+ 强制tool_choice让模型以工具调用形式返回结构化结果,再由createFunctionCallingParser解析。
3.3 Groq 严格模式下的 Schema 变换原理
Groq 的 strict JSON Schema 模式对 schema 有硬性要求,groqStrictifySchema(groq-schema.ts)通过递归变换满足这些约束:
- 所有对象必须
additionalProperties: false; - 所有属性必须进入
required数组(原来可选的属性也会被强制 required); - 原可选属性必须变为 nullable(类型联合加入
"null"),由makeNullable实现——注意它使用type: [T, "null"]的数组语法而非anyOf,因为 Groq 严格模式禁止顶层anyOf; - 根 schema 不允许
anyOf/oneOf/enum/not:遇到顶层oneOf或not直接抛错;遇到顶层anyOf则尝试提取其中的 object 变体作为根 schema,找不到 object 变体时抛错; - 递归处理嵌套对象、数组
items、$defs引用;对$ref这类无法推断的结构保持原样返回。
这些行为在 groq-schema.test.ts 中有超过 15 个用例覆盖,包括"可选属性变为 nullable""enum 追加 null""嵌套对象递归处理""$defs 递归严格化""根 oneOf/not 抛错"等边界场景,是理解该包结构化输出能力的最佳测试文档。
四、v1.0.x:LangChain v1.0 兼容与新基建
4.1 整体升级 v1.0(1.0.0)
1.0.0 将包升级为兼容 LangChain v1.0 的版本,package.json 中@langchain/corepeer 依赖为^1.1.30,groq-sdk为^1.6.0。对使用方而言,升级到 1.x 意味着整体迁移到新的 core 体系(消息、runnable、callback 均为 v1 语义)。
4.2 模型能力 Profile(1.0.1)
1.0.1 为ChatModel增加了ModelProfile与.profile属性。在 chat_models.ts 中:
get profile(): ModelProfile { return PROFILES[this.model] ?? {}; }profile 数据由 profiles.ts 提供(该文件头注释标明由脚本自动生成,源自仓库根目录profiles.toml),记录每个模型的输入/输出 token 上限、多模态支持、推理输出、工具调用与结构化输出能力。例如:
llama3-70b-8192:maxInputTokens 8192、toolCalling true、structuredOutput false;qwen-qwq-32b:maxInputTokens 131072、maxOutputTokens 16384、reasoningOutput true、toolCalling true。
这让上层应用可以在调用前查询模型能力(如model.profile.maxInputTokens)以决定是否截断上下文,或判断是否支持工具调用。
4.3 中止信号处理(1.0.4)
1.0.4 是 v1.0.x 中行为变化最大的一次,统一了各 provider 的 abort 语义:
- 新增
ModelAbortError(定义于@langchain/core/errors),当invoke()在流式中途被中止时,抛出该错误并携带累积的partialOutput; stream()被中止时抛出普通AbortError(因为 chunk 已经逐块交给调用方);_generate()与_streamResponseChunks()都必须检查并传播 abort 信号。
ChatGroq的实现与此完全对应:
- _generate 开头 执行
options.signal?.throwIfAborted(),信号已中止时立即抛出; - _streamResponseChunks 流式循环内 每次迭代检查
options.signal?.aborted并提前 return;流结束后若信号已中止则抛出AbortError(见 L1306-L1308); _streamChatModelEvents中的abortableStream同样在信号中止时停止 yield。
这套机制保证了:使用 fallback 链时,前一个 runnable 被中止后能正确流转到下一个 runnable;使用流式 UI 时,用户取消请求不会泄漏资源。
4.4 其它 1.0.x 修复
- 1.0.2:修复
moduleResolution: "node"兼容性,保证在旧式模块解析配置下也能正确加载; - 1.0.3:修复推理 token(reasoning tokens)在 core 层的提升逻辑,确保推理模型的思考过程能以正确消息类型呈现。
五、其它值得关注的变更
5.1 构造函数重载与包版本元数据(1.1.2 / 1.1.3)
- 1.1.2为聊天模型增加字符串式构造函数重载。
ChatGroq的构造函数(chat_models.ts)因此支持两种等价写法:
// 写法一:字符串模型名 + 可选字段 const m1 = new ChatGroq("llama-3.3-70b-versatile", { temperature: 0 }); // 写法二:对象形式(官方 README 推荐) const m2 = new ChatGroq({ model: "llama-3.3-70b-versatile", temperature: 0, });- 1.1.3为每个包在构造时通过
this._addVersion("@langchain/groq", __PKG_VERSION__)(见构造函数 L1044)向metadata.versions打版本戳,使 LangSmith trace 元数据中直接携带包版本,便于排查"线上跑的到底是哪个版本"。
5.2 groq-sdk 升级与依赖清理(1.2.0 / 1.2.1)
1.2.0 将groq-sdk从 0.37.0 升级到 1.1.2(当前已进一步升至 ^1.6.0);1.2.1 移除了冗余的@types/uuid声明——因为包实际经由@langchain/core/utils/uuid获取 uuid 能力,无需直接依赖类型桩。这类变更提醒集成包维护者:类型依赖应跟随实际使用路径,而非盲目复制。
5.3 通用消息角色映射(0.2.4)
0.2.4 修复了"generic messages 在messageToGroqRole中的支持"。该函数(chat_models.ts)将 LangChain 消息类型映射为 Groq 角色:system→system、ai→assistant、human→user、function→function、tool→tool,其中generic类型通过extractGenericMessageCustomRole校验其 role 必须属于system | assistant | user | function之一,否则抛错。这是保证消息能在 LangChain 与 Groq API 之间无损往返的基础设施。
六、实践:安装、初始化与能力对照
6.1 安装与最小示例
按官方 README.md 安装并设置环境变量:
npm install @langchain/groq @langchain/core export GROQ_API_KEY=你的密钥import { ChatGroq } from "@langchain/groq"; import { HumanMessage } from "@langchain/core/messages"; const model = new ChatGroq({ apiKey: process.env.GROQ_API_KEY, // 也可省略,自动读取环境变量 model: "llama-3.3-70b-versatile", }); const res = await model.invoke([ new HumanMessage("What color is the sky?"), ]);6.2 常用调用参数速查
构造函数可用的关键参数(来自 ChatGroqInput):
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
model | string | 必填 | Groq 模型名 |
temperature | number | 0.7 | 采样温度 |
maxTokens | number | - | 单次响应最大 token 数(对应max_completion_tokens) |
topP/topLogprobs | number | - | 核采样 / top-logprobs |
frequencyPenalty/presencePenalty | number | - | 频率/存在惩罚 |
reasoningEffort | 枚举 | - | 推理强度:none/default/low/medium/high |
streamUsage | boolean | true | 流式响应中是否附带 usage |
stop/stopSequences | string[] | - | 停止序列(最多 4 个) |
baseUrl/timeout/httpAgent/fetch | - | - | 底层 HTTP 客户端定制 |
streaming | boolean | false | 是否默认流式 |
运行期调用选项(第二个参数传给.invoke/.stream/.batch)还包括tool_choice、response_format、seed、reasoning_effort、stream_options.include_usage与自定义headers等,其中tools支持 LangChain 风格工具定义。
6.3 结构化输出与工具调用的落地范式
工具调用(使用.bindTools):
import { z } from "zod"; const GetWeather = { name: "GetWeather", description: "Get the current weather in a given location", schema: z.object({ location: z.string().describe("The city and state, e.g. San Francisco, CA"), }), }; const llmWithTools = model.bindTools([GetWeather]); const aiMsg = await llmWithTools.invoke( "Which city is hotter today: LA or NY?" ); console.log(aiMsg.tool_calls);结构化输出(withStructuredOutput会根据模型自动选择方法):
const Joke = z .object({ setup: z.string().describe("The setup of the joke"), punchline: z.string().describe("The punchline to the joke"), rating: z.number().optional().describe("How funny the joke is, from 1 to 10"), }) .describe("Joke to tell user."); const structuredLlm = model.withStructuredOutput(Joke, { name: "Joke" }); const jokeResult = await structuredLlm.invoke("Tell me a joke about cats");若使用openai/gpt-oss-*模型,将自动走原生 JSON Schema 严格模式;其它模型默认走 functionCalling 方式。如需强制某种方式,可在withStructuredOutput的config.method中显式指定"jsonSchema" | "functionCalling" | "jsonMode"。
6.4 包内测试与质量保障
仓库为@langchain/groq准备了完整的测试矩阵(见 src/tests):
- 单元测试(
.test.ts):chat_models.test.ts、chat_models_stream_events.test.ts、groq-schema.test.ts; - 集成测试(
.int.test.ts):chat_models.int.test.ts、chat_models_structured_output.int.test.ts、agent.int.test.ts; - 标准测试(
.standard.test.ts/.standard.int.test.ts):对接仓库内internal/standard-tests的统一标准用例,覆盖通用聊天模型行为、abort 语义与结构化输出。
本地开发时可在包目录运行pnpm test(单元)与pnpm test:int(集成),或从仓库根目录pnpm build --filter @langchain/groq构建,具体命令见 package.json 的scripts字段。
七、总结:从 CHANGELOG 读懂一个生产级集成包的演进逻辑
回看这份 CHANGELOG,可以提炼出几条值得所有集成包维护者借鉴的规律:
- peer 依赖的边界由实际 import 决定(1.3.1):代码用了哪个 core 子路径,peer 下限就应钉在引入该子路径的版本上;
- 能力分层推进:先补齐消息转换等基础(0.2.x),再对齐大版本与新核心基建(1.0.x),随后逐项强化推理模型、结构化输出与流事件(1.1.x–1.3.x);
- 每项能力都有源码与测试佐证:结构化输出的方法决策、严格 schema 变换、abort 语义、streamEvents 事件分类,均可在 chat_models.ts、groq-schema.ts 与对应测试文件中找到可验证的实现。
对应用开发者而言,当前 1.3.1 版本已经具备生产可用的完整能力面:流式事件、推理模型控制、三种结构化输出路径、健全的中止与 fallback 语义,以及可查询的模型能力 profile——这些正是构建 Groq 驱动的 Agent 应用所需的核心拼图。
【免费下载链接】langchainjsThe agent engineering platform项目地址: https://gitcode.com/GitHub_Trending/la/langchainjs
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考