@langchain/openai 0.4.5-rc.0 → 0.4.5

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.
@@ -97,283 +97,6 @@ function _convertMessagesToOpenAIParams(messages, model) {
97
97
  });
98
98
  }
99
99
  exports._convertMessagesToOpenAIParams = _convertMessagesToOpenAIParams;
100
- const _FUNCTION_CALL_IDS_MAP_KEY = "__openai_function_call_ids__";
101
- function _convertMessagesToOpenAIResponsesParams(messages, model) {
102
- return messages.flatMap((lcMsg) => {
103
- let role = messageToOpenAIRole(lcMsg);
104
- if (role === "system" && isReasoningModel(model))
105
- role = "developer";
106
- if (role === "function") {
107
- throw new Error("Function messages are not supported in Responses API");
108
- }
109
- if (role === "tool") {
110
- const toolMessage = lcMsg;
111
- return {
112
- type: "function_call_output",
113
- call_id: toolMessage.tool_call_id,
114
- id: toolMessage.id,
115
- output: typeof toolMessage.content !== "string"
116
- ? JSON.stringify(toolMessage.content)
117
- : toolMessage.content,
118
- };
119
- }
120
- if (role === "assistant") {
121
- const functionCallIds =
122
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
123
- lcMsg.additional_kwargs[_FUNCTION_CALL_IDS_MAP_KEY];
124
- if ((0, messages_1.isAIMessage)(lcMsg) && !!lcMsg.tool_calls?.length) {
125
- return lcMsg.tool_calls.map((toolCall) => ({
126
- type: "function_call",
127
- name: toolCall.name,
128
- arguments: JSON.stringify(toolCall.args),
129
- call_id: toolCall.id,
130
- id: functionCallIds[toolCall.id],
131
- }));
132
- }
133
- if (lcMsg.additional_kwargs.tool_calls != null) {
134
- return lcMsg.additional_kwargs.tool_calls.map((toolCall) => ({
135
- type: "function_call",
136
- name: toolCall.function.name,
137
- call_id: toolCall.id,
138
- id: functionCallIds[toolCall.id],
139
- arguments: toolCall.function.arguments,
140
- }));
141
- }
142
- let { content } = lcMsg;
143
- if (lcMsg.additional_kwargs.refusal != null) {
144
- if (typeof content === "string") {
145
- content = [{ type: "output_text", text: content, annotations: [] }];
146
- }
147
- content = [
148
- ...content,
149
- { type: "refusal", refusal: lcMsg.additional_kwargs.refusal },
150
- ];
151
- }
152
- return {
153
- type: "message",
154
- role: "assistant",
155
- content: typeof content === "string"
156
- ? content
157
- : content.flatMap((item) => {
158
- if (item.type === "text") {
159
- return {
160
- type: "output_text",
161
- text: item.text,
162
- // @ts-expect-error TODO: add types for `annotations`
163
- annotations: item.annotations ?? [],
164
- };
165
- }
166
- if (item.type === "output_text" || item.type === "refusal") {
167
- return item;
168
- }
169
- return [];
170
- }),
171
- };
172
- }
173
- if (role === "user") {
174
- return {
175
- type: "message",
176
- role: "user",
177
- content: typeof lcMsg.content === "string"
178
- ? lcMsg.content
179
- : lcMsg.content.flatMap((item) => {
180
- if (item.type === "text") {
181
- return { type: "input_text", text: item.text };
182
- }
183
- if (item.type === "image_url") {
184
- const image_url = typeof item.image_url === "string"
185
- ? item.image_url
186
- : item.image_url.url;
187
- const detail = typeof item.image_url === "string"
188
- ? "auto"
189
- : item.image_url.detail;
190
- return { type: "input_image", image_url, detail };
191
- }
192
- if (item.type === "input_text" ||
193
- item.type === "input_image" ||
194
- item.type === "input_file") {
195
- return item;
196
- }
197
- return [];
198
- }),
199
- };
200
- }
201
- return [];
202
- });
203
- }
204
- function _convertOpenAIResponsesMessageToBaseMessage(response) {
205
- if (response.error) {
206
- // TODO: add support for `addLangChainErrorFields`
207
- const error = new Error(response.error.message);
208
- error.name = response.error.code;
209
- throw error;
210
- }
211
- const content = [];
212
- const tool_calls = [];
213
- const invalid_tool_calls = [];
214
- const response_metadata = {
215
- model: response.model,
216
- created_at: response.created_at,
217
- id: response.id,
218
- incomplete_details: response.incomplete_details,
219
- metadata: response.metadata,
220
- object: response.object,
221
- status: response.status,
222
- user: response.user,
223
- // for compatibility with chat completion calls.
224
- model_name: response.model,
225
- };
226
- const additional_kwargs = {};
227
- for (const item of response.output) {
228
- if (item.type === "message") {
229
- // TODO: how to handle refusals?
230
- content.push(...item.content.map((part) => {
231
- if (part.type === "output_text") {
232
- return {
233
- type: "text",
234
- text: part.text,
235
- annotations: part.annotations,
236
- };
237
- }
238
- return part;
239
- }));
240
- }
241
- else if (item.type === "function_call") {
242
- const fnAdapter = {
243
- function: { name: item.name, arguments: item.arguments },
244
- id: item.call_id,
245
- };
246
- try {
247
- tool_calls.push((0, openai_tools_1.parseToolCall)(fnAdapter, { returnId: true }));
248
- }
249
- catch (e) {
250
- let errMessage;
251
- if (typeof e === "object" &&
252
- e != null &&
253
- "message" in e &&
254
- typeof e.message === "string") {
255
- errMessage = e.message;
256
- }
257
- invalid_tool_calls.push((0, openai_tools_1.makeInvalidToolCall)(fnAdapter, errMessage));
258
- }
259
- }
260
- else if (item.type === "reasoning") {
261
- additional_kwargs.reasoning = item;
262
- }
263
- else {
264
- additional_kwargs.tool_outputs ??= [];
265
- additional_kwargs.tool_outputs.push(item);
266
- }
267
- }
268
- return new messages_1.AIMessage({
269
- id: response.id,
270
- content,
271
- tool_calls,
272
- invalid_tool_calls,
273
- usage_metadata: response.usage,
274
- additional_kwargs,
275
- response_metadata,
276
- });
277
- }
278
- function _convertOpenAIResponsesDeltaToBaseMessageChunk(chunk) {
279
- const content = [];
280
- let generationInfo = {};
281
- let usage_metadata;
282
- const tool_call_chunks = [];
283
- const response_metadata = {};
284
- const additional_kwargs = {};
285
- let id;
286
- if (chunk.type === "response.output_text.delta") {
287
- content.push({
288
- type: "text",
289
- text: chunk.delta,
290
- index: chunk.content_index,
291
- });
292
- }
293
- else if (chunk.type === "response.output_text.annotation.added") {
294
- content.push({
295
- type: "text",
296
- text: "",
297
- annotations: [chunk.annotation],
298
- index: chunk.content_index,
299
- });
300
- }
301
- else if (chunk.type === "response.output_item.added" &&
302
- chunk.item.type === "message") {
303
- id = chunk.item.id;
304
- }
305
- else if (chunk.type === "response.output_item.added" &&
306
- chunk.item.type === "function_call") {
307
- tool_call_chunks.push({
308
- type: "tool_call_chunk",
309
- name: chunk.item.name,
310
- args: chunk.item.arguments,
311
- id: chunk.item.id,
312
- index: chunk.output_index,
313
- });
314
- additional_kwargs[_FUNCTION_CALL_IDS_MAP_KEY] = {
315
- [chunk.item.call_id]: chunk.item.id,
316
- };
317
- }
318
- else if (chunk.type === "response.output_item.done" &&
319
- (chunk.item.type === "web_search_call" ||
320
- chunk.item.type === "file_search_call")) {
321
- additional_kwargs.tool_outputs = [chunk.item];
322
- }
323
- else if (chunk.type === "response.created") {
324
- response_metadata.id = chunk.response.id;
325
- response_metadata.model_name = chunk.response.model;
326
- response_metadata.model = chunk.response.model;
327
- }
328
- else if (chunk.type === "response.completed") {
329
- usage_metadata = chunk.response.usage;
330
- }
331
- else if (chunk.type === "response.function_call_arguments.delta") {
332
- tool_call_chunks.push({
333
- type: "tool_call_chunk",
334
- args: chunk.delta,
335
- index: chunk.output_index,
336
- });
337
- }
338
- else if (chunk.type === "response.web_search_call.completed" ||
339
- chunk.type === "response.file_search_call.completed") {
340
- generationInfo = {
341
- tool_outputs: {
342
- id: chunk.item_id,
343
- type: chunk.type.replace("response.", "").replace(".completed", ""),
344
- status: "completed",
345
- },
346
- };
347
- }
348
- else if (chunk.type === "response.refusal.done") {
349
- additional_kwargs.refusal = chunk.refusal;
350
- }
351
- else {
352
- return null;
353
- }
354
- return new outputs_1.ChatGenerationChunk({
355
- // Legacy reasons, `onLLMNewToken` should pulls this out
356
- text: content.map((part) => part.text).join(""),
357
- message: new messages_1.AIMessageChunk({
358
- id,
359
- content,
360
- tool_call_chunks,
361
- usage_metadata,
362
- additional_kwargs,
363
- response_metadata,
364
- }),
365
- generationInfo,
366
- });
367
- }
368
- function isBuiltInTool(tool) {
369
- return "type" in tool && tool.type !== "function";
370
- }
371
- function isBuiltInToolChoice(tool_choice) {
372
- return (tool_choice != null &&
373
- typeof tool_choice === "object" &&
374
- "type" in tool_choice &&
375
- tool_choice.type !== "function");
376
- }
377
100
  function _convertChatOpenAIToolTypeToOpenAITool(tool, fields) {
378
101
  if ((0, base_1.isOpenAITool)(tool)) {
379
102
  if (fields?.strict !== undefined) {
@@ -1181,12 +904,6 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
1181
904
  writable: true,
1182
905
  value: void 0
1183
906
  });
1184
- Object.defineProperty(this, "useResponsesApi", {
1185
- enumerable: true,
1186
- configurable: true,
1187
- writable: true,
1188
- value: false
1189
- });
1190
907
  this.openAIApiKey =
1191
908
  fields?.apiKey ??
1192
909
  fields?.openAIApiKey ??
@@ -1216,7 +933,6 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
1216
933
  this.modalities = fields?.modalities;
1217
934
  this.reasoningEffort = fields?.reasoningEffort;
1218
935
  this.maxTokens = fields?.maxCompletionTokens ?? fields?.maxTokens;
1219
- this.useResponsesApi = fields?.useResponsesApi ?? this.useResponsesApi;
1220
936
  if (this.model === "o1") {
1221
937
  this.disableStreaming = true;
1222
938
  }
@@ -1254,9 +970,7 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
1254
970
  strict = this.supportsStrictToolCalling;
1255
971
  }
