@langchain/openai 0.6.1 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ChatOpenAI = exports.ChatOpenAICompletions = exports.ChatOpenAIResponses = void 0;
3
+ exports.ChatOpenAI = exports.ChatOpenAICompletions = exports.ChatOpenAIResponses = exports.BaseChatOpenAI = void 0;
4
4
  exports.messageToOpenAIRole = messageToOpenAIRole;
5
5
  exports._convertMessagesToOpenAIParams = _convertMessagesToOpenAIParams;
6
6
  const openai_1 = require("openai");
@@ -476,12 +476,14 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
476
476
  writable: true,
477
477
  value: void 0
478
478
  });
479
+ /** @internal */
479
480
  Object.defineProperty(this, "client", {
480
481
  enumerable: true,
481
482
  configurable: true,
482
483
  writable: true,
483
484
  value: void 0
484
485
  });
486
+ /** @internal */
485
487
  Object.defineProperty(this, "clientConfig", {
486
488
  enumerable: true,
487
489
  configurable: true,
@@ -543,6 +545,12 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
543
545
  writable: true,
544
546
  value: void 0
545
547
  });
548
+ Object.defineProperty(this, "defaultOptions", {
549
+ enumerable: true,
550
+ configurable: true,
551
+ writable: true,
552
+ value: void 0
553
+ });
546
554
  Object.defineProperty(this, "lc_serializable", {
547
555
  enumerable: true,
548
556
  configurable: true,
@@ -637,6 +645,13 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
637
645
  }
638
646
  return resFormat;
639
647
  }
648
+ _combineCallOptions(additionalOptions) {
649
+ return {
650
+ ...this.defaultOptions,
651
+ ...(additionalOptions ?? {}),
652
+ };
653
+ }
654
+ /** @internal */
640
655
  _getClientOptions(options) {
641
656
  if (!this.client) {
642
657
  const openAIEndpointConfig = {
@@ -691,6 +706,12 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
691
706
  ...kwargs,
692
707
  });
693
708
  }
709
+ async stream(input, options) {
710
+ return super.stream(input, this._combineCallOptions(options));
711
+ }
712
+ async invoke(input, options) {
713
+ return super.invoke(input, this._combineCallOptions(options));
714
+ }
694
715
  /** @ignore */
