@langchain/openai 0.2.5 → 0.2.6

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 base_1 = require("@langchain/core/language_models/base");
9
10
  const function_calling_1 = require("@langchain/core/utils/function_calling");
10
11
  const runnables_1 = require("@langchain/core/runnables");
11
12
  const output_parsers_1 = require("@langchain/core/output_parsers");
@@ -184,6 +185,21 @@ function convertMessagesToOpenAIParams(messages) {
184
185
  return completionParam;
185
186
  });
186
187
  }
188
+ function _convertChatOpenAIToolTypeToOpenAITool(tool, fields) {
189
+ if ((0, base_1.isOpenAITool)(tool)) {
190
+ if (fields?.strict !== undefined) {
191
+ return {
192
+ ...tool,
193
+ function: {
194
+ ...tool.function,
195
+ strict: fields.strict,
196
+ },
197
+ };
198
+ }
199
+ return tool;
200
+ }
201
+ return (0, function_calling_1.convertToOpenAITool)(tool, fields);
202
+ }
187
203
  /**
188
204
  * Wrapper around OpenAI large language models that use the Chat endpoint.
189
205
  *
@@ -443,6 +459,16 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
443
459
  writable: true,
444
460
  value: void 0
445
461
  });
462
+ /**
463
+ * Whether the model supports the `strict` argument when passing in tools.
464
+ * If `undefined` the `strict` argument will not be passed to OpenAI.
465
+ */
466
+ Object.defineProperty(this, "supportsStrictToolCalling", {
467
+ enumerable: true,
468
+ configurable: true,
469
+ writable: true,
470
+ value: void 0
471
+ });
446
472
  this.openAIApiKey =
447
473
  fields?.apiKey ??
448
474
  fields?.openAIApiKey ??
@@ -515,6 +541,11 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
515
541
  ...configuration,
516
542
  ...fields?.configuration,
517
543
  };
544
+ // If `supportsStrictToolCalling` is explicitly set, use that value.
545
+ // Else leave undefined so it's not passed to OpenAI.
546
+ if (fields?.supportsStrictToolCalling !== undefined) {
547
+ this.supportsStrictToolCalling = fields.supportsStrictToolCalling;
548
+ }
518
549
  }
519
550
  getLsParams(options) {
520
551
  const params = this.invocationParams(options);
@@ -528,8 +559,15 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
528
559
  };
529
560
  }
530
561
  bindTools(tools, kwargs) {
562
+ let strict;
563
+ if (kwargs?.strict !== undefined) {
564
+ strict = kwargs.strict;
565
+ }
566
+ else if (this.supportsStrictToolCalling !== undefined) {
567
+ strict = this.supportsStrictToolCalling;
568
+ }
531
569
  return this.bind({
532
- tools: tools.map(function_calling_1.convertToOpenAITool),
570
+ tools: tools.map((tool) => _convertChatOpenAIToolTypeToOpenAITool(tool, { strict })),
533
571
  ...kwargs,
534
572
  });
535
573
  }
@@ -537,9 +575,12 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
537
575
  * Get the parameters used to invoke the model
538
576
  */