1256
972
  return this.bind({
1257
- tools: tools.map((tool) => isBuiltInTool(tool)
1258
- ? tool
1259
- : _convertChatOpenAIToolTypeToOpenAITool(tool, { strict })),
973
+ tools: tools.map((tool) => _convertChatOpenAIToolTypeToOpenAITool(tool, { strict })),
1260
974
  ...kwargs,
1261
975
  });
1262
976
  }
@@ -1282,80 +996,6 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
1282
996
  else if (this.supportsStrictToolCalling !== undefined) {
1283
997
  strict = this.supportsStrictToolCalling;
1284
998
  }
1285
- if (this._useResponseApi(options)) {
1286
- const params = {
1287
- model: this.model,
1288
- temperature: this.temperature,
1289
- top_p: this.topP,
1290
- user: this.user,
1291
- // if include_usage is set or streamUsage then stream must be set to true.
1292
- stream: this.streaming,
1293
- previous_response_id: options?.previous_response_id,
1294
- truncation: options?.truncation,
1295
- include: options?.include,
1296
- tools: options?.tools?.length
1297
- ? options.tools
1298
- .map((tool) => {
1299
- if (isBuiltInTool(tool)) {
1300
- return tool;
1301
- }
1302
- else if ((0, base_1.isOpenAITool)(tool)) {
1303
- return {
1304
- type: "function",
1305
- name: tool.function.name,
1306
- parameters: tool.function.parameters,
1307
- description: tool.function.description,
1308
- strict,
1309
- };
1310
- }
1311
- else {
1312
- return null;
1313
- }
1314
- })
1315
- .filter((tool) => tool !== null)
1316
- : undefined,
1317
- tool_choice: isBuiltInToolChoice(options?.tool_choice)
1318
- ? options?.tool_choice
1319
- : (() => {
1320
- const formatted = (0, openai_js_1.formatToOpenAIToolChoice)(options?.tool_choice);
1321
- if (typeof formatted === "object" && "type" in formatted) {
1322
- return { type: "function", name: formatted.function.name };
1323
- }
1324
- else {
1325
- return undefined;
1326
- }
1327
- })(),
1328
- text: (() => {
1329
- if (options?.text)
1330
- return options.text;
1331
- const format = this.createResponseFormat(options?.response_format);
1332
- if (format?.type === "json_schema") {
1333
- if (format.json_schema.schema != null) {
1334
- return {
1335
- format: {
1336
- type: "json_schema",
1337
- schema: format.json_schema.schema,
1338
- description: format.json_schema.description,
1339
- name: format.json_schema.name,
1340
- strict: format.json_schema.strict,
1341
- },
1342
- };
1343
- }
1344
- return undefined;
1345
- }
1346
- return { format };
1347
- })(),
1348
- parallel_tool_calls: options?.parallel_tool_calls,
1349
- max_output_tokens: this.maxTokens === -1 ? undefined : this.maxTokens,
1350
- ...this.modelKwargs,
1351
- };
1352
- const reasoningEffort = options?.reasoning_effort ?? this.reasoningEffort;
1353
- if (reasoningEffort !== undefined) {
1354
- params.reasoning = { effort: reasoningEffort };
1355
- }
1356
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1357
- return params;
1358
- }
1359
999
  let streamOptionsConfig = {};
