@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.
- package/dist/chat_models.cjs +1 -442
- package/dist/chat_models.d.ts +5 -46
- package/dist/chat_models.js +1 -442
- package/package.json +1 -1
package/dist/chat_models.cjs
CHANGED
|
@@ -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) =>
|
|
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".
|
package/dist/chat_models.d.ts
CHANGED
|
@@ -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,
|
|
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
|
|
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
|
|
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
|
|
699
|
+
invocationParams(options?: this["ParsedCallOptions"], extra?: {
|
|
734
700
|
streaming?: boolean;
|
|
735
|
-
}):
|
|
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".
|
package/dist/chat_models.js
CHANGED
|
@@ -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) =>
|
|
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".
|