539
577
  invocationParams(options, extra) {
540
- function isStructuredToolArray(tools) {
541
- return (tools !== undefined &&
542
- tools.every((tool) => Array.isArray(tool.lc_namespace)));
578
+ let strict;
579
+ if (options?.strict !== undefined) {
580
+ strict = options.strict;
581
+ }
582
+ else if (this.supportsStrictToolCalling !== undefined) {
583
+ strict = this.supportsStrictToolCalling;
543
584
  }
544
585
  let streamOptionsConfig = {};
545
586
  if (options?.stream_options !== undefined) {
@@ -565,9 +606,9 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
565
606
  stream: this.streaming,
566
607
  functions: options?.functions,
567
608
  function_call: options?.function_call,
568
- tools: isStructuredToolArray(options?.tools)
569
- ? options?.tools.map(function_calling_1.convertToOpenAITool)
570
- : options?.tools,
609
+ tools: options?.tools?.length
610
+ ? options.tools.map((tool) => _convertChatOpenAIToolTypeToOpenAITool(tool, { strict }))
611
+ : undefined,
571
612
  tool_choice: (0, openai_js_1.formatToOpenAIToolChoice)(options?.tool_choice),
572
613
  response_format: options?.response_format,
573
614
  seed: options?.seed,
@@ -928,6 +969,9 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
928
969
  }
929
970
  let llm;
930
971
  let outputParser;
972
+ if (config?.strict !== undefined && method === "jsonMode") {
973
+ throw new Error("Argument `strict` is only supported for `method` = 'function_calling'");
974
+ }
931
975
  if (method === "jsonMode") {
932
976
  llm = this.bind({
933
977
  response_format: { type: "json_object" },
@@ -961,6 +1005,8 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
961
1005
  name: functionName,
962
1006
  },
963
1007
  },
1008
+ // Do not pass `strict` argument to OpenAI if `config.strict` is undefined
1009
+ ...(config?.strict !== undefined ? { strict: config.strict } : {}),
964
1010
  });
965
1011
  outputParser = new openai_tools_1.JsonOutputKeyToolsParser({
966
1012
  returnSingle: true,
@@ -997,6 +1043,8 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
997
1043
  name: functionName,
998
1044
  },
999
1045
  },
1046
+ // Do not pass `strict` argument to OpenAI if `config.strict` is undefined
1047
+ ...(config?.strict !== undefined ? { strict: config.strict } : {}),
1000
1048
  });