1360
1000
  if (options?.stream_options !== undefined) {
1361
1001
  streamOptionsConfig = { stream_options: options.stream_options };
@@ -1409,7 +1049,6 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
1409
1049
  else {
1410
1050
  params.max_tokens = this.maxTokens === -1 ? undefined : this.maxTokens;
1411
1051
  }
1412
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1413
1052
  return params;
1414
1053
  }
1415
1054
  _convertOpenAIChatCompletionMessageToBaseMessage(message, rawResponse) {
@@ -1553,20 +1192,6 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
1553
1192
  };
1554
1193
  }
1555
1194
  async *_streamResponseChunks(messages, options, runManager) {
1556
- if (this._useResponseApi(options)) {
1557
- const streamIterable = await this.responseApiWithRetry({
1558
- ...this.invocationParams(options, { streaming: true }),
1559
- input: _convertMessagesToOpenAIResponsesParams(messages, this.model),
1560
- stream: true,
1561
- }, options);
1562
- for await (const data of streamIterable) {
1563
- const chunk = _convertOpenAIResponsesDeltaToBaseMessageChunk(data);
1564
- if (chunk == null)
1565
- continue;
1566
- yield chunk;
1567
- }
1568
- return;
1569
- }
1570
1195
  const messagesMapped = _convertMessagesToOpenAIParams(messages, this.model);
1571
1196
  const params = {
1572
1197
  ...this.invocationParams(options, {
@@ -1671,60 +1296,7 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
1671
1296
  return this._identifyingParams();
1672
1297
  }
1673
1298
  /** @ignore */
1674
- async _responseApiGenerate(messages, options, runManager) {
1675
- const invocationParams = this.invocationParams(options);
1676
- if (invocationParams.stream) {
1677
- const stream = this._streamResponseChunks(messages, options, runManager);
1678
- let finalChunk;
1679
- for await (const chunk of stream) {
1680
- chunk.message.response_metadata = {
1681
- ...chunk.generationInfo,
1682
- ...chunk.message.response_metadata,
1683
- };
1684
- finalChunk = finalChunk?.concat(chunk) ?? chunk;
1685
- }
1686
- return {
1687
- generations: finalChunk ? [finalChunk] : [],
1688
- llmOutput: {
1689
- estimatedTokenUsage: finalChunk?.message
1690
- ?.usage_metadata,
1691
- },
1692
- };
1693
- }
1694
- const input = _convertMessagesToOpenAIResponsesParams(messages, this.model);
1695
- const data = await this.responseApiWithRetry({ input, ...invocationParams }, { signal: options?.signal, ...options?.options });
1696
- return {
1697
- generations: [
1698
- {
1699
- text: data.output_text,
1700
- message: _convertOpenAIResponsesMessageToBaseMessage(data),
1701
- },
1702
- ],
1703
- llmOutput: {
1704
- id: data.id,
1705
- estimatedTokenUsage: data.usage
1706
- ? {
1707
- promptTokens: data.usage.input_tokens,
1708
- completionTokens: data.usage.output_tokens,
1709
- totalTokens: data.usage.total_tokens,
1710
- }
1711
- : undefined,
1712
- },
1713
- };
1714
- }
1715
- _useResponseApi(options) {
1716
- const usesBuiltInTools = options?.tools?.some(isBuiltInTool);
1717
- const hasResponsesOnlyKwargs = options?.previous_response_id != null ||
1718
- options?.text != null ||
1719
- options?.truncation != null ||
1720
- options?.include != null;
1721
- return this.useResponsesApi || usesBuiltInTools || hasResponsesOnlyKwargs;
1722
- }
1723
- /** @ignore */
1724
1299
  async _generate(messages, options, runManager) {
1725
- if (this._useResponseApi(options)) {
1726
- return this._responseApiGenerate(messages, options, runManager);
1727
- }
1728
1300
  const usageMetadata = {};
1729
1301
  const params = this.invocationParams(options);
1730
1302
  const messagesMapped = _convertMessagesToOpenAIParams(messages, this.model);
@@ -1962,19 +1534,6 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
1962
1534
  }
1963
1535
  });
1964
1536
  }
