@langchain/openai 0.5.12 → 0.5.14
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/azure/chat_models.cjs +5 -2
- package/dist/azure/chat_models.d.ts +4 -4
- package/dist/azure/chat_models.js +5 -2
- package/dist/azure/embeddings.cjs +5 -8
- package/dist/azure/embeddings.d.ts +1 -1
- package/dist/azure/embeddings.js +5 -8
- package/dist/azure/llms.cjs +4 -2
- package/dist/azure/llms.js +4 -2
- package/dist/chat_models.cjs +209 -101
- package/dist/chat_models.d.ts +5 -5
- package/dist/chat_models.js +173 -98
- package/dist/embeddings.d.ts +7 -3
- package/dist/tools/dalle.d.ts +7 -2
- package/dist/types.d.ts +8 -5
- package/dist/utils/azure.cjs +1 -2
- package/dist/utils/errors.cjs +1 -2
- package/dist/utils/headers.cjs +39 -0
- package/dist/utils/headers.d.ts +8 -0
- package/dist/utils/headers.js +35 -0
- package/dist/utils/openai-format-fndef.cjs +1 -2
- package/dist/utils/openai.cjs +7 -7
- package/dist/utils/openai.js +4 -4
- package/dist/utils/prompts.cjs +1 -2
- package/dist/utils/tools.cjs +18 -3
- package/dist/utils/tools.js +17 -1
- package/package.json +10 -11
package/dist/chat_models.cjs
CHANGED
|
@@ -1,6 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ChatOpenAI =
|
|
36
|
+
exports.ChatOpenAI = void 0;
|
|
37
|
+
exports.messageToOpenAIRole = messageToOpenAIRole;
|
|
38
|
+
exports._convertMessagesToOpenAIParams = _convertMessagesToOpenAIParams;
|
|
39
|
+
const z4 = __importStar(require("zod/v4/core"));
|
|
4
40
|
const openai_1 = require("openai");
|
|
5
41
|
const messages_1 = require("@langchain/core/messages");
|
|
6
42
|
const outputs_1 = require("@langchain/core/outputs");
|
|
@@ -10,8 +46,9 @@ const base_1 = require("@langchain/core/language_models/base");
|
|
|
10
46
|
const runnables_1 = require("@langchain/core/runnables");
|
|
11
47
|
const output_parsers_1 = require("@langchain/core/output_parsers");
|
|
12
48
|
const openai_tools_1 = require("@langchain/core/output_parsers/openai_tools");
|
|
13
|
-
const zod_to_json_schema_1 = require("zod-to-json-schema");
|
|
14
49
|
const zod_1 = require("openai/helpers/zod");
|
|
50
|
+
const types_1 = require("@langchain/core/utils/types");
|
|
51
|
+
const json_schema_1 = require("@langchain/core/utils/json_schema");
|
|
15
52
|
const azure_js_1 = require("./utils/azure.cjs");
|
|
16
53
|
const openai_js_1 = require("./utils/openai.cjs");
|
|
17
54
|
const openai_format_fndef_js_1 = require("./utils/openai-format-fndef.cjs");
|
|
@@ -49,7 +86,6 @@ function messageToOpenAIRole(message) {
|
|
|
49
86
|
throw new Error(`Unknown message type: ${type}`);
|
|
50
87
|
}
|
|
51
88
|
}
|
|
52
|
-
exports.messageToOpenAIRole = messageToOpenAIRole;
|
|
53
89
|
const completionsApiContentBlockConverter = {
|
|
54
90
|
providerName: "ChatOpenAI",
|
|
55
91
|
fromStandardTextBlock(block) {
|
|
@@ -138,7 +174,7 @@ const completionsApiContentBlockConverter = {
|
|
|
138
174
|
return {
|
|
139
175
|
type: "file",
|
|
140
176
|
file: {
|
|
141
|
-
file_data: block.url,
|
|
177
|
+
file_data: block.url, // formatted as base64 data URL
|
|
142
178
|
...(block.metadata?.filename || block.metadata?.name
|
|
143
179
|
? {
|
|
144
180
|
filename: (block.metadata?.filename ||
|
|
@@ -230,7 +266,6 @@ function _convertMessagesToOpenAIParams(messages, model) {
|
|
|
230
266
|
return completionParam;
|
|
231
267
|
});
|
|
232
268
|
}
|
|
233
|
-
exports._convertMessagesToOpenAIParams = _convertMessagesToOpenAIParams;
|
|
234
269
|
const _FUNCTION_CALL_IDS_MAP_KEY = "__openai_function_call_ids__";
|
|
235
270
|
function _convertReasoningSummaryToOpenAIResponsesParams(reasoning) {
|
|
236
271
|
// combine summary parts that have the the same index and then remove the indexes
|
|
@@ -252,12 +287,8 @@ function _convertReasoningSummaryToOpenAIResponsesParams(reasoning) {
|
|
|
252
287
|
};
|
|
253
288
|
}
|
|
254
289
|
function _convertMessagesToOpenAIResponsesParams(messages, model, zdrEnabled) {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
const newMessages = lastAIMessageId && lastAIMessageId.startsWith("resp_") && !zdrEnabled
|
|
258
|
-
? messages.slice(messages.indexOf(lastAIMessage) + 1)
|
|
259
|
-
: messages;
|
|
260
|
-
return newMessages.flatMap((lcMsg) => {
|
|
290
|
+
return messages.flatMap((lcMsg) => {
|
|
291
|
+
const additional_kwargs = lcMsg.additional_kwargs;
|
|
261
292
|
let role = messageToOpenAIRole(lcMsg);
|
|
262
293
|
if (role === "system" && isReasoningModel(model))
|
|
263
294
|
role = "developer";
|
|
@@ -267,7 +298,7 @@ function _convertMessagesToOpenAIResponsesParams(messages, model, zdrEnabled) {
|
|
|
267
298
|
if (role === "tool") {
|
|
268
299
|
const toolMessage = lcMsg;
|
|
269
300
|
// Handle computer call output
|
|
270
|
-
if (
|
|
301
|
+
if (additional_kwargs?.type === "computer_call_output") {
|
|
271
302
|
const output = (() => {
|
|
272
303
|
if (typeof toolMessage.content === "string") {
|
|
273
304
|
return {
|
|
@@ -318,25 +349,19 @@ function _convertMessagesToOpenAIResponsesParams(messages, model, zdrEnabled) {
|
|
|
318
349
|
// otherwise, try to reconstruct the response from what we have
|
|
319
350
|
const input = [];
|
|
320
351
|
// reasoning items
|
|
321
|
-
if (
|
|
322
|
-
const
|
|
323
|
-
|
|
324
|
-
"type" in item &&
|
|
325
|
-
item.type === "reasoning";
|
|
326
|
-
if (isReasoningItem(lcMsg.additional_kwargs.reasoning)) {
|
|
327
|
-
const reasoningItem = _convertReasoningSummaryToOpenAIResponsesParams(lcMsg.additional_kwargs.reasoning);
|
|
328
|
-
input.push(reasoningItem);
|
|
329
|
-
}
|
|
352
|
+
if (additional_kwargs?.reasoning && !zdrEnabled) {
|
|
353
|
+
const reasoningItem = _convertReasoningSummaryToOpenAIResponsesParams(additional_kwargs.reasoning);
|
|
354
|
+
input.push(reasoningItem);
|
|
330
355
|
}
|
|
331
356
|
// ai content
|
|
332
357
|
let { content } = lcMsg;
|
|
333
|
-
if (
|
|
358
|
+
if (additional_kwargs?.refusal) {
|
|
334
359
|
if (typeof content === "string") {
|
|
335
360
|
content = [{ type: "output_text", text: content, annotations: [] }];
|
|
336
361
|
}
|
|
337
362
|
content = [
|
|
338
363
|
...content,
|
|
339
|
-
{ type: "refusal", refusal:
|
|
364
|
+
{ type: "refusal", refusal: additional_kwargs.refusal },
|
|
340
365
|
];
|
|
341
366
|
}
|
|
342
367
|
input.push({
|
|
@@ -360,10 +385,7 @@ function _convertMessagesToOpenAIResponsesParams(messages, model, zdrEnabled) {
|
|
|
360
385
|
return [];
|
|
361
386
|
}),
|
|
362
387
|
});
|
|
363
|
-
|
|
364
|
-
const functionCallIds =
|
|
365
|
-
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
366
|
-
lcMsg.additional_kwargs[_FUNCTION_CALL_IDS_MAP_KEY];
|
|
388
|
+
const functionCallIds = additional_kwargs?.[_FUNCTION_CALL_IDS_MAP_KEY];
|
|
367
389
|
if ((0, messages_1.isAIMessage)(lcMsg) && !!lcMsg.tool_calls?.length) {
|
|
368
390
|
input.push(...lcMsg.tool_calls.map((toolCall) => ({
|
|
369
391
|
type: "function_call",
|
|
@@ -373,44 +395,64 @@ function _convertMessagesToOpenAIResponsesParams(messages, model, zdrEnabled) {
|
|
|
373
395
|
...(zdrEnabled ? { id: functionCallIds?.[toolCall.id] } : {}),
|
|
374
396
|
})));
|
|
375
397
|
}
|
|
376
|
-
else if (
|
|
377
|
-
input.push(...
|
|
398
|
+
else if (additional_kwargs?.tool_calls) {
|
|
399
|
+
input.push(...additional_kwargs.tool_calls.map((toolCall) => ({
|
|
378
400
|
type: "function_call",
|
|
379
401
|
name: toolCall.function.name,
|
|
380
402
|
call_id: toolCall.id,
|
|
381
|
-
...(zdrEnabled ? { id: functionCallIds?.[toolCall.id] } : {}),
|
|
382
403
|
arguments: toolCall.function.arguments,
|
|
404
|
+
...(zdrEnabled ? { id: functionCallIds?.[toolCall.id] } : {}),
|
|
383
405
|
})));
|
|
384
406
|
}
|
|
385
407
|
const toolOutputs = lcMsg.response_metadata.output?.length
|
|
386
408
|
? lcMsg.response_metadata.output
|
|
387
|
-
:
|
|
388
|
-
|
|
409
|
+
: additional_kwargs.tool_outputs;
|
|
410
|
+
const fallthroughCallTypes = [
|
|
411
|
+
"computer_call",
|
|
412
|
+
"mcp_call",
|
|
413
|
+
"code_interpreter_call",
|
|
414
|
+
"image_generation_call",
|
|
415
|
+
];
|
|
389
416
|
if (toolOutputs != null) {
|
|
390
417
|
const castToolOutputs = toolOutputs;
|
|
391
|
-
|
|
392
|
-
if (
|
|
393
|
-
input.push(...
|
|
418
|
+
const fallthroughCalls = castToolOutputs?.filter((item) => fallthroughCallTypes.includes(item.type));
|
|
419
|
+
if (fallthroughCalls.length > 0)
|
|
420
|
+
input.push(...fallthroughCalls);
|
|
394
421
|
}
|
|
395
422
|
return input;
|
|
396
423
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
424
|
+
if (role === "user" || role === "system" || role === "developer") {
|
|
425
|
+
if (typeof lcMsg.content === "string") {
|
|
426
|
+
return { type: "message", role, content: lcMsg.content };
|
|
427
|
+
}
|
|
428
|
+
const messages = [];
|
|
429
|
+
const content = lcMsg.content.flatMap((item) => {
|
|
430
|
+
if (item.type === "mcp_approval_response") {
|
|
431
|
+
messages.push({
|
|
432
|
+
type: "mcp_approval_response",
|
|
433
|
+
approval_request_id: item.approval_request_id,
|
|
434
|
+
approve: item.approve,
|
|
435
|
+
});
|
|
436
|
+
}
|
|
400
437
|
if ((0, messages_1.isDataContentBlock)(item)) {
|
|
401
438
|
return (0, messages_1.convertToProviderContentBlock)(item, completionsApiContentBlockConverter);
|
|
402
439
|
}
|
|
403
440
|
if (item.type === "text") {
|
|
404
|
-
return {
|
|
441
|
+
return {
|
|
442
|
+
type: "input_text",
|
|
443
|
+
text: item.text,
|
|
444
|
+
};
|
|
405
445
|
}
|
|
406
446
|
if (item.type === "image_url") {
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
: item.image_url
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
: item.image_url
|
|
413
|
-
|
|
447
|
+
return {
|
|
448
|
+
type: "input_image",
|
|
449
|
+
image_url: typeof item.image_url === "string"
|
|
450
|
+
? item.image_url
|
|
451
|
+
: item.image_url.url,
|
|
452
|
+
detail: typeof item.image_url === "string"
|
|
453
|
+
? "auto"
|
|
454
|
+
: item.image_url.detail,
|
|
455
|
+
};
|
|
414
456
|
}
|
|
415
457
|
if (item.type === "input_text" ||
|
|
416
458
|
item.type === "input_image" ||
|
|
@@ -419,8 +461,10 @@ function _convertMessagesToOpenAIResponsesParams(messages, model, zdrEnabled) {
|
|
|
419
461
|
}
|
|
420
462
|
return [];
|
|
421
463
|
});
|
|
422
|
-
|
|
423
|
-
|
|
464
|
+
if (content.length > 0) {
|
|
465
|
+
messages.push({ type: "message", role, content });
|
|
466
|
+
}
|
|
467
|
+
return messages;
|
|
424
468
|
}
|
|
425
469
|
console.warn(`Unsupported role found when converting to OpenAI Responses API: ${role}`);
|
|
426
470
|
return [];
|
|
@@ -527,7 +571,7 @@ function _convertOpenAIResponsesDeltaToBaseMessageChunk(chunk) {
|
|
|
527
571
|
index: chunk.content_index,
|
|
528
572
|
});
|
|
529
573
|
}
|
|
530
|
-
else if (chunk.type === "response.
|
|
574
|
+
else if (chunk.type === "response.output_text_annotation.added") {
|
|
531
575
|
content.push({
|
|
532
576
|
type: "text",
|
|
533
577
|
text: "",
|
|
@@ -553,9 +597,16 @@ function _convertOpenAIResponsesDeltaToBaseMessageChunk(chunk) {
|
|
|
553
597
|
};
|
|
554
598
|
}
|
|
555
599
|
else if (chunk.type === "response.output_item.done" &&
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
600
|
+
[
|
|
601
|
+
"web_search_call",
|
|
602
|
+
"file_search_call",
|
|
603
|
+
"computer_call",
|
|
604
|
+
"code_interpreter_call",
|
|
605
|
+
"mcp_call",
|
|
606
|
+
"mcp_list_tools",
|
|
607
|
+
"mcp_approval_request",
|
|
608
|
+
"image_generation_call",
|
|
609
|
+
].includes(chunk.item.type)) {
|
|
559
610
|
additional_kwargs.tool_outputs = [chunk.item];
|
|
560
611
|
}
|
|
561
612
|
else if (chunk.type === "response.created") {
|
|
@@ -627,6 +678,11 @@ function _convertOpenAIResponsesDeltaToBaseMessageChunk(chunk) {
|
|
|
627
678
|
],
|
|
628
679
|
};
|
|
629
680
|
}
|
|
681
|
+
else if (chunk.type === "response.image_generation_call.partial_image") {
|
|
682
|
+
// noop/fixme: retaining partial images in a message chunk means that _all_
|
|
683
|
+
// partial images get kept in history, so we don't do anything here.
|
|
684
|
+
return null;
|
|
685
|
+
}
|
|
630
686
|
else {
|
|
631
687
|
return null;
|
|
632
688
|
}
|
|
@@ -653,6 +709,29 @@ function isBuiltInToolChoice(tool_choice) {
|
|
|
653
709
|
"type" in tool_choice &&
|
|
654
710
|
tool_choice.type !== "function");
|
|
655
711
|
}
|
|
712
|
+
function _reduceChatOpenAIToolsForResponses(tools, fields) {
|
|
713
|
+
const reducedTools = [];
|
|
714
|
+
for (const tool of tools) {
|
|
715
|
+
if (isBuiltInTool(tool)) {
|
|
716
|
+
if (tool.type === "image_generation" && fields?.stream) {
|
|
717
|
+
// OpenAI sends a 400 error if partial_images is not set and we want to stream.
|
|
718
|
+
// We also set it to 1 since we don't support partial images yet.
|
|
719
|
+
tool.partial_images = 1;
|
|
720
|
+
}
|
|
721
|
+
reducedTools.push(tool);
|
|
722
|
+
}
|
|
723
|
+
else if ((0, base_1.isOpenAITool)(tool)) {
|
|
724
|
+
reducedTools.push({
|
|
725
|
+
type: "function",
|
|
726
|
+
name: tool.function.name,
|
|
727
|
+
parameters: tool.function.parameters,
|
|
728
|
+
description: tool.function.description,
|
|
729
|
+
strict: fields?.strict ?? null,
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
return reducedTools;
|
|
734
|
+
}
|
|
656
735
|
function _convertChatOpenAIToolTypeToOpenAITool(tool, fields) {
|
|
657
736
|
if ((0, base_1.isOpenAITool)(tool)) {
|
|
658
737
|
if (fields?.strict !== undefined) {
|
|
@@ -1587,8 +1666,8 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
1587
1666
|
if (resFormat &&
|
|
1588
1667
|
resFormat.type === "json_schema" &&
|
|
1589
1668
|
resFormat.json_schema.schema &&
|
|
1590
|
-
|
|
1591
|
-
return (
|
|
1669
|
+
(0, types_1.isInteropZodSchema)(resFormat.json_schema.schema)) {
|
|
1670
|
+
return interopZodResponseFormat(resFormat.json_schema.schema, resFormat.json_schema.name, {
|
|
1592
1671
|
description: resFormat.json_schema.description,
|
|
1593
1672
|
});
|
|
1594
1673
|
}
|
|
@@ -1646,25 +1725,10 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
1646
1725
|
truncation: options?.truncation,
|
|
1647
1726
|
include: options?.include,
|
|
1648
1727
|
tools: options?.tools?.length
|
|
1649
|
-
? options.tools
|
|
1650
|
-
.
|
|
1651
|
-
|
|
1652
|
-
return tool;
|
|
1653
|
-
}
|
|
1654
|
-
else if ((0, base_1.isOpenAITool)(tool)) {
|
|
1655
|
-
return {
|
|
1656
|
-
type: "function",
|
|
1657
|
-
name: tool.function.name,
|
|
1658
|
-
parameters: tool.function.parameters,
|
|
1659
|
-
description: tool.function.description,
|
|
1660
|
-
strict,
|
|
1661
|
-
};
|
|
1662
|
-
}
|
|
1663
|
-
else {
|
|
1664
|
-
return null;
|
|
1665
|
-
}
|
|
1728
|
+
? _reduceChatOpenAIToolsForResponses(options.tools, {
|
|
1729
|
+
stream: this.streaming,
|
|
1730
|
+
strict,
|
|
1666
1731
|
})
|
|
1667
|
-
.filter((tool) => tool !== null)
|
|
1668
1732
|
: undefined,
|
|
1669
1733
|
tool_choice: isBuiltInToolChoice(options?.tool_choice)
|
|
1670
1734
|
? options?.tool_choice
|
|
@@ -1907,17 +1971,10 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
1907
1971
|
}
|
|
1908
1972
|
async *_streamResponseChunks(messages, options, runManager) {
|
|
1909
1973
|
if (this._useResponseApi(options)) {
|
|
1910
|
-
const lastAIMessage = messages.filter((m) => (0, messages_1.isAIMessage)(m)).pop();
|
|
1911
|
-
const lastAIMessageId = lastAIMessage?.response_metadata?.id;
|
|
1912
1974
|
const streamIterable = await this.responseApiWithRetry({
|
|
1913
1975
|
...this.invocationParams(options, { streaming: true }),
|
|
1914
1976
|
input: _convertMessagesToOpenAIResponsesParams(messages, this.model, this.zdrEnabled),
|
|
1915
1977
|
stream: true,
|
|
1916
|
-
...(lastAIMessageId &&
|
|
1917
|
-
lastAIMessageId.startsWith("resp_") &&
|
|
1918
|
-
!this.zdrEnabled
|
|
1919
|
-
? { previous_response_id: lastAIMessageId }
|
|
1920
|
-
: {}),
|
|
1921
1978
|
}, options);
|
|
1922
1979
|
for await (const data of streamIterable) {
|
|
1923
1980
|
const chunk = _convertOpenAIResponsesDeltaToBaseMessageChunk(data);
|
|
@@ -2051,17 +2108,10 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
2051
2108
|
},
|
|
2052
2109
|
};
|
|
2053
2110
|
}
|
|
2054
|
-
const lastAIMessage = messages.filter((m) => (0, messages_1.isAIMessage)(m)).pop();
|
|
2055
|
-
const lastAIMessageId = lastAIMessage?.response_metadata?.id;
|
|
2056
2111
|
const input = _convertMessagesToOpenAIResponsesParams(messages, this.model, this.zdrEnabled);
|
|
2057
2112
|
const data = await this.responseApiWithRetry({
|
|
2058
2113
|
input,
|
|
2059
2114
|
...invocationParams,
|
|
2060
|
-
...(lastAIMessageId &&
|
|
2061
|
-
lastAIMessageId.startsWith("resp_") &&
|
|
2062
|
-
!this.zdrEnabled
|
|
2063
|
-
? { previous_response_id: lastAIMessageId }
|
|
2064
|
-
: {}),
|
|
2065
2115
|
}, { signal: options?.signal, ...options?.options });
|
|
2066
2116
|
return {
|
|
2067
2117
|
generations: [
|
|
@@ -2371,7 +2421,7 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
2371
2421
|
const requestOptions = this._getClientOptions(options);
|
|
2372
2422
|
return this.caller.call(async () => {
|
|
2373
2423
|
try {
|
|
2374
|
-
const res = await this.client.
|
|
2424
|
+
const res = await this.client.chat.completions.parse(request, requestOptions);
|
|
2375
2425
|
return res;
|
|
2376
2426
|
}
|
|
2377
2427
|
catch (e) {
|
|
@@ -2458,15 +2508,21 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
2458
2508
|
console.warn(`[WARNING]: JSON Schema is not supported for model "${this.model}". Falling back to tool calling.`);
|
|
2459
2509
|
}
|
|
2460
2510
|
if (method === "jsonMode") {
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
});
|
|
2464
|
-
if (isZodSchema(schema)) {
|
|
2511
|
+
let outputFormatSchema;
|
|
2512
|
+
if ((0, types_1.isInteropZodSchema)(schema)) {
|
|
2465
2513
|
outputParser = output_parsers_1.StructuredOutputParser.fromZodSchema(schema);
|
|
2514
|
+
outputFormatSchema = (0, json_schema_1.toJsonSchema)(schema);
|
|
2466
2515
|
}
|
|
2467
2516
|
else {
|
|
2468
2517
|
outputParser = new output_parsers_1.JsonOutputParser();
|
|
2469
2518
|
}
|
|
2519
|
+
llm = this.withConfig({
|
|
2520
|
+
response_format: { type: "json_object" },
|
|
2521
|
+
ls_structured_output_format: {
|
|
2522
|
+
kwargs: { method: "jsonMode" },
|
|
2523
|
+
schema: outputFormatSchema,
|
|
2524
|
+
},
|
|
2525
|
+
});
|
|
2470
2526
|
}
|
|
2471
2527
|
else if (method === "jsonSchema") {
|
|
2472
2528
|
llm = this.withConfig({
|
|
@@ -2474,13 +2530,17 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
2474
2530
|
type: "json_schema",
|
|
2475
2531
|
json_schema: {
|
|
2476
2532
|
name: name ?? "extract",
|
|
2477
|
-
description: schema
|
|
2533
|
+
description: (0, types_1.getSchemaDescription)(schema),
|
|
2478
2534
|
schema,
|
|
2479
2535
|
strict: config?.strict,
|
|
2480
2536
|
},
|
|
2481
2537
|
},
|
|
2538
|
+
ls_structured_output_format: {
|
|
2539
|
+
kwargs: { method: "jsonSchema" },
|
|
2540
|
+
schema: (0, json_schema_1.toJsonSchema)(schema),
|
|
2541
|
+
},
|
|
2482
2542
|
});
|
|
2483
|
-
if (
|
|
2543
|
+
if ((0, types_1.isInteropZodSchema)(schema)) {
|
|
2484
2544
|
const altParser = output_parsers_1.StructuredOutputParser.fromZodSchema(schema);
|
|
2485
2545
|
outputParser = runnables_1.RunnableLambda.from((aiMessage) => {
|
|
2486
2546
|
if ("parsed" in aiMessage.additional_kwargs) {
|
|
@@ -2496,8 +2556,8 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
2496
2556
|
else {
|
|
2497
2557
|
let functionName = name ?? "extract";
|
|
2498
2558
|
// Is function calling
|
|
2499
|
-
if (
|
|
2500
|
-
const asJsonSchema = (0,
|
|
2559
|
+
if ((0, types_1.isInteropZodSchema)(schema)) {
|
|
2560
|
+
const asJsonSchema = (0, json_schema_1.toJsonSchema)(schema);
|
|
2501
2561
|
llm = this.withConfig({
|
|
2502
2562
|
tools: [
|
|
2503
2563
|
{
|
|
@@ -2515,6 +2575,10 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
2515
2575
|
name: functionName,
|
|
2516
2576
|
},
|
|
2517
2577
|
},
|
|
2578
|
+
ls_structured_output_format: {
|
|
2579
|
+
kwargs: { method: "functionCalling" },
|
|
2580
|
+
schema: asJsonSchema,
|
|
2581
|
+
},
|
|
2518
2582
|
// Do not pass `strict` argument to OpenAI if `config.strict` is undefined
|
|
2519
2583
|
...(config?.strict !== undefined ? { strict: config.strict } : {}),
|
|
2520
2584
|
});
|
|
@@ -2553,6 +2617,10 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
2553
2617
|
name: functionName,
|
|
2554
2618
|
},
|
|
2555
2619
|
},
|
|
2620
|
+
ls_structured_output_format: {
|
|
2621
|
+
kwargs: { method: "functionCalling" },
|
|
2622
|
+
schema: (0, json_schema_1.toJsonSchema)(schema),
|
|
2623
|
+
},
|
|
2556
2624
|
// Do not pass `strict` argument to OpenAI if `config.strict` is undefined
|
|
2557
2625
|
...(config?.strict !== undefined ? { strict: config.strict } : {}),
|
|
2558
2626
|
});
|
|
@@ -2579,12 +2647,6 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
2579
2647
|
}
|
|
2580
2648
|
}
|
|
2581
2649
|
exports.ChatOpenAI = ChatOpenAI;
|
|
2582
|
-
function isZodSchema(
|
|
2583
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2584
|
-
input) {
|
|
2585
|
-
// Check for a characteristic method of Zod schemas
|
|
2586
|
-
return typeof input?.parse === "function";
|
|
2587
|
-
}
|
|
2588
2650
|
function isStructuredOutputMethodParams(x
|
|
2589
2651
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2590
2652
|
) {
|
|
@@ -2593,3 +2655,49 @@ function isStructuredOutputMethodParams(x
|
|
|
2593
2655
|
typeof x.schema ===
|
|
2594
2656
|
"object");
|
|
2595
2657
|
}
|
|
2658
|
+
// inlined from openai/lib/parser.ts
|
|
2659
|
+
function makeParseableResponseFormat(response_format, parser) {
|
|
2660
|
+
const obj = { ...response_format };
|
|
2661
|
+
Object.defineProperties(obj, {
|
|
2662
|
+
$brand: {
|
|
2663
|
+
value: "auto-parseable-response-format",
|
|
2664
|
+
enumerable: false,
|
|
2665
|
+
},
|
|
2666
|
+
$parseRaw: {
|
|
2667
|
+
value: parser,
|
|
2668
|
+
enumerable: false,
|
|
2669
|
+
},
|
|
2670
|
+
});
|
|
2671
|
+
return obj;
|
|
2672
|
+
}
|
|
2673
|
+
function interopZodResponseFormat(zodSchema, name, props) {
|
|
2674
|
+
if ((0, types_1.isZodSchemaV3)(zodSchema)) {
|
|
2675
|
+
return (0, zod_1.zodResponseFormat)(zodSchema, name, props);
|
|
2676
|
+
}
|
|
2677
|
+
if ((0, types_1.isZodSchemaV4)(zodSchema)) {
|
|
2678
|
+
return makeParseableResponseFormat({
|
|
2679
|
+
type: "json_schema",
|
|
2680
|
+
json_schema: {
|
|
2681
|
+
...props,
|
|
2682
|
+
name,
|
|
2683
|
+
strict: true,
|
|
2684
|
+
schema: z4.toJSONSchema(zodSchema, {
|
|
2685
|
+
cycles: "ref", // equivalent to nameStrategy: 'duplicate-ref'
|
|
2686
|
+
reused: "ref", // equivalent to $refStrategy: 'extract-to-root'
|
|
2687
|
+
override(ctx) {
|
|
2688
|
+
ctx.jsonSchema.title = name; // equivalent to `name` property
|
|
2689
|
+
// TODO: implement `nullableStrategy` patch-fix (zod doesn't support openApi3 json schema target)
|
|
2690
|
+
// TODO: implement `openaiStrictMode` patch-fix (where optional properties without `nullable` are not supported)
|
|
2691
|
+
},
|
|
2692
|
+
/// property equivalents from native `zodResponseFormat` fn
|
|
2693
|
+
// openaiStrictMode: true,
|
|
2694
|
+
// name,
|
|
2695
|
+
// nameStrategy: 'duplicate-ref',
|
|
2696
|
+
// $refStrategy: 'extract-to-root',
|
|
2697
|
+
// nullableStrategy: 'property',
|
|
2698
|
+
}),
|
|
2699
|
+
},
|
|
2700
|
+
}, (content) => z4.parse(zodSchema, JSON.parse(content)));
|
|
2701
|
+
}
|
|
2702
|
+
throw new Error("Unsupported schema response format");
|
|
2703
|
+
}
|
package/dist/chat_models.d.ts
CHANGED
|
@@ -4,8 +4,8 @@ import { AIMessageChunk, type BaseMessage, ChatMessageChunk, FunctionMessageChun
|
|
|
4
4
|
import { ChatGenerationChunk, type ChatResult } from "@langchain/core/outputs";
|
|
5
5
|
import { BaseChatModel, type BindToolsInput, type 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
|
-
import { z } from "zod";
|
|
8
7
|
import { Runnable } from "@langchain/core/runnables";
|
|
8
|
+
import { InteropZodType } from "@langchain/core/utils/types";
|
|
9
9
|
import { type OpenAICallOptions, type OpenAIChatInput, type OpenAICoreRequestOptions, type ChatOpenAIResponseFormat } from "./types.js";
|
|
10
10
|
import { OpenAIToolChoice } from "./utils/openai.js";
|
|
11
11
|
export type { OpenAICallOptions, OpenAIChatInput };
|
|
@@ -841,17 +841,17 @@ export declare class ChatOpenAI<CallOptions extends ChatOpenAICallOptions = Chat
|
|
|
841
841
|
* @param {OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming} request
|
|
842
842
|
* @param {OpenAICoreRequestOptions | undefined} options
|
|
843
843
|
*/
|
|
844
|
-
betaParsedCompletionWithRetry(request: OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming, options?: OpenAICoreRequestOptions): Promise<ReturnType<OpenAIClient["
|
|
844
|
+
betaParsedCompletionWithRetry(request: OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming, options?: OpenAICoreRequestOptions): Promise<ReturnType<OpenAIClient["chat"]["completions"]["parse"]>>;
|
|
845
845
|
protected _getClientOptions(options: OpenAICoreRequestOptions | undefined): OpenAICoreRequestOptions;
|
|
846
846
|
_llmType(): string;
|
|
847
847
|
/** @ignore */
|
|
848
848
|
_combineLLMOutput(...llmOutputs: OpenAILLMOutput[]): OpenAILLMOutput;
|
|
849
|
-
withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema:
|
|
850
|
-
withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema:
|
|
849
|
+
withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: InteropZodType<RunOutput> | Record<string, any>, config?: ChatOpenAIStructuredOutputMethodOptions<false>): Runnable<BaseLanguageModelInput, RunOutput>;
|
|
850
|
+
withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: InteropZodType<RunOutput> | Record<string, any>, config?: ChatOpenAIStructuredOutputMethodOptions<true>): Runnable<BaseLanguageModelInput, {
|
|
851
851
|
raw: BaseMessage;
|
|
852
852
|
parsed: RunOutput;
|
|
853
853
|
}>;
|
|
854
|
-
withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema:
|
|
854
|
+
withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: InteropZodType<RunOutput> | Record<string, any>, config?: ChatOpenAIStructuredOutputMethodOptions<boolean>): Runnable<BaseLanguageModelInput, RunOutput> | Runnable<BaseLanguageModelInput, {
|
|
855
855
|
raw: BaseMessage;
|
|
856
856
|
parsed: RunOutput;
|
|
857
857
|
}>;
|