695
716
  _combineLLMOutput(...llmOutputs) {
696
717
  return llmOutputs.reduce((acc, llmOutput) => {
@@ -798,13 +819,22 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
798
819
  }
799
820
  return tokens;
800
821
  }
822
+ /** @internal */
823
+ _getStructuredOutputMethod(config) {
824
+ const ensuredConfig = { ...config };
825
+ if (!this.model.startsWith("gpt-3") &&
826
+ !this.model.startsWith("gpt-4-") &&
827
+ this.model !== "gpt-4") {
828
+ if (ensuredConfig?.method === undefined) {
829
+ return "jsonSchema";
830
+ }
831
+ }
832
+ else if (ensuredConfig.method === "jsonSchema") {
833
+ console.warn(`[WARNING]: JSON Schema is not supported for model "${this.model}". Falling back to tool calling.`);
834
+ }
835
+ return ensuredConfig.method;
836
+ }
801
837
  withStructuredOutput(outputSchema, config) {
802
- // ):
803
- // | Runnable<BaseLanguageModelInput, RunOutput>
804
- // | Runnable<
805
- // BaseLanguageModelInput,
806
- // { raw: BaseMessage; parsed: RunOutput }
807
- // > {
808
838
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
809
839
  let schema;
810
840
  let name;
@@ -827,47 +857,43 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
827
857
  if (config?.strict !== undefined && method === "jsonMode") {
828
858
  throw new Error("Argument `strict` is only supported for `method` = 'function_calling'");
829
859
  }
830
- if (!this.model.startsWith("gpt-3") &&
831
- !this.model.startsWith("gpt-4-") &&
832
- this.model !== "gpt-4") {
833
- if (method === undefined) {
834
- method = "jsonSchema";
835
- }
836
- }
837
- else if (method === "jsonSchema") {
838
- console.warn(`[WARNING]: JSON Schema is not supported for model "${this.model}". Falling back to tool calling.`);
839
- }
860
+ method = this._getStructuredOutputMethod({ ...config, method });
840
861
  if (method === "jsonMode") {
841
- let outputFormatSchema;
842
862
  if ((0, types_1.isInteropZodSchema)(schema)) {
843
863
  outputParser = output_parsers_1.StructuredOutputParser.fromZodSchema(schema);
844
- outputFormatSchema = (0, json_schema_1.toJsonSchema)(schema);
845
864
  }
846
865
  else {
847
866
  outputParser = new output_parsers_1.JsonOutputParser();
848
867
  }
868
+ const asJsonSchema = (0, json_schema_1.toJsonSchema)(schema);
849
869
  llm = this.withConfig({
850
870
  response_format: { type: "json_object" },
851
871
  ls_structured_output_format: {
852
- kwargs: { method: "jsonMode" },
853
- schema: outputFormatSchema,
872
+ kwargs: { method: "json_mode" },
873
+ schema: { title: name ?? "extract", ...asJsonSchema },
854
874
  },
855
875
  });
856
876
  }
857
877
  else if (method === "jsonSchema") {
878
+ const openaiJsonSchemaParams = {
879
+ name: name ?? "extract",
880
+ description: (0, types_1.getSchemaDescription)(schema),
881
+ schema,
882
+ strict: config?.strict,
883
+ };
884
+ const asJsonSchema = (0, json_schema_1.toJsonSchema)(openaiJsonSchemaParams.schema);
858
885
  llm = this.withConfig({
859
886
  response_format: {
860
887
  type: "json_schema",
861
- json_schema: {
862
- name: name ?? "extract",
863
- description: (0, types_1.getSchemaDescription)(schema),
864
- schema,
865
- strict: config?.strict,
866
- },
888
+ json_schema: openaiJsonSchemaParams,
867
889
  },
868
890
  ls_structured_output_format: {
869
- kwargs: { method: "jsonSchema" },
870
- schema: (0, json_schema_1.toJsonSchema)(schema),
891
+ kwargs: { method: "json_schema" },
892
+ schema: {
893
+ title: openaiJsonSchemaParams.name,
894
+ description: openaiJsonSchemaParams.description,
895
+ ...asJsonSchema,
896
+ },
871
897
  },
872
898
  });
873
899
  if ((0, types_1.isInteropZodSchema)(schema)) {
@@ -906,8 +932,8 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
906
932
  },
907
933
  },
908
934
  ls_structured_output_format: {
909
- kwargs: { method: "functionCalling" },
910
- schema: asJsonSchema,
935
+ kwargs: { method: "function_calling" },
936
+ schema: { title: functionName, ...asJsonSchema },
911
937
  },
912
938
  // Do not pass `strict` argument to OpenAI if `config.strict` is undefined
913
939
  ...(config?.strict !== undefined ? { strict: config.strict } : {}),
@@ -934,6 +960,7 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
934
960
  parameters: schema,
935
961
  };
936
962
  }
963
+ const asJsonSchema = (0, json_schema_1.toJsonSchema)(schema);
937
964
  llm = this.withConfig({
938
965
  tools: [
939
966
  {
@@ -948,8 +975,8 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
948
975
  },
949
976
  },
950
977
  ls_structured_output_format: {
951
- kwargs: { method: "functionCalling" },
952
- schema: (0, json_schema_1.toJsonSchema)(schema),
978
+ kwargs: { method: "function_calling" },
979
+ schema: { title: functionName, ...asJsonSchema },
953
980
  },
954
981
  // Do not pass `strict` argument to OpenAI if `config.strict` is undefined
955
982
  ...(config?.strict !== undefined ? { strict: config.strict } : {}),
@@ -976,6 +1003,7 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
976
1003
  return runnables_1.RunnableSequence.from([{ raw: llm }, parsedWithFallback]);
977
1004
  }
978
1005
  }
