{"version":3,"file":"chat_models.cjs","names":["ChatMessage","convertLangChainToolCallToOpenAI","AIMessage","HumanMessageChunk","AIMessageChunk","SystemMessageChunk","FunctionMessageChunk","ToolMessageChunk","ChatMessageChunk","BaseChatModel","Groq","ChatGenerationChunk","PROFILES","getGroqStructuredOutputMethod","groqStrictifySchema"],"sources":["../src/chat_models.ts"],"sourcesContent":["import { toJsonSchema } from \"@langchain/core/utils/json_schema\";\nimport { NewTokenIndices } from \"@langchain/core/callbacks/base\";\nimport { CallbackManagerForLLMRun } from \"@langchain/core/callbacks/manager\";\nimport {\n  BaseChatModel,\n  BaseChatModelCallOptions,\n  BindToolsInput,\n  LangSmithParams,\n  type BaseChatModelParams,\n} from \"@langchain/core/language_models/chat_models\";\nimport * as ChatCompletionsAPI from \"groq-sdk/resources/chat/completions\";\nimport * as CompletionsAPI from \"groq-sdk/resources/completions\";\nimport {\n  AIMessage,\n  AIMessageChunk,\n  BaseMessage,\n  ChatMessage,\n  ChatMessageChunk,\n  HumanMessageChunk,\n  SystemMessageChunk,\n  ToolMessage,\n  OpenAIToolCall,\n  isAIMessage,\n  BaseMessageChunk,\n  UsageMetadata,\n  FunctionMessageChunk,\n  ToolMessageChunk,\n} from \"@langchain/core/messages\";\nimport {\n  ChatGeneration,\n  ChatGenerationChunk,\n  ChatResult,\n} from \"@langchain/core/outputs\";\nimport { getEnvironmentVariable } from \"@langchain/core/utils/env\";\nimport {\n  InteropZodType,\n  isInteropZodSchema,\n} from \"@langchain/core/utils/types\";\nimport Groq from \"groq-sdk\";\nimport type {\n  ChatCompletion,\n  ChatCompletionCreateParams,\n  ChatCompletionCreateParamsNonStreaming,\n  ChatCompletionCreateParamsStreaming,\n  ChatCompletionTool,\n} from \"groq-sdk/resources/chat/completions\";\nimport type { RequestOptions } from \"groq-sdk/core\";\nimport { Runnable } from \"@langchain/core/runnables\";\nimport {\n  BaseLanguageModelInput,\n  FunctionDefinition,\n  StructuredOutputMethodOptions,\n} from \"@langchain/core/language_models/base\";\nimport { ModelProfile } from \"@langchain/core/language_models/profile\";\nimport { BaseLLMOutputParser } from \"@langchain/core/output_parsers\";\nimport {\n  parseToolCall,\n  makeInvalidToolCall,\n  convertLangChainToolCallToOpenAI,\n} from \"@langchain/core/output_parsers/openai_tools\";\nimport { convertToOpenAITool } from \"@langchain/core/utils/function_calling\";\nimport { ToolCallChunk } from \"@langchain/core/messages/tool\";\nimport { getSchemaDescription } from \"@langchain/core/utils/types\";\n\nimport PROFILES from \"./profiles.js\";\nimport {\n  getGroqStructuredOutputMethod,\n  groqStrictifySchema,\n} from \"./utils/groq-schema.js\";\nimport {\n  isSerializableSchema,\n  SerializableSchema,\n} from \"@langchain/core/utils/standard_schema\";\nimport {\n  assembleStructuredOutputPipeline,\n  createContentParser,\n  createFunctionCallingParser,\n} from \"@langchain/core/language_models/structured_output\";\n\ntype ChatGroqToolType = BindToolsInput | ChatCompletionTool;\n\n/**\n * Const list of fields that we'll pick from the `ChatCompletionCreateParams` interface\n * to use as the options allowed to be passed to invocation methods.\n *\n * @internal\n */\nconst CREATE_PARAMS_BASE_CALL_KEYS = [\n  // \"messages\", // passed as input arg to invocation methods\n  // \"model\", // don't allow override on invoke\n  \"frequency_penalty\",\n  \"function_call\",\n  \"functions\",\n  \"logit_bias\", // not supported, but left in for forward compatibility\n  \"logprobs\", // not supported, but left in for forward compatibility\n  \"max_completion_tokens\",\n  \"max_tokens\",\n  \"n\", // not supported, but left in for forward compatibility\n  \"parallel_tool_calls\",\n  \"presence_penalty\",\n  \"reasoning_effort\",\n  \"reasoning_format\",\n  \"response_format\",\n  \"seed\",\n  // TODO: also pass as constructor arg\n  \"service_tier\",\n  \"stop\",\n  // \"stream\", // determined by invocation method\n  // other models only specify temperature as a constructor arg, but I don't see the harm in\n  // allowing overrides on invocation\n  \"temperature\",\n  \"tool_choice\",\n  // \"tools\", // need to allow users to specify langchain style tools, so we use a different type\n  \"top_logprobs\",\n  \"top_p\",\n  // \"user\", // don't allow override on invoke\n] as const;\n\nconst ADDED_CALL_KEYS = [\n  \"headers\",\n  \"promptIndex\",\n  \"stream_options\",\n  \"tools\",\n] as const;\n\nexport type ChatGroqCallOptions = Pick<\n  ChatCompletionsAPI.ChatCompletionCreateParamsBase,\n  (typeof CREATE_PARAMS_BASE_CALL_KEYS)[number]\n> &\n  BaseChatModelCallOptions & {\n    /**\n     * Additional headers to pass to the API.\n     */\n    headers?: Record<string, string | null | undefined>;\n    /**\n     * The index of the prompt in the list of prompts.\n     */\n    promptIndex?: number;\n    /**\n     * Additional options to pass to streamed completions.\n     * If provided takes precedence over \"streamUsage\" set at initialization time.\n     */\n    stream_options?: {\n      /**\n       * Whether or not to include token usage in the stream.\n       * If set to `true`, this will include an additional\n       * chunk at the end of the stream with the token usage.\n       *\n       * Defaults to `true` when streaming, `false` otherwise.\n       */\n      include_usage: boolean;\n    };\n\n    tools?: ChatGroqToolType[];\n\n    // IMPORTANT: If you add a new key here you MUST add it to the `ADDED_CALL_KEYS`\n    // list above. Keep this comment at the bottom so people see it when they go to\n    // make additions.\n  };\n\nconst ALL_CALL_KEYS: readonly (keyof ChatGroqCallOptions)[] = [\n  ...CREATE_PARAMS_BASE_CALL_KEYS,\n  ...ADDED_CALL_KEYS,\n] as const;\n\n/**\n * Timing details about the request, useful for collecting performance metrics.\n */\ninterface TimingMetadata {\n  /**\n   * Time spent generating tokens\n   */\n  completion_time?: number;\n\n  /**\n   * Time spent processing input tokens\n   */\n  prompt_time?: number;\n\n  /**\n   * Time the requests was spent queued\n   */\n  queue_time?: number;\n\n  /**\n   * completion time and prompt time combined\n   */\n  total_time?: number;\n}\nexport interface ChatGroqInput extends BaseChatModelParams {\n  /**\n   * The temperature to use for sampling.\n   * @default 0.7\n   */\n  temperature?: number;\n\n  /**\n   * The maximum number of tokens that the model can process in a single response.\n   * This limits ensures computational efficiency and resource management.\n   */\n  maxTokens?: number;\n\n  /** Total probability mass of tokens to consider at each step */\n  topP?: number;\n\n  /** Penalizes repeated tokens according to frequency */\n  frequencyPenalty?: number;\n\n  /** Penalizes repeated tokens */\n  presencePenalty?: number;\n\n  /** Number of completions to generate for each prompt */\n  n?: number;\n\n  /** Dictionary used to adjust the probability of specific tokens being generated */\n  logitBias?: Record<string, number>;\n\n  /** Unique string identifier representing your end-user, which can help OpenAI to monitor and detect abuse. */\n  user?: string;\n\n  /**\n   * Whether or not to include token usage data in streamed chunks.\n   * @default true\n   */\n  streamUsage?: boolean;\n\n  /**\n   * Whether to return log probabilities of the output tokens or not.\n   * If true, returns the log probabilities of each output token returned in the content of message.\n   */\n  logprobs?: boolean;\n\n  /**\n   * An integer between 0 and 5 specifying the number of most likely tokens to return at each token position,\n   * each with an associated log probability. logprobs must be set to true if this parameter is used.\n   */\n  topLogprobs?: number;\n\n  /**\n   * The Groq API key to use for requests.\n   * @default process.env.GROQ_API_KEY\n   */\n  apiKey?: string;\n  /**\n   * The name of the model to use.\n   */\n  model: ChatCompletionCreateParams[\"model\"];\n  /**\n   * Up to 4 sequences where the API will stop generating further tokens. The\n   * returned text will not contain the stop sequence.\n   * Alias for `stopSequences`\n   */\n  stop?: string | null | Array<string>;\n  /**\n   * Up to 4 sequences where the API will stop generating further tokens. The\n   * returned text will not contain the stop sequence.\n   */\n  stopSequences?: Array<string>;\n  /**\n   * Whether or not to stream responses.\n   */\n  streaming?: boolean;\n  /**\n   * Override the default base URL for the API\n   */\n  baseUrl?: string;\n  /**\n   * The maximum amount of time (in milliseconds) the client will wait for a response\n   */\n  timeout?: number;\n  /**\n   * HTTP agent used to manage connections\n   */\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  httpAgent?: any;\n  /**\n   * Custom fetch function implementation\n   */\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  fetch?: (...args: any) => any;\n\n  /**\n   * Default headers included with every request\n   */\n  defaultHeaders?: Record<string, string>;\n\n  /**\n   * Default query parameters included with every request\n   */\n  defaultQuery?: Record<string, string>;\n\n  /**\n   * The level of reasoning effort the model will use.\n   * Supported by `openai/gpt-oss-20b`, `openai/gpt-oss-120b`, and `qwen/qwen3-32b`.\n   * @see https://console.groq.com/docs/reasoning#options-for-reasoning-effort\n   */\n  reasoningEffort?: \"none\" | \"default\" | \"low\" | \"medium\" | \"high\" | null;\n}\n\ntype GroqRoleEnum = \"system\" | \"assistant\" | \"user\" | \"function\";\n\ninterface TokenUsage {\n  completionTokens?: number;\n  promptTokens?: number;\n  totalTokens?: number;\n}\n\n/**\n * Extract the custom role from a message.\n * @param message - The message to extract the custom role from.\n * @returns The custom role of the message.\n */\nfunction extractGenericMessageCustomRole(message: ChatMessage): GroqRoleEnum {\n  if (\n    message.role !== \"system\" &&\n    message.role !== \"assistant\" &&\n    message.role !== \"user\" &&\n    message.role !== \"function\"\n  ) {\n    throw new Error(\n      `Unsupported message role: ${message.role}. Expected \"system\", \"assistant\", \"user\", or \"function\"`\n    );\n  }\n  return message.role as GroqRoleEnum;\n}\n\n/**\n * Extract the role from a message.\n * @param message - The message to extract the role from.\n * @returns The role of the message.\n */\nexport function messageToGroqRole(message: BaseMessage): GroqRoleEnum {\n  switch (message.type) {\n    case \"system\":\n      return \"system\";\n    case \"ai\":\n      return \"assistant\";\n    case \"human\":\n      return \"user\";\n    case \"function\":\n      return \"function\";\n    case \"tool\":\n      // Not yet supported as a type\n      return \"tool\" as GroqRoleEnum;\n    case \"generic\": {\n      if (!ChatMessage.isInstance(message))\n        throw new Error(\"Invalid generic chat message\");\n      return extractGenericMessageCustomRole(message);\n    }\n    default:\n      throw new Error(`Unknown message type: ${message.type}`);\n  }\n}\n\nfunction convertMessagesToGroqParams(\n  messages: BaseMessage[]\n): Array<ChatCompletionsAPI.ChatCompletionMessage> {\n  return messages.map((message): ChatCompletionsAPI.ChatCompletionMessage => {\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    const completionParam: Record<string, any> = {\n      role: messageToGroqRole(message),\n      content: message.content,\n      name: message.name,\n      function_call: message.additional_kwargs.function_call,\n      tool_calls: message.additional_kwargs.tool_calls,\n      tool_call_id: (message as ToolMessage).tool_call_id,\n    };\n    if (isAIMessage(message) && !!message.tool_calls?.length) {\n      completionParam.tool_calls = message.tool_calls.map(\n        convertLangChainToolCallToOpenAI\n      );\n    } else {\n      if (message.additional_kwargs.tool_calls != null) {\n        completionParam.tool_calls = message.additional_kwargs.tool_calls;\n      }\n      if ((message as ToolMessage).tool_call_id != null) {\n        completionParam.tool_call_id = (message as ToolMessage).tool_call_id;\n      }\n    }\n    return completionParam as ChatCompletionsAPI.ChatCompletionMessage;\n  });\n}\n\nfunction groqResponseToChatMessage(\n  message: ChatCompletionsAPI.ChatCompletionMessage,\n  usageMetadata?: UsageMetadata,\n  responseMetadata?: Record<string, unknown>\n): BaseMessage {\n  const rawToolCalls: OpenAIToolCall[] | undefined = message.tool_calls as\n    | OpenAIToolCall[]\n    | undefined;\n  // Add model_provider for block translator lookup\n  const enrichedMetadata = { ...responseMetadata, model_provider: \"groq\" };\n  switch (message.role) {\n    case \"assistant\": {\n      const toolCalls = [];\n      const invalidToolCalls = [];\n      for (const rawToolCall of rawToolCalls ?? []) {\n        try {\n          toolCalls.push(parseToolCall(rawToolCall, { returnId: true }));\n          // eslint-disable-next-line @typescript-eslint/no-explicit-any\n        } catch (e: any) {\n          invalidToolCalls.push(makeInvalidToolCall(rawToolCall, e.message));\n        }\n      }\n      return new AIMessage({\n        content: message.content || \"\",\n        additional_kwargs: { tool_calls: rawToolCalls },\n        tool_calls: toolCalls,\n        invalid_tool_calls: invalidToolCalls,\n        usage_metadata: usageMetadata,\n        response_metadata: enrichedMetadata,\n      });\n    }\n    default:\n      return new ChatMessage(message.content || \"\", message.role ?? \"unknown\");\n  }\n}\n\nfunction _convertDeltaToMessageChunk(\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  delta: Record<string, any>,\n  defaultRole: GroqRoleEnum | undefined,\n  rawResponse: ChatCompletionsAPI.ChatCompletionChunk,\n  lastMessageId: string | undefined\n): BaseMessageChunk {\n  const role = delta.role ?? defaultRole;\n  const content = delta.content ?? \"\";\n  let additional_kwargs: Record<string, unknown>;\n  if (delta.function_call) {\n    additional_kwargs = {\n      function_call: delta.function_call,\n    };\n  } else if (delta.tool_calls) {\n    additional_kwargs = {\n      tool_calls: delta.tool_calls,\n    };\n  } else {\n    additional_kwargs = {};\n  }\n  if (delta.audio) {\n    additional_kwargs.audio = {\n      ...delta.audio,\n      index: rawResponse.choices[0].index,\n    };\n  }\n\n  let usage: UsageMetadata | undefined;\n  let groqMessageId: string | undefined = lastMessageId;\n  let timing: TimingMetadata | undefined;\n\n  const xGroq = rawResponse.x_groq;\n  if (xGroq?.usage) {\n    usage = {\n      input_tokens: xGroq.usage.prompt_tokens,\n      output_tokens: xGroq.usage.completion_tokens,\n      total_tokens: xGroq.usage.total_tokens,\n    };\n    timing = {\n      completion_time: xGroq.usage.completion_time,\n      prompt_time: xGroq.usage.prompt_time,\n      queue_time: xGroq.usage.queue_time,\n      total_time: xGroq.usage.total_time,\n    };\n  }\n\n  if (xGroq?.id) {\n    groqMessageId = xGroq.id;\n  }\n\n  const response_metadata = { usage, timing, model_provider: \"groq\" };\n  if (role === \"user\") {\n    return new HumanMessageChunk({ content, response_metadata });\n  } else if (role === \"assistant\") {\n    const toolCallChunks: ToolCallChunk[] = [];\n    if (Array.isArray(delta.tool_calls)) {\n      for (const rawToolCall of delta.tool_calls) {\n        toolCallChunks.push({\n          name: rawToolCall.function?.name,\n          args: rawToolCall.function?.arguments,\n          id: rawToolCall.id,\n          index: rawToolCall.index,\n          type: \"tool_call_chunk\",\n        });\n      }\n    }\n    return new AIMessageChunk({\n      content,\n      tool_call_chunks: toolCallChunks,\n      additional_kwargs,\n      id: groqMessageId,\n      response_metadata,\n    });\n  } else if (role === \"system\") {\n    return new SystemMessageChunk({ content, response_metadata });\n  } else if (role === \"developer\") {\n    return new SystemMessageChunk({\n      content,\n      response_metadata,\n      additional_kwargs: {\n        __openai_role__: \"developer\",\n      },\n    });\n  } else if (role === \"function\") {\n    return new FunctionMessageChunk({\n      content,\n      additional_kwargs,\n      name: delta.name,\n      response_metadata,\n    });\n  } else if (role === \"tool\") {\n    return new ToolMessageChunk({\n      content,\n      additional_kwargs,\n      tool_call_id: delta.tool_call_id,\n      response_metadata,\n    });\n  } else {\n    return new ChatMessageChunk({ content, role, response_metadata });\n  }\n}\n\n/*\nfunction _oldConvertDeltaToMessageChunk(\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  delta: Record<string, any>,\n  rawResponse: ChatCompletionsAPI.ChatCompletionChunk,\n  index: number,\n  defaultRole: GroqRoleEnum | undefined,\n  xGroq?: ChatCompletionsAPI.ChatCompletionChunk.XGroq\n): {\n  message: BaseMessageChunk;\n  toolCallData?: {\n    id: string;\n    name: string;\n    index: number;\n    type: \"tool_call_chunk\";\n  }[];\n} {\n  const { role } = delta;\n  const content = delta.content ?? \"\";\n  let additional_kwargs;\n  if (delta.function_call) {\n    additional_kwargs = {\n      function_call: delta.function_call,\n    };\n  } else if (delta.tool_calls) {\n    additional_kwargs = {\n      tool_calls: delta.tool_calls,\n    };\n  } else {\n    additional_kwargs = {};\n  }\n\n  let usageMetadata: UsageMetadata | undefined;\n  let groqMessageId: string | undefined;\n  if (xGroq?.usage) {\n    usageMetadata = {\n      input_tokens: xGroq.usage.prompt_tokens,\n      output_tokens: xGroq.usage.completion_tokens,\n      total_tokens: xGroq.usage.total_tokens,\n    };\n    groqMessageId = xGroq.id;\n  }\n\n  if (role === \"user\") {\n    return {\n      message: new HumanMessageChunk({ content }),\n    };\n  } else if (role === \"assistant\") {\n    const toolCallChunks = _convertDeltaToolCallToToolCallChunk(\n      delta.tool_calls,\n      index\n    );\n    return {\n      message: new AIMessageChunk({\n        content,\n        additional_kwargs,\n        tool_call_chunks: toolCallChunks\n          ? toolCallChunks.map((tc) => ({\n              type: tc.type,\n              args: tc.args,\n              index: tc.index,\n            }))\n          : undefined,\n        usage_metadata: usageMetadata,\n        id: groqMessageId,\n      }),\n      toolCallData: toolCallChunks\n        ? toolCallChunks.map((tc) => ({\n            id: tc.id ?? \"\",\n            name: tc.name ?? \"\",\n            index: tc.index ?? index,\n            type: \"tool_call_chunk\",\n          }))\n        : undefined,\n    };\n  } else if (role === \"system\") {\n    return {\n      message: new SystemMessageChunk({ content }),\n    };\n  } else {\n    return {\n      message: new ChatMessageChunk({ content, role }),\n    };\n  }\n}\n*/\n\n/**\n * Groq chat model integration.\n *\n * The Groq API is compatible to the OpenAI API with some limitations. View the\n * full API ref at:\n * @link {https://docs.api.groq.com/md/openai.oas.html}\n *\n * Setup:\n * Install `@langchain/groq` and set an environment variable named `GROQ_API_KEY`.\n *\n * ```bash\n * npm install @langchain/groq\n * export GROQ_API_KEY=\"your-api-key\"\n * ```\n *\n * ## [Constructor args](https://api.js.langchain.com/classes/langchain_groq.ChatGroq.html#constructor)\n *\n * ## [Runtime args](https://api.js.langchain.com/interfaces/langchain_groq.ChatGroqCallOptions.html)\n *\n * Runtime args can be passed as the second argument to any of the base runnable methods `.invoke`. `.stream`, `.batch`, etc.\n * They can also be passed via `.withConfig`, or the second arg in `.bindTools`, like shown in the examples below:\n *\n * ```typescript\n * // When calling `.withConfig`, call options should be passed via the first argument\n * const llmWithArgsBound = llm.withConfig({\n *   stop: [\"\\n\"],\n * });\n *\n * // When calling `.bindTools`, call options should be passed via the second argument\n * const llmWithTools = llm.bindTools(\n *   [...],\n *   {\n *     tool_choice: \"auto\",\n *   }\n * );\n * ```\n *\n * ## Examples\n *\n * <details open>\n * <summary><strong>Instantiate</strong></summary>\n *\n * ```typescript\n * import { ChatGroq } from '@langchain/groq';\n *\n * const llm = new ChatGroq({\n *   model: \"llama-3.3-70b-versatile\",\n *   temperature: 0,\n *   // other params...\n * });\n * ```\n * </details>\n *\n * <br />\n *\n * <details>\n * <summary><strong>Invoking</strong></summary>\n *\n * ```typescript\n * const input = `Translate \"I love programming\" into French.`;\n *\n * // Models also accept a list of chat messages or a formatted prompt\n * const result = await llm.invoke(input);\n * console.log(result);\n * ```\n *\n * ```txt\n * AIMessage {\n *   \"content\": \"The French translation of \\\"I love programming\\\" is \\\"J'aime programmer\\\". In this sentence, \\\"J'aime\\\" is the first person singular conjugation of the French verb \\\"aimer\\\" which means \\\"to love\\\", and \\\"programmer\\\" is the French infinitive for \\\"to program\\\". I hope this helps! Let me know if you have any other questions.\",\n *   \"additional_kwargs\": {},\n *   \"response_metadata\": {\n *     \"tokenUsage\": {\n *       \"completionTokens\": 82,\n *       \"promptTokens\": 20,\n *       \"totalTokens\": 102\n *     },\n *     \"finish_reason\": \"stop\"\n *   },\n *   \"tool_calls\": [],\n *   \"invalid_tool_calls\": []\n * }\n * ```\n * </details>\n *\n * <br />\n *\n * <details>\n * <summary><strong>Streaming Chunks</strong></summary>\n *\n * ```typescript\n * for await (const chunk of await llm.stream(input)) {\n *   console.log(chunk);\n * }\n * ```\n *\n * ```txt\n * AIMessageChunk {\n *   \"content\": \"\",\n *   \"additional_kwargs\": {},\n *   \"response_metadata\": {\n *     \"finishReason\": null\n *   },\n *   \"tool_calls\": [],\n *   \"tool_call_chunks\": [],\n *   \"invalid_tool_calls\": []\n * }\n * AIMessageChunk {\n *   \"content\": \"The\",\n *   \"additional_kwargs\": {},\n *   \"response_metadata\": {\n *     \"finishReason\": null\n *   },\n *   \"tool_calls\": [],\n *   \"tool_call_chunks\": [],\n *   \"invalid_tool_calls\": []\n * }\n * AIMessageChunk {\n *   \"content\": \" French\",\n *   \"additional_kwargs\": {},\n *   \"response_metadata\": {\n *     \"finishReason\": null\n *   },\n *   \"tool_calls\": [],\n *   \"tool_call_chunks\": [],\n *   \"invalid_tool_calls\": []\n * }\n * AIMessageChunk {\n *   \"content\": \" translation\",\n *   \"additional_kwargs\": {},\n *   \"response_metadata\": {\n *     \"finishReason\": null\n *   },\n *   \"tool_calls\": [],\n *   \"tool_call_chunks\": [],\n *   \"invalid_tool_calls\": []\n * }\n * AIMessageChunk {\n *   \"content\": \" of\",\n *   \"additional_kwargs\": {},\n *   \"response_metadata\": {\n *     \"finishReason\": null\n *   },\n *   \"tool_calls\": [],\n *   \"tool_call_chunks\": [],\n *   \"invalid_tool_calls\": []\n * }\n * AIMessageChunk {\n *   \"content\": \" \\\"\",\n *   \"additional_kwargs\": {},\n *   \"response_metadata\": {\n *     \"finishReason\": null\n *   },\n *   \"tool_calls\": [],\n *   \"tool_call_chunks\": [],\n *   \"invalid_tool_calls\": []\n * }\n * AIMessageChunk {\n *   \"content\": \"I\",\n *   \"additional_kwargs\": {},\n *   \"response_metadata\": {\n *     \"finishReason\": null\n *   },\n *   \"tool_calls\": [],\n *   \"tool_call_chunks\": [],\n *   \"invalid_tool_calls\": []\n * }\n * AIMessageChunk {\n *   \"content\": \" love\",\n *   \"additional_kwargs\": {},\n *   \"response_metadata\": {\n *     \"finishReason\": null\n *   },\n *   \"tool_calls\": [],\n *   \"tool_call_chunks\": [],\n *   \"invalid_tool_calls\": []\n * }\n * ...\n * AIMessageChunk {\n *   \"content\": \".\",\n *   \"additional_kwargs\": {},\n *   \"response_metadata\": {\n *     \"finishReason\": null\n *   },\n *   \"tool_calls\": [],\n *   \"tool_call_chunks\": [],\n *   \"invalid_tool_calls\": []\n * }\n * AIMessageChunk {\n *   \"content\": \"\",\n *   \"additional_kwargs\": {},\n *   \"response_metadata\": {\n *     \"finishReason\": \"stop\"\n *   },\n *   \"tool_calls\": [],\n *   \"tool_call_chunks\": [],\n *   \"invalid_tool_calls\": []\n * }\n * ```\n * </details>\n *\n * <br />\n *\n * <details>\n * <summary><strong>Aggregate Streamed Chunks</strong></summary>\n *\n * ```typescript\n * import { AIMessageChunk } from '@langchain/core/messages';\n * import { concat } from '@langchain/core/utils/stream';\n *\n * const stream = await llm.stream(input);\n * let full: AIMessageChunk | undefined;\n * for await (const chunk of stream) {\n *   full = !full ? chunk : concat(full, chunk);\n * }\n * console.log(full);\n * ```\n *\n * ```txt\n * AIMessageChunk {\n *   \"content\": \"The French translation of \\\"I love programming\\\" is \\\"J'aime programmer\\\". In this sentence, \\\"J'aime\\\" is the first person singular conjugation of the French verb \\\"aimer\\\" which means \\\"to love\\\", and \\\"programmer\\\" is the French infinitive for \\\"to program\\\". I hope this helps! Let me know if you have any other questions.\",\n *   \"additional_kwargs\": {},\n *   \"response_metadata\": {\n *     \"finishReason\": \"stop\"\n *   },\n *   \"tool_calls\": [],\n *   \"tool_call_chunks\": [],\n *   \"invalid_tool_calls\": []\n * }\n * ```\n * </details>\n *\n * <br />\n *\n * <details>\n * <summary><strong>Bind tools</strong></summary>\n *\n * ```typescript\n * import { z } from 'zod';\n *\n * const llmForToolCalling = new ChatGroq({\n *   model: \"llama3-groq-70b-8192-tool-use-preview\",\n *   temperature: 0,\n *   // other params...\n * });\n *\n * const GetWeather = {\n *   name: \"GetWeather\",\n *   description: \"Get the current weather in a given location\",\n *   schema: z.object({\n *     location: z.string().describe(\"The city and state, e.g. San Francisco, CA\")\n *   }),\n * }\n *\n * const GetPopulation = {\n *   name: \"GetPopulation\",\n *   description: \"Get the current population in a given location\",\n *   schema: z.object({\n *     location: z.string().describe(\"The city and state, e.g. San Francisco, CA\")\n *   }),\n * }\n *\n * const llmWithTools = llmForToolCalling.bindTools([GetWeather, GetPopulation]);\n * const aiMsg = await llmWithTools.invoke(\n *   \"Which city is hotter today and which is bigger: LA or NY?\"\n * );\n * console.log(aiMsg.tool_calls);\n * ```\n *\n * ```txt\n * [\n *   {\n *     name: 'GetWeather',\n *     args: { location: 'Los Angeles, CA' },\n *     type: 'tool_call',\n *     id: 'call_cd34'\n *   },\n *   {\n *     name: 'GetWeather',\n *     args: { location: 'New York, NY' },\n *     type: 'tool_call',\n *     id: 'call_68rf'\n *   },\n *   {\n *     name: 'GetPopulation',\n *     args: { location: 'Los Angeles, CA' },\n *     type: 'tool_call',\n *     id: 'call_f81z'\n *   },\n *   {\n *     name: 'GetPopulation',\n *     args: { location: 'New York, NY' },\n *     type: 'tool_call',\n *     id: 'call_8byt'\n *   }\n * ]\n * ```\n * </details>\n *\n * <br />\n *\n * <details>\n * <summary><strong>Structured Output</strong></summary>\n *\n * ```typescript\n * import { z } from 'zod';\n *\n * const Joke = z.object({\n *   setup: z.string().describe(\"The setup of the joke\"),\n *   punchline: z.string().describe(\"The punchline to the joke\"),\n *   rating: z.number().optional().describe(\"How funny the joke is, from 1 to 10\")\n * }).describe('Joke to tell user.');\n *\n * const structuredLlm = llmForToolCalling.withStructuredOutput(Joke, { name: \"Joke\" });\n * const jokeResult = await structuredLlm.invoke(\"Tell me a joke about cats\");\n * console.log(jokeResult);\n * ```\n *\n * ```txt\n * {\n *   setup: \"Why don't cats play poker in the wild?\",\n *   punchline: 'Because there are too many cheetahs.'\n * }\n * ```\n * </details>\n *\n * <br />\n */\nexport class ChatGroq extends BaseChatModel<\n  ChatGroqCallOptions,\n  AIMessageChunk\n> {\n  lc_namespace = [\"langchain\", \"chat_models\", \"groq\"];\n\n  client: Groq;\n\n  model: string;\n\n  temperature = 0.7;\n\n  stop?: string[];\n\n  stopSequences?: string[];\n\n  maxTokens?: number;\n\n  streaming = false;\n\n  apiKey?: string;\n\n  streamUsage: boolean = true;\n\n  topP: number | null | undefined;\n\n  frequencyPenalty: number | null | undefined;\n\n  presencePenalty: number | null | undefined;\n\n  logprobs: boolean | null | undefined;\n\n  n: number | null | undefined;\n\n  logitBias: Record<string, number> | null | undefined;\n\n  user: string | null | undefined;\n\n  reasoningEffort: ChatCompletionsAPI.ChatCompletionCreateParamsBase[\"reasoning_effort\"];\n\n  reasoningFormat: ChatCompletionsAPI.ChatCompletionCreateParamsBase[\"reasoning_format\"];\n\n  serviceTier: ChatCompletionsAPI.ChatCompletionCreateParamsBase[\"service_tier\"];\n\n  topLogprobs: number | null | undefined;\n\n  lc_serializable = true;\n\n  get lc_serialized_keys(): string[] {\n    return [\n      \"client\",\n      \"model\",\n      \"temperature\",\n      \"stop\",\n      \"stopSequences\",\n      \"maxTokens\",\n      \"streaming\",\n      \"apiKey\",\n      \"streamUsage\",\n      \"topP\",\n      \"frequencyPenalty\",\n      \"presencePenalty\",\n      \"logprobs\",\n      \"n\",\n      \"logitBias\",\n      \"user\",\n      \"reasoningEffort\",\n      \"reasoningFormat\",\n      \"serviceTier\",\n      \"topLogprobs\",\n    ];\n  }\n\n  static lc_name() {\n    return \"ChatGroq\";\n  }\n\n  _llmType() {\n    return \"groq\";\n  }\n\n  get lc_secrets(): { [key: string]: string } | undefined {\n    return {\n      apiKey: \"GROQ_API_KEY\",\n    };\n  }\n\n  get callKeys() {\n    return [...super.callKeys, ...ALL_CALL_KEYS];\n  }\n\n  constructor(\n    model: ChatCompletionCreateParams[\"model\"],\n    fields?: Omit<ChatGroqInput, \"model\">\n  );\n  constructor(fields: ChatGroqInput);\n  constructor(\n    modelOrFields?: string | ChatGroqInput,\n    fields?: Omit<ChatGroqInput, \"model\">\n  ) {\n    const params =\n      typeof modelOrFields === \"string\"\n        ? { ...(fields ?? {}), model: modelOrFields }\n        : (modelOrFields ?? {});\n    super(params);\n    this._addVersion(\"@langchain/groq\", __PKG_VERSION__);\n\n    const apiKey = params.apiKey || getEnvironmentVariable(\"GROQ_API_KEY\");\n    if (!apiKey) {\n      throw new Error(\n        `Groq API key not found. Please set the GROQ_API_KEY environment variable or provide the key into \"apiKey\"`\n      );\n    }\n    const defaultHeaders = {\n      \"User-Agent\": \"langchainjs\",\n      ...(params.defaultHeaders ?? {}),\n    };\n\n    this.client = new Groq({\n      apiKey,\n      dangerouslyAllowBrowser: true,\n      baseURL: params.baseUrl,\n      timeout: params.timeout,\n      httpAgent: params.httpAgent,\n      fetch: params.fetch,\n      maxRetries: 0,\n      defaultHeaders,\n      defaultQuery: params.defaultQuery,\n    });\n    this.apiKey = apiKey;\n    this.temperature = params.temperature ?? this.temperature;\n    this.model = params.model;\n    this.streaming = params.streaming ?? this.streaming;\n    this.stop =\n      params.stopSequences ??\n      (typeof params.stop === \"string\" ? [params.stop] : params.stop) ??\n      [];\n    this.stopSequences = this.stop;\n    this.maxTokens = params.maxTokens;\n    this.topP = params.topP;\n    this.frequencyPenalty = params.frequencyPenalty;\n    this.presencePenalty = params.presencePenalty;\n    this.logprobs = params.logprobs;\n    this.n = params.n;\n    this.logitBias = params.logitBias;\n    this.user = params.user;\n    this.reasoningEffort = params.reasoningEffort;\n  }\n\n  getLsParams(options: this[\"ParsedCallOptions\"]): LangSmithParams {\n    const params = this.invocationParams(options);\n    return {\n      ls_provider: \"groq\",\n      ls_model_name: this.model,\n      ls_model_type: \"chat\",\n      ls_temperature: params.temperature ?? this.temperature,\n      ls_max_tokens: params.max_tokens ?? this.maxTokens,\n      ls_stop: options.stop,\n    };\n  }\n\n  async completionWithRetry(\n    request: ChatCompletionCreateParamsStreaming,\n    options?: RequestOptions\n  ): Promise<AsyncIterable<ChatCompletionsAPI.ChatCompletionChunk>>;\n\n  async completionWithRetry(\n    request: ChatCompletionCreateParamsNonStreaming,\n    options?: RequestOptions\n  ): Promise<ChatCompletion>;\n\n  async completionWithRetry(\n    request: ChatCompletionCreateParams,\n    options?: RequestOptions\n  ): Promise<\n    AsyncIterable<ChatCompletionsAPI.ChatCompletionChunk> | ChatCompletion\n  > {\n    return this.caller.call(async () =>\n      this.client.chat.completions.create(request, options)\n    );\n  }\n\n  invocationParams(\n    options: this[\"ParsedCallOptions\"],\n    extra?: { streaming?: boolean }\n  ): Omit<ChatCompletionCreateParams, \"messages\"> {\n    const params = super.invocationParams(options);\n\n    let streamOptionsConfig = {};\n\n    if (options?.stream_options !== undefined) {\n      streamOptionsConfig = { stream_options: options.stream_options };\n    } else if ((this.streamUsage && this.streaming) || extra?.streaming) {\n      streamOptionsConfig = { stream_options: { include_usage: true } };\n    }\n\n    const toReturn: Omit<ChatCompletionCreateParams, \"messages\"> = {\n      model: this.model,\n      frequency_penalty: this.frequencyPenalty,\n      function_call: options?.function_call,\n      functions: options?.functions,\n      logit_bias: this.logitBias,\n      logprobs: this.logprobs,\n      // max_completion_tokens\n      // max_tokens\n      n: this.n,\n      parallel_tool_calls: options?.parallel_tool_calls,\n      presence_penalty: this.presencePenalty,\n      reasoning_effort: options?.reasoning_effort ?? this.reasoningEffort,\n      reasoning_format: this.reasoningFormat,\n      response_format: options?.response_format,\n      seed: options?.seed,\n      service_tier: this.serviceTier,\n      stop: options?.stop ?? this.stopSequences,\n      temperature: options?.temperature ?? this.temperature,\n      tool_choice: _formatToGroqToolChoice(options?.tool_choice),\n      tools: options?.tools?.length\n        ? options.tools.map((tool) => convertToOpenAITool(tool))\n        : undefined,\n      top_logprobs: this.topLogprobs,\n      top_p: this.topP,\n      user: this.user,\n      // if include_usage is set or streamUsage then stream must be set to true.\n      stream: this.streaming,\n      ...params,\n      ...streamOptionsConfig,\n    };\n\n    toReturn.max_completion_tokens =\n      options?.max_completion_tokens ?? options?.max_tokens ?? this.maxTokens;\n    if (toReturn.max_completion_tokens === -1) {\n      delete toReturn.max_completion_tokens;\n    }\n\n    return toReturn;\n  }\n\n  override bindTools(\n    tools: ChatGroqToolType[],\n    kwargs?: Partial<ChatGroqCallOptions>\n  ): Runnable<BaseLanguageModelInput, AIMessageChunk, ChatGroqCallOptions> {\n    return this.withConfig({\n      tools: tools.map((tool) => convertToOpenAITool(tool)),\n      ...kwargs,\n    });\n  }\n\n  override async *_streamResponseChunks(\n    messages: BaseMessage[],\n    options: this[\"ParsedCallOptions\"],\n    runManager?: CallbackManagerForLLMRun\n  ): AsyncGenerator<ChatGenerationChunk> {\n    const params = this.invocationParams(options, { streaming: true });\n    const messagesMapped = convertMessagesToGroqParams(messages);\n    const response = await this.completionWithRetry(\n      {\n        ...params,\n        messages: messagesMapped,\n        stream: true,\n      },\n      {\n        signal: options?.signal,\n        headers: options?.headers,\n      }\n    );\n    let role: GroqRoleEnum | undefined;\n    let lastMessageId: string | undefined;\n\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    let responseMetadata: Record<string, any> | undefined;\n\n    for await (const data of response) {\n      if (options.signal?.aborted) {\n        return;\n      }\n      responseMetadata = data;\n      const choice = data?.choices[0];\n      if (!choice) {\n        continue;\n      }\n      // The `role` field is populated in the first delta of the response\n      // but is not present in subsequent deltas. Extract it when available.\n      if (choice.delta?.role) {\n        role = choice.delta.role as GroqRoleEnum;\n      }\n\n      const chunk = _convertDeltaToMessageChunk(\n        choice.delta,\n        role,\n        data,\n        lastMessageId\n      );\n      const newTokenIndices = {\n        prompt: options.promptIndex ?? 0,\n        completion: choice.index ?? 0,\n      };\n      if (typeof chunk.content !== \"string\") {\n        console.log(\n          \"[WARNING]: Received non-string content from OpenAI. This is currently not supported.\"\n        );\n        continue;\n      }\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      const generationInfo: Record<string, any> = { ...newTokenIndices };\n      if (choice.finish_reason != null) {\n        generationInfo.finish_reason = choice.finish_reason;\n        // Only include system fingerprint in the last chunk for now\n        // to avoid concatenation issues\n        generationInfo.system_fingerprint = data.system_fingerprint;\n        generationInfo.model_name = data.model;\n      }\n      const generationChunk = new ChatGenerationChunk({\n        message: chunk,\n        text: chunk.content,\n        generationInfo,\n      });\n      yield generationChunk;\n      await runManager?.handleLLMNewToken(\n        generationChunk.text ?? \"\",\n        newTokenIndices,\n        undefined,\n        undefined,\n        undefined,\n        { chunk: generationChunk }\n      );\n    }\n\n    if (responseMetadata) {\n      if (\"choices\" in responseMetadata) {\n        delete responseMetadata.choices;\n      }\n      yield new ChatGenerationChunk({\n        message: new AIMessageChunk({\n          content: \"\",\n          response_metadata: responseMetadata,\n        }),\n        text: \"\",\n      });\n    }\n\n    if (options.signal?.aborted) {\n      throw new Error(\"AbortError\");\n    }\n  }\n\n  override async _generate(\n    messages: BaseMessage[],\n    options: this[\"ParsedCallOptions\"],\n    runManager?: CallbackManagerForLLMRun\n  ): Promise<ChatResult> {\n    options.signal?.throwIfAborted();\n    if (this.streaming) {\n      const tokenUsage: TokenUsage = {};\n      const stream = this._streamResponseChunks(messages, options, runManager);\n      const finalChunks: Record<number, ChatGenerationChunk> = {};\n      for await (const chunk of stream) {\n        const index =\n          (chunk.generationInfo as NewTokenIndices)?.completion ?? 0;\n        if (finalChunks[index] === undefined) {\n          finalChunks[index] = chunk;\n        } else {\n          finalChunks[index] = finalChunks[index].concat(chunk);\n        }\n      }\n      const generations = Object.entries(finalChunks)\n        .sort(([aKey], [bKey]) => parseInt(aKey, 10) - parseInt(bKey, 10))\n        .map(([_, value]) => value);\n\n      return { generations, llmOutput: { estimatedTokenUsage: tokenUsage } };\n    } else {\n      return this._generateNonStreaming(messages, options, runManager);\n    }\n  }\n\n  async _generateNonStreaming(\n    messages: BaseMessage[],\n    options: this[\"ParsedCallOptions\"],\n    _runManager?: CallbackManagerForLLMRun\n  ): Promise<ChatResult> {\n    const tokenUsage: TokenUsage = {};\n    const params = this.invocationParams(options);\n    const messagesMapped = convertMessagesToGroqParams(messages);\n\n    const data = await this.completionWithRetry(\n      {\n        ...params,\n        stream: false,\n        messages: messagesMapped,\n      },\n      {\n        signal: options?.signal,\n        headers: options?.headers,\n      }\n    );\n\n    if (\"usage\" in data && data.usage) {\n      const {\n        completion_tokens: completionTokens,\n        prompt_tokens: promptTokens,\n        total_tokens: totalTokens,\n      } = data.usage as CompletionsAPI.CompletionUsage;\n\n      if (completionTokens) {\n        tokenUsage.completionTokens =\n          (tokenUsage.completionTokens ?? 0) + completionTokens;\n      }\n\n      if (promptTokens) {\n        tokenUsage.promptTokens = (tokenUsage.promptTokens ?? 0) + promptTokens;\n      }\n\n      if (totalTokens) {\n        tokenUsage.totalTokens = (tokenUsage.totalTokens ?? 0) + totalTokens;\n      }\n    }\n\n    const generations: ChatGeneration[] = [];\n\n    if (\"choices\" in data && data.choices) {\n      for (const part of (data as ChatCompletion).choices) {\n        const text = part.message?.content ?? \"\";\n        let usageMetadata: UsageMetadata | undefined;\n        if (tokenUsage.totalTokens !== undefined) {\n          usageMetadata = {\n            input_tokens: tokenUsage.promptTokens ?? 0,\n            output_tokens: tokenUsage.completionTokens ?? 0,\n            total_tokens: tokenUsage.totalTokens,\n          };\n        }\n        // extract all fields from the response object except\n        // choices to be included as response metadata\n        const { choices: _choices, ...metadata } = data;\n\n        const generation: ChatGeneration = {\n          text,\n          message: groqResponseToChatMessage(\n            part.message ?? { role: \"assistant\" },\n            usageMetadata,\n            metadata\n          ),\n        };\n        generation.generationInfo = {\n          ...(part.finish_reason ? { finish_reason: part.finish_reason } : {}),\n          ...(part.logprobs ? { logprobs: part.logprobs } : {}),\n        };\n        generations.push(generation);\n      }\n    }\n\n    return {\n      generations,\n      llmOutput: { tokenUsage },\n    };\n  }\n\n  /**\n   * Return profiling information for the model.\n   *\n   * Provides information about the model's capabilities and constraints,\n   * including token limits, multimodal support, and advanced features like\n   * tool calling and structured output.\n   *\n   * @returns {ModelProfile} An object describing the model's capabilities and constraints\n   *\n   * @example\n   * ```typescript\n   * const model = new ChatGroq({ model: \"llama-3.1-8b-instant\" });\n   * const profile = model.profile;\n   * console.log(profile.maxInputTokens); // 128000\n   * console.log(profile.imageInputs); // true\n   * ```\n   */\n  get profile(): ModelProfile {\n    return PROFILES[this.model] ?? {};\n  }\n\n  withStructuredOutput<\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    RunOutput extends Record<string, any> = Record<string, any>,\n  >(\n    outputSchema:\n      | InteropZodType<RunOutput>\n      | SerializableSchema<RunOutput>\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      | Record<string, any>,\n    config?: StructuredOutputMethodOptions<false>\n  ): Runnable<BaseLanguageModelInput, RunOutput>;\n\n  withStructuredOutput<\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    RunOutput extends Record<string, any> = Record<string, any>,\n  >(\n    outputSchema:\n      | InteropZodType<RunOutput>\n      | SerializableSchema<RunOutput>\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      | Record<string, any>,\n    config?: StructuredOutputMethodOptions<true>\n  ): Runnable<BaseLanguageModelInput, { raw: BaseMessage; parsed: RunOutput }>;\n\n  withStructuredOutput<\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    RunOutput extends Record<string, any> = Record<string, any>,\n  >(\n    outputSchema:\n      | InteropZodType<RunOutput>\n      | SerializableSchema<RunOutput>\n      // eslint-disable-next-line @typescript-eslint/no-explicit-any\n      | Record<string, any>,\n    config?: StructuredOutputMethodOptions<boolean>\n  ):\n    | Runnable<BaseLanguageModelInput, RunOutput>\n    | Runnable<\n        BaseLanguageModelInput,\n        { raw: BaseMessage; parsed: RunOutput }\n      > {\n    const schema = outputSchema;\n    const name = config?.name;\n    const includeRaw = config?.includeRaw;\n\n    // Determine the structured output method based on model capabilities\n    const method = getGroqStructuredOutputMethod(this.model, config?.method);\n\n    let functionName = name ?? \"extract\";\n    let outputParser: BaseLLMOutputParser<RunOutput>;\n    let llm: Runnable<BaseLanguageModelInput>;\n\n    if (method === \"jsonSchema\") {\n      // Native JSON Schema mode for gpt-oss models\n      // Uses Groq's strict JSON Schema response format\n      const schemaName = name ?? \"structured_output\";\n      const description = getSchemaDescription(schema);\n      const jsonSchema =\n        isInteropZodSchema(schema) || isSerializableSchema(schema)\n          ? toJsonSchema(schema)\n          : schema;\n\n      // Transform schema for Groq strict mode requirements\n      const strictSchema = groqStrictifySchema(jsonSchema);\n\n      llm = this.withConfig({\n        response_format: {\n          type: \"json_schema\",\n          json_schema: {\n            name: schemaName,\n            description,\n            strict: true,\n            schema: strictSchema,\n          },\n        },\n        ls_structured_output_format: {\n          kwargs: { method: \"jsonSchema\" },\n          schema: {\n            title: schemaName,\n            description,\n            ...jsonSchema,\n          },\n        },\n      });\n\n      outputParser = createContentParser(schema);\n    } else if (method === \"jsonMode\") {\n      outputParser = createContentParser(schema);\n\n      const outputSchema =\n        isInteropZodSchema(schema) || isSerializableSchema(schema)\n          ? toJsonSchema(schema)\n          : schema;\n\n      llm = this.withConfig({\n        response_format: { type: \"json_object\" },\n        ls_structured_output_format: {\n          kwargs: { method: \"jsonMode\" },\n          schema: outputSchema,\n        },\n      });\n    } else {\n      let toolFunction: FunctionDefinition;\n      if (isInteropZodSchema(schema) || isSerializableSchema(schema)) {\n        const asJsonSchema = toJsonSchema(schema);\n        toolFunction = {\n          name: functionName,\n          description: asJsonSchema.description,\n          parameters: asJsonSchema,\n        };\n      } else if (\n        typeof schema.name === \"string\" &&\n        typeof schema.parameters === \"object\" &&\n        schema.parameters != null\n      ) {\n        toolFunction = schema as FunctionDefinition;\n        functionName = schema.name;\n      } else {\n        functionName = schema.title ?? functionName;\n        toolFunction = {\n          name: functionName,\n          description: schema.description ?? \"\",\n          parameters: schema,\n        };\n      }\n\n      llm = this.bindTools([\n        { type: \"function\" as const, function: toolFunction },\n      ]).withConfig({\n        tool_choice: {\n          type: \"function\" as const,\n          function: { name: functionName },\n        },\n        ls_structured_output_format: {\n          kwargs: { method: \"functionCalling\" },\n          schema: toolFunction.parameters,\n        },\n      });\n\n      outputParser = createFunctionCallingParser(schema, functionName);\n    }\n\n    return assembleStructuredOutputPipeline(\n      llm,\n      outputParser,\n      includeRaw,\n      \"ChatGroqStructuredOutput\"\n    );\n  }\n}\n\nfunction _formatToGroqToolChoice(\n  toolChoice?: string | ChatCompletionsAPI.ChatCompletionNamedToolChoice\n):\n  | ChatCompletionsAPI.ChatCompletionToolChoiceOption\n  | Record<string, unknown>\n  | null\n  | undefined {\n  if (!toolChoice) {\n    return undefined;\n  } else if (toolChoice === \"any\" || toolChoice === \"required\") {\n    return \"required\";\n  } else if (toolChoice === \"auto\") {\n    return \"auto\";\n  } else if (toolChoice === \"none\") {\n    return \"none\";\n  } else if (typeof toolChoice === \"string\") {\n    return {\n      type: \"function\",\n      function: {\n        name: toolChoice,\n      },\n    };\n  } else {\n    return toolChoice;\n  }\n}\n"],"mappings":"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"}