@langchain/openai 0.2.2 → 0.2.4
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 +35 -11
- package/dist/chat_models.d.ts +3 -1
- package/dist/chat_models.js +36 -12
- package/dist/types.d.ts +6 -1
- package/dist/utils/openai.cjs +27 -1
- package/dist/utils/openai.d.ts +3 -0
- package/dist/utils/openai.js +26 -1
- package/package.json +1 -1
package/dist/chat_models.cjs
CHANGED
|
@@ -47,7 +47,7 @@ function messageToOpenAIRole(message) {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
exports.messageToOpenAIRole = messageToOpenAIRole;
|
|
50
|
-
function openAIResponseToChatMessage(message,
|
|
50
|
+
function openAIResponseToChatMessage(message, rawResponse, includeRawResponse) {
|
|
51
51
|
const rawToolCalls = message.tool_calls;
|
|
52
52
|
switch (message.role) {
|
|
53
53
|
case "assistant": {
|
|
@@ -62,15 +62,26 @@ function openAIResponseToChatMessage(message, messageId) {
|
|
|
62
62
|
invalidToolCalls.push((0, openai_tools_1.makeInvalidToolCall)(rawToolCall, e.message));
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
+
const additional_kwargs = {
|
|
66
|
+
function_call: message.function_call,
|
|
67
|
+
tool_calls: rawToolCalls,
|
|
68
|
+
};
|
|
69
|
+
if (includeRawResponse !== undefined) {
|
|
70
|
+
additional_kwargs.__raw_response = rawResponse;
|
|
71
|
+
}
|
|
72
|
+
let response_metadata;
|
|
73
|
+
if (rawResponse.system_fingerprint) {
|
|
74
|
+
response_metadata = {
|
|
75
|
+
system_fingerprint: rawResponse.system_fingerprint,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
65
78
|
return new messages_1.AIMessage({
|
|
66
79
|
content: message.content || "",
|
|
67
80
|
tool_calls: toolCalls,
|
|
68
81
|
invalid_tool_calls: invalidToolCalls,
|
|
69
|
-
additional_kwargs
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
},
|
|
73
|
-
id: messageId,
|
|
82
|
+
additional_kwargs,
|
|
83
|
+
response_metadata,
|
|
84
|
+
id: rawResponse.id,
|
|
74
85
|
});
|
|
75
86
|
}
|
|
76
87
|
default:
|
|
@@ -79,7 +90,7 @@ function openAIResponseToChatMessage(message, messageId) {
|
|
|
79
90
|
}
|
|
80
91
|
function _convertDeltaToMessageChunk(
|
|
81
92
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
82
|
-
delta,
|
|
93
|
+
delta, rawResponse, defaultRole, includeRawResponse) {
|
|
83
94
|
const role = delta.role ?? defaultRole;
|
|
84
95
|
const content = delta.content ?? "";
|
|
85
96
|
let additional_kwargs;
|
|
@@ -96,6 +107,9 @@ delta, messageId, defaultRole) {
|
|
|
96
107
|
else {
|
|
97
108
|
additional_kwargs = {};
|
|
98
109
|
}
|
|
110
|
+
if (includeRawResponse) {
|
|
111
|
+
additional_kwargs.__raw_response = rawResponse;
|
|
112
|
+
}
|
|
99
113
|
if (role === "user") {
|
|
100
114
|
return new messages_1.HumanMessageChunk({ content });
|
|
101
115
|
}
|
|
@@ -116,7 +130,7 @@ delta, messageId, defaultRole) {
|
|
|
116
130
|
content,
|
|
117
131
|
tool_call_chunks: toolCallChunks,
|
|
118
132
|
additional_kwargs,
|
|
119
|
-
id:
|
|
133
|
+
id: rawResponse.id,
|
|
120
134
|
});
|
|
121
135
|
}
|
|
122
136
|
else if (role === "system") {
|
|
@@ -411,6 +425,12 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
411
425
|
writable: true,
|
|
412
426
|
value: void 0
|
|
413
427
|
});
|
|
428
|
+
Object.defineProperty(this, "__includeRawResponse", {
|
|
429
|
+
enumerable: true,
|
|
430
|
+
configurable: true,
|
|
431
|
+
writable: true,
|
|
432
|
+
value: void 0
|
|
433
|
+
});
|
|
414
434
|
Object.defineProperty(this, "client", {
|
|
415
435
|
enumerable: true,
|
|
416
436
|
configurable: true,
|
|
@@ -466,6 +486,7 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
466
486
|
this.stop = fields?.stopSequences ?? fields?.stop;
|
|
467
487
|
this.stopSequences = this?.stop;
|
|
468
488
|
this.user = fields?.user;
|
|
489
|
+
this.__includeRawResponse = fields?.__includeRawResponse;
|
|
469
490
|
if (this.azureOpenAIApiKey || this.azureADTokenProvider) {
|
|
470
491
|
if (!this.azureOpenAIApiInstanceName && !this.azureOpenAIBasePath) {
|
|
471
492
|
throw new Error("Azure OpenAI API instance name not found");
|
|
@@ -547,7 +568,7 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
547
568
|
tools: isStructuredToolArray(options?.tools)
|
|
548
569
|
? options?.tools.map(function_calling_1.convertToOpenAITool)
|
|
549
570
|
: options?.tools,
|
|
550
|
-
tool_choice: options?.tool_choice,
|
|
571
|
+
tool_choice: (0, openai_js_1.formatToOpenAIToolChoice)(options?.tool_choice),
|
|
551
572
|
response_format: options?.response_format,
|
|
552
573
|
seed: options?.seed,
|
|
553
574
|
...streamOptionsConfig,
|
|
@@ -588,7 +609,7 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
588
609
|
if (!delta) {
|
|
589
610
|
continue;
|
|
590
611
|
}
|
|
591
|
-
const chunk = _convertDeltaToMessageChunk(delta, data
|
|
612
|
+
const chunk = _convertDeltaToMessageChunk(delta, data, defaultRole, this.__includeRawResponse);
|
|
592
613
|
defaultRole = delta.role ?? defaultRole;
|
|
593
614
|
const newTokenIndices = {
|
|
594
615
|
prompt: options.promptIndex ?? 0,
|
|
@@ -602,6 +623,9 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
602
623
|
const generationInfo = { ...newTokenIndices };
|
|
603
624
|
if (choice.finish_reason !== undefined) {
|
|
604
625
|
generationInfo.finish_reason = choice.finish_reason;
|
|
626
|
+
// Only include system fingerprint in the last chunk for now
|
|
627
|
+
// to avoid concatenation issues
|
|
628
|
+
generationInfo.system_fingerprint = data.system_fingerprint;
|
|
605
629
|
}
|
|
606
630
|
if (this.logprobs) {
|
|
607
631
|
generationInfo.logprobs = choice.logprobs;
|
|
@@ -698,7 +722,7 @@ class ChatOpenAI extends chat_models_1.BaseChatModel {
|
|
|
698
722
|
const text = part.message?.content ?? "";
|
|
699
723
|
const generation = {
|
|
700
724
|
text,
|
|
701
|
-
message: openAIResponseToChatMessage(part.message ?? { role: "assistant" }, data.
|
|
725
|
+
message: openAIResponseToChatMessage(part.message ?? { role: "assistant" }, data, this.__includeRawResponse),
|
|
702
726
|
};
|
|
703
727
|
generation.generationInfo = {
|
|
704
728
|
...(part.finish_reason ? { finish_reason: part.finish_reason } : {}),
|
package/dist/chat_models.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type { BaseFunctionCallOptions, BaseLanguageModelInput, StructuredOutputM
|
|
|
8
8
|
import { z } from "zod";
|
|
9
9
|
import { Runnable, RunnableToolLike } from "@langchain/core/runnables";
|
|
10
10
|
import type { AzureOpenAIInput, OpenAICallOptions, OpenAIChatInput, OpenAICoreRequestOptions, LegacyOpenAIInput } from "./types.js";
|
|
11
|
+
import { OpenAIToolChoice } from "./utils/openai.js";
|
|
11
12
|
export type { AzureOpenAIInput, OpenAICallOptions, OpenAIChatInput };
|
|
12
13
|
interface TokenUsage {
|
|
13
14
|
completionTokens?: number;
|
|
@@ -21,7 +22,7 @@ type OpenAIRoleEnum = "system" | "assistant" | "user" | "function" | "tool";
|
|
|
21
22
|
export declare function messageToOpenAIRole(message: BaseMessage): OpenAIRoleEnum;
|
|
22
23
|
export interface ChatOpenAICallOptions extends OpenAICallOptions, BaseFunctionCallOptions {
|
|
23
24
|
tools?: StructuredToolInterface[] | OpenAIClient.ChatCompletionTool[];
|
|
24
|
-
tool_choice?:
|
|
25
|
+
tool_choice?: OpenAIToolChoice;
|
|
25
26
|
promptIndex?: number;
|
|
26
27
|
response_format?: {
|
|
27
28
|
type: "json_object";
|
|
@@ -113,6 +114,7 @@ export declare class ChatOpenAI<CallOptions extends ChatOpenAICallOptions = Chat
|
|
|
113
114
|
azureOpenAIApiDeploymentName?: string;
|
|
114
115
|
azureOpenAIBasePath?: string;
|
|
115
116
|
organization?: string;
|
|
117
|
+
__includeRawResponse?: boolean;
|
|
116
118
|
protected client: OpenAIClient;
|
|
117
119
|
protected clientConfig: ClientOptions;
|
|
118
120
|
constructor(fields?: Partial<OpenAIChatInput> & Partial<AzureOpenAIInput> & BaseChatModelParams & {
|
package/dist/chat_models.js
CHANGED
|
@@ -9,7 +9,7 @@ import { JsonOutputParser, StructuredOutputParser, } from "@langchain/core/outpu
|
|
|
9
9
|
import { JsonOutputKeyToolsParser, convertLangChainToolCallToOpenAI, makeInvalidToolCall, parseToolCall, } from "@langchain/core/output_parsers/openai_tools";
|
|
10
10
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
11
11
|
import { getEndpoint } from "./utils/azure.js";
|
|
12
|
-
import { wrapOpenAIClientError } from "./utils/openai.js";
|
|
12
|
+
import { formatToOpenAIToolChoice, wrapOpenAIClientError, } from "./utils/openai.js";
|
|
13
13
|
import { formatFunctionDefinitions, } from "./utils/openai-format-fndef.js";
|
|
14
14
|
function extractGenericMessageCustomRole(message) {
|
|
15
15
|
if (message.role !== "system" &&
|
|
@@ -43,7 +43,7 @@ export function messageToOpenAIRole(message) {
|
|
|
43
43
|
throw new Error(`Unknown message type: ${type}`);
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
|
-
function openAIResponseToChatMessage(message,
|
|
46
|
+
function openAIResponseToChatMessage(message, rawResponse, includeRawResponse) {
|
|
47
47
|
const rawToolCalls = message.tool_calls;
|
|
48
48
|
switch (message.role) {
|
|
49
49
|
case "assistant": {
|
|
@@ -58,15 +58,26 @@ function openAIResponseToChatMessage(message, messageId) {
|
|
|
58
58
|
invalidToolCalls.push(makeInvalidToolCall(rawToolCall, e.message));
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
+
const additional_kwargs = {
|
|
62
|
+
function_call: message.function_call,
|
|
63
|
+
tool_calls: rawToolCalls,
|
|
64
|
+
};
|
|
65
|
+
if (includeRawResponse !== undefined) {
|
|
66
|
+
additional_kwargs.__raw_response = rawResponse;
|
|
67
|
+
}
|
|
68
|
+
let response_metadata;
|
|
69
|
+
if (rawResponse.system_fingerprint) {
|
|
70
|
+
response_metadata = {
|
|
71
|
+
system_fingerprint: rawResponse.system_fingerprint,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
61
74
|
return new AIMessage({
|
|
62
75
|
content: message.content || "",
|
|
63
76
|
tool_calls: toolCalls,
|
|
64
77
|
invalid_tool_calls: invalidToolCalls,
|
|
65
|
-
additional_kwargs
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
},
|
|
69
|
-
id: messageId,
|
|
78
|
+
additional_kwargs,
|
|
79
|
+
response_metadata,
|
|
80
|
+
id: rawResponse.id,
|
|
70
81
|
});
|
|
71
82
|
}
|
|
72
83
|
default:
|
|
@@ -75,7 +86,7 @@ function openAIResponseToChatMessage(message, messageId) {
|
|
|
75
86
|
}
|
|
76
87
|
function _convertDeltaToMessageChunk(
|
|
77
88
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
78
|
-
delta,
|
|
89
|
+
delta, rawResponse, defaultRole, includeRawResponse) {
|
|
79
90
|
const role = delta.role ?? defaultRole;
|
|
80
91
|
const content = delta.content ?? "";
|
|
81
92
|
let additional_kwargs;
|
|
@@ -92,6 +103,9 @@ delta, messageId, defaultRole) {
|
|
|
92
103
|
else {
|
|
93
104
|
additional_kwargs = {};
|
|
94
105
|
}
|
|
106
|
+
if (includeRawResponse) {
|
|
107
|
+
additional_kwargs.__raw_response = rawResponse;
|
|
108
|
+
}
|
|
95
109
|
if (role === "user") {
|
|
96
110
|
return new HumanMessageChunk({ content });
|
|
97
111
|
}
|
|
@@ -112,7 +126,7 @@ delta, messageId, defaultRole) {
|
|
|
112
126
|
content,
|
|
113
127
|
tool_call_chunks: toolCallChunks,
|
|
114
128
|
additional_kwargs,
|
|
115
|
-
id:
|
|
129
|
+
id: rawResponse.id,
|
|
116
130
|
});
|
|
117
131
|
}
|
|
118
132
|
else if (role === "system") {
|
|
@@ -407,6 +421,12 @@ export class ChatOpenAI extends BaseChatModel {
|
|
|
407
421
|
writable: true,
|
|
408
422
|
value: void 0
|
|
409
423
|
});
|
|
424
|
+
Object.defineProperty(this, "__includeRawResponse", {
|
|
425
|
+
enumerable: true,
|
|
426
|
+
configurable: true,
|
|
427
|
+
writable: true,
|
|
428
|
+
value: void 0
|
|
429
|
+
});
|
|
410
430
|
Object.defineProperty(this, "client", {
|
|
411
431
|
enumerable: true,
|
|
412
432
|
configurable: true,
|
|
@@ -462,6 +482,7 @@ export class ChatOpenAI extends BaseChatModel {
|
|
|
462
482
|
this.stop = fields?.stopSequences ?? fields?.stop;
|
|
463
483
|
this.stopSequences = this?.stop;
|
|
464
484
|
this.user = fields?.user;
|
|
485
|
+
this.__includeRawResponse = fields?.__includeRawResponse;
|
|
465
486
|
if (this.azureOpenAIApiKey || this.azureADTokenProvider) {
|
|
466
487
|
if (!this.azureOpenAIApiInstanceName && !this.azureOpenAIBasePath) {
|
|
467
488
|
throw new Error("Azure OpenAI API instance name not found");
|
|
@@ -543,7 +564,7 @@ export class ChatOpenAI extends BaseChatModel {
|
|
|
543
564
|
tools: isStructuredToolArray(options?.tools)
|
|
544
565
|
? options?.tools.map(convertToOpenAITool)
|
|
545
566
|
: options?.tools,
|
|
546
|
-
tool_choice: options?.tool_choice,
|
|
567
|
+
tool_choice: formatToOpenAIToolChoice(options?.tool_choice),
|
|
547
568
|
response_format: options?.response_format,
|
|
548
569
|
seed: options?.seed,
|
|
549
570
|
...streamOptionsConfig,
|
|
@@ -584,7 +605,7 @@ export class ChatOpenAI extends BaseChatModel {
|
|
|
584
605
|
if (!delta) {
|
|
585
606
|
continue;
|
|
586
607
|
}
|
|
587
|
-
const chunk = _convertDeltaToMessageChunk(delta, data
|
|
608
|
+
const chunk = _convertDeltaToMessageChunk(delta, data, defaultRole, this.__includeRawResponse);
|
|
588
609
|
defaultRole = delta.role ?? defaultRole;
|
|
589
610
|
const newTokenIndices = {
|
|
590
611
|
prompt: options.promptIndex ?? 0,
|
|
@@ -598,6 +619,9 @@ export class ChatOpenAI extends BaseChatModel {
|
|
|
598
619
|
const generationInfo = { ...newTokenIndices };
|
|
599
620
|
if (choice.finish_reason !== undefined) {
|
|
600
621
|
generationInfo.finish_reason = choice.finish_reason;
|
|
622
|
+
// Only include system fingerprint in the last chunk for now
|
|
623
|
+
// to avoid concatenation issues
|
|
624
|
+
generationInfo.system_fingerprint = data.system_fingerprint;
|
|
601
625
|
}
|
|
602
626
|
if (this.logprobs) {
|
|
603
627
|
generationInfo.logprobs = choice.logprobs;
|
|
@@ -694,7 +718,7 @@ export class ChatOpenAI extends BaseChatModel {
|
|
|
694
718
|
const text = part.message?.content ?? "";
|
|
695
719
|
const generation = {
|
|
696
720
|
text,
|
|
697
|
-
message: openAIResponseToChatMessage(part.message ?? { role: "assistant" }, data.
|
|
721
|
+
message: openAIResponseToChatMessage(part.message ?? { role: "assistant" }, data, this.__includeRawResponse),
|
|
698
722
|
};
|
|
699
723
|
generation.generationInfo = {
|
|
700
724
|
...(part.finish_reason ? { finish_reason: part.finish_reason } : {}),
|
package/dist/types.d.ts
CHANGED
|
@@ -115,7 +115,12 @@ export interface OpenAIChatInput extends OpenAIBaseInput {
|
|
|
115
115
|
*/
|
|
116
116
|
topLogprobs?: number;
|
|
117
117
|
/** ChatGPT messages to pass as a prefix to the prompt */
|
|
118
|
-
prefixMessages?: OpenAIClient.Chat.
|
|
118
|
+
prefixMessages?: OpenAIClient.Chat.ChatCompletionMessageParam[];
|
|
119
|
+
/**
|
|
120
|
+
* Whether to include the raw OpenAI response in the output message's "additional_kwargs" field.
|
|
121
|
+
* Currently in experimental beta.
|
|
122
|
+
*/
|
|
123
|
+
__includeRawResponse?: boolean;
|
|
119
124
|
}
|
|
120
125
|
export declare interface AzureOpenAIInput {
|
|
121
126
|
/**
|
package/dist/utils/openai.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.formatToOpenAIAssistantTool = exports.formatToOpenAITool = exports.formatToOpenAIFunction = exports.wrapOpenAIClientError = void 0;
|
|
3
|
+
exports.formatToOpenAIToolChoice = 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
6
|
const function_calling_1 = require("@langchain/core/utils/function_calling");
|
|
@@ -34,3 +34,29 @@ function formatToOpenAIAssistantTool(tool) {
|
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
exports.formatToOpenAIAssistantTool = formatToOpenAIAssistantTool;
|
|
37
|
+
function formatToOpenAIToolChoice(toolChoice) {
|
|
38
|
+
if (!toolChoice) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
else if (toolChoice === "any" || toolChoice === "required") {
|
|
42
|
+
return "required";
|
|
43
|
+
}
|
|
44
|
+
else if (toolChoice === "auto") {
|
|
45
|
+
return "auto";
|
|
46
|
+
}
|
|
47
|
+
else if (toolChoice === "none") {
|
|
48
|
+
return "none";
|
|
49
|
+
}
|
|
50
|
+
else if (typeof toolChoice === "string") {
|
|
51
|
+
return {
|
|
52
|
+
type: "function",
|
|
53
|
+
function: {
|
|
54
|
+
name: toolChoice,
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
return toolChoice;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.formatToOpenAIToolChoice = formatToOpenAIToolChoice;
|
package/dist/utils/openai.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { OpenAI as OpenAIClient } from "openai";
|
|
1
2
|
import type { StructuredToolInterface } from "@langchain/core/tools";
|
|
2
3
|
import { convertToOpenAIFunction, convertToOpenAITool } from "@langchain/core/utils/function_calling";
|
|
3
4
|
export declare function wrapOpenAIClientError(e: any): any;
|
|
@@ -15,3 +16,5 @@ export declare function formatToOpenAIAssistantTool(tool: StructuredToolInterfac
|
|
|
15
16
|
};
|
|
16
17
|
};
|
|
17
18
|
};
|
|
19
|
+
export type OpenAIToolChoice = OpenAIClient.ChatCompletionToolChoiceOption | "any" | string;
|
|
20
|
+
export declare function formatToOpenAIToolChoice(toolChoice?: OpenAIToolChoice): OpenAIClient.ChatCompletionToolChoiceOption | undefined;
|
package/dist/utils/openai.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { APIConnectionTimeoutError, APIUserAbortError } from "openai";
|
|
1
|
+
import { APIConnectionTimeoutError, APIUserAbortError, } from "openai";
|
|
2
2
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
3
3
|
import { convertToOpenAIFunction, convertToOpenAITool, } from "@langchain/core/utils/function_calling";
|
|
4
4
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -28,3 +28,28 @@ export function formatToOpenAIAssistantTool(tool) {
|
|
|
28
28
|
},
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
|
+
export function formatToOpenAIToolChoice(toolChoice) {
|
|
32
|
+
if (!toolChoice) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
else if (toolChoice === "any" || toolChoice === "required") {
|
|
36
|
+
return "required";
|
|
37
|
+
}
|
|
38
|
+
else if (toolChoice === "auto") {
|
|
39
|
+
return "auto";
|
|
40
|
+
}
|
|
41
|
+
else if (toolChoice === "none") {
|
|
42
|
+
return "none";
|
|
43
|
+
}
|
|
44
|
+
else if (typeof toolChoice === "string") {
|
|
45
|
+
return {
|
|
46
|
+
type: "function",
|
|
47
|
+
function: {
|
|
48
|
+
name: toolChoice,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
return toolChoice;
|
|
54
|
+
}
|
|
55
|
+
}
|