@langchain/openai 0.6.10 → 0.6.12
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 +13 -9
- package/dist/chat_models.js +13 -9
- package/dist/embeddings.cjs +13 -0
- package/dist/embeddings.d.ts +8 -3
- package/dist/embeddings.js +13 -0
- package/dist/types.d.ts +1 -1
- package/dist/utils/output.cjs +30 -0
- package/dist/utils/output.d.ts +9 -0
- package/dist/utils/output.js +27 -0
- package/package.json +1 -1
package/dist/chat_models.cjs
CHANGED
|
@@ -18,6 +18,7 @@ const azure_js_1 = require("./utils/azure.cjs");
|
|
|
18
18
|
const openai_js_1 = require("./utils/openai.cjs");
|
|
19
19
|
const openai_format_fndef_js_1 = require("./utils/openai-format-fndef.cjs");
|
|
20
20
|
const tools_js_1 = require("./utils/tools.cjs");
|
|
21
|
+
const output_js_1 = require("./utils/output.cjs");
|
|
21
22
|
const _FUNCTION_CALL_IDS_MAP_KEY = "__openai_function_call_ids__";
|
|
22
23
|
function isReasoningModel(model) {
|
|
23
24
|
if (!model)
|
|
@@ -273,7 +274,7 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
273
274
|
"response_format",
|
|
274
275
|
"seed",
|
|
275
276
|
"reasoning",
|
|
276
|
-
"
|
|
277
|
+
"reasoningEffort",
|
|
277
278
|
"service_tier",
|
|
278
279
|
];
|
|
279
280
|
}
|
|
@@ -287,6 +288,7 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
287
288
|
return {
|
|
288
289
|
apiKey: "openai_api_key",
|
|
289
290
|
modelName: "model",
|
|
291
|
+
reasoningEffort: "reasoning_effort",
|
|
290
292
|
};
|
|
291
293
|
}
|
|
292
294
|
get lc_serializable_keys() {
|
|
@@ -325,7 +327,7 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
325
327
|
"disableStreaming",
|
|
326
328
|
"zdrEnabled",
|
|
327
329
|
"reasoning",
|
|
328
|
-
"
|
|
330
|
+
"reasoningEffort",
|
|
329
331
|
"promptCacheKey",
|
|
330
332
|
"verbosity",
|
|
331
333
|
];
|
|
@@ -603,18 +605,18 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
603
605
|
this.audio = fields?.audio;
|
|
604
606
|
this.modalities = fields?.modalities;
|
|
605
607
|
this.reasoning =
|
|
606
|
-
fields?.reasoning ?? fields?.
|
|
607
|
-
? { effort: fields.
|
|
608
|
+
fields?.reasoning ?? fields?.reasoningEffort
|
|
609
|
+
? { effort: fields.reasoningEffort }
|
|
608
610
|
: undefined;
|
|
609
611
|
this.maxTokens = fields?.maxCompletionTokens ?? fields?.maxTokens;
|
|
610
|
-
this.disableStreaming = fields?.disableStreaming
|
|
612
|
+
this.disableStreaming = fields?.disableStreaming === true;
|
|
613
|
+
this.streaming = fields?.streaming === true;
|
|
611
614
|
this.promptCacheKey = fields?.promptCacheKey ?? this.promptCacheKey;
|
|
612
615
|
this.verbosity = fields?.verbosity ?? this.verbosity;
|
|
613
|
-
this.streaming = fields?.streaming ?? false;
|
|
614
616
|
// disable streaming in BaseChatModel if explicitly disabled
|
|
615
617
|
if (this.streaming === false)
|
|
616
618
|
this.disableStreaming = true;
|
|
617
|
-
if (this.disableStreaming)
|
|
619
|
+
if (this.disableStreaming === true)
|
|
618
620
|
this.streaming = false;
|
|
619
621
|
this.streamUsage = fields?.streamUsage ?? this.streamUsage;
|
|
620
622
|
if (this.disableStreaming)
|
|
@@ -1373,7 +1375,8 @@ class ChatOpenAIResponses extends BaseChatOpenAI {
|
|
|
1373
1375
|
response_metadata[key] = value;
|
|
1374
1376
|
}
|
|
1375
1377
|
}
|
|
1376
|
-
else if (chunk.type === "response.function_call_arguments.delta"
|
|
1378
|
+
else if (chunk.type === "response.function_call_arguments.delta" ||
|
|
1379
|
+
chunk.type === "response.custom_tool_call_input.delta") {
|
|
1377
1380
|
tool_call_chunks.push({
|
|
1378
1381
|
type: "tool_call_chunk",
|
|
1379
1382
|
args: chunk.delta,
|
|
@@ -2061,8 +2064,9 @@ class ChatOpenAICompletions extends BaseChatOpenAI {
|
|
|
2061
2064
|
if (message.audio) {
|
|
2062
2065
|
additional_kwargs.audio = message.audio;
|
|
2063
2066
|
}
|
|
2067
|
+
const content = (0, output_js_1.handleMultiModalOutput)(message.content || "", rawResponse.choices?.[0]?.message);
|
|
2064
2068
|
return new messages_1.AIMessage({
|
|
2065
|
-
content
|
|
2069
|
+
content,
|
|
2066
2070
|
tool_calls: toolCalls,
|
|
2067
2071
|
invalid_tool_calls: invalidToolCalls,
|
|
2068
2072
|
additional_kwargs,
|
package/dist/chat_models.js
CHANGED
|
@@ -13,6 +13,7 @@ import { getEndpoint } from "./utils/azure.js";
|
|
|
13
13
|
import { formatToOpenAIToolChoice, interopZodResponseFormat, wrapOpenAIClientError, } from "./utils/openai.js";
|
|
14
14
|
import { formatFunctionDefinitions, } from "./utils/openai-format-fndef.js";
|
|
15
15
|
import { _convertToOpenAITool, convertCompletionsCustomTool, convertResponsesCustomTool, isBuiltInTool, isBuiltInToolChoice, isCustomTool, isCustomToolCall, isOpenAICustomTool, parseCustomToolCall, } from "./utils/tools.js";
|
|
16
|
+
import { handleMultiModalOutput } from "./utils/output.js";
|
|
16
17
|
const _FUNCTION_CALL_IDS_MAP_KEY = "__openai_function_call_ids__";
|
|
17
18
|
function isReasoningModel(model) {
|
|
18
19
|
if (!model)
|
|
@@ -268,7 +269,7 @@ export class BaseChatOpenAI extends BaseChatModel {
|
|
|
268
269
|
"response_format",
|
|
269
270
|
"seed",
|
|
270
271
|
"reasoning",
|
|
271
|
-
"
|
|
272
|
+
"reasoningEffort",
|
|
272
273
|
"service_tier",
|
|
273
274
|
];
|
|
274
275
|
}
|
|
@@ -282,6 +283,7 @@ export class BaseChatOpenAI extends BaseChatModel {
|
|
|
282
283
|
return {
|
|
283
284
|
apiKey: "openai_api_key",
|
|
284
285
|
modelName: "model",
|
|
286
|
+
reasoningEffort: "reasoning_effort",
|
|
285
287
|
};
|
|
286
288
|
}
|
|
287
289
|
get lc_serializable_keys() {
|
|
@@ -320,7 +322,7 @@ export class BaseChatOpenAI extends BaseChatModel {
|
|
|
320
322
|
"disableStreaming",
|
|
321
323
|
"zdrEnabled",
|
|
322
324
|
"reasoning",
|
|
323
|
-
"
|
|
325
|
+
"reasoningEffort",
|
|
324
326
|
"promptCacheKey",
|
|
325
327
|
"verbosity",
|
|
326
328
|
];
|
|
@@ -598,18 +600,18 @@ export class BaseChatOpenAI extends BaseChatModel {
|
|
|
598
600
|
this.audio = fields?.audio;
|
|
599
601
|
this.modalities = fields?.modalities;
|
|
600
602
|
this.reasoning =
|
|
601
|
-
fields?.reasoning ?? fields?.
|
|
602
|
-
? { effort: fields.
|
|
603
|
+
fields?.reasoning ?? fields?.reasoningEffort
|
|
604
|
+
? { effort: fields.reasoningEffort }
|
|
603
605
|
: undefined;
|
|
604
606
|
this.maxTokens = fields?.maxCompletionTokens ?? fields?.maxTokens;
|
|
605
|
-
this.disableStreaming = fields?.disableStreaming
|
|
607
|
+
this.disableStreaming = fields?.disableStreaming === true;
|
|
608
|
+
this.streaming = fields?.streaming === true;
|
|
606
609
|
this.promptCacheKey = fields?.promptCacheKey ?? this.promptCacheKey;
|
|
607
610
|
this.verbosity = fields?.verbosity ?? this.verbosity;
|
|
608
|
-
this.streaming = fields?.streaming ?? false;
|
|
609
611
|
// disable streaming in BaseChatModel if explicitly disabled
|
|
610
612
|
if (this.streaming === false)
|
|
611
613
|
this.disableStreaming = true;
|
|
612
|
-
if (this.disableStreaming)
|
|
614
|
+
if (this.disableStreaming === true)
|
|
613
615
|
this.streaming = false;
|
|
614
616
|
this.streamUsage = fields?.streamUsage ?? this.streamUsage;
|
|
615
617
|
if (this.disableStreaming)
|
|
@@ -1367,7 +1369,8 @@ export class ChatOpenAIResponses extends BaseChatOpenAI {
|
|
|
1367
1369
|
response_metadata[key] = value;
|
|
1368
1370
|
}
|
|
1369
1371
|
}
|
|
1370
|
-
else if (chunk.type === "response.function_call_arguments.delta"
|
|
1372
|
+
else if (chunk.type === "response.function_call_arguments.delta" ||
|
|
1373
|
+
chunk.type === "response.custom_tool_call_input.delta") {
|
|
1371
1374
|
tool_call_chunks.push({
|
|
1372
1375
|
type: "tool_call_chunk",
|
|
1373
1376
|
args: chunk.delta,
|
|
@@ -2054,8 +2057,9 @@ export class ChatOpenAICompletions extends BaseChatOpenAI {
|
|
|
2054
2057
|
if (message.audio) {
|
|
2055
2058
|
additional_kwargs.audio = message.audio;
|
|
2056
2059
|
}
|
|
2060
|
+
const content = handleMultiModalOutput(message.content || "", rawResponse.choices?.[0]?.message);
|
|
2057
2061
|
return new AIMessage({
|
|
2058
|
-
content
|
|
2062
|
+
content,
|
|
2059
2063
|
tool_calls: toolCalls,
|
|
2060
2064
|
invalid_tool_calls: invalidToolCalls,
|
|
2061
2065
|
additional_kwargs,
|
package/dist/embeddings.cjs
CHANGED
|
@@ -75,6 +75,12 @@ class OpenAIEmbeddings extends embeddings_1.Embeddings {
|
|
|
75
75
|
writable: true,
|
|
76
76
|
value: void 0
|
|
77
77
|
});
|
|
78
|
+
Object.defineProperty(this, "encodingFormat", {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
configurable: true,
|
|
81
|
+
writable: true,
|
|
82
|
+
value: void 0
|
|
83
|
+
});
|
|
78
84
|
Object.defineProperty(this, "client", {
|
|
79
85
|
enumerable: true,
|
|
80
86
|
configurable: true,
|
|
@@ -101,6 +107,7 @@ class OpenAIEmbeddings extends embeddings_1.Embeddings {
|
|
|
101
107
|
fieldsWithDefaults?.stripNewLines ?? this.stripNewLines;
|
|
102
108
|
this.timeout = fieldsWithDefaults?.timeout;
|
|
103
109
|
this.dimensions = fieldsWithDefaults?.dimensions;
|
|
110
|
+
this.encodingFormat = fieldsWithDefaults?.encodingFormat;
|
|
104
111
|
this.clientConfig = {
|
|
105
112
|
apiKey,
|
|
106
113
|
organization: this.organization,
|
|
@@ -125,6 +132,9 @@ class OpenAIEmbeddings extends embeddings_1.Embeddings {
|
|
|
125
132
|
if (this.dimensions) {
|
|
126
133
|
params.dimensions = this.dimensions;
|
|
127
134
|
}
|
|
135
|
+
if (this.encodingFormat) {
|
|
136
|
+
params.encoding_format = this.encodingFormat;
|
|
137
|
+
}
|
|
128
138
|
return this.embeddingWithRetry(params);
|
|
129
139
|
});
|
|
130
140
|
const batchResponses = await Promise.all(batchRequests);
|
|
@@ -152,6 +162,9 @@ class OpenAIEmbeddings extends embeddings_1.Embeddings {
|
|
|
152
162
|
if (this.dimensions) {
|
|
153
163
|
params.dimensions = this.dimensions;
|
|
154
164
|
}
|
|
165
|
+
if (this.encodingFormat) {
|
|
166
|
+
params.encoding_format = this.encodingFormat;
|
|
167
|
+
}
|
|
155
168
|
const { data } = await this.embeddingWithRetry(params);
|
|
156
169
|
return data[0].embedding;
|
|
157
170
|
}
|
package/dist/embeddings.d.ts
CHANGED
|
@@ -37,6 +37,10 @@ export interface OpenAIEmbeddingsParams extends EmbeddingsParams {
|
|
|
37
37
|
* See: https://github.com/openai/openai-python/issues/418#issuecomment-1525939500
|
|
38
38
|
*/
|
|
39
39
|
stripNewLines?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* The format to return the embeddings in. Can be either 'float' or 'base64'.
|
|
42
|
+
*/
|
|
43
|
+
encodingFormat?: "float" | "base64";
|
|
40
44
|
}
|
|
41
45
|
/**
|
|
42
46
|
* Class for generating embeddings using the OpenAI API.
|
|
@@ -54,7 +58,7 @@ export interface OpenAIEmbeddingsParams extends EmbeddingsParams {
|
|
|
54
58
|
*
|
|
55
59
|
* ```
|
|
56
60
|
*/
|
|
57
|
-
export declare class OpenAIEmbeddings extends Embeddings implements Partial<OpenAIEmbeddingsParams> {
|
|
61
|
+
export declare class OpenAIEmbeddings<TOutput = number[]> extends Embeddings<TOutput> implements Partial<OpenAIEmbeddingsParams> {
|
|
58
62
|
model: string;
|
|
59
63
|
/** @deprecated Use "model" instead */
|
|
60
64
|
modelName: string;
|
|
@@ -67,6 +71,7 @@ export declare class OpenAIEmbeddings extends Embeddings implements Partial<Open
|
|
|
67
71
|
dimensions?: number;
|
|
68
72
|
timeout?: number;
|
|
69
73
|
organization?: string;
|
|
74
|
+
encodingFormat?: "float" | "base64";
|
|
70
75
|
protected client: OpenAIClient;
|
|
71
76
|
protected clientConfig: ClientOptions;
|
|
72
77
|
constructor(fields?: Partial<OpenAIEmbeddingsParams> & {
|
|
@@ -87,14 +92,14 @@ export declare class OpenAIEmbeddings extends Embeddings implements Partial<Open
|
|
|
87
92
|
* @param texts Array of documents to generate embeddings for.
|
|
88
93
|
* @returns Promise that resolves to a 2D array of embeddings for each document.
|
|
89
94
|
*/
|
|
90
|
-
embedDocuments(texts: string[]): Promise<
|
|
95
|
+
embedDocuments(texts: string[]): Promise<TOutput[]>;
|
|
91
96
|
/**
|
|
92
97
|
* Method to generate an embedding for a single document. Calls the
|
|
93
98
|
* embeddingWithRetry method with the document as the input.
|
|
94
99
|
* @param text Document to generate an embedding for.
|
|
95
100
|
* @returns Promise that resolves to an embedding for the document.
|
|
96
101
|
*/
|
|
97
|
-
embedQuery(text: string): Promise<
|
|
102
|
+
embedQuery(text: string): Promise<TOutput>;
|
|
98
103
|
/**
|
|
99
104
|
* Private method to make a request to the OpenAI API to generate
|
|
100
105
|
* embeddings. Handles the retry logic and returns the response from the
|
package/dist/embeddings.js
CHANGED
|
@@ -72,6 +72,12 @@ export class OpenAIEmbeddings extends Embeddings {
|
|
|
72
72
|
writable: true,
|
|
73
73
|
value: void 0
|
|
74
74
|
});
|
|
75
|
+
Object.defineProperty(this, "encodingFormat", {
|
|
76
|
+
enumerable: true,
|
|
77
|
+
configurable: true,
|
|
78
|
+
writable: true,
|
|
79
|
+
value: void 0
|
|
80
|
+
});
|
|
75
81
|
Object.defineProperty(this, "client", {
|
|
76
82
|
enumerable: true,
|
|
77
83
|
configurable: true,
|
|
@@ -98,6 +104,7 @@ export class OpenAIEmbeddings extends Embeddings {
|
|
|
98
104
|
fieldsWithDefaults?.stripNewLines ?? this.stripNewLines;
|
|
99
105
|
this.timeout = fieldsWithDefaults?.timeout;
|
|
100
106
|
this.dimensions = fieldsWithDefaults?.dimensions;
|
|
107
|
+
this.encodingFormat = fieldsWithDefaults?.encodingFormat;
|
|
101
108
|
this.clientConfig = {
|
|
102
109
|
apiKey,
|
|
103
110
|
organization: this.organization,
|
|
@@ -122,6 +129,9 @@ export class OpenAIEmbeddings extends Embeddings {
|
|
|
122
129
|
if (this.dimensions) {
|
|
123
130
|
params.dimensions = this.dimensions;
|
|
124
131
|
}
|
|
132
|
+
if (this.encodingFormat) {
|
|
133
|
+
params.encoding_format = this.encodingFormat;
|
|
134
|
+
}
|
|
125
135
|
return this.embeddingWithRetry(params);
|
|
126
136
|
});
|
|
127
137
|
const batchResponses = await Promise.all(batchRequests);
|
|
@@ -149,6 +159,9 @@ export class OpenAIEmbeddings extends Embeddings {
|
|
|
149
159
|
if (this.dimensions) {
|
|
150
160
|
params.dimensions = this.dimensions;
|
|
151
161
|
}
|
|
162
|
+
if (this.encodingFormat) {
|
|
163
|
+
params.encoding_format = this.encodingFormat;
|
|
164
|
+
}
|
|
152
165
|
const { data } = await this.embeddingWithRetry(params);
|
|
153
166
|
return data[0].embedding;
|
|
154
167
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -155,7 +155,7 @@ export interface OpenAIChatInput extends OpenAIBaseInput {
|
|
|
155
155
|
*
|
|
156
156
|
* @deprecated Use `reasoning` instead.
|
|
157
157
|
*/
|
|
158
|
-
|
|
158
|
+
reasoningEffort?: OpenAIClient.ReasoningEffort;
|
|
159
159
|
/**
|
|
160
160
|
* Should be set to `true` in tenancies with Zero Data Retention
|
|
161
161
|
* @see https://platform.openai.com/docs/guides/your-data
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleMultiModalOutput = handleMultiModalOutput;
|
|
4
|
+
/**
|
|
5
|
+
* Handle multi modal response content.
|
|
6
|
+
*
|
|
7
|
+
* @param content The content of the message.
|
|
8
|
+
* @param messages The messages of the response.
|
|
9
|
+
* @returns The new content of the message.
|
|
10
|
+
*/
|
|
11
|
+
function handleMultiModalOutput(content, messages) {
|
|
12
|
+
/**
|
|
13
|
+
* Handle OpenRouter image responses
|
|
14
|
+
* @see https://openrouter.ai/docs/features/multimodal/image-generation#api-usage
|
|
15
|
+
*/
|
|
16
|
+
if (messages &&
|
|
17
|
+
typeof messages === "object" &&
|
|
18
|
+
"images" in messages &&
|
|
19
|
+
Array.isArray(messages.images)) {
|
|
20
|
+
const images = messages.images
|
|
21
|
+
.filter((image) => typeof image?.image_url?.url === "string")
|
|
22
|
+
.map((image) => ({
|
|
23
|
+
type: "image",
|
|
24
|
+
url: image.image_url.url,
|
|
25
|
+
source_type: "url",
|
|
26
|
+
}));
|
|
27
|
+
return [{ type: "text", text: content, source_type: "text" }, ...images];
|
|
28
|
+
}
|
|
29
|
+
return content;
|
|
30
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { StandardImageBlock, StandardTextBlock } from "@langchain/core/messages";
|
|
2
|
+
/**
|
|
3
|
+
* Handle multi modal response content.
|
|
4
|
+
*
|
|
5
|
+
* @param content The content of the message.
|
|
6
|
+
* @param messages The messages of the response.
|
|
7
|
+
* @returns The new content of the message.
|
|
8
|
+
*/
|
|
9
|
+
export declare function handleMultiModalOutput(content: string, messages: unknown): (StandardImageBlock | StandardTextBlock)[] | string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handle multi modal response content.
|
|
3
|
+
*
|
|
4
|
+
* @param content The content of the message.
|
|
5
|
+
* @param messages The messages of the response.
|
|
6
|
+
* @returns The new content of the message.
|
|
7
|
+
*/
|
|
8
|
+
export function handleMultiModalOutput(content, messages) {
|
|
9
|
+
/**
|
|
10
|
+
* Handle OpenRouter image responses
|
|
11
|
+
* @see https://openrouter.ai/docs/features/multimodal/image-generation#api-usage
|
|
12
|
+
*/
|
|
13
|
+
if (messages &&
|
|
14
|
+
typeof messages === "object" &&
|
|
15
|
+
"images" in messages &&
|
|
16
|
+
Array.isArray(messages.images)) {
|
|
17
|
+
const images = messages.images
|
|
18
|
+
.filter((image) => typeof image?.image_url?.url === "string")
|
|
19
|
+
.map((image) => ({
|
|
20
|
+
type: "image",
|
|
21
|
+
url: image.image_url.url,
|
|
22
|
+
source_type: "url",
|
|
23
|
+
}));
|
|
24
|
+
return [{ type: "text", text: content, source_type: "text" }, ...images];
|
|
25
|
+
}
|
|
26
|
+
return content;
|
|
27
|
+
}
|