1001
1049
  outputParser = new openai_tools_1.JsonOutputKeyToolsParser({
1002
1050
  returnSingle: true,
@@ -2,11 +2,10 @@ import { type ClientOptions, OpenAI as OpenAIClient } from "openai";
2
2
  import { CallbackManagerForLLMRun } from "@langchain/core/callbacks/manager";
3
3
  import { AIMessageChunk, type BaseMessage } from "@langchain/core/messages";
4
4
  import { ChatGenerationChunk, type ChatResult } from "@langchain/core/outputs";
5
- import { type StructuredToolInterface } from "@langchain/core/tools";
6
- import { BaseChatModel, LangSmithParams, type BaseChatModelParams } from "@langchain/core/language_models/chat_models";
7
- import type { BaseFunctionCallOptions, BaseLanguageModelInput, StructuredOutputMethodOptions, StructuredOutputMethodParams } from "@langchain/core/language_models/base";
5
+ import { BaseChatModel, BindToolsInput, LangSmithParams, type BaseChatModelParams } from "@langchain/core/language_models/chat_models";
6
+ import { type BaseFunctionCallOptions, type BaseLanguageModelInput, type StructuredOutputMethodOptions, type StructuredOutputMethodParams } from "@langchain/core/language_models/base";
8
7
  import { z } from "zod";
9
- import { Runnable, RunnableToolLike } from "@langchain/core/runnables";
8
+ import { Runnable } from "@langchain/core/runnables";
10
9
  import type { AzureOpenAIInput, OpenAICallOptions, OpenAIChatInput, OpenAICoreRequestOptions, LegacyOpenAIInput } from "./types.js";
11
10
  import { OpenAIToolChoice } from "./utils/openai.js";
12
11
  export type { AzureOpenAIInput, OpenAICallOptions, OpenAIChatInput };
@@ -20,8 +19,26 @@ interface OpenAILLMOutput {
20
19
  }
21
20
  type OpenAIRoleEnum = "system" | "assistant" | "user" | "function" | "tool";
22
21
  export declare function messageToOpenAIRole(message: BaseMessage): OpenAIRoleEnum;
22
+ type ChatOpenAIToolType = BindToolsInput | OpenAIClient.ChatCompletionTool;
23
+ export interface ChatOpenAIStructuredOutputMethodOptions<IncludeRaw extends boolean> extends StructuredOutputMethodOptions<IncludeRaw> {
24
+ /**
25
+ * strict: If `true` and `method` = "function_calling", model output is
26
+ * guaranteed to exactly match the schema. If `true`, the input schema
27
+ * will also be validated according to
28
+ * https://platform.openai.com/docs/guides/structured-outputs/supported-schemas.
29
+ * If `false`, input schema will not be validated and model output will not
30
+ * be validated.
31
+ * If `undefined`, `strict` argument will not be passed to the model.
32
+ *
33
+ * @version 0.2.6
34
+ * @note Planned breaking change in version `0.3.0`:
35
+ * `strict` will default to `true` when `method` is
36
+ * "function_calling" as of version `0.3.0`.
37
+ */
38
+ strict?: boolean;
39
+ }
23
40
  export interface ChatOpenAICallOptions extends OpenAICallOptions, BaseFunctionCallOptions {
24
- tools?: StructuredToolInterface[] | OpenAIClient.ChatCompletionTool[];
41
+ tools?: ChatOpenAIToolType[];
25
42
  tool_choice?: OpenAIToolChoice;
26
43
  promptIndex?: number;
27
44
  response_format?: {
@@ -45,6 +62,23 @@ export interface ChatOpenAICallOptions extends OpenAICallOptions, BaseFunctionCa
45
62
  * call multiple tools in one response.
46
63
  */
47
64
  parallel_tool_calls?: boolean;
65
+ /**
66
+ * If `true`, model output is guaranteed to exactly match the JSON Schema
67
+ * provided in the tool definition. If `true`, the input schema will also be
68
+ * validated according to
69
+ * https://platform.openai.com/docs/guides/structured-outputs/supported-schemas.
70
+ *
71
+ * If `false`, input schema will not be validated and model output will not
72
+ * be validated.
73
+ *
74
+ * If `undefined`, `strict` argument will not be passed to the model.
75
+ *
76
+ * @version 0.2.6
77
+ */
78
+ strict?: boolean;
79
+ }
80
+ export interface ChatOpenAIFields extends Partial<OpenAIChatInput>, Partial<AzureOpenAIInput>, BaseChatModelParams {
81
+ configuration?: ClientOptions & LegacyOpenAIInput;
48
82
  }
49
83
  /**
50
84
  * Wrapper around OpenAI large language models that use the Chat endpoint.
@@ -117,13 +151,16 @@ export declare class ChatOpenAI<CallOptions extends ChatOpenAICallOptions = Chat
117
151
  __includeRawResponse?: boolean;
118
152
  protected client: OpenAIClient;
119
153
  protected clientConfig: ClientOptions;
120
- constructor(fields?: Partial<OpenAIChatInput> & Partial<AzureOpenAIInput> & BaseChatModelParams & {
121
- configuration?: ClientOptions & LegacyOpenAIInput;
122
- },
154
+ /**
155
+ * Whether the model supports the `strict` argument when passing in tools.
156
+ * If `undefined` the `strict` argument will not be passed to OpenAI.
157
+ */
158
+ supportsStrictToolCalling?: boolean;
159
+ constructor(fields?: ChatOpenAIFields,
123
160
  /** @deprecated */
124
161
  configuration?: ClientOptions & LegacyOpenAIInput);
125
162
  getLsParams(options: this["ParsedCallOptions"]): LangSmithParams;
126
- bindTools(tools: (Record<string, unknown> | StructuredToolInterface | RunnableToolLike)[], kwargs?: Partial<CallOptions>): Runnable<BaseLanguageModelInput, AIMessageChunk, CallOptions>;
163
+ bindTools(tools: ChatOpenAIToolType[], kwargs?: Partial<CallOptions>): Runnable<BaseLanguageModelInput, AIMessageChunk, CallOptions>;
127
164
  /**
128
165
  * Get the parameters used to invoke the model
129
166
  */
@@ -169,8 +206,8 @@ export declare class ChatOpenAI<CallOptions extends ChatOpenAICallOptions = Chat
169
206
  _llmType(): string;
170
207
  /** @ignore */
171
208
  _combineLLMOutput(...llmOutputs: OpenAILLMOutput[]): OpenAILLMOutput;
172
- withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: StructuredOutputMethodParams<RunOutput, false> | z.ZodType<RunOutput> | Record<string, any>, config?: StructuredOutputMethodOptions<false>): Runnable<BaseLanguageModelInput, RunOutput>;
173
- withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: StructuredOutputMethodParams<RunOutput, true> | z.ZodType<RunOutput> | Record<string, any>, config?: StructuredOutputMethodOptions<true>): Runnable<BaseLanguageModelInput, {
209
+ withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: StructuredOutputMethodParams<RunOutput, false> | z.ZodType<RunOutput> | Record<string, any>, config?: ChatOpenAIStructuredOutputMethodOptions<false>): Runnable<BaseLanguageModelInput, RunOutput>;
210
+ withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>(outputSchema: StructuredOutputMethodParams<RunOutput, true> | z.ZodType<RunOutput> | Record<string, any>, config?: ChatOpenAIStructuredOutputMethodOptions<true>): Runnable<BaseLanguageModelInput, {
174
211
  raw: BaseMessage;
175
212
  parsed: RunOutput;
176
213
  }>;
@@ -3,6 +3,7 @@ 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 { isOpenAITool, } from "@langchain/core/language_models/base";
6
7
  import { convertToOpenAITool } from "@langchain/core/utils/function_calling";
7
8
  import { RunnablePassthrough, RunnableSequence, } from "@langchain/core/runnables";
8
9
  import { JsonOutputParser, StructuredOutputParser, } from "@langchain/core/output_parsers";
@@ -180,6 +181,21 @@ function convertMessagesToOpenAIParams(messages) {
180
181
  return completionParam;
181
182
  });
