@langchain/openai 0.6.11 → 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.
@@ -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)
@@ -608,14 +609,14 @@ class BaseChatOpenAI extends chat_models_1.BaseChatModel {
608
609
  ? { effort: fields.reasoningEffort }
609
610
  : undefined;
610
611
  this.maxTokens = fields?.maxCompletionTokens ?? fields?.maxTokens;
611
- this.disableStreaming = fields?.disableStreaming ?? this.disableStreaming;
612
+ this.disableStreaming = fields?.disableStreaming === true;
613
+ this.streaming = fields?.streaming === true;
612
614
  this.promptCacheKey = fields?.promptCacheKey ?? this.promptCacheKey;
613
615
  this.verbosity = fields?.verbosity ?? this.verbosity;
614
- this.streaming = fields?.streaming ?? false;
615
616
  // disable streaming in BaseChatModel if explicitly disabled
616
617
  if (this.streaming === false)
617
618
  this.disableStreaming = true;
618
- if (this.disableStreaming)
619
+ if (this.disableStreaming === true)
619
620
  this.streaming = false;
620
621
  this.streamUsage = fields?.streamUsage ?? this.streamUsage;
621
622
  if (this.disableStreaming)
@@ -1374,7 +1375,8 @@ class ChatOpenAIResponses extends BaseChatOpenAI {
1374
1375
  response_metadata[key] = value;
1375
1376
  }
1376
1377
  }
1377
- 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") {
1378
1380
  tool_call_chunks.push({
1379
1381
  type: "tool_call_chunk",
1380
1382
  args: chunk.delta,
@@ -2062,8 +2064,9 @@ class ChatOpenAICompletions extends BaseChatOpenAI {
2062
2064
  if (message.audio) {
2063
2065
  additional_kwargs.audio = message.audio;
2064
2066
  }
2067
+ const content = (0, output_js_1.handleMultiModalOutput)(message.content || "", rawResponse.choices?.[0]?.message);
2065
2068
  return new messages_1.AIMessage({
2066
- content: message.content || "",
2069
+ content,
2067
2070
  tool_calls: toolCalls,
2068
2071
  invalid_tool_calls: invalidToolCalls,
2069
2072
  additional_kwargs,
@@ -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)
@@ -603,14 +604,14 @@ export class BaseChatOpenAI extends BaseChatModel {
603
604
  ? { effort: fields.reasoningEffort }
604
605
  : undefined;
605
606
  this.maxTokens = fields?.maxCompletionTokens ?? fields?.maxTokens;
606
- this.disableStreaming = fields?.disableStreaming ?? this.disableStreaming;
607
+ this.disableStreaming = fields?.disableStreaming === true;
608
+ this.streaming = fields?.streaming === true;
607
609
  this.promptCacheKey = fields?.promptCacheKey ?? this.promptCacheKey;
608
610
  this.verbosity = fields?.verbosity ?? this.verbosity;
609
- this.streaming = fields?.streaming ?? false;
610
611
  // disable streaming in BaseChatModel if explicitly disabled
611
612
  if (this.streaming === false)
612
613
  this.disableStreaming = true;
613
- if (this.disableStreaming)
614
+ if (this.disableStreaming === true)
614
615
  this.streaming = false;
615
616
  this.streamUsage = fields?.streamUsage ?? this.streamUsage;
616
617
  if (this.disableStreaming)
@@ -1368,7 +1369,8 @@ export class ChatOpenAIResponses extends BaseChatOpenAI {
1368
1369
  response_metadata[key] = value;
1369
1370
  }
1370
1371
  }
1371
- 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") {
1372
1374
  tool_call_chunks.push({
1373
1375
  type: "tool_call_chunk",
1374
1376
  args: chunk.delta,
@@ -2055,8 +2057,9 @@ export class ChatOpenAICompletions extends BaseChatOpenAI {
2055
2057
  if (message.audio) {
2056
2058
  additional_kwargs.audio = message.audio;
2057
2059
  }
2060
+ const content = handleMultiModalOutput(message.content || "", rawResponse.choices?.[0]?.message);
2058
2061
  return new AIMessage({
2059
- content: message.content || "",
2062
+ content,
2060
2063
  tool_calls: toolCalls,
2061
2064
  invalid_tool_calls: invalidToolCalls,
2062
2065
  additional_kwargs,
@@ -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
  }
@@ -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<number[][]>;
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<number[]>;
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
@@ -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
  }
@@ -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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/openai",
3
- "version": "0.6.11",
3
+ "version": "0.6.12",
4
4
  "description": "OpenAI integrations for LangChain.js",
5
5
  "type": "module",
6
6
  "engines": {