1006
+ exports.BaseChatOpenAI = BaseChatOpenAI;
979
1007
  /**
980
1008
  * OpenAI Responses API implementation.
981
1009
  *
@@ -2590,7 +2618,7 @@ class ChatOpenAI extends BaseChatOpenAI {
2590
2618
  return [...super.lc_serializable_keys, "useResponsesApi"];
2591
2619
  }
2592
2620
  constructor(fields) {
2593
- super(fields ?? {});
2621
+ super(fields);
2594
2622
  /**
2595
2623
  * Whether to use the responses API for all requests. If `false` the responses API will be used
2596
2624
  * only when required in order to fulfill the request.
@@ -2614,8 +2642,8 @@ class ChatOpenAI extends BaseChatOpenAI {
2614
2642
  value: void 0
2615
2643
  });
2616
2644
  this.useResponsesApi = fields?.useResponsesApi ?? false;
2617
- this.responses = new ChatOpenAIResponses(fields);
2618
- this.completions = new ChatOpenAICompletions(fields);
2645
+ this.responses = fields?.responses ?? new ChatOpenAIResponses(fields);
2646
+ this.completions = fields?.completions ?? new ChatOpenAICompletions(fields);
2619
2647
  }
2620
2648
  _useResponsesApi(options) {
2621
2649
  const usesBuiltInTools = options?.tools?.some(isBuiltInTool);
@@ -2627,6 +2655,20 @@ class ChatOpenAI extends BaseChatOpenAI {
2627
2655
  this.reasoning?.summary != null;
2628
2656
  return this.useResponsesApi || usesBuiltInTools || hasResponsesOnlyKwargs;
2629
2657
  }
2658
+ getLsParams(options) {
2659
+ const optionsWithDefaults = this._combineCallOptions(options);
2660
+ if (this._useResponsesApi(options)) {
2661
+ return this.responses.getLsParams(optionsWithDefaults);
2662
+ }
2663
+ return this.completions.getLsParams(optionsWithDefaults);
2664
+ }
2665
+ invocationParams(options) {
2666
+ const optionsWithDefaults = this._combineCallOptions(options);
2667
+ if (this._useResponsesApi(options)) {
2668
+ return this.responses.invocationParams(optionsWithDefaults);
2669
+ }
2670
+ return this.completions.invocationParams(optionsWithDefaults);
2671
+ }
2630
2672
  /** @ignore */