182
183
  }
184
+ function _convertChatOpenAIToolTypeToOpenAITool(tool, fields) {
185
+ if (isOpenAITool(tool)) {
186
+ if (fields?.strict !== undefined) {
187
+ return {
188
+ ...tool,
189
+ function: {
190
+ ...tool.function,
191
+ strict: fields.strict,
192
+ },
193
+ };
194
+ }
195
+ return tool;
196
+ }
197
+ return convertToOpenAITool(tool, fields);
198
+ }
183
199
  /**
184
200
  * Wrapper around OpenAI large language models that use the Chat endpoint.
185
201
  *
@@ -439,6 +455,16 @@ export class ChatOpenAI extends BaseChatModel {
439
455
  writable: true,
440
456
  value: void 0
441
457
  });
458
+ /**
459
+ * Whether the model supports the `strict` argument when passing in tools.
460
+ * If `undefined` the `strict` argument will not be passed to OpenAI.
461
+ */
462
+ Object.defineProperty(this, "supportsStrictToolCalling", {
463
+ enumerable: true,
464
+ configurable: true,
465
+ writable: true,
466
+ value: void 0
467
+ });
442
468
  this.openAIApiKey =
443
469
  fields?.apiKey ??
444
470
  fields?.openAIApiKey ??
@@ -511,6 +537,11 @@ export class ChatOpenAI extends BaseChatModel {
511
537
  ...configuration,
512
538
  ...fields?.configuration,
513
539
  };
540
+ // If `supportsStrictToolCalling` is explicitly set, use that value.
541
+ // Else leave undefined so it's not passed to OpenAI.
542
+ if (fields?.supportsStrictToolCalling !== undefined) {
543
+ this.supportsStrictToolCalling = fields.supportsStrictToolCalling;
544
+ }
514
545
  }
515
546
  getLsParams(options) {
516
547
  const params = this.invocationParams(options);
@@ -524,8 +555,15 @@ export class ChatOpenAI extends BaseChatModel {
524
555
  };
525
556
  }
526
557
  bindTools(tools, kwargs) {
558
+ let strict;
559
+ if (kwargs?.strict !== undefined) {
560
+ strict = kwargs.strict;
561
+ }
562
+ else if (this.supportsStrictToolCalling !== undefined) {
563
+ strict = this.supportsStrictToolCalling;
564
+ }
527
565
  return this.bind({
528
- tools: tools.map(convertToOpenAITool),
566
+ tools: tools.map((tool) => _convertChatOpenAIToolTypeToOpenAITool(tool, { strict })),
529
567
  ...kwargs,
530
568
  });
531
569
  }