1965
- async responseApiWithRetry(request, options) {
1966
- return this.caller.call(async () => {
1967
- const requestOptions = this._getClientOptions(options);
1968
- try {
1969
- const res = await this.client.responses.create(request, requestOptions);
1970
- return res;
1971
- }
1972
- catch (e) {
1973
- const error = (0, openai_js_1.wrapOpenAIClientError)(e);
1974
- throw error;
1975
- }
1976
- });
1977
- }
1978
1537
  /**
1979
1538
  * Call the beta chat completions parse endpoint. This should only be called if
1980
1539
  * response_format is set to "json_object".
@@ -2,7 +2,7 @@ import { type ClientOptions, OpenAI as OpenAIClient } from "openai";
2
2
  import { CallbackManagerForLLMRun } from "@langchain/core/callbacks/manager";
3
3
  import { AIMessageChunk, type BaseMessage, ChatMessageChunk, FunctionMessageChunk, HumanMessageChunk, SystemMessageChunk, ToolMessageChunk } from "@langchain/core/messages";
4
4
  import { ChatGenerationChunk, type ChatResult } from "@langchain/core/outputs";
5
- import { BaseChatModel, type BindToolsInput, type LangSmithParams, type BaseChatModelParams } from "@langchain/core/language_models/chat_models";
5
+ import { BaseChatModel, BindToolsInput, LangSmithParams, type BaseChatModelParams } from "@langchain/core/language_models/chat_models";
6
6
  import { type BaseFunctionCallOptions, type BaseLanguageModelInput, type StructuredOutputMethodOptions } from "@langchain/core/language_models/base";
7
7
  import { z } from "zod";
8
8
  import { Runnable } from "@langchain/core/runnables";
@@ -21,21 +21,7 @@ type OpenAIRoleEnum = "system" | "developer" | "assistant" | "user" | "function"
21
21
  type OpenAICompletionParam = OpenAIClient.Chat.Completions.ChatCompletionMessageParam;
22
22
  export declare function messageToOpenAIRole(message: BaseMessage): OpenAIRoleEnum;
23
23
  export declare function _convertMessagesToOpenAIParams(messages: BaseMessage[], model?: string): OpenAICompletionParam[];
24
- type ExcludeController<T> = T extends {
25
- controller: unknown;
26
- } ? never : T;
27
- type ExcludeNonController<T> = T extends {
28
- controller: unknown;
29
- } ? T : never;
30
- type ResponsesCreate = OpenAIClient.Responses["create"];
31
- type ResponsesCreateParams = Parameters<OpenAIClient.Responses["create"]>[0];
32
- type ResponsesTool = Exclude<ResponsesCreateParams["tools"], undefined>[number];
33
- type ResponsesToolChoice = Exclude<ResponsesCreateParams["tool_choice"], undefined>;
34
- type ResponsesCreateInvoke = ExcludeController<Awaited<ReturnType<ResponsesCreate>>>;
35
- type ResponsesCreateStream = ExcludeNonController<Awaited<ReturnType<ResponsesCreate>>>;
36
- type ResponseInvocationParams = Omit<ResponsesCreateParams, "input">;
37
- type ChatCompletionInvocationParams = Omit<OpenAIClient.Chat.ChatCompletionCreateParams, "messages">;
38
- type ChatOpenAIToolType = BindToolsInput | OpenAIClient.ChatCompletionTool | ResponsesTool;
24
+ type ChatOpenAIToolType = BindToolsInput | OpenAIClient.ChatCompletionTool;
39
25
  export interface ChatOpenAIStructuredOutputMethodOptions<IncludeRaw extends boolean> extends StructuredOutputMethodOptions<IncludeRaw> {
40
26
  /**
41
27
  * strict: If `true` and `method` = "function_calling", model output is
@@ -55,7 +41,7 @@ export interface ChatOpenAIStructuredOutputMethodOptions<IncludeRaw extends bool
55
41
  }
56
42
  export interface ChatOpenAICallOptions extends OpenAICallOptions, BaseFunctionCallOptions {
57
43
  tools?: ChatOpenAIToolType[];
58
- tool_choice?: OpenAIToolChoice | ResponsesToolChoice;
44
+ tool_choice?: OpenAIToolChoice;
59
45
  promptIndex?: number;
60
46
  response_format?: ChatOpenAIResponseFormat;
61
47
  seed?: number;
@@ -119,28 +105,9 @@ export interface ChatOpenAICallOptions extends OpenAICallOptions, BaseFunctionCa
119
105
  * Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response.
120
106
  */
121
107
  reasoning_effort?: OpenAIClient.Chat.ChatCompletionReasoningEffort;
122
- /**
123
- * Configuration options for a text response from the model. Can be plain text or
124
- * structured JSON data.
125
- */
126
- text?: ResponsesCreateParams["text"];
127
- /**
128
- * The truncation strategy to use for the model response.
129
- */
130
- truncation?: ResponsesCreateParams["truncation"];
131
- /**
132
- * Specify additional output data to include in the model response.
133
- */
134
- include?: ResponsesCreateParams["include"];
135
- /**
136
- * The unique ID of the previous response to the model. Use this to create
137
- * multi-turn conversations.
138
- */
139
- previous_response_id?: ResponsesCreateParams["previous_response_id"];
140
108
  }
