@langchain/openai 0.0.11 → 0.0.13

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.
@@ -6,6 +6,7 @@ const messages_1 = require("@langchain/core/messages");
6
6
  const outputs_1 = require("@langchain/core/outputs");
7
7
  const env_1 = require("@langchain/core/utils/env");
8
8
  const chat_models_1 = require("@langchain/core/language_models/chat_models");
9
+ const function_calling_1 = require("@langchain/core/utils/function_calling");
9
10
  const azure_js_1 = require("./utils/azure.cjs");
10
11
  const openai_js_1 = require("./utils/openai.cjs");
11
12
  const openai_format_fndef_js_1 = require("./utils/openai-format-fndef.cjs");
@@ -420,7 +421,7 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
420
421
  functions: options?.functions,
421
422
  function_call: options?.function_call,
422
423
  tools: isStructuredToolArray(options?.tools)
423
- ? options?.tools.map(openai_js_1.formatToOpenAITool)
424
+ ? options?.tools.map(function_calling_1.convertToOpenAITool)
424
425
  : options?.tools,
425
426
  tool_choice: options?.tool_choice,
426
427
  response_format: options?.response_format,
@@ -3,8 +3,9 @@ import { AIMessage, AIMessageChunk, ChatMessage, ChatMessageChunk, FunctionMessa
3
3
  import { ChatGenerationChunk, } from "@langchain/core/outputs";
4
4
  import { getEnvironmentVariable } from "@langchain/core/utils/env";
5
5
  import { BaseChatModel, } from "@langchain/core/language_models/chat_models";
6
+ import { convertToOpenAITool } from "@langchain/core/utils/function_calling";
6
7
  import { getEndpoint } from "./utils/azure.js";
7
- import { wrapOpenAIClientError, formatToOpenAITool } from "./utils/openai.js";
8
+ import { wrapOpenAIClientError } from "./utils/openai.js";
8
9
  import { formatFunctionDefinitions, } from "./utils/openai-format-fndef.js";
9
10
  function extractGenericMessageCustomRole(message) {
10
11
  if (message.role !== "system" &&
@@ -416,7 +417,7 @@ export class ChatOpenAI extends BaseChatModel {
416
417
  functions: options?.functions,
417
418
  function_call: options?.function_call,
418
419
  tools: isStructuredToolArray(options?.tools)
419
- ? options?.tools.map(formatToOpenAITool)
420
+ ? options?.tools.map(convertToOpenAITool)
420
421
  : options?.tools,
421
422
  tool_choice: options?.tool_choice,
422
423
  response_format: options?.response_format,
@@ -45,6 +45,16 @@ class OpenAIEmbeddings extends embeddings_1.Embeddings {
45
45
  writable: true,
46
46
  value: true
47
47
  });
48
+ /**
49
+ * The number of dimensions the resulting output embeddings should have.
50
+ * Only supported in `text-embedding-3` and later models.
51
+ */
52
+ Object.defineProperty(this, "dimensions", {
53
+ enumerable: true,
54
+ configurable: true,
55
+ writable: true,
56
+ value: void 0
57
+ });
48
58
  Object.defineProperty(this, "timeout", {
49
59
  enumerable: true,
50
60
  configurable: true,
@@ -126,6 +136,7 @@ class OpenAIEmbeddings extends embeddings_1.Embeddings {
126
136
  this.stripNewLines =
127
137
  fieldsWithDefaults?.stripNewLines ?? this.stripNewLines;
128
138
  this.timeout = fieldsWithDefaults?.timeout;
139
+ this.dimensions = fieldsWithDefaults?.dimensions;
129
140
  this.azureOpenAIApiVersion = azureApiVersion;
130
141
  this.azureOpenAIApiKey = azureApiKey;
131
142
  this.azureOpenAIApiInstanceName = azureApiInstanceName;
@@ -162,10 +173,16 @@ class OpenAIEmbeddings extends embeddings_1.Embeddings {
162
173
  */
163
174
  async embedDocuments(texts) {
164
175
  const batches = (0, chunk_array_1.chunkArray)(this.stripNewLines ? texts.map((t) => t.replace(/\n/g, " ")) : texts, this.batchSize);
165
- const batchRequests = batches.map((batch) => this.embeddingWithRetry({
166
- model: this.modelName,
167
- input: batch,
168
- }));
176
+ const batchRequests = batches.map((batch) => {
177
+ const params = {
178
+ model: this.modelName,
179
+ input: batch,
180
+ };
181
+ if (this.dimensions) {
182
+ params.dimensions = this.dimensions;
183
+ }
184
+ return this.embeddingWithRetry(params);
185
+ });
169
186
  const batchResponses = await Promise.all(batchRequests);
170
187
  const embeddings = [];
171
188
  for (let i = 0; i < batchResponses.length; i += 1) {
@@ -184,10 +201,14 @@ class OpenAIEmbeddings extends embeddings_1.Embeddings {
184
201
  * @returns Promise that resolves to an embedding for the document.
185
202
  */
186
203
  async embedQuery(text) {
187
- const { data } = await this.embeddingWithRetry({
204
+ const params = {
188
205
  model: this.modelName,
189
206
  input: this.stripNewLines ? text.replace(/\n/g, " ") : text,
190
- });
207
+ };
208
+ if (this.dimensions) {
209
+ params.dimensions = this.dimensions;
210
+ }
211
+ const { data } = await this.embeddingWithRetry(params);
191
212
  return data[0].embedding;
192
213
  }
193
214
  /**
@@ -8,6 +8,11 @@ import { AzureOpenAIInput, LegacyOpenAIInput } from "./types.js";
8
8
  export interface OpenAIEmbeddingsParams extends EmbeddingsParams {
9
9
  /** Model name to use */
10
10
  modelName: string;
11
+ /**
12
+ * The number of dimensions the resulting output embeddings should have.
13
+ * Only supported in `text-embedding-3` and later models.
14
+ */
15
+ dimensions?: number;
11
16
  /**
12
17
  * Timeout to use when making requests to OpenAI.
13
18
  */
@@ -43,6 +48,11 @@ export declare class OpenAIEmbeddings extends Embeddings implements OpenAIEmbedd
43
48
  modelName: string;
44
49
  batchSize: number;
45
50
  stripNewLines: boolean;
51
+ /**
52
+ * The number of dimensions the resulting output embeddings should have.
53
+ * Only supported in `text-embedding-3` and later models.
54
+ */
55
+ dimensions?: number;
46
56
  timeout?: number;
47
57
  azureOpenAIApiVersion?: string;
48
58
  azureOpenAIApiKey?: string;
@@ -42,6 +42,16 @@ export class OpenAIEmbeddings extends Embeddings {
42
42
  writable: true,
43
43
  value: true
44
44
  });
45
+ /**
46
+ * The number of dimensions the resulting output embeddings should have.
47
+ * Only supported in `text-embedding-3` and later models.
48
+ */
49
+ Object.defineProperty(this, "dimensions", {
50
+ enumerable: true,
51
+ configurable: true,
52
+ writable: true,
53
+ value: void 0
54
+ });
45
55
  Object.defineProperty(this, "timeout", {
46
56
  enumerable: true,
47
57
  configurable: true,
@@ -123,6 +133,7 @@ export class OpenAIEmbeddings extends Embeddings {
123
133
  this.stripNewLines =
124
134
  fieldsWithDefaults?.stripNewLines ?? this.stripNewLines;
125
135
  this.timeout = fieldsWithDefaults?.timeout;
136
+ this.dimensions = fieldsWithDefaults?.dimensions;
126
137
  this.azureOpenAIApiVersion = azureApiVersion;
127
138
  this.azureOpenAIApiKey = azureApiKey;
128
139
  this.azureOpenAIApiInstanceName = azureApiInstanceName;
@@ -159,10 +170,16 @@ export class OpenAIEmbeddings extends Embeddings {
159
170
  */
160
171
  async embedDocuments(texts) {
161
172
  const batches = chunkArray(this.stripNewLines ? texts.map((t) => t.replace(/\n/g, " ")) : texts, this.batchSize);
162
- const batchRequests = batches.map((batch) => this.embeddingWithRetry({
163
- model: this.modelName,
164
- input: batch,
165
- }));
173
+ const batchRequests = batches.map((batch) => {
174
+ const params = {
175
+ model: this.modelName,
176
+ input: batch,
177
+ };
178
+ if (this.dimensions) {
179
+ params.dimensions = this.dimensions;
180
+ }
181
+ return this.embeddingWithRetry(params);
182
+ });
166
183
  const batchResponses = await Promise.all(batchRequests);
167
184
  const embeddings = [];
168
185
  for (let i = 0; i < batchResponses.length; i += 1) {
@@ -181,10 +198,14 @@ export class OpenAIEmbeddings extends Embeddings {
181
198
  * @returns Promise that resolves to an embedding for the document.
182
199
  */
183
200
  async embedQuery(text) {
184
- const { data } = await this.embeddingWithRetry({
201
+ const params = {
185
202
  model: this.modelName,
186
203
  input: this.stripNewLines ? text.replace(/\n/g, " ") : text,
187
- });
204
+ };
205
+ if (this.dimensions) {
206
+ params.dimensions = this.dimensions;
207
+ }
208
+ const { data } = await this.embeddingWithRetry(params);
188
209
  return data[0].embedding;
189
210
  }
190
211
  /**
@@ -60,3 +60,24 @@ test("Test OpenAI embeddings with an invalid org throws", async () => {
60
60
  ]);
61
61
  }).rejects.toThrow();
62
62
  });
63
+ test("Test OpenAIEmbeddings.embedQuery with v3 and dimensions", async () => {
64
+ const embeddings = new OpenAIEmbeddings({
65
+ modelName: "text-embedding-3-small",
66
+ dimensions: 127,
67
+ });
68
+ const res = await embeddings.embedQuery("Hello world");
69
+ expect(typeof res[0]).toBe("number");
70
+ expect(res.length).toBe(127);
71
+ });
72
+ test("Test OpenAIEmbeddings.embedDocuments with v3 and dimensions", async () => {
73
+ const embeddings = new OpenAIEmbeddings({
74
+ modelName: "text-embedding-3-small",
75
+ dimensions: 127,
76
+ });
77
+ const res = await embeddings.embedDocuments(["Hello world", "Bye bye"]);
78
+ expect(res).toHaveLength(2);
79
+ expect(typeof res[0][0]).toBe("number");
80
+ expect(typeof res[1][0]).toBe("number");
81
+ expect(res[0].length).toBe(127);
82
+ expect(res[1].length).toBe(127);
83
+ });
@@ -3,6 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.formatToOpenAIAssistantTool = exports.formatToOpenAITool = exports.formatToOpenAIFunction = exports.wrapOpenAIClientError = void 0;
4
4
  const openai_1 = require("openai");
5
5
  const zod_to_json_schema_1 = require("zod-to-json-schema");
6
+ const function_calling_1 = require("@langchain/core/utils/function_calling");
7
+ Object.defineProperty(exports, "formatToOpenAIFunction", { enumerable: true, get: function () { return function_calling_1.convertToOpenAIFunction; } });
8
+ Object.defineProperty(exports, "formatToOpenAITool", { enumerable: true, get: function () { return function_calling_1.convertToOpenAITool; } });
6
9
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
10
  function wrapOpenAIClientError(e) {
8
11
  let error;
@@ -20,32 +23,6 @@ function wrapOpenAIClientError(e) {
20
23
  return error;
21
24
  }
22
25
  exports.wrapOpenAIClientError = wrapOpenAIClientError;
23
- /**
24
- * Formats a `StructuredTool` instance into a format that is compatible
25
- * with OpenAI's ChatCompletionFunctions. It uses the `zodToJsonSchema`
26
- * function to convert the schema of the `StructuredTool` into a JSON
27
- * schema, which is then used as the parameters for the OpenAI function.
28
- */
29
- function formatToOpenAIFunction(tool) {
30
- return {
31
- name: tool.name,
32
- description: tool.description,
33
- parameters: (0, zod_to_json_schema_1.zodToJsonSchema)(tool.schema),
34
- };
35
- }
36
- exports.formatToOpenAIFunction = formatToOpenAIFunction;
37
- function formatToOpenAITool(tool) {
38
- const schema = (0, zod_to_json_schema_1.zodToJsonSchema)(tool.schema);
39
- return {
40
- type: "function",
41
- function: {
42
- name: tool.name,
43
- description: tool.description,
44
- parameters: schema,
45
- },
46
- };
47
- }
48
- exports.formatToOpenAITool = formatToOpenAITool;
49
26
  function formatToOpenAIAssistantTool(tool) {
50
27
  return {
51
28
  type: "function",
@@ -1,13 +1,6 @@
1
1
  import { type OpenAI as OpenAIClient } from "openai";
2
2
  import type { StructuredToolInterface } from "@langchain/core/tools";
3
- import type { FunctionDefinition } from "@langchain/core/language_models/base";
3
+ import { convertToOpenAIFunction, convertToOpenAITool } from "@langchain/core/utils/function_calling";
4
4
  export declare function wrapOpenAIClientError(e: any): any;
5
- /**
6
- * Formats a `StructuredTool` instance into a format that is compatible
7
- * with OpenAI's ChatCompletionFunctions. It uses the `zodToJsonSchema`
8
- * function to convert the schema of the `StructuredTool` into a JSON
9
- * schema, which is then used as the parameters for the OpenAI function.
10
- */
11
- export declare function formatToOpenAIFunction(tool: StructuredToolInterface): FunctionDefinition;
12
- export declare function formatToOpenAITool(tool: StructuredToolInterface): OpenAIClient.Chat.ChatCompletionTool;
5
+ export { convertToOpenAIFunction as formatToOpenAIFunction, convertToOpenAITool as formatToOpenAITool, };
13
6
  export declare function formatToOpenAIAssistantTool(tool: StructuredToolInterface): OpenAIClient.Beta.AssistantCreateParams.AssistantToolsFunction;
@@ -1,5 +1,6 @@
1
1
  import { APIConnectionTimeoutError, APIUserAbortError, } from "openai";
2
2
  import { zodToJsonSchema } from "zod-to-json-schema";
3
+ import { convertToOpenAIFunction, convertToOpenAITool, } from "@langchain/core/utils/function_calling";
3
4
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
5
  export function wrapOpenAIClientError(e) {
5
6
  let error;
@@ -16,30 +17,7 @@ export function wrapOpenAIClientError(e) {
16
17
  }
17
18
  return error;
18
19
  }
19
- /**
20
- * Formats a `StructuredTool` instance into a format that is compatible
21
- * with OpenAI's ChatCompletionFunctions. It uses the `zodToJsonSchema`
22
- * function to convert the schema of the `StructuredTool` into a JSON
23
- * schema, which is then used as the parameters for the OpenAI function.
24
- */
25
- export function formatToOpenAIFunction(tool) {
26
- return {
27
- name: tool.name,
28
- description: tool.description,
29
- parameters: zodToJsonSchema(tool.schema),
30
- };
31
- }
32
- export function formatToOpenAITool(tool) {
33
- const schema = zodToJsonSchema(tool.schema);
34
- return {
35
- type: "function",
36
- function: {
37
- name: tool.name,
38
- description: tool.description,
39
- parameters: schema,
40
- },
41
- };
42
- }
20
+ export { convertToOpenAIFunction as formatToOpenAIFunction, convertToOpenAITool as formatToOpenAITool, };
43
21
  export function formatToOpenAIAssistantTool(tool) {
44
22
  return {
45
23
  type: "function",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/openai",
3
- "version": "0.0.11",
3
+ "version": "0.0.13",
4
4
  "description": "OpenAI integrations for LangChain.js",
5
5
  "type": "module",
6
6
  "engines": {
@@ -19,7 +19,7 @@
19
19
  "build:cjs": "NODE_OPTIONS=--max-old-space-size=4096 tsc --outDir dist-cjs/ -p tsconfig.cjs.json && node scripts/move-cjs-to-dist.js && rimraf dist-cjs",
20
20
  "build:watch": "node scripts/create-entrypoints.js && tsc --outDir dist/ --watch",
21
21
  "build:scripts": "node scripts/create-entrypoints.js && node scripts/check-tree-shaking.js",
22
- "lint:eslint": "NODE_OPTIONS=--max-old-space-size=4096 eslint src",
22
+ "lint:eslint": "NODE_OPTIONS=--max-old-space-size=4096 eslint --cache --ext .ts,.js src/",
23
23
  "lint:dpdm": "dpdm --exit-code circular:1 --no-warning --no-tree src/*.ts src/**/*.ts",
24
24
  "lint": "yarn lint:eslint && yarn lint:dpdm",
25
25
  "lint:fix": "yarn lint:eslint --fix && yarn lint:dpdm",
@@ -29,17 +29,17 @@
29
29
  "test:watch": "yarn run build:deps && NODE_OPTIONS=--experimental-vm-modules jest --watch --testPathIgnorePatterns=\\.int\\.test.ts",
30
30
  "test:single": "yarn run build:deps && NODE_OPTIONS=--experimental-vm-modules yarn run jest --config jest.config.cjs --testTimeout 100000",
31
31
  "test:int": "NODE_OPTIONS=--experimental-vm-modules jest --testPathPattern=\\.int\\.test.ts --testTimeout 100000 --maxWorkers=50%",
32
- "format": "prettier --write \"src\"",
33
- "format:check": "prettier --check \"src\""
32
+ "format": "prettier --config .prettierrc --write \"src\" \"scripts\"",
33
+ "format:check": "prettier --config .prettierrc --check \"src\" \"scripts\""
34
34
  },
35
35
  "author": "LangChain",
36
36
  "license": "MIT",
37
37
  "dependencies": {
38
- "@langchain/core": "~0.1.9",
38
+ "@langchain/core": "~0.1.13",
39
39
  "js-tiktoken": "^1.0.7",
40
- "openai": "^4.24.2",
41
- "zod": "^3.22.3",
42
- "zod-to-json-schema": "3.20.3"
40
+ "openai": "^4.26.0",
41
+ "zod": "^3.22.4",
42
+ "zod-to-json-schema": "^3.22.3"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@jest/globals": "^29.5.0",