@@ -533,9 +571,12 @@ export class ChatOpenAI extends BaseChatModel {
533
571
  * Get the parameters used to invoke the model
534
572
  */
535
573
  invocationParams(options, extra) {
536
- function isStructuredToolArray(tools) {
537
- return (tools !== undefined &&
538
- tools.every((tool) => Array.isArray(tool.lc_namespace)));
574
+ let strict;
575
+ if (options?.strict !== undefined) {
576
+ strict = options.strict;
577
+ }
578
+ else if (this.supportsStrictToolCalling !== undefined) {
579
+ strict = this.supportsStrictToolCalling;
539
580
  }
540
581
  let streamOptionsConfig = {};
541
582
  if (options?.stream_options !== undefined) {
@@ -561,9 +602,9 @@ export class ChatOpenAI extends BaseChatModel {
561
602
  stream: this.streaming,
562
603
  functions: options?.functions,
563
604
  function_call: options?.function_call,
564
- tools: isStructuredToolArray(options?.tools)
565
- ? options?.tools.map(convertToOpenAITool)
566
- : options?.tools,
605
+ tools: options?.tools?.length
606
+ ? options.tools.map((tool) => _convertChatOpenAIToolTypeToOpenAITool(tool, { strict }))
607
+ : undefined,
567
608
  tool_choice: formatToOpenAIToolChoice(options?.tool_choice),
568
609
  response_format: options?.response_format,
569
610
  seed: options?.seed,
@@ -924,6 +965,9 @@ export class ChatOpenAI extends BaseChatModel {
924
965
  }
925
966
  let llm;
926
967
  let outputParser;
968
+ if (config?.strict !== undefined && method === "jsonMode") {
969
+ throw new Error("Argument `strict` is only supported for `method` = 'function_calling'");
970
+ }
927
971
  if (method === "jsonMode") {
928
972
  llm = this.bind({
929
973
  response_format: { type: "json_object" },
@@ -957,6 +1001,8 @@ export class ChatOpenAI extends BaseChatModel {
957
1001
  name: functionName,
958
1002
  },
959
1003
  },
1004
+ // Do not pass `strict` argument to OpenAI if `config.strict` is undefined
1005
+ ...(config?.strict !== undefined ? { strict: config.strict } : {}),
960
1006
  });
961
1007
  outputParser = new JsonOutputKeyToolsParser({
962
1008
  returnSingle: true,
@@ -993,6 +1039,8 @@ export class ChatOpenAI extends BaseChatModel {
993
1039
  name: functionName,
994
1040
  },
995
1041
  },
1042
+ // Do not pass `strict` argument to OpenAI if `config.strict` is undefined
1043
+ ...(config?.strict !== undefined ? { strict: config.strict } : {}),
996
1044
  });
997
1045
  outputParser = new JsonOutputKeyToolsParser({
998
1046
  returnSingle: true,
package/dist/types.d.ts CHANGED
@@ -121,6 +121,11 @@ export interface OpenAIChatInput extends OpenAIBaseInput {
121
121
  * Currently in experimental beta.
122
122
  */
123
123
  __includeRawResponse?: boolean;
124
+ /**
125
+ * Whether the model supports the `strict` argument when passing in tools.
126
+ * If `undefined` the `strict` argument will not be passed to OpenAI.
127
+ */
128
+ supportsStrictToolCalling?: boolean;
124
129
  }
125
130
  export declare interface AzureOpenAIInput {
126
131
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/openai",
3
- "version": "0.2.5",
3
+ "version": "0.2.6",
4
4
  "description": "OpenAI integrations for LangChain.js",
5
5
  "type": "module",
6
6
  "engines": {
@@ -15,7 +15,7 @@
15
15
  "homepage": "https://github.com/langchain-ai/langchainjs/tree/main/libs/langchain-openai/",
16
16
  "scripts": {
17
17
  "build": "yarn turbo:command build:internal --filter=@langchain/openai",
18
- "build:internal": "yarn lc-build:v2 --create-entrypoints --pre --tree-shaking",
18
+ "build:internal": "yarn lc_build_v2 --create-entrypoints --pre --tree-shaking",
19
19
  "lint:eslint": "NODE_OPTIONS=--max-old-space-size=4096 eslint --cache --ext .ts,.js src/",
20
20
  "lint:dpdm": "dpdm --exit-code circular:1 --no-warning --no-tree src/*.ts src/**/*.ts",
21
21
  "lint": "yarn lint:eslint && yarn lint:dpdm",
@@ -35,16 +35,16 @@
35
35
  "author": "LangChain",
36
36
  "license": "MIT",
37
37
  "dependencies": {
38
- "@langchain/core": ">=0.2.16 <0.3.0",
38
+ "@langchain/core": ">=0.2.21 <0.3.0",
39
39
  "js-tiktoken": "^1.0.12",
40
- "openai": "^4.49.1",
40
+ "openai": "^4.55.0",
41
41
  "zod": "^3.22.4",
42
42
  "zod-to-json-schema": "^3.22.3"
43
43
  },
44
44
  "devDependencies": {
45
- "@azure/identity": "^4.2.0",
45
+ "@azure/identity": "^4.2.1",
46
46
  "@jest/globals": "^29.5.0",
47
- "@langchain/scripts": "~0.0.14",
47
+ "@langchain/scripts": "~0.0.20",
48
48
  "@langchain/standard-tests": "0.0.0",
49
49
  "@swc/core": "^1.3.90",
50
50
  "@swc/jest": "^0.2.29",
@@ -59,7 +59,7 @@
59
59
  "jest": "^29.5.0",
60
60
  "jest-environment-node": "^29.6.4",
61
61
  "prettier": "^2.8.3",
62
- "release-it": "^15.10.1",
62
+ "release-it": "^17.6.0",
63
63
  "rimraf": "^5.0.1",
64
64
  "ts-jest": "^29.1.0",
65
65
  "typescript": "~5.1.6"
@@ -1 +0,0 @@
1
- export {};
@@ -1,57 +0,0 @@
1
- import { test, expect } from "@jest/globals";
2
- import { DallEAPIWrapper } from "../dalle.js";
3
- test.skip("Dalle can generate images", async () => {
4
- const dalle = new DallEAPIWrapper();
5
- const res = await dalle.invoke("A painting of a cat");
6
- expect(res).toBeDefined();
7
- expect(res).toContain("https://");
8
- });
9
- test.skip("Dalle can generate images with base 64 response format", async () => {
10
- const dalle = new DallEAPIWrapper({
11
- responseFormat: "b64_json",
12
- });
13
- const res = await dalle.invoke("A painting of a cat");
14
- expect(res).toBeDefined();
15
- expect(res).not.toContain("https://");
16
- });
17
- test.skip("Dalle returns multiple image URLs if n > 1", async () => {
18
- const dalle = new DallEAPIWrapper({
19
- n: 2,
20
- });
21
- const res = await dalle.invoke("A painting of a cat");
22
- expect(res).toBeDefined();
23
- expect(res).toBeInstanceOf(Array);
24
- if (!Array.isArray(res))
25
- return;
26
- expect(res).toHaveLength(2);
27
- // The types for each should be `image_url` with an `image_url` field containing the URL
28
- expect(res[0].type).toBe("image_url");
29
- expect(res[1].type).toBe("image_url");
30
- expect(res[0]).toHaveProperty("image_url");
31
- expect(res[1]).toHaveProperty("image_url");
32
- expect(res[0].image_url.startsWith("https://")).toBe(true);
33
- expect(res[1].image_url.startsWith("https://")).toBe(true);
34
- });
35
- test.skip("Dalle returns multiple base64 image strings if n > 1", async () => {
36
- const dalle = new DallEAPIWrapper({
37
- n: 2,
38
- dallEResponseFormat: "b64_json",
39
- });
40
- const res = await dalle.invoke("A painting of a cat");
41
- expect(res).toBeDefined();
42
- expect(res).toBeInstanceOf(Array);
43
- if (!Array.isArray(res))
44
- return;
45
- expect(res).toHaveLength(2);
46
- // The types for each should be `b64_json` with an `b64_json` field containing the URL
47
- expect(res[0].type).toBe("image_url");
48
- expect(res[1].type).toBe("image_url");
49
- expect(res[0]).toHaveProperty("image_url");
50
- expect(res[1]).toHaveProperty("image_url");
51
- expect(res[0].image_url).toHaveProperty("url");
52
- expect(res[1].image_url).toHaveProperty("url");
53
- expect(res[0].image_url.url).toBeDefined();
54
- expect(res[1].image_url.url).toBeDefined();
55
- expect(res[0].image_url.url).not.toBe("");
56
- expect(res[1].image_url.url).not.toBe("");
57
- });