141
109
  export interface ChatOpenAIFields extends Partial<OpenAIChatInput>, BaseChatModelParams {
142
110
  configuration?: ClientOptions;
143
- useResponsesApi?: boolean;
144
111
  }
145
112
  /**
146
113
  * OpenAI chat model integration.
@@ -722,7 +689,6 @@ export declare class ChatOpenAI<CallOptions extends ChatOpenAICallOptions = Chat
722
689
  audio?: OpenAIClient.Chat.ChatCompletionAudioParam;
723
690
  modalities?: Array<OpenAIClient.Chat.ChatCompletionModality>;
724
691
  reasoningEffort?: OpenAIClient.Chat.ChatCompletionReasoningEffort;
725
- useResponsesApi: boolean;
726
692
  constructor(fields?: ChatOpenAIFields);
727
693
  getLsParams(options: this["ParsedCallOptions"]): LangSmithParams;
728
694
  bindTools(tools: ChatOpenAIToolType[], kwargs?: Partial<CallOptions>): Runnable<BaseLanguageModelInput, AIMessageChunk, CallOptions>;
@@ -730,9 +696,9 @@ export declare class ChatOpenAI<CallOptions extends ChatOpenAICallOptions = Chat
730
696
  /**
731
697
  * Get the parameters used to invoke the model
732
698
  */
733
- invocationParams<Type extends "responses" | "completion" = "completion">(options?: this["ParsedCallOptions"], extra?: {
699
+ invocationParams(options?: this["ParsedCallOptions"], extra?: {
734
700
  streaming?: boolean;
735
- }): Type extends "responses" ? ResponseInvocationParams : ChatCompletionInvocationParams;
701
+ }): Omit<OpenAIClient.Chat.ChatCompletionCreateParams, "messages">;
736
702
  protected _convertOpenAIChatCompletionMessageToBaseMessage(message: OpenAIClient.Chat.Completions.ChatCompletionMessage, rawResponse: OpenAIClient.Chat.Completions.ChatCompletion): BaseMessage;
737
703
  protected _convertOpenAIDeltaToBaseMessageChunk(delta: Record<string, any>, rawResponse: OpenAIClient.Chat.Completions.ChatCompletionChunk, defaultRole?: OpenAIRoleEnum): AIMessageChunk | HumanMessageChunk | SystemMessageChunk | FunctionMessageChunk | ToolMessageChunk | ChatMessageChunk;
738
704
  /** @ignore */
@@ -748,9 +714,6 @@ export declare class ChatOpenAI<CallOptions extends ChatOpenAICallOptions = Chat
748
714
  model_name: string;
749
715
  } & ClientOptions;
750
716
  /** @ignore */
751
- _responseApiGenerate(messages: BaseMessage[], options: this["ParsedCallOptions"], runManager?: CallbackManagerForLLMRun): Promise<ChatResult>;
752
- protected _useResponseApi(options: this["ParsedCallOptions"] | undefined): boolean;
753
- /** @ignore */
754
717
  _generate(messages: BaseMessage[], options: this["ParsedCallOptions"], runManager?: CallbackManagerForLLMRun): Promise<ChatResult>;
755
718
  /**
756
719
  * Estimate the number of tokens a prompt will use.
@@ -773,10 +736,6 @@ export declare class ChatOpenAI<CallOptions extends ChatOpenAICallOptions = Chat
773
736
  */
774
737
  completionWithRetry(request: OpenAIClient.Chat.ChatCompletionCreateParamsStreaming, options?: OpenAICoreRequestOptions): Promise<AsyncIterable<OpenAIClient.Chat.Completions.ChatCompletionChunk>>;
775
738
  completionWithRetry(request: OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming, options?: OpenAICoreRequestOptions): Promise<OpenAIClient.Chat.Completions.ChatCompletion>;