2631
2673
  async _generate(messages, options, runManager) {
2632
2674
  if (this._useResponsesApi(options)) {
@@ -2636,33 +2678,14 @@ class ChatOpenAI extends BaseChatOpenAI {
2636
2678
  }
2637
2679
  async *_streamResponseChunks(messages, options, runManager) {
2638
2680
  if (this._useResponsesApi(options)) {
2639
- yield* this.responses._streamResponseChunks(messages, options);
2681
+ yield* this.responses._streamResponseChunks(messages, this._combineCallOptions(options));
2640
2682
  return;
2641
2683
  }
2642
- yield* this.completions._streamResponseChunks(messages, options, runManager);
2684
+ yield* this.completions._streamResponseChunks(messages, this._combineCallOptions(options), runManager);
2643
2685
  }
2644
2686
  withConfig(config) {
2645
- // FIXME: assigning additional config options to the inner chat classes this way
2646
- // is awkward, but it's the only way to preserve the original object identity
2647
- // and still thread config options, which is important since this class is a "proxy"
2648
- // for the inner chat classes. This will be fixed in a later version of langchain
2649
- // when the core runnable interface is improved (0.4) to support this out of the box.
2650
- const bindChatOpenAIConfig = (cls, config) => {
2651
- const oldGenerate = cls._generate;
2652
- const oldStreamResponseChunks = cls._streamResponseChunks;
2653
- return Object.assign(cls, {
2654
- _generate(messages, options, runManager) {
2655
- return oldGenerate.call(cls, messages, { ...options, ...config }, runManager);
2656
- },
2657
- _streamResponseChunks(messages, options, runManager) {
2658
- return oldStreamResponseChunks.call(cls, messages, { ...options, ...config }, runManager);
2659
- },
2660
- });
2661
- };
2662
- this.responses = bindChatOpenAIConfig(this.responses, config);
2663
- this.completions = bindChatOpenAIConfig(this.completions, config);
2664
- // Proxy chat class is also bound for `_useResponsesApi`,
2665
- return bindChatOpenAIConfig(this, config);
2687
+ this.defaultOptions = { ...this.defaultOptions, ...config };
2688
+ return this;
2666
2689
  }
2667
2690
  }
2668
2691
  exports.ChatOpenAI = ChatOpenAI;
@@ -22,7 +22,7 @@ interface OpenAILLMOutput {
22
22
  export type { OpenAICallOptions, OpenAIChatInput };
23
23
  export declare function messageToOpenAIRole(message: BaseMessage): OpenAIClient.ChatCompletionRole;
24
24
  export declare function _convertMessagesToOpenAIParams(messages: BaseMessage[], model?: string): OpenAIClient.Chat.Completions.ChatCompletionMessageParam[];
25
- interface BaseChatOpenAICallOptions extends OpenAICallOptions, BaseFunctionCallOptions {
25
+ export interface BaseChatOpenAICallOptions extends OpenAICallOptions, BaseFunctionCallOptions {
26
26
  /**
27
27
  * A list of tools that the model may use to generate responses.
28
28
  * Each tool can be a function, a built-in tool, or a custom tool definition.
@@ -120,7 +120,7 @@ export interface BaseChatOpenAIFields extends Partial<OpenAIChatInput>, BaseChat
120
120
  configuration?: ClientOptions;
121
121
  }
122
122
  /** @internal */
123
- declare abstract class BaseChatOpenAI<CallOptions extends BaseChatOpenAICallOptions> extends BaseChatModel<CallOptions, AIMessageChunk> implements Partial<OpenAIChatInput> {
123
+ export declare abstract class BaseChatOpenAI<CallOptions extends BaseChatOpenAICallOptions> extends BaseChatModel<CallOptions, AIMessageChunk> implements Partial<OpenAIChatInput> {
124
124
  temperature?: number;
125
125
  topP?: number;
126
126
  frequencyPenalty?: number;
@@ -141,8 +141,10 @@ declare abstract class BaseChatOpenAI<CallOptions extends BaseChatOpenAICallOpti
141
141
  apiKey?: string;
142
142
  organization?: string;
143
143
  __includeRawResponse?: boolean;
144
- protected client: OpenAIClient;
145
- protected clientConfig: ClientOptions;
144
+ /** @internal */
145
+ client: OpenAIClient;
146
+ /** @internal */
147
+ clientConfig: ClientOptions;
146
148
  /**
147
149
  * Whether the model supports the `strict` argument when passing in tools.
148
150
  * If `undefined` the `strict` argument will not be passed to OpenAI.
@@ -168,6 +170,7 @@ declare abstract class BaseChatOpenAI<CallOptions extends BaseChatOpenAICallOpti
168
170
  * Specifies the service tier for prioritization and latency optimization.
169
171
  */
170
172
  service_tier?: OpenAIClient.Chat.ChatCompletionCreateParams["service_tier"];
173
+ protected defaultOptions: CallOptions;
171
174
  _llmType(): string;
172
175
  static lc_name(): string;
173
176
  get callKeys(): string[];
@@ -199,11 +202,15 @@ declare abstract class BaseChatOpenAI<CallOptions extends BaseChatOpenAICallOpti
199
202
  * @internal
200
203
  */
201
204
  protected _getResponseFormat(resFormat?: CallOptions["response_format"]): ResponseFormatText | ResponseFormatJSONObject | ResponseFormatJSONSchema | undefined;
202
- protected _getClientOptions(options: OpenAICoreRequestOptions | undefined): OpenAICoreRequestOptions;
205
+ protected _combineCallOptions(additionalOptions?: this["ParsedCallOptions"]): this["ParsedCallOptions"];
206
+ /** @internal */
207
+ _getClientOptions(options: OpenAICoreRequestOptions | undefined): OpenAICoreRequestOptions;
203
208
  protected _convertChatOpenAIToolToCompletionsTool(tool: ChatOpenAIToolType, fields?: {
204
209
  strict?: boolean;
205
210
  }): OpenAIClient.ChatCompletionTool;
206
211
  bindTools(tools: ChatOpenAIToolType[], kwargs?: Partial<CallOptions>): Runnable<BaseLanguageModelInput, AIMessageChunk, CallOptions>;
212
+ stream(input: BaseLanguageModelInput, options?: CallOptions): Promise<import("@langchain/core/utils/stream").IterableReadableStream<AIMessageChunk>>;
213
+ invoke(input: BaseLanguageModelInput, options?: CallOptions): Promise<AIMessageChunk>;
207
214
  /** @ignore */
208
215
  _combineLLMOutput(...llmOutputs: OpenAILLMOutput[]): OpenAILLMOutput;
209
216
  getNumTokensFromMessages(messages: BaseMessage[]): Promise<{
@@ -214,6 +221,8 @@ declare abstract class BaseChatOpenAI<CallOptions extends BaseChatOpenAICallOpti
214
221
  protected _getNumTokensFromGenerations(generations: ChatGeneration[]): Promise<number>;
215
222
  /** @internal */
216
223
  protected _getEstimatedTokenCountFromPrompt(messages: BaseMessage[], functions?: OpenAIClient.Chat.ChatCompletionCreateParams.Function[], function_call?: "none" | "auto" | OpenAIClient.Chat.ChatCompletionFunctionCallOption): Promise<number>;
224
+ /** @internal */
225
+ protected _getStructuredOutputMethod(config: StructuredOutputMethodOptions<boolean>): string | undefined;
217
226
  withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: InteropZodType<RunOutput> | Record<string, any>, config?: StructuredOutputMethodOptions<false>): Runnable<BaseLanguageModelInput, RunOutput>;
218
227
  withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: InteropZodType<RunOutput> | Record<string, any>, config?: StructuredOutputMethodOptions<true>): Runnable<BaseLanguageModelInput, {
219
228
  raw: BaseMessage;
@@ -231,7 +240,7 @@ type ResponsesCreate = OpenAIClient.Responses["create"];
231
240
  type ResponsesParse = OpenAIClient.Responses["parse"];
232
241
  type ResponsesCreateInvoke = ExcludeController<Awaited<ReturnType<ResponsesCreate>>>;
233
242
  type ResponsesParseInvoke = ExcludeController<Awaited<ReturnType<ResponsesParse>>>;
234
- interface ChatOpenAIResponsesCallOptions extends BaseChatOpenAICallOptions {
243
+ export interface ChatOpenAIResponsesCallOptions extends BaseChatOpenAICallOptions {
235
244
  /**
236
245
  * Configuration options for a text response from the model. Can be plain text or
237
246
  * structured JSON data.
@@ -285,7 +294,7 @@ export declare class ChatOpenAIResponses<CallOptions extends ChatOpenAIResponses
285
294
  strict?: boolean;
286
295
  }): ResponsesTool[];
287
296
  }
288
- interface ChatOpenAICompletionsCallOptions extends BaseChatOpenAICallOptions {
297
+ export interface ChatOpenAICompletionsCallOptions extends BaseChatOpenAICallOptions {
289
298
  }
290
299
  type ChatCompletionsInvocationParams = Omit<OpenAIClient.Chat.Completions.ChatCompletionCreateParams, "messages">;
291
300
  /**
@@ -313,6 +322,16 @@ export interface ChatOpenAIFields extends BaseChatOpenAIFields {
313
322
  * only when required in order to fulfill the request.
314
323
  */
315
324
  useResponsesApi?: boolean;
325
+ /**
326
+ * The completions chat instance
327
+ * @internal
328
+ */
329
+ completions?: ChatOpenAICompletions;
330
+ /**
331
+ * The responses chat instance
332
+ * @internal
333
+ */
334
+ responses?: ChatOpenAIResponses;
316
335
  }
317
336
  /**
318
337
  * OpenAI chat model integration.
@@ -852,17 +871,19 @@ export interface ChatOpenAIFields extends BaseChatOpenAIFields {
852
871
  *
853
872
  * <br />
854
873
  */
855
- export declare class ChatOpenAI<CallOptions extends ChatOpenAICallOptions = ChatOpenAICallOptions> extends BaseChatOpenAI<CallOptions> implements Partial<OpenAIChatInput> {
874
+ export declare class ChatOpenAI<CallOptions extends ChatOpenAICallOptions = ChatOpenAICallOptions> extends BaseChatOpenAI<CallOptions> {
856
875
  /**
857
876
  * Whether to use the responses API for all requests. If `false` the responses API will be used
858
877
  * only when required in order to fulfill the request.
859
878
  */
860
879
  useResponsesApi: boolean;
861
- private responses;
862
- private completions;
880
+ protected responses: ChatOpenAIResponses;
881
+ protected completions: ChatOpenAICompletions;
863
882
  get lc_serializable_keys(): string[];
864
883
  constructor(fields?: ChatOpenAIFields);
865
884
  protected _useResponsesApi(options: this["ParsedCallOptions"] | undefined): boolean;
885
+ getLsParams(options: this["ParsedCallOptions"]): LangSmithParams;
886
+ invocationParams(options?: this["ParsedCallOptions"]): ChatResponsesInvocationParams | ChatCompletionsInvocationParams;
866
887
  /** @ignore */
867
888
  _generate(messages: BaseMessage[], options: this["ParsedCallOptions"], runManager?: CallbackManagerForLLMRun): Promise<ChatResult>;
868
889
  _streamResponseChunks(messages: BaseMessage[], options: this["ParsedCallOptions"], runManager?: CallbackManagerForLLMRun): AsyncGenerator<ChatGenerationChunk>;
@@ -8,7 +8,7 @@ import { RunnableLambda, RunnablePassthrough, RunnableSequence, } from "@langcha
8
8
  import { JsonOutputParser, StructuredOutputParser, } from "@langchain/core/output_parsers";
9
9
  import { JsonOutputKeyToolsParser, convertLangChainToolCallToOpenAI, makeInvalidToolCall, parseToolCall, } from "@langchain/core/output_parsers/openai_tools";
10
10
  import { getSchemaDescription, isInteropZodSchema, } from "@langchain/core/utils/types";
11
- import { toJsonSchema, } from "@langchain/core/utils/json_schema";
11
+ import { toJsonSchema } from "@langchain/core/utils/json_schema";
12
12
  import { getEndpoint } from "./utils/azure.js";
13
13
  import { formatToOpenAIToolChoice, interopZodResponseFormat, wrapOpenAIClientError, } from "./utils/openai.js";
14
14
  import { formatFunctionDefinitions, } from "./utils/openai-format-fndef.js";
@@ -252,7 +252,7 @@ export function _convertMessagesToOpenAIParams(messages, model) {
252
252
  });
253
253
  }
254
254
  /** @internal */
255
- class BaseChatOpenAI extends BaseChatModel {
255
+ export class BaseChatOpenAI extends BaseChatModel {
256
256
  _llmType() {
257
257
  return "openai";
258
258
  }
@@ -471,12 +471,14 @@ class BaseChatOpenAI extends BaseChatModel {
471
471
  writable: true,
472
472
  value: void 0
473
473
  });
474
+ /** @internal */
474
475
  Object.defineProperty(this, "client", {
475
476
  enumerable: true,
476
477
  configurable: true,
477
478
  writable: true,
478
479
  value: void 0
479
480
  });
481
+ /** @internal */
480
482
  Object.defineProperty(this, "clientConfig", {
481
483
  enumerable: true,
482
484
  configurable: true,
@@ -538,6 +540,12 @@ class BaseChatOpenAI extends BaseChatModel {
538
540
  writable: true,
539
541
  value: void 0
540
542
  });
543
+ Object.defineProperty(this, "defaultOptions", {
544
+ enumerable: true,
545
+ configurable: true,
546
+ writable: true,
547
+ value: void 0
548
+ });
541
549
  Object.defineProperty(this, "lc_serializable", {
542
550
  enumerable: true,
543
551
  configurable: true,
@@ -632,6 +640,13 @@ class BaseChatOpenAI extends BaseChatModel {
632
640
  }
633
641
  return resFormat;
634
642
  }
643
+ _combineCallOptions(additionalOptions) {
644
+ return {
645
+ ...this.defaultOptions,
646
+ ...(additionalOptions ?? {}),
647
+ };
648
+ }
649
+ /** @internal */
635
650
  _getClientOptions(options) {
636
651
  if (!this.client) {
637
652
  const openAIEndpointConfig = {
@@ -686,6 +701,12 @@ class BaseChatOpenAI extends BaseChatModel {
686
701
  ...kwargs,
687
702
  });
688
703
  }
704
+ async stream(input, options) {
705
+ return super.stream(input, this._combineCallOptions(options));
706
+ }
707
+ async invoke(input, options) {
708
+ return super.invoke(input, this._combineCallOptions(options));
709
+ }
689
710
  /** @ignore */
690
711
  _combineLLMOutput(...llmOutputs) {
691
712
  return llmOutputs.reduce((acc, llmOutput) => {
@@ -793,13 +814,22 @@ class BaseChatOpenAI extends BaseChatModel {
793
814
  }
794
815
  return tokens;
795
816
  }
817
+ /** @internal */
818
+ _getStructuredOutputMethod(config) {
819
+ const ensuredConfig = { ...config };
820
+ if (!this.model.startsWith("gpt-3") &&
821
+ !this.model.startsWith("gpt-4-") &&
822
+ this.model !== "gpt-4") {
823
+ if (ensuredConfig?.method === undefined) {
824
+ return "jsonSchema";
825
+ }
826
+ }
827
+ else if (ensuredConfig.method === "jsonSchema") {
828
+ console.warn(`[WARNING]: JSON Schema is not supported for model "${this.model}". Falling back to tool calling.`);
829
+ }
830
+ return ensuredConfig.method;
831
+ }
796
832
  withStructuredOutput(outputSchema, config) {
797
- // ):
798
- // | Runnable<BaseLanguageModelInput, RunOutput>
799
- // | Runnable<
800
- // BaseLanguageModelInput,
801
- // { raw: BaseMessage; parsed: RunOutput }
802
- // > {
803
833
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
804
834
  let schema;
805
835
  let name;
@@ -822,47 +852,43 @@ class BaseChatOpenAI extends BaseChatModel {
822
852
  if (config?.strict !== undefined && method === "jsonMode") {
823
853
  throw new Error("Argument `strict` is only supported for `method` = 'function_calling'");
824
854
  }
825
- if (!this.model.startsWith("gpt-3") &&
826
- !this.model.startsWith("gpt-4-") &&
827
- this.model !== "gpt-4") {
828
- if (method === undefined) {
829
- method = "jsonSchema";
830
- }
831
- }
832
- else if (method === "jsonSchema") {
833
- console.warn(`[WARNING]: JSON Schema is not supported for model "${this.model}". Falling back to tool calling.`);
834
- }
855
+ method = this._getStructuredOutputMethod({ ...config, method });
835
856
  if (method === "jsonMode") {
836
- let outputFormatSchema;
837
857
  if (isInteropZodSchema(schema)) {
838
858
  outputParser = StructuredOutputParser.fromZodSchema(schema);
839
- outputFormatSchema = toJsonSchema(schema);
840
859
  }
841
860
  else {
842
861
  outputParser = new JsonOutputParser();
843
862
  }
863
+ const asJsonSchema = toJsonSchema(schema);
844
864
  llm = this.withConfig({
845
865
  response_format: { type: "json_object" },
846
866
  ls_structured_output_format: {
847
- kwargs: { method: "jsonMode" },
848
- schema: outputFormatSchema,
867
+ kwargs: { method: "json_mode" },
868
+ schema: { title: name ?? "extract", ...asJsonSchema },
849
869
  },
850
870
  });
851
871
  }
852
872
  else if (method === "jsonSchema") {
873
+ const openaiJsonSchemaParams = {
874
+ name: name ?? "extract",
875
+ description: getSchemaDescription(schema),
876
+ schema,
877
+ strict: config?.strict,
878
+ };
879
+ const asJsonSchema = toJsonSchema(openaiJsonSchemaParams.schema);
853
880
  llm = this.withConfig({
854
881
  response_format: {
855
882
  type: "json_schema",
856
- json_schema: {
857
- name: name ?? "extract",
858
- description: getSchemaDescription(schema),
859
- schema,
860
- strict: config?.strict,
861
- },
883
+ json_schema: openaiJsonSchemaParams,
862
884
  },
863
885
  ls_structured_output_format: {
864
- kwargs: { method: "jsonSchema" },
865
- schema: toJsonSchema(schema),
886
+ kwargs: { method: "json_schema" },
887
+ schema: {
888
+ title: openaiJsonSchemaParams.name,
889
+ description: openaiJsonSchemaParams.description,
890
+ ...asJsonSchema,
891
+ },
866
892
  },
867
893
  });
868
894
  if (isInteropZodSchema(schema)) {
@@ -901,8 +927,8 @@ class BaseChatOpenAI extends BaseChatModel {
901
927
  },
902
928
  },
903
929
  ls_structured_output_format: {
904
- kwargs: { method: "functionCalling" },
905
- schema: asJsonSchema,
930
+ kwargs: { method: "function_calling" },
931
+ schema: { title: functionName, ...asJsonSchema },
906
932
  },
907
933
  // Do not pass `strict` argument to OpenAI if `config.strict` is undefined
908
934
  ...(config?.strict !== undefined ? { strict: config.strict } : {}),
@@ -929,6 +955,7 @@ class BaseChatOpenAI extends BaseChatModel {
929
955
  parameters: schema,
930
956
  };
931
957
  }
958
+ const asJsonSchema = toJsonSchema(schema);
932
959
  llm = this.withConfig({
933
960
  tools: [
934
961
  {
@@ -943,8 +970,8 @@ class BaseChatOpenAI extends BaseChatModel {
943
970
  },
944
971
  },
945
972
  ls_structured_output_format: {
946
- kwargs: { method: "functionCalling" },
947
- schema: toJsonSchema(schema),
973
+ kwargs: { method: "function_calling" },
974
+ schema: { title: functionName, ...asJsonSchema },
948
975
  },
949
976
  // Do not pass `strict` argument to OpenAI if `config.strict` is undefined
950
977
  ...(config?.strict !== undefined ? { strict: config.strict } : {}),
@@ -2583,7 +2610,7 @@ export class ChatOpenAI extends BaseChatOpenAI {
2583
2610
  return [...super.lc_serializable_keys, "useResponsesApi"];
2584
2611
  }
2585
2612
  constructor(fields) {
2586
- super(fields ?? {});
2613
+ super(fields);
2587
2614
  /**
2588
2615
  * Whether to use the responses API for all requests. If `false` the responses API will be used
2589
2616
  * only when required in order to fulfill the request.
@@ -2607,8 +2634,8 @@ export class ChatOpenAI extends BaseChatOpenAI {
2607
2634
  value: void 0
2608
2635
  });
2609
2636
  this.useResponsesApi = fields?.useResponsesApi ?? false;
2610
- this.responses = new ChatOpenAIResponses(fields);
2611
- this.completions = new ChatOpenAICompletions(fields);
2637
+ this.responses = fields?.responses ?? new ChatOpenAIResponses(fields);
2638
+ this.completions = fields?.completions ?? new ChatOpenAICompletions(fields);
2612
2639
  }
2613
2640
  _useResponsesApi(options) {
2614
2641
  const usesBuiltInTools = options?.tools?.some(isBuiltInTool);
@@ -2620,6 +2647,20 @@ export class ChatOpenAI extends BaseChatOpenAI {
2620
2647
  this.reasoning?.summary != null;
2621
2648
  return this.useResponsesApi || usesBuiltInTools || hasResponsesOnlyKwargs;
2622
2649
  }
2650
+ getLsParams(options) {
2651
+ const optionsWithDefaults = this._combineCallOptions(options);
2652
+ if (this._useResponsesApi(options)) {
2653
+ return this.responses.getLsParams(optionsWithDefaults);
2654
+ }
2655
+ return this.completions.getLsParams(optionsWithDefaults);
2656
+ }
2657
+ invocationParams(options) {
2658
+ const optionsWithDefaults = this._combineCallOptions(options);
2659
+ if (this._useResponsesApi(options)) {
2660
+ return this.responses.invocationParams(optionsWithDefaults);
2661
+ }
2662
+ return this.completions.invocationParams(optionsWithDefaults);
2663
+ }
2623
2664
  /** @ignore */
2624
2665
  async _generate(messages, options, runManager) {
2625
2666
  if (this._useResponsesApi(options)) {
@@ -2629,32 +2670,13 @@ export class ChatOpenAI extends BaseChatOpenAI {
2629
2670
  }
2630
2671
  async *_streamResponseChunks(messages, options, runManager) {
2631
2672
  if (this._useResponsesApi(options)) {
2632
- yield* this.responses._streamResponseChunks(messages, options);
2673
+ yield* this.responses._streamResponseChunks(messages, this._combineCallOptions(options));
2633
2674
  return;
2634
2675
  }
2635
- yield* this.completions._streamResponseChunks(messages, options, runManager);
2676
+ yield* this.completions._streamResponseChunks(messages, this._combineCallOptions(options), runManager);
2636
2677
  }
2637
2678
  withConfig(config) {
2638
- // FIXME: assigning additional config options to the inner chat classes this way
2639
- // is awkward, but it's the only way to preserve the original object identity
2640
- // and still thread config options, which is important since this class is a "proxy"
2641
- // for the inner chat classes. This will be fixed in a later version of langchain
2642
- // when the core runnable interface is improved (0.4) to support this out of the box.
2643
- const bindChatOpenAIConfig = (cls, config) => {
2644
- const oldGenerate = cls._generate;
2645
- const oldStreamResponseChunks = cls._streamResponseChunks;
2646
- return Object.assign(cls, {
2647
- _generate(messages, options, runManager) {
2648
- return oldGenerate.call(cls, messages, { ...options, ...config }, runManager);
2649
- },
2650
- _streamResponseChunks(messages, options, runManager) {
2651
- return oldStreamResponseChunks.call(cls, messages, { ...options, ...config }, runManager);
2652
- },
2653
- });
2654
- };
2655
- this.responses = bindChatOpenAIConfig(this.responses, config);
2656
- this.completions = bindChatOpenAIConfig(this.completions, config);
2657
- // Proxy chat class is also bound for `_useResponsesApi`,
2658
- return bindChatOpenAIConfig(this, config);
2679
+ this.defaultOptions = { ...this.defaultOptions, ...config };
2680
+ return this;
2659
2681
  }
2660
2682
  }