776
- protected responseApiWithRetry(request: ResponsesCreateParams & {
777
- stream: true;
778
- }, options?: OpenAICoreRequestOptions): Promise<ResponsesCreateStream>;
779
- protected responseApiWithRetry(request: ResponsesCreateParams, options?: OpenAICoreRequestOptions): Promise<ResponsesCreateInvoke>;
780
739
  /**
781
740
  * Call the beta chat completions parse endpoint. This should only be called if
782
741
  * response_format is set to "json_object".
@@ -92,283 +92,6 @@ export function _convertMessagesToOpenAIParams(messages, model) {
92
92
  return completionParam;
93
93
  });
94
94
  }
95
- const _FUNCTION_CALL_IDS_MAP_KEY = "__openai_function_call_ids__";
96
- function _convertMessagesToOpenAIResponsesParams(messages, model) {
97
- return messages.flatMap((lcMsg) => {
98
- let role = messageToOpenAIRole(lcMsg);
99
- if (role === "system" && isReasoningModel(model))
100
- role = "developer";
101
- if (role === "function") {
102
- throw new Error("Function messages are not supported in Responses API");
103
- }
104
- if (role === "tool") {
105
- const toolMessage = lcMsg;
106
- return {
107
- type: "function_call_output",
108
- call_id: toolMessage.tool_call_id,
109
- id: toolMessage.id,
110
- output: typeof toolMessage.content !== "string"
111
- ? JSON.stringify(toolMessage.content)
112
- : toolMessage.content,
113
- };
114
- }
115
- if (role === "assistant") {
116
- const functionCallIds =
117
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
118
- lcMsg.additional_kwargs[_FUNCTION_CALL_IDS_MAP_KEY];
119
- if (isAIMessage(lcMsg) && !!lcMsg.tool_calls?.length) {
120
- return lcMsg.tool_calls.map((toolCall) => ({
121
- type: "function_call",
122
- name: toolCall.name,
123
- arguments: JSON.stringify(toolCall.args),
124
- call_id: toolCall.id,
125
- id: functionCallIds[toolCall.id],
126
- }));
127
- }
128
- if (lcMsg.additional_kwargs.tool_calls != null) {
129
- return lcMsg.additional_kwargs.tool_calls.map((toolCall) => ({
130
- type: "function_call",
131
- name: toolCall.function.name,
132
- call_id: toolCall.id,
133
- id: functionCallIds[toolCall.id],
134
- arguments: toolCall.function.arguments,
135
- }));
136
- }
137
- let { content } = lcMsg;
138
- if (lcMsg.additional_kwargs.refusal != null) {
139
- if (typeof content === "string") {
140
- content = [{ type: "output_text", text: content, annotations: [] }];
141
- }
142
- content = [
143
- ...content,
144
- { type: "refusal", refusal: lcMsg.additional_kwargs.refusal },
145
- ];
146
- }
147
- return {
148
- type: "message",
149
- role: "assistant",
150
- content: typeof content === "string"
151
- ? content
152
- : content.flatMap((item) => {
153
- if (item.type === "text") {
154
- return {
155
- type: "output_text",
156
- text: item.text,
157
- // @ts-expect-error TODO: add types for `annotations`
158
- annotations: item.annotations ?? [],
159
- };
160
- }
161
- if (item.type === "output_text" || item.type === "refusal") {
162
- return item;
163
- }
164
- return [];
165
- }),
166
- };
167
- }
168
- if (role === "user") {
169
- return {
170
- type: "message",
171
- role: "user",
172
- content: typeof lcMsg.content === "string"
173
- ? lcMsg.content
174
- : lcMsg.content.flatMap((item) => {
175
- if (item.type === "text") {
176
- return { type: "input_text", text: item.text };
177
- }
178
- if (item.type === "image_url") {
179
- const image_url = typeof item.image_url === "string"
180
- ? item.image_url
181
- : item.image_url.url;
182
- const detail = typeof item.image_url === "string"
183
- ? "auto"
184
- : item.image_url.detail;
185
- return { type: "input_image", image_url, detail };
186
- }
187
- if (item.type === "input_text" ||
188
- item.type === "input_image" ||
189
- item.type === "input_file") {
190
- return item;
191
- }
192
- return [];
193
- }),
194
- };
195
- }
196
- return [];
197
- });
198
- }
199
- function _convertOpenAIResponsesMessageToBaseMessage(response) {
200
- if (response.error) {
201
- // TODO: add support for `addLangChainErrorFields`
202
- const error = new Error(response.error.message);
203
- error.name = response.error.code;
204
- throw error;
205
- }
206
- const content = [];
207
- const tool_calls = [];
208
- const invalid_tool_calls = [];
209
- const response_metadata = {
210
- model: response.model,
211
- created_at: response.created_at,
212
- id: response.id,
213
- incomplete_details: response.incomplete_details,
214
- metadata: response.metadata,
215
- object: response.object,
216
- status: response.status,
217
- user: response.user,
218
- // for compatibility with chat completion calls.
219
- model_name: response.model,
220
- };
221
- const additional_kwargs = {};
222
- for (const item of response.output) {
223
- if (item.type === "message") {
224
- // TODO: how to handle refusals?
225
- content.push(...item.content.map((part) => {
226
- if (part.type === "output_text") {
227
- return {
228
- type: "text",
229
- text: part.text,
230
- annotations: part.annotations,
231
- };
232
- }
233
- return part;
234
- }));
235
- }
236
- else if (item.type === "function_call") {
237
- const fnAdapter = {
238
- function: { name: item.name, arguments: item.arguments },
239
- id: item.call_id,
240
- };
241
- try {
242
- tool_calls.push(parseToolCall(fnAdapter, { returnId: true }));
243
- }
244
- catch (e) {
245
- let errMessage;
246
- if (typeof e === "object" &&
247
- e != null &&
248
- "message" in e &&
249
- typeof e.message === "string") {
250
- errMessage = e.message;
251
- }
252
- invalid_tool_calls.push(makeInvalidToolCall(fnAdapter, errMessage));
253
- }
254
- }
255
- else if (item.type === "reasoning") {
256
- additional_kwargs.reasoning = item;
257
- }
258
- else {
259
- additional_kwargs.tool_outputs ??= [];
260
- additional_kwargs.tool_outputs.push(item);
261
- }
262
- }
263
- return new AIMessage({
264
- id: response.id,
265
- content,
266
- tool_calls,
267
- invalid_tool_calls,
268
- usage_metadata: response.usage,
269
- additional_kwargs,
270
- response_metadata,
271
- });
272
- }
273
- function _convertOpenAIResponsesDeltaToBaseMessageChunk(chunk) {
274
- const content = [];
275
- let generationInfo = {};
276
- let usage_metadata;
277
- const tool_call_chunks = [];
278
- const response_metadata = {};
279
- const additional_kwargs = {};
280
- let id;
281
- if (chunk.type === "response.output_text.delta") {
282
- content.push({
283
- type: "text",
284
- text: chunk.delta,
285
- index: chunk.content_index,
286
- });
287
- }
288
- else if (chunk.type === "response.output_text.annotation.added") {
289
- content.push({
290
- type: "text",
291
- text: "",
292
- annotations: [chunk.annotation],
293
- index: chunk.content_index,
294
- });
295
- }
296
- else if (chunk.type === "response.output_item.added" &&
297
- chunk.item.type === "message") {
298
- id = chunk.item.id;
299
- }
300
- else if (chunk.type === "response.output_item.added" &&
301
- chunk.item.type === "function_call") {
302
- tool_call_chunks.push({
303
- type: "tool_call_chunk",
304
- name: chunk.item.name,
305
- args: chunk.item.arguments,
306
- id: chunk.item.id,
307
- index: chunk.output_index,
308
- });
309
- additional_kwargs[_FUNCTION_CALL_IDS_MAP_KEY] = {
310
- [chunk.item.call_id]: chunk.item.id,
311
- };
312
- }
313
- else if (chunk.type === "response.output_item.done" &&
314
- (chunk.item.type === "web_search_call" ||
315
- chunk.item.type === "file_search_call")) {
316
- additional_kwargs.tool_outputs = [chunk.item];
317
- }
318
- else if (chunk.type === "response.created") {
319
- response_metadata.id = chunk.response.id;
320
- response_metadata.model_name = chunk.response.model;
321
- response_metadata.model = chunk.response.model;
322
- }
323
- else if (chunk.type === "response.completed") {
324
- usage_metadata = chunk.response.usage;
325
- }
326
- else if (chunk.type === "response.function_call_arguments.delta") {
327
- tool_call_chunks.push({
328
- type: "tool_call_chunk",
329
- args: chunk.delta,
330
- index: chunk.output_index,
331
- });
332
- }
333
- else if (chunk.type === "response.web_search_call.completed" ||
334
- chunk.type === "response.file_search_call.completed") {
335
- generationInfo = {
336
- tool_outputs: {
337
- id: chunk.item_id,
338
- type: chunk.type.replace("response.", "").replace(".completed", ""),
339
- status: "completed",
340
- },
341
- };
342
- }
343
- else if (chunk.type === "response.refusal.done") {
344
- additional_kwargs.refusal = chunk.refusal;
345
- }
346
- else {
347
- return null;
348
- }
349
- return new ChatGenerationChunk({
350
- // Legacy reasons, `onLLMNewToken` should pulls this out
351
- text: content.map((part) => part.text).join(""),
352
- message: new AIMessageChunk({
353
- id,
354
- content,
355
- tool_call_chunks,
356
- usage_metadata,
357
- additional_kwargs,
358
- response_metadata,
359
- }),
360
- generationInfo,
361
- });
362
- }
363
- function isBuiltInTool(tool) {
364
- return "type" in tool && tool.type !== "function";
365
- }
366
- function isBuiltInToolChoice(tool_choice) {
367
- return (tool_choice != null &&
368
- typeof tool_choice === "object" &&
369
- "type" in tool_choice &&
370
- tool_choice.type !== "function");
371
- }
372
95
  function _convertChatOpenAIToolTypeToOpenAITool(tool, fields) {
373
96
  if (isOpenAITool(tool)) {
374
97
  if (fields?.strict !== undefined) {
@@ -1176,12 +899,6 @@ export class ChatOpenAI extends BaseChatModel {
1176
899
  writable: true,
1177
900
  value: void 0
1178
901
  });
1179
- Object.defineProperty(this, "useResponsesApi", {
1180
- enumerable: true,
1181
- configurable: true,
1182
- writable: true,
1183
- value: false
1184
- });
1185
902
  this.openAIApiKey =
1186
903
  fields?.apiKey ??
1187
904
  fields?.openAIApiKey ??
@@ -1211,7 +928,6 @@ export class ChatOpenAI extends BaseChatModel {
1211
928
  this.modalities = fields?.modalities;
1212
929
  this.reasoningEffort = fields?.reasoningEffort;
1213
930
  this.maxTokens = fields?.maxCompletionTokens ?? fields?.maxTokens;
1214
- this.useResponsesApi = fields?.useResponsesApi ?? this.useResponsesApi;
1215
931
  if (this.model === "o1") {
1216
932
  this.disableStreaming = true;
1217
933
  }
@@ -1249,9 +965,7 @@ export class ChatOpenAI extends BaseChatModel {
1249
965
  strict = this.supportsStrictToolCalling;
1250
966
  }
1251
967
  return this.bind({
1252
- tools: tools.map((tool) => isBuiltInTool(tool)
1253
- ? tool
1254
- : _convertChatOpenAIToolTypeToOpenAITool(tool, { strict })),
968
+ tools: tools.map((tool) => _convertChatOpenAIToolTypeToOpenAITool(tool, { strict })),
1255
969
  ...kwargs,
1256
970
  });
1257
971
  }
@@ -1277,80 +991,6 @@ export class ChatOpenAI extends BaseChatModel {
1277
991
  else if (this.supportsStrictToolCalling !== undefined) {
1278
992
  strict = this.supportsStrictToolCalling;
1279
993
  }
1280
- if (this._useResponseApi(options)) {
1281
- const params = {
1282
- model: this.model,
1283
- temperature: this.temperature,
1284
- top_p: this.topP,
1285
- user: this.user,
1286
- // if include_usage is set or streamUsage then stream must be set to true.
1287
- stream: this.streaming,
1288
- previous_response_id: options?.previous_response_id,
1289
- truncation: options?.truncation,
1290
- include: options?.include,
1291
- tools: options?.tools?.length
1292
- ? options.tools
1293
- .map((tool) => {
1294
- if (isBuiltInTool(tool)) {
1295
- return tool;
1296
- }
1297
- else if (isOpenAITool(tool)) {
1298
- return {
1299
- type: "function",
1300
- name: tool.function.name,
1301
- parameters: tool.function.parameters,
1302
- description: tool.function.description,
1303
- strict,
1304
- };
1305
- }
1306
- else {
1307
- return null;
1308
- }
1309
- })
1310
- .filter((tool) => tool !== null)
1311
- : undefined,
1312
- tool_choice: isBuiltInToolChoice(options?.tool_choice)
1313
- ? options?.tool_choice
1314
- : (() => {
1315
- const formatted = formatToOpenAIToolChoice(options?.tool_choice);
1316
- if (typeof formatted === "object" && "type" in formatted) {
1317
- return { type: "function", name: formatted.function.name };
1318
- }
1319
- else {
1320
- return undefined;
1321
- }
1322
- })(),
1323
- text: (() => {
1324
- if (options?.text)
1325
- return options.text;
1326
- const format = this.createResponseFormat(options?.response_format);
1327
- if (format?.type === "json_schema") {
1328
- if (format.json_schema.schema != null) {
1329
- return {
1330
- format: {
1331
- type: "json_schema",
1332
- schema: format.json_schema.schema,
1333
- description: format.json_schema.description,
1334
- name: format.json_schema.name,
1335
- strict: format.json_schema.strict,
1336
- },
1337
- };
1338
- }
1339
- return undefined;
1340
- }
1341
- return { format };
1342
- })(),
1343
- parallel_tool_calls: options?.parallel_tool_calls,
1344
- max_output_tokens: this.maxTokens === -1 ? undefined : this.maxTokens,
1345
- ...this.modelKwargs,
1346
- };
1347
- const reasoningEffort = options?.reasoning_effort ?? this.reasoningEffort;
1348
- if (reasoningEffort !== undefined) {
1349
- params.reasoning = { effort: reasoningEffort };
1350
- }
1351
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1352
- return params;
1353
- }
1354
994
  let streamOptionsConfig = {};
1355
995
  if (options?.stream_options !== undefined) {
1356
996
  streamOptionsConfig = { stream_options: options.stream_options };
@@ -1404,7 +1044,6 @@ export class ChatOpenAI extends BaseChatModel {
1404
1044
  else {
1405
1045
  params.max_tokens = this.maxTokens === -1 ? undefined : this.maxTokens;
1406
1046
  }
1407
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1408
1047
  return params;
1409
1048
  }
1410
1049
  _convertOpenAIChatCompletionMessageToBaseMessage(message, rawResponse) {
@@ -1548,20 +1187,6 @@ export class ChatOpenAI extends BaseChatModel {
1548
1187
  };
1549
1188
  }
1550
1189
  async *_streamResponseChunks(messages, options, runManager) {
1551
- if (this._useResponseApi(options)) {
1552
- const streamIterable = await this.responseApiWithRetry({
1553
- ...this.invocationParams(options, { streaming: true }),
1554
- input: _convertMessagesToOpenAIResponsesParams(messages, this.model),
1555
- stream: true,
1556
- }, options);
1557
- for await (const data of streamIterable) {
1558
- const chunk = _convertOpenAIResponsesDeltaToBaseMessageChunk(data);
1559
- if (chunk == null)
1560
- continue;
1561
- yield chunk;
1562
- }
1563
- return;
1564
- }
1565
1190
  const messagesMapped = _convertMessagesToOpenAIParams(messages, this.model);
1566
1191
  const params = {
1567
1192
  ...this.invocationParams(options, {
@@ -1666,60 +1291,7 @@ export class ChatOpenAI extends BaseChatModel {
1666
1291
  return this._identifyingParams();
1667
1292
  }
1668
1293
  /** @ignore */
1669
- async _responseApiGenerate(messages, options, runManager) {
1670
- const invocationParams = this.invocationParams(options);
1671
- if (invocationParams.stream) {
1672
- const stream = this._streamResponseChunks(messages, options, runManager);
1673
- let finalChunk;
1674
- for await (const chunk of stream) {
1675
- chunk.message.response_metadata = {
1676
- ...chunk.generationInfo,
1677
- ...chunk.message.response_metadata,
1678
- };
1679
- finalChunk = finalChunk?.concat(chunk) ?? chunk;
1680
- }
1681
- return {
1682
- generations: finalChunk ? [finalChunk] : [],
1683
- llmOutput: {
1684
- estimatedTokenUsage: finalChunk?.message
1685
- ?.usage_metadata,
1686
- },
1687
- };
1688
- }
1689
- const input = _convertMessagesToOpenAIResponsesParams(messages, this.model);
1690
- const data = await this.responseApiWithRetry({ input, ...invocationParams }, { signal: options?.signal, ...options?.options });
1691
- return {
1692
- generations: [
1693
- {
1694
- text: data.output_text,
1695
- message: _convertOpenAIResponsesMessageToBaseMessage(data),
1696
- },
1697
- ],
1698
- llmOutput: {
1699
- id: data.id,
1700
- estimatedTokenUsage: data.usage
1701
- ? {
1702
- promptTokens: data.usage.input_tokens,
1703
- completionTokens: data.usage.output_tokens,
1704
- totalTokens: data.usage.total_tokens,
1705
- }
1706
- : undefined,
1707
- },
1708
- };
1709
- }
1710
- _useResponseApi(options) {
1711
- const usesBuiltInTools = options?.tools?.some(isBuiltInTool);
1712
- const hasResponsesOnlyKwargs = options?.previous_response_id != null ||
1713
- options?.text != null ||
1714
- options?.truncation != null ||
1715
- options?.include != null;
1716
- return this.useResponsesApi || usesBuiltInTools || hasResponsesOnlyKwargs;
1717
- }
1718
- /** @ignore */
1719
1294
  async _generate(messages, options, runManager) {
1720
- if (this._useResponseApi(options)) {
1721
- return this._responseApiGenerate(messages, options, runManager);
1722
- }
1723
1295
  const usageMetadata = {};
1724
1296
  const params = this.invocationParams(options);
1725
1297
  const messagesMapped = _convertMessagesToOpenAIParams(messages, this.model);
@@ -1957,19 +1529,6 @@ export class ChatOpenAI extends BaseChatModel {
1957
1529
  }
1958
1530
  });
1959
1531
  }
1960
- async responseApiWithRetry(request, options) {
1961
- return this.caller.call(async () => {
1962
- const requestOptions = this._getClientOptions(options);
1963
- try {
1964
- const res = await this.client.responses.create(request, requestOptions);
1965
- return res;
1966
- }
1967
- catch (e) {
1968
- const error = wrapOpenAIClientError(e);
1969
- throw error;
1970
- }
1971
- });
1972
- }
1973
1532
  /**
1974
1533
  * Call the beta chat completions parse endpoint. This should only be called if
1975
1534
  * response_format is set to "json_object".
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/openai",
3
- "version": "0.4.5-rc.0",
3
+ "version": "0.4.5",
4
4
  "description": "OpenAI integrations for LangChain.js",
5
5
  "type": "module",
6
6
  "engines": {