@librechat/agents 3.1.75 → 3.1.77-dev.1
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/cjs/graphs/Graph.cjs +22 -3
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/hitl/askUserQuestion.cjs +67 -0
- package/dist/cjs/hitl/askUserQuestion.cjs.map +1 -0
- package/dist/cjs/hooks/HookRegistry.cjs +54 -0
- package/dist/cjs/hooks/HookRegistry.cjs.map +1 -1
- package/dist/cjs/hooks/createToolPolicyHook.cjs +115 -0
- package/dist/cjs/hooks/createToolPolicyHook.cjs.map +1 -0
- package/dist/cjs/hooks/executeHooks.cjs +40 -1
- package/dist/cjs/hooks/executeHooks.cjs.map +1 -1
- package/dist/cjs/hooks/types.cjs +1 -0
- package/dist/cjs/hooks/types.cjs.map +1 -1
- package/dist/cjs/langchain/google-common.cjs +3 -0
- package/dist/cjs/langchain/google-common.cjs.map +1 -0
- package/dist/cjs/langchain/index.cjs +86 -0
- package/dist/cjs/langchain/index.cjs.map +1 -0
- package/dist/cjs/langchain/language_models/chat_models.cjs +3 -0
- package/dist/cjs/langchain/language_models/chat_models.cjs.map +1 -0
- package/dist/cjs/langchain/messages/tool.cjs +3 -0
- package/dist/cjs/langchain/messages/tool.cjs.map +1 -0
- package/dist/cjs/langchain/messages.cjs +51 -0
- package/dist/cjs/langchain/messages.cjs.map +1 -0
- package/dist/cjs/langchain/openai.cjs +3 -0
- package/dist/cjs/langchain/openai.cjs.map +1 -0
- package/dist/cjs/langchain/prompts.cjs +11 -0
- package/dist/cjs/langchain/prompts.cjs.map +1 -0
- package/dist/cjs/langchain/runnables.cjs +19 -0
- package/dist/cjs/langchain/runnables.cjs.map +1 -0
- package/dist/cjs/langchain/tools.cjs +23 -0
- package/dist/cjs/langchain/tools.cjs.map +1 -0
- package/dist/cjs/langchain/utils/env.cjs +11 -0
- package/dist/cjs/langchain/utils/env.cjs.map +1 -0
- package/dist/cjs/llm/anthropic/index.cjs +145 -52
- package/dist/cjs/llm/anthropic/index.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/types.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs +21 -14
- package/dist/cjs/llm/anthropic/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs +84 -70
- package/dist/cjs/llm/anthropic/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/index.cjs +1 -1
- package/dist/cjs/llm/bedrock/index.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs +213 -3
- package/dist/cjs/llm/bedrock/utils/message_inputs.cjs.map +1 -1
- package/dist/cjs/llm/bedrock/utils/message_outputs.cjs +2 -1
- package/dist/cjs/llm/bedrock/utils/message_outputs.cjs.map +1 -1
- package/dist/cjs/llm/google/utils/common.cjs +5 -4
- package/dist/cjs/llm/google/utils/common.cjs.map +1 -1
- package/dist/cjs/llm/openai/index.cjs +519 -655
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs +20 -458
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
- package/dist/cjs/llm/openrouter/index.cjs +57 -175
- package/dist/cjs/llm/openrouter/index.cjs.map +1 -1
- package/dist/cjs/llm/vertexai/index.cjs +5 -3
- package/dist/cjs/llm/vertexai/index.cjs.map +1 -1
- package/dist/cjs/main.cjs +112 -3
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/messages/cache.cjs +2 -1
- package/dist/cjs/messages/cache.cjs.map +1 -1
- package/dist/cjs/messages/core.cjs +7 -6
- package/dist/cjs/messages/core.cjs.map +1 -1
- package/dist/cjs/messages/format.cjs +73 -15
- package/dist/cjs/messages/format.cjs.map +1 -1
- package/dist/cjs/messages/langchain.cjs +26 -0
- package/dist/cjs/messages/langchain.cjs.map +1 -0
- package/dist/cjs/messages/prune.cjs +7 -6
- package/dist/cjs/messages/prune.cjs.map +1 -1
- package/dist/cjs/run.cjs +400 -42
- package/dist/cjs/run.cjs.map +1 -1
- package/dist/cjs/tools/ToolNode.cjs +556 -56
- package/dist/cjs/tools/ToolNode.cjs.map +1 -1
- package/dist/cjs/tools/search/search.cjs +55 -66
- package/dist/cjs/tools/search/search.cjs.map +1 -1
- package/dist/cjs/tools/search/tavily-scraper.cjs +189 -0
- package/dist/cjs/tools/search/tavily-scraper.cjs.map +1 -0
- package/dist/cjs/tools/search/tavily-search.cjs +372 -0
- package/dist/cjs/tools/search/tavily-search.cjs.map +1 -0
- package/dist/cjs/tools/search/tool.cjs +26 -4
- package/dist/cjs/tools/search/tool.cjs.map +1 -1
- package/dist/cjs/tools/search/utils.cjs +10 -3
- package/dist/cjs/tools/search/utils.cjs.map +1 -1
- package/dist/esm/graphs/Graph.mjs +22 -3
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/hitl/askUserQuestion.mjs +65 -0
- package/dist/esm/hitl/askUserQuestion.mjs.map +1 -0
- package/dist/esm/hooks/HookRegistry.mjs +54 -0
- package/dist/esm/hooks/HookRegistry.mjs.map +1 -1
- package/dist/esm/hooks/createToolPolicyHook.mjs +113 -0
- package/dist/esm/hooks/createToolPolicyHook.mjs.map +1 -0
- package/dist/esm/hooks/executeHooks.mjs +40 -1
- package/dist/esm/hooks/executeHooks.mjs.map +1 -1
- package/dist/esm/hooks/types.mjs +1 -0
- package/dist/esm/hooks/types.mjs.map +1 -1
- package/dist/esm/langchain/google-common.mjs +2 -0
- package/dist/esm/langchain/google-common.mjs.map +1 -0
- package/dist/esm/langchain/index.mjs +5 -0
- package/dist/esm/langchain/index.mjs.map +1 -0
- package/dist/esm/langchain/language_models/chat_models.mjs +2 -0
- package/dist/esm/langchain/language_models/chat_models.mjs.map +1 -0
- package/dist/esm/langchain/messages/tool.mjs +2 -0
- package/dist/esm/langchain/messages/tool.mjs.map +1 -0
- package/dist/esm/langchain/messages.mjs +2 -0
- package/dist/esm/langchain/messages.mjs.map +1 -0
- package/dist/esm/langchain/openai.mjs +2 -0
- package/dist/esm/langchain/openai.mjs.map +1 -0
- package/dist/esm/langchain/prompts.mjs +2 -0
- package/dist/esm/langchain/prompts.mjs.map +1 -0
- package/dist/esm/langchain/runnables.mjs +2 -0
- package/dist/esm/langchain/runnables.mjs.map +1 -0
- package/dist/esm/langchain/tools.mjs +2 -0
- package/dist/esm/langchain/tools.mjs.map +1 -0
- package/dist/esm/langchain/utils/env.mjs +2 -0
- package/dist/esm/langchain/utils/env.mjs.map +1 -0
- package/dist/esm/llm/anthropic/index.mjs +146 -54
- package/dist/esm/llm/anthropic/index.mjs.map +1 -1
- package/dist/esm/llm/anthropic/types.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs +21 -14
- package/dist/esm/llm/anthropic/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs +84 -71
- package/dist/esm/llm/anthropic/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/llm/bedrock/index.mjs +1 -1
- package/dist/esm/llm/bedrock/index.mjs.map +1 -1
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs +214 -4
- package/dist/esm/llm/bedrock/utils/message_inputs.mjs.map +1 -1
- package/dist/esm/llm/bedrock/utils/message_outputs.mjs +2 -1
- package/dist/esm/llm/bedrock/utils/message_outputs.mjs.map +1 -1
- package/dist/esm/llm/google/utils/common.mjs +5 -4
- package/dist/esm/llm/google/utils/common.mjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +520 -656
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs +23 -459
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
- package/dist/esm/llm/openrouter/index.mjs +57 -175
- package/dist/esm/llm/openrouter/index.mjs.map +1 -1
- package/dist/esm/llm/vertexai/index.mjs +5 -3
- package/dist/esm/llm/vertexai/index.mjs.map +1 -1
- package/dist/esm/main.mjs +7 -0
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/messages/cache.mjs +2 -1
- package/dist/esm/messages/cache.mjs.map +1 -1
- package/dist/esm/messages/core.mjs +7 -6
- package/dist/esm/messages/core.mjs.map +1 -1
- package/dist/esm/messages/format.mjs +73 -15
- package/dist/esm/messages/format.mjs.map +1 -1
- package/dist/esm/messages/langchain.mjs +23 -0
- package/dist/esm/messages/langchain.mjs.map +1 -0
- package/dist/esm/messages/prune.mjs +7 -6
- package/dist/esm/messages/prune.mjs.map +1 -1
- package/dist/esm/run.mjs +400 -42
- package/dist/esm/run.mjs.map +1 -1
- package/dist/esm/tools/ToolNode.mjs +557 -57
- package/dist/esm/tools/ToolNode.mjs.map +1 -1
- package/dist/esm/tools/search/search.mjs +55 -66
- package/dist/esm/tools/search/search.mjs.map +1 -1
- package/dist/esm/tools/search/tavily-scraper.mjs +186 -0
- package/dist/esm/tools/search/tavily-scraper.mjs.map +1 -0
- package/dist/esm/tools/search/tavily-search.mjs +370 -0
- package/dist/esm/tools/search/tavily-search.mjs.map +1 -0
- package/dist/esm/tools/search/tool.mjs +26 -4
- package/dist/esm/tools/search/tool.mjs.map +1 -1
- package/dist/esm/tools/search/utils.mjs +10 -3
- package/dist/esm/tools/search/utils.mjs.map +1 -1
- package/dist/types/graphs/Graph.d.ts +7 -0
- package/dist/types/hitl/askUserQuestion.d.ts +55 -0
- package/dist/types/hitl/index.d.ts +6 -0
- package/dist/types/hooks/HookRegistry.d.ts +58 -0
- package/dist/types/hooks/createToolPolicyHook.d.ts +87 -0
- package/dist/types/hooks/index.d.ts +4 -1
- package/dist/types/hooks/types.d.ts +109 -3
- package/dist/types/index.d.ts +10 -0
- package/dist/types/langchain/google-common.d.ts +1 -0
- package/dist/types/langchain/index.d.ts +8 -0
- package/dist/types/langchain/language_models/chat_models.d.ts +1 -0
- package/dist/types/langchain/messages/tool.d.ts +1 -0
- package/dist/types/langchain/messages.d.ts +2 -0
- package/dist/types/langchain/openai.d.ts +1 -0
- package/dist/types/langchain/prompts.d.ts +1 -0
- package/dist/types/langchain/runnables.d.ts +2 -0
- package/dist/types/langchain/tools.d.ts +2 -0
- package/dist/types/langchain/utils/env.d.ts +1 -0
- package/dist/types/llm/anthropic/index.d.ts +22 -9
- package/dist/types/llm/anthropic/types.d.ts +5 -1
- package/dist/types/llm/anthropic/utils/message_outputs.d.ts +13 -6
- package/dist/types/llm/anthropic/utils/output_parsers.d.ts +1 -1
- package/dist/types/llm/openai/index.d.ts +21 -24
- package/dist/types/llm/openrouter/index.d.ts +11 -9
- package/dist/types/llm/vertexai/index.d.ts +1 -0
- package/dist/types/messages/cache.d.ts +4 -1
- package/dist/types/messages/format.d.ts +4 -1
- package/dist/types/messages/langchain.d.ts +27 -0
- package/dist/types/run.d.ts +117 -1
- package/dist/types/tools/ToolNode.d.ts +26 -1
- package/dist/types/tools/search/tavily-scraper.d.ts +19 -0
- package/dist/types/tools/search/tavily-search.d.ts +4 -0
- package/dist/types/tools/search/types.d.ts +99 -5
- package/dist/types/tools/search/utils.d.ts +2 -2
- package/dist/types/types/graph.d.ts +23 -37
- package/dist/types/types/hitl.d.ts +272 -0
- package/dist/types/types/index.d.ts +1 -0
- package/dist/types/types/llm.d.ts +3 -3
- package/dist/types/types/run.d.ts +33 -0
- package/dist/types/types/stream.d.ts +1 -1
- package/dist/types/types/tools.d.ts +19 -0
- package/package.json +80 -17
- package/src/graphs/Graph.ts +33 -4
- package/src/graphs/__tests__/composition.smoke.test.ts +188 -0
- package/src/hitl/askUserQuestion.ts +72 -0
- package/src/hitl/index.ts +7 -0
- package/src/hooks/HookRegistry.ts +71 -0
- package/src/hooks/__tests__/createToolPolicyHook.test.ts +259 -0
- package/src/hooks/createToolPolicyHook.ts +184 -0
- package/src/hooks/executeHooks.ts +50 -1
- package/src/hooks/index.ts +6 -0
- package/src/hooks/types.ts +112 -0
- package/src/index.ts +22 -0
- package/src/langchain/google-common.ts +1 -0
- package/src/langchain/index.ts +8 -0
- package/src/langchain/language_models/chat_models.ts +1 -0
- package/src/langchain/messages/tool.ts +5 -0
- package/src/langchain/messages.ts +21 -0
- package/src/langchain/openai.ts +1 -0
- package/src/langchain/prompts.ts +1 -0
- package/src/langchain/runnables.ts +7 -0
- package/src/langchain/tools.ts +8 -0
- package/src/langchain/utils/env.ts +1 -0
- package/src/llm/anthropic/index.ts +252 -84
- package/src/llm/anthropic/llm.spec.ts +751 -102
- package/src/llm/anthropic/types.ts +9 -1
- package/src/llm/anthropic/utils/message_inputs.ts +37 -19
- package/src/llm/anthropic/utils/message_outputs.ts +119 -101
- package/src/llm/bedrock/index.ts +2 -2
- package/src/llm/bedrock/llm.spec.ts +341 -0
- package/src/llm/bedrock/utils/message_inputs.ts +303 -4
- package/src/llm/bedrock/utils/message_outputs.ts +2 -1
- package/src/llm/custom-chat-models.smoke.test.ts +836 -0
- package/src/llm/google/llm.spec.ts +339 -57
- package/src/llm/google/utils/common.ts +53 -48
- package/src/llm/openai/contentBlocks.test.ts +346 -0
- package/src/llm/openai/index.ts +856 -833
- package/src/llm/openai/utils/index.ts +107 -78
- package/src/llm/openai/utils/messages.test.ts +159 -0
- package/src/llm/openrouter/index.ts +124 -247
- package/src/llm/openrouter/reasoning.test.ts +8 -1
- package/src/llm/vertexai/index.ts +11 -5
- package/src/llm/vertexai/llm.spec.ts +28 -1
- package/src/messages/cache.test.ts +4 -3
- package/src/messages/cache.ts +3 -2
- package/src/messages/core.ts +16 -9
- package/src/messages/format.ts +96 -16
- package/src/messages/formatAgentMessages.test.ts +166 -1
- package/src/messages/langchain.ts +39 -0
- package/src/messages/prune.ts +12 -8
- package/src/run.ts +456 -47
- package/src/scripts/caching.ts +2 -3
- package/src/specs/summarization.test.ts +51 -58
- package/src/tools/ToolNode.ts +706 -63
- package/src/tools/__tests__/hitl.test.ts +3593 -0
- package/src/tools/search/search.ts +83 -73
- package/src/tools/search/tavily-scraper.ts +235 -0
- package/src/tools/search/tavily-search.ts +424 -0
- package/src/tools/search/tavily.test.ts +965 -0
- package/src/tools/search/tool.ts +36 -26
- package/src/tools/search/types.ts +133 -8
- package/src/tools/search/utils.ts +13 -5
- package/src/types/graph.ts +32 -87
- package/src/types/hitl.ts +303 -0
- package/src/types/index.ts +1 -0
- package/src/types/llm.ts +3 -3
- package/src/types/run.ts +33 -0
- package/src/types/stream.ts +1 -1
- package/src/types/tools.ts +19 -0
- package/src/utils/llmConfig.ts +1 -6
package/src/llm/openai/index.ts
CHANGED
|
@@ -1,36 +1,40 @@
|
|
|
1
1
|
import { AzureOpenAI as AzureOpenAIClient } from 'openai';
|
|
2
2
|
import { ChatXAI as OriginalChatXAI } from '@langchain/xai';
|
|
3
3
|
import { ChatGenerationChunk } from '@langchain/core/outputs';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
AIMessage,
|
|
6
|
+
AIMessageChunk,
|
|
7
|
+
isAIMessage,
|
|
8
|
+
} from '@langchain/core/messages';
|
|
5
9
|
import { ToolDefinition } from '@langchain/core/language_models/base';
|
|
6
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
convertToOpenAITool,
|
|
12
|
+
isLangChainTool,
|
|
13
|
+
} from '@langchain/core/utils/function_calling';
|
|
7
14
|
import { ChatDeepSeek as OriginalChatDeepSeek } from '@langchain/deepseek';
|
|
8
15
|
import { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
|
|
9
16
|
import {
|
|
10
17
|
getEndpoint,
|
|
11
18
|
OpenAIClient,
|
|
12
|
-
|
|
19
|
+
getHeadersWithUserAgent,
|
|
13
20
|
ChatOpenAI as OriginalChatOpenAI,
|
|
21
|
+
ChatOpenAIResponses as OriginalChatOpenAIResponses,
|
|
22
|
+
ChatOpenAICompletions as OriginalChatOpenAICompletions,
|
|
14
23
|
AzureChatOpenAI as OriginalAzureChatOpenAI,
|
|
24
|
+
AzureChatOpenAIResponses as OriginalAzureChatOpenAIResponses,
|
|
25
|
+
AzureChatOpenAICompletions as OriginalAzureChatOpenAICompletions,
|
|
15
26
|
} from '@langchain/openai';
|
|
27
|
+
import type { HeaderValue, HeadersLike } from './types';
|
|
16
28
|
import type {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} from './types';
|
|
29
|
+
BaseMessage,
|
|
30
|
+
BaseMessageChunk,
|
|
31
|
+
UsageMetadata,
|
|
32
|
+
} from '@langchain/core/messages';
|
|
22
33
|
import type { BindToolsInput } from '@langchain/core/language_models/chat_models';
|
|
23
|
-
import type {
|
|
24
|
-
import type { ChatResult, ChatGeneration } from '@langchain/core/outputs';
|
|
34
|
+
import type { ChatGeneration, ChatResult } from '@langchain/core/outputs';
|
|
25
35
|
import type { ChatXAIInput } from '@langchain/xai';
|
|
26
36
|
import type * as t from '@langchain/openai';
|
|
27
|
-
import {
|
|
28
|
-
isReasoningModel,
|
|
29
|
-
_convertMessagesToOpenAIParams,
|
|
30
|
-
_convertMessagesToOpenAIResponsesParams,
|
|
31
|
-
_convertOpenAIResponsesDeltaToBaseMessageChunk,
|
|
32
|
-
type ResponseReturnStreamEvents,
|
|
33
|
-
} from './utils';
|
|
37
|
+
import { isReasoningModel, _convertMessagesToOpenAIParams } from './utils';
|
|
34
38
|
import { sleep } from '@/utils';
|
|
35
39
|
|
|
36
40
|
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
|
@@ -79,10 +83,274 @@ export function normalizeHeaders(
|
|
|
79
83
|
return Object.fromEntries(output.entries());
|
|
80
84
|
}
|
|
81
85
|
|
|
86
|
+
type OpenAICoreRequestOptions = OpenAIClient.RequestOptions;
|
|
82
87
|
type OpenAICompletionParam =
|
|
83
88
|
OpenAIClient.Chat.Completions.ChatCompletionMessageParam;
|
|
89
|
+
type OpenAIClientConfig = NonNullable<
|
|
90
|
+
ConstructorParameters<typeof OpenAIClient>[0]
|
|
91
|
+
>;
|
|
92
|
+
type LibreChatOpenAIFields = t.ChatOpenAIFields & {
|
|
93
|
+
_lc_stream_delay?: number;
|
|
94
|
+
includeReasoningContent?: boolean;
|
|
95
|
+
includeReasoningDetails?: boolean;
|
|
96
|
+
convertReasoningDetailsToContent?: boolean;
|
|
97
|
+
};
|
|
98
|
+
type LibreChatAzureOpenAIFields = t.AzureOpenAIInput & {
|
|
99
|
+
_lc_stream_delay?: number;
|
|
100
|
+
};
|
|
101
|
+
type ReasoningCallOptions = {
|
|
102
|
+
reasoning?: OpenAIClient.Reasoning;
|
|
103
|
+
reasoningEffort?: OpenAIClient.Reasoning['effort'];
|
|
104
|
+
};
|
|
105
|
+
type OpenAIDeltaWithLibreChatFields = Record<string, unknown> & {
|
|
106
|
+
reasoning?: unknown;
|
|
107
|
+
reasoning_details?: unknown;
|
|
108
|
+
provider_specific_fields?: unknown;
|
|
109
|
+
};
|
|
110
|
+
type OpenAIClientOwner = {
|
|
111
|
+
client?: OpenAIClient;
|
|
112
|
+
clientConfig: OpenAIClientConfig;
|
|
113
|
+
timeout?: number;
|
|
114
|
+
};
|
|
115
|
+
type AbortableOpenAIClient = CustomOpenAIClient | CustomAzureOpenAIClient;
|
|
116
|
+
type OpenAIClientDelegate = {
|
|
117
|
+
client?: AbortableOpenAIClient;
|
|
118
|
+
_getClientOptions(
|
|
119
|
+
options: OpenAICoreRequestOptions | undefined
|
|
120
|
+
): OpenAICoreRequestOptions;
|
|
121
|
+
};
|
|
122
|
+
type OpenAIChatCompletion = OpenAIClient.Chat.Completions.ChatCompletion;
|
|
123
|
+
type OpenAIChatCompletionChunk =
|
|
124
|
+
OpenAIClient.Chat.Completions.ChatCompletionChunk;
|
|
125
|
+
type OpenAIChatCompletionStreamItem =
|
|
126
|
+
| OpenAIChatCompletionChunk
|
|
127
|
+
| {
|
|
128
|
+
event: string;
|
|
129
|
+
data?: unknown;
|
|
130
|
+
};
|
|
131
|
+
type OpenAIChatCompletionRequest =
|
|
132
|
+
| OpenAIClient.Chat.ChatCompletionCreateParamsStreaming
|
|
133
|
+
| OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming;
|
|
134
|
+
type OpenAIChatCompletionResult =
|
|
135
|
+
| AsyncIterable<OpenAIChatCompletionChunk>
|
|
136
|
+
| OpenAIChatCompletion;
|
|
137
|
+
type OpenAIChatCompletionRetry = (
|
|
138
|
+
request: OpenAIChatCompletionRequest,
|
|
139
|
+
requestOptions?: OpenAICoreRequestOptions
|
|
140
|
+
) => Promise<
|
|
141
|
+
AsyncIterable<OpenAIChatCompletionStreamItem> | OpenAIChatCompletion
|
|
142
|
+
>;
|
|
143
|
+
|
|
144
|
+
function getExposedOpenAIClient(
|
|
145
|
+
completions: OpenAIClientDelegate,
|
|
146
|
+
responses: OpenAIClientDelegate,
|
|
147
|
+
preferResponses: boolean
|
|
148
|
+
): AbortableOpenAIClient {
|
|
149
|
+
const responsesClient = responses.client;
|
|
150
|
+
if (responsesClient?.abortHandler != null) {
|
|
151
|
+
return responsesClient;
|
|
152
|
+
}
|
|
153
|
+
const completionsClient = completions.client;
|
|
154
|
+
if (completionsClient?.abortHandler != null) {
|
|
155
|
+
return completionsClient;
|
|
156
|
+
}
|
|
84
157
|
|
|
85
|
-
|
|
158
|
+
const delegate = preferResponses ? responses : completions;
|
|
159
|
+
delegate._getClientOptions(undefined);
|
|
160
|
+
return delegate.client as AbortableOpenAIClient;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function getReasoningParams(
|
|
164
|
+
baseReasoning: OpenAIClient.Reasoning | undefined,
|
|
165
|
+
options?: ReasoningCallOptions
|
|
166
|
+
): OpenAIClient.Reasoning | undefined {
|
|
167
|
+
let reasoning: OpenAIClient.Reasoning | undefined;
|
|
168
|
+
if (baseReasoning !== undefined) {
|
|
169
|
+
reasoning = {
|
|
170
|
+
...reasoning,
|
|
171
|
+
...baseReasoning,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
if (options?.reasoning !== undefined) {
|
|
175
|
+
reasoning = {
|
|
176
|
+
...reasoning,
|
|
177
|
+
...options.reasoning,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
if (
|
|
181
|
+
options?.reasoningEffort !== undefined &&
|
|
182
|
+
reasoning?.effort === undefined
|
|
183
|
+
) {
|
|
184
|
+
reasoning = {
|
|
185
|
+
...reasoning,
|
|
186
|
+
effort: options.reasoningEffort,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
return reasoning;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function getGatedReasoningParams(
|
|
193
|
+
model: string,
|
|
194
|
+
baseReasoning: OpenAIClient.Reasoning | undefined,
|
|
195
|
+
options?: ReasoningCallOptions
|
|
196
|
+
): OpenAIClient.Reasoning | undefined {
|
|
197
|
+
if (!isReasoningModel(model)) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
return getReasoningParams(baseReasoning, options);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function isObject(value: unknown): value is object {
|
|
204
|
+
return typeof value === 'object' && value !== null;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function isOpenAIChatCompletionChunk(
|
|
208
|
+
value: unknown
|
|
209
|
+
): value is OpenAIChatCompletionChunk {
|
|
210
|
+
if (!isObject(value)) {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Intentionally loose: downstream handlers already tolerate empty choices.
|
|
215
|
+
const { choices } = value as { choices?: unknown };
|
|
216
|
+
return Array.isArray(choices);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function getOpenAIChatCompletionChunk(
|
|
220
|
+
value: OpenAIChatCompletionStreamItem
|
|
221
|
+
): OpenAIChatCompletionChunk | undefined {
|
|
222
|
+
if (isOpenAIChatCompletionChunk(value)) {
|
|
223
|
+
return value;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const { data } = value;
|
|
227
|
+
if (isOpenAIChatCompletionChunk(data)) {
|
|
228
|
+
return data;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return undefined;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async function* filterOpenAIChatCompletionStream(
|
|
235
|
+
stream: AsyncIterable<OpenAIChatCompletionStreamItem>
|
|
236
|
+
): AsyncGenerator<OpenAIChatCompletionChunk> {
|
|
237
|
+
for await (const item of stream) {
|
|
238
|
+
const chunk = getOpenAIChatCompletionChunk(item);
|
|
239
|
+
if (chunk == null) {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
yield chunk;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async function completionWithFilteredOpenAIStream(
|
|
247
|
+
request: OpenAIChatCompletionRequest,
|
|
248
|
+
requestOptions: OpenAICoreRequestOptions | undefined,
|
|
249
|
+
completionWithRetry: OpenAIChatCompletionRetry
|
|
250
|
+
): Promise<OpenAIChatCompletionResult> {
|
|
251
|
+
if (request.stream !== true) {
|
|
252
|
+
return (await completionWithRetry(
|
|
253
|
+
request,
|
|
254
|
+
requestOptions
|
|
255
|
+
)) as OpenAIChatCompletion;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
const stream = await completionWithRetry(request, requestOptions);
|
|
259
|
+
return filterOpenAIChatCompletionStream(
|
|
260
|
+
stream as AsyncIterable<OpenAIChatCompletionStreamItem>
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function attachLibreChatDeltaFields(
|
|
265
|
+
chunk: BaseMessageChunk,
|
|
266
|
+
delta: Record<string, unknown>
|
|
267
|
+
): BaseMessageChunk {
|
|
268
|
+
if (!AIMessageChunk.isInstance(chunk)) {
|
|
269
|
+
return chunk;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const libreChatDelta = delta as OpenAIDeltaWithLibreChatFields;
|
|
273
|
+
if (
|
|
274
|
+
libreChatDelta.reasoning != null &&
|
|
275
|
+
chunk.additional_kwargs.reasoning_content == null
|
|
276
|
+
) {
|
|
277
|
+
chunk.additional_kwargs.reasoning_content = libreChatDelta.reasoning;
|
|
278
|
+
}
|
|
279
|
+
if (libreChatDelta.reasoning_details != null) {
|
|
280
|
+
chunk.additional_kwargs.reasoning_details =
|
|
281
|
+
libreChatDelta.reasoning_details;
|
|
282
|
+
}
|
|
283
|
+
if (libreChatDelta.provider_specific_fields != null) {
|
|
284
|
+
chunk.additional_kwargs.provider_specific_fields =
|
|
285
|
+
libreChatDelta.provider_specific_fields;
|
|
286
|
+
}
|
|
287
|
+
return chunk;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
function attachLibreChatMessageFields(
|
|
291
|
+
message: BaseMessage,
|
|
292
|
+
rawMessage: Record<string, unknown>
|
|
293
|
+
): BaseMessage {
|
|
294
|
+
if (!isAIMessage(message)) {
|
|
295
|
+
return message;
|
|
296
|
+
}
|
|
297
|
+
if (
|
|
298
|
+
rawMessage.reasoning != null &&
|
|
299
|
+
message.additional_kwargs.reasoning_content == null
|
|
300
|
+
) {
|
|
301
|
+
message.additional_kwargs.reasoning_content = rawMessage.reasoning;
|
|
302
|
+
}
|
|
303
|
+
if (rawMessage.reasoning_details != null) {
|
|
304
|
+
message.additional_kwargs.reasoning_details = rawMessage.reasoning_details;
|
|
305
|
+
}
|
|
306
|
+
if (rawMessage.provider_specific_fields != null) {
|
|
307
|
+
message.additional_kwargs.provider_specific_fields =
|
|
308
|
+
rawMessage.provider_specific_fields;
|
|
309
|
+
}
|
|
310
|
+
return message;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function getCustomOpenAIClientOptions(
|
|
314
|
+
owner: OpenAIClientOwner,
|
|
315
|
+
options?: OpenAICoreRequestOptions
|
|
316
|
+
): OpenAICoreRequestOptions {
|
|
317
|
+
if (!(owner.client as OpenAIClient | undefined)) {
|
|
318
|
+
const openAIEndpointConfig: t.OpenAIEndpointConfig = {
|
|
319
|
+
baseURL: owner.clientConfig.baseURL,
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
const endpoint = getEndpoint(openAIEndpointConfig);
|
|
323
|
+
const params = {
|
|
324
|
+
...owner.clientConfig,
|
|
325
|
+
baseURL: endpoint,
|
|
326
|
+
timeout: owner.timeout,
|
|
327
|
+
maxRetries: 0,
|
|
328
|
+
};
|
|
329
|
+
if (params.baseURL == null) {
|
|
330
|
+
delete params.baseURL;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
params.defaultHeaders = getHeadersWithUserAgent(params.defaultHeaders);
|
|
334
|
+
owner.client = new CustomOpenAIClient(params);
|
|
335
|
+
}
|
|
336
|
+
const requestOptions = {
|
|
337
|
+
...owner.clientConfig,
|
|
338
|
+
...options,
|
|
339
|
+
} as OpenAICoreRequestOptions;
|
|
340
|
+
return requestOptions;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
async function* delayStreamChunks<T>(
|
|
344
|
+
chunks: AsyncGenerator<T>,
|
|
345
|
+
delay?: number
|
|
346
|
+
): AsyncGenerator<T> {
|
|
347
|
+
for await (const chunk of chunks) {
|
|
348
|
+
yield chunk;
|
|
349
|
+
if (delay != null) {
|
|
350
|
+
await sleep(delay);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
86
354
|
|
|
87
355
|
function createAbortHandler(controller: AbortController): () => void {
|
|
88
356
|
return function (): void {
|
|
@@ -113,7 +381,7 @@ export function _convertToOpenAITool(
|
|
|
113
381
|
let toolDef: OpenAIClient.ChatCompletionTool | undefined;
|
|
114
382
|
|
|
115
383
|
if (isLangChainTool(tool)) {
|
|
116
|
-
toolDef =
|
|
384
|
+
toolDef = convertToOpenAITool(tool);
|
|
117
385
|
} else {
|
|
118
386
|
toolDef = tool as ToolDefinition;
|
|
119
387
|
}
|
|
@@ -195,134 +463,261 @@ export class CustomAzureOpenAIClient extends AzureOpenAIClient {
|
|
|
195
463
|
}
|
|
196
464
|
}
|
|
197
465
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
466
|
+
class LibreChatOpenAICompletions extends OriginalChatOpenAICompletions {
|
|
467
|
+
private includeReasoningContent?: boolean;
|
|
468
|
+
private includeReasoningDetails?: boolean;
|
|
469
|
+
private convertReasoningDetailsToContent?: boolean;
|
|
201
470
|
|
|
202
|
-
constructor(
|
|
203
|
-
fields?: t.ChatOpenAICallOptions & {
|
|
204
|
-
_lc_stream_delay?: number;
|
|
205
|
-
} & t.OpenAIChatInput['modelKwargs']
|
|
206
|
-
) {
|
|
471
|
+
constructor(fields?: LibreChatOpenAIFields) {
|
|
207
472
|
super(fields);
|
|
208
|
-
this.
|
|
473
|
+
this.includeReasoningContent = fields?.includeReasoningContent;
|
|
474
|
+
this.includeReasoningDetails = fields?.includeReasoningDetails;
|
|
475
|
+
this.convertReasoningDetailsToContent =
|
|
476
|
+
fields?.convertReasoningDetailsToContent;
|
|
209
477
|
}
|
|
210
478
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
return 'LibreChatOpenAI';
|
|
479
|
+
protected _getReasoningParams(
|
|
480
|
+
options?: this['ParsedCallOptions']
|
|
481
|
+
): OpenAIClient.Reasoning | undefined {
|
|
482
|
+
return getReasoningParams(this.reasoning, options);
|
|
216
483
|
}
|
|
217
|
-
|
|
484
|
+
|
|
485
|
+
_getClientOptions(
|
|
218
486
|
options?: OpenAICoreRequestOptions
|
|
219
487
|
): OpenAICoreRequestOptions {
|
|
220
|
-
|
|
221
|
-
const openAIEndpointConfig: t.OpenAIEndpointConfig = {
|
|
222
|
-
baseURL: this.clientConfig.baseURL,
|
|
223
|
-
};
|
|
224
|
-
|
|
225
|
-
const endpoint = getEndpoint(openAIEndpointConfig);
|
|
226
|
-
const params = {
|
|
227
|
-
...this.clientConfig,
|
|
228
|
-
baseURL: endpoint,
|
|
229
|
-
timeout: this.timeout,
|
|
230
|
-
maxRetries: 0,
|
|
231
|
-
};
|
|
232
|
-
if (params.baseURL == null) {
|
|
233
|
-
delete params.baseURL;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
this.client = new CustomOpenAIClient(params);
|
|
237
|
-
}
|
|
238
|
-
const requestOptions = {
|
|
239
|
-
...this.clientConfig,
|
|
240
|
-
...options,
|
|
241
|
-
} as OpenAICoreRequestOptions;
|
|
242
|
-
return requestOptions;
|
|
488
|
+
return getCustomOpenAIClientOptions(this, options);
|
|
243
489
|
}
|
|
244
490
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}
|
|
491
|
+
async completionWithRetry(
|
|
492
|
+
request: OpenAIClient.Chat.ChatCompletionCreateParamsStreaming,
|
|
493
|
+
requestOptions?: OpenAICoreRequestOptions
|
|
494
|
+
): Promise<AsyncIterable<OpenAIChatCompletionChunk>>;
|
|
495
|
+
async completionWithRetry(
|
|
496
|
+
request: OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming,
|
|
497
|
+
requestOptions?: OpenAICoreRequestOptions
|
|
498
|
+
): Promise<OpenAIChatCompletion>;
|
|
499
|
+
async completionWithRetry(
|
|
500
|
+
request:
|
|
501
|
+
| OpenAIClient.Chat.ChatCompletionCreateParamsStreaming
|
|
502
|
+
| OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming,
|
|
503
|
+
requestOptions?: OpenAICoreRequestOptions
|
|
504
|
+
): Promise<AsyncIterable<OpenAIChatCompletionChunk> | OpenAIChatCompletion> {
|
|
505
|
+
return completionWithFilteredOpenAIStream(
|
|
506
|
+
request,
|
|
507
|
+
requestOptions,
|
|
508
|
+
super.completionWithRetry.bind(this) as OpenAIChatCompletionRetry
|
|
509
|
+
);
|
|
510
|
+
}
|
|
266
511
|
|
|
267
|
-
|
|
512
|
+
protected _convertCompletionsDeltaToBaseMessageChunk(
|
|
513
|
+
delta: Record<string, unknown>,
|
|
514
|
+
rawResponse: OpenAIClient.Chat.Completions.ChatCompletionChunk,
|
|
515
|
+
defaultRole?: OpenAIClient.Chat.ChatCompletionRole
|
|
516
|
+
): BaseMessageChunk {
|
|
517
|
+
return attachLibreChatDeltaFields(
|
|
518
|
+
super._convertCompletionsDeltaToBaseMessageChunk(
|
|
519
|
+
delta,
|
|
520
|
+
rawResponse,
|
|
521
|
+
defaultRole
|
|
522
|
+
),
|
|
523
|
+
delta
|
|
524
|
+
);
|
|
268
525
|
}
|
|
269
526
|
|
|
270
|
-
protected
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
527
|
+
protected _convertCompletionsMessageToBaseMessage(
|
|
528
|
+
message: OpenAIClient.ChatCompletionMessage,
|
|
529
|
+
rawResponse: OpenAIClient.ChatCompletion
|
|
530
|
+
): BaseMessage {
|
|
531
|
+
return attachLibreChatMessageFields(
|
|
532
|
+
super._convertCompletionsMessageToBaseMessage(message, rawResponse),
|
|
533
|
+
message as unknown as Record<string, unknown>
|
|
534
|
+
);
|
|
274
535
|
}
|
|
275
536
|
|
|
276
|
-
async
|
|
537
|
+
async _generate(
|
|
277
538
|
messages: BaseMessage[],
|
|
278
539
|
options: this['ParsedCallOptions'],
|
|
279
540
|
runManager?: CallbackManagerForLLMRun
|
|
280
|
-
):
|
|
281
|
-
if (
|
|
282
|
-
|
|
541
|
+
): Promise<ChatResult> {
|
|
542
|
+
if (
|
|
543
|
+
this.includeReasoningContent !== true &&
|
|
544
|
+
this.includeReasoningDetails !== true
|
|
545
|
+
) {
|
|
546
|
+
return super._generate(messages, options, runManager);
|
|
283
547
|
}
|
|
284
|
-
|
|
548
|
+
|
|
549
|
+
options.signal?.throwIfAborted();
|
|
550
|
+
const usageMetadata: Partial<UsageMetadata> = {};
|
|
551
|
+
const params = this.invocationParams(options);
|
|
552
|
+
const messagesMapped = _convertMessagesToOpenAIParams(
|
|
553
|
+
messages,
|
|
554
|
+
this.model,
|
|
285
555
|
{
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
this.zdrEnabled
|
|
291
|
-
),
|
|
292
|
-
stream: true,
|
|
293
|
-
},
|
|
294
|
-
options
|
|
556
|
+
includeReasoningContent: this.includeReasoningContent,
|
|
557
|
+
includeReasoningDetails: this.includeReasoningDetails,
|
|
558
|
+
convertReasoningDetailsToContent: this.convertReasoningDetailsToContent,
|
|
559
|
+
}
|
|
295
560
|
);
|
|
296
561
|
|
|
297
|
-
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
)
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
562
|
+
if (params.stream === true) {
|
|
563
|
+
const stream = this._streamResponseChunks(messages, options, runManager);
|
|
564
|
+
const finalChunks = new Map<number, ChatGenerationChunk>();
|
|
565
|
+
for await (const chunk of stream) {
|
|
566
|
+
chunk.message.response_metadata = {
|
|
567
|
+
...chunk.generationInfo,
|
|
568
|
+
...chunk.message.response_metadata,
|
|
569
|
+
};
|
|
570
|
+
const index =
|
|
571
|
+
typeof chunk.generationInfo?.completion === 'number'
|
|
572
|
+
? chunk.generationInfo.completion
|
|
573
|
+
: 0;
|
|
574
|
+
const existingChunk = finalChunks.get(index);
|
|
575
|
+
if (existingChunk == null) {
|
|
576
|
+
finalChunks.set(index, chunk);
|
|
577
|
+
} else {
|
|
578
|
+
finalChunks.set(index, existingChunk.concat(chunk));
|
|
579
|
+
}
|
|
305
580
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
581
|
+
const generations = Array.from(finalChunks.entries())
|
|
582
|
+
.sort(([aKey], [bKey]) => aKey - bKey)
|
|
583
|
+
.map(([, value]) => value);
|
|
584
|
+
const { functions, function_call } = this.invocationParams(options);
|
|
585
|
+
const promptTokenUsage = await this._getEstimatedTokenCountFromPrompt(
|
|
586
|
+
messages,
|
|
587
|
+
functions,
|
|
588
|
+
function_call
|
|
313
589
|
);
|
|
590
|
+
const completionTokenUsage =
|
|
591
|
+
await this._getNumTokensFromGenerations(generations);
|
|
592
|
+
usageMetadata.input_tokens = promptTokenUsage;
|
|
593
|
+
usageMetadata.output_tokens = completionTokenUsage;
|
|
594
|
+
usageMetadata.total_tokens = promptTokenUsage + completionTokenUsage;
|
|
595
|
+
return {
|
|
596
|
+
generations,
|
|
597
|
+
llmOutput: {
|
|
598
|
+
estimatedTokenUsage: {
|
|
599
|
+
promptTokens: usageMetadata.input_tokens,
|
|
600
|
+
completionTokens: usageMetadata.output_tokens,
|
|
601
|
+
totalTokens: usageMetadata.total_tokens,
|
|
602
|
+
},
|
|
603
|
+
},
|
|
604
|
+
};
|
|
314
605
|
}
|
|
315
606
|
|
|
316
|
-
|
|
607
|
+
const data = await this.completionWithRetry(
|
|
608
|
+
{
|
|
609
|
+
...params,
|
|
610
|
+
stream: false,
|
|
611
|
+
messages: messagesMapped,
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
signal: options.signal,
|
|
615
|
+
...options.options,
|
|
616
|
+
}
|
|
617
|
+
);
|
|
618
|
+
const {
|
|
619
|
+
completion_tokens: completionTokens,
|
|
620
|
+
prompt_tokens: promptTokens,
|
|
621
|
+
total_tokens: totalTokens,
|
|
622
|
+
prompt_tokens_details: promptTokensDetails,
|
|
623
|
+
completion_tokens_details: completionTokensDetails,
|
|
624
|
+
} = data.usage ?? {};
|
|
625
|
+
|
|
626
|
+
if (completionTokens != null) {
|
|
627
|
+
usageMetadata.output_tokens =
|
|
628
|
+
(usageMetadata.output_tokens ?? 0) + completionTokens;
|
|
629
|
+
}
|
|
630
|
+
if (promptTokens != null) {
|
|
631
|
+
usageMetadata.input_tokens =
|
|
632
|
+
(usageMetadata.input_tokens ?? 0) + promptTokens;
|
|
633
|
+
}
|
|
634
|
+
if (totalTokens != null) {
|
|
635
|
+
usageMetadata.total_tokens =
|
|
636
|
+
(usageMetadata.total_tokens ?? 0) + totalTokens;
|
|
637
|
+
}
|
|
638
|
+
if (
|
|
639
|
+
promptTokensDetails?.audio_tokens != null ||
|
|
640
|
+
promptTokensDetails?.cached_tokens != null
|
|
641
|
+
) {
|
|
642
|
+
usageMetadata.input_token_details = {
|
|
643
|
+
...(promptTokensDetails.audio_tokens != null && {
|
|
644
|
+
audio: promptTokensDetails.audio_tokens,
|
|
645
|
+
}),
|
|
646
|
+
...(promptTokensDetails.cached_tokens != null && {
|
|
647
|
+
cache_read: promptTokensDetails.cached_tokens,
|
|
648
|
+
}),
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
if (
|
|
652
|
+
completionTokensDetails?.audio_tokens != null ||
|
|
653
|
+
completionTokensDetails?.reasoning_tokens != null
|
|
654
|
+
) {
|
|
655
|
+
usageMetadata.output_token_details = {
|
|
656
|
+
...(completionTokensDetails.audio_tokens != null && {
|
|
657
|
+
audio: completionTokensDetails.audio_tokens,
|
|
658
|
+
}),
|
|
659
|
+
...(completionTokensDetails.reasoning_tokens != null && {
|
|
660
|
+
reasoning: completionTokensDetails.reasoning_tokens,
|
|
661
|
+
}),
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
const generations: ChatGeneration[] = [];
|
|
666
|
+
for (const part of data.choices) {
|
|
667
|
+
const generation: ChatGeneration = {
|
|
668
|
+
text: part.message.content ?? '',
|
|
669
|
+
message: this._convertCompletionsMessageToBaseMessage(
|
|
670
|
+
part.message,
|
|
671
|
+
data
|
|
672
|
+
),
|
|
673
|
+
};
|
|
674
|
+
generation.generationInfo = {
|
|
675
|
+
finish_reason: part.finish_reason,
|
|
676
|
+
...(part.logprobs ? { logprobs: part.logprobs } : {}),
|
|
677
|
+
};
|
|
678
|
+
if (isAIMessage(generation.message)) {
|
|
679
|
+
generation.message.usage_metadata = usageMetadata as UsageMetadata;
|
|
680
|
+
}
|
|
681
|
+
generation.message = new AIMessage(
|
|
682
|
+
Object.fromEntries(
|
|
683
|
+
Object.entries(generation.message).filter(
|
|
684
|
+
([key]) => !key.startsWith('lc_')
|
|
685
|
+
)
|
|
686
|
+
)
|
|
687
|
+
);
|
|
688
|
+
generations.push(generation);
|
|
689
|
+
}
|
|
690
|
+
return {
|
|
691
|
+
generations,
|
|
692
|
+
llmOutput: {
|
|
693
|
+
tokenUsage: {
|
|
694
|
+
promptTokens: usageMetadata.input_tokens,
|
|
695
|
+
completionTokens: usageMetadata.output_tokens,
|
|
696
|
+
totalTokens: usageMetadata.total_tokens,
|
|
697
|
+
},
|
|
698
|
+
},
|
|
699
|
+
};
|
|
317
700
|
}
|
|
318
701
|
|
|
319
|
-
async *
|
|
702
|
+
async *_streamResponseChunks(
|
|
320
703
|
messages: BaseMessage[],
|
|
321
704
|
options: this['ParsedCallOptions'],
|
|
322
705
|
runManager?: CallbackManagerForLLMRun
|
|
323
706
|
): AsyncGenerator<ChatGenerationChunk> {
|
|
707
|
+
if (
|
|
708
|
+
this.includeReasoningContent !== true &&
|
|
709
|
+
this.includeReasoningDetails !== true
|
|
710
|
+
) {
|
|
711
|
+
yield* super._streamResponseChunks(messages, options, runManager);
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
|
|
324
715
|
const messagesMapped: OpenAICompletionParam[] =
|
|
325
|
-
_convertMessagesToOpenAIParams(messages, this.model
|
|
716
|
+
_convertMessagesToOpenAIParams(messages, this.model, {
|
|
717
|
+
includeReasoningContent: this.includeReasoningContent,
|
|
718
|
+
includeReasoningDetails: this.includeReasoningDetails,
|
|
719
|
+
convertReasoningDetailsToContent: this.convertReasoningDetailsToContent,
|
|
720
|
+
});
|
|
326
721
|
|
|
327
722
|
const params = {
|
|
328
723
|
...this.invocationParams(options, {
|
|
@@ -331,43 +726,42 @@ export class ChatOpenAI extends OriginalChatOpenAI<t.ChatOpenAICallOptions> {
|
|
|
331
726
|
messages: messagesMapped,
|
|
332
727
|
stream: true as const,
|
|
333
728
|
};
|
|
334
|
-
let defaultRole:
|
|
729
|
+
let defaultRole: OpenAIClient.Chat.ChatCompletionRole | undefined;
|
|
335
730
|
|
|
336
731
|
const streamIterable = await this.completionWithRetry(params, options);
|
|
337
732
|
let usage: OpenAIClient.Completions.CompletionUsage | undefined;
|
|
338
733
|
for await (const data of streamIterable) {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
734
|
+
if (options.signal?.aborted === true) {
|
|
735
|
+
return;
|
|
736
|
+
}
|
|
737
|
+
type StreamChoice = Omit<
|
|
738
|
+
OpenAIClient.Chat.Completions.ChatCompletionChunk.Choice,
|
|
739
|
+
'delta'
|
|
740
|
+
> & {
|
|
741
|
+
delta?: OpenAIClient.Chat.Completions.ChatCompletionChunk.Choice['delta'];
|
|
742
|
+
};
|
|
743
|
+
const choices = data.choices as StreamChoice[] | undefined;
|
|
744
|
+
const choice = choices?.[0];
|
|
745
|
+
if (data.usage != null) {
|
|
343
746
|
usage = data.usage;
|
|
344
747
|
}
|
|
345
|
-
if (
|
|
748
|
+
if (choice == null) {
|
|
346
749
|
continue;
|
|
347
750
|
}
|
|
348
751
|
|
|
349
752
|
const { delta } = choice;
|
|
350
|
-
if (
|
|
753
|
+
if (delta == null) {
|
|
351
754
|
continue;
|
|
352
755
|
}
|
|
353
|
-
const chunk = this.
|
|
354
|
-
delta,
|
|
756
|
+
const chunk = this._convertCompletionsDeltaToBaseMessageChunk(
|
|
757
|
+
delta as unknown as Record<string, unknown>,
|
|
355
758
|
data,
|
|
356
759
|
defaultRole
|
|
357
760
|
);
|
|
358
|
-
if ('reasoning_content' in delta) {
|
|
359
|
-
chunk.additional_kwargs.reasoning_content = delta.reasoning_content;
|
|
360
|
-
} else if ('reasoning' in delta) {
|
|
361
|
-
chunk.additional_kwargs.reasoning_content = delta.reasoning;
|
|
362
|
-
}
|
|
363
|
-
if ('provider_specific_fields' in delta) {
|
|
364
|
-
chunk.additional_kwargs.provider_specific_fields =
|
|
365
|
-
delta.provider_specific_fields;
|
|
366
|
-
}
|
|
367
761
|
defaultRole = delta.role ?? defaultRole;
|
|
368
762
|
const newTokenIndices = {
|
|
369
763
|
prompt: options.promptIndex ?? 0,
|
|
370
|
-
completion: choice.index
|
|
764
|
+
completion: choice.index,
|
|
371
765
|
};
|
|
372
766
|
if (typeof chunk.content !== 'string') {
|
|
373
767
|
// eslint-disable-next-line no-console
|
|
@@ -376,17 +770,14 @@ export class ChatOpenAI extends OriginalChatOpenAI<t.ChatOpenAICallOptions> {
|
|
|
376
770
|
);
|
|
377
771
|
continue;
|
|
378
772
|
}
|
|
379
|
-
|
|
380
|
-
const generationInfo: Record<string, any> = { ...newTokenIndices };
|
|
773
|
+
const generationInfo: Record<string, unknown> = { ...newTokenIndices };
|
|
381
774
|
if (choice.finish_reason != null) {
|
|
382
775
|
generationInfo.finish_reason = choice.finish_reason;
|
|
383
|
-
// Only include system fingerprint in the last chunk for now
|
|
384
|
-
// to avoid concatenation issues
|
|
385
776
|
generationInfo.system_fingerprint = data.system_fingerprint;
|
|
386
777
|
generationInfo.model_name = data.model;
|
|
387
778
|
generationInfo.service_tier = data.service_tier;
|
|
388
779
|
}
|
|
389
|
-
if (this.logprobs
|
|
780
|
+
if (this.logprobs === true) {
|
|
390
781
|
generationInfo.logprobs = choice.logprobs;
|
|
391
782
|
}
|
|
392
783
|
const generationChunk = new ChatGenerationChunk({
|
|
@@ -395,11 +786,8 @@ export class ChatOpenAI extends OriginalChatOpenAI<t.ChatOpenAICallOptions> {
|
|
|
395
786
|
generationInfo,
|
|
396
787
|
});
|
|
397
788
|
yield generationChunk;
|
|
398
|
-
if (this._lc_stream_delay != null) {
|
|
399
|
-
await sleep(this._lc_stream_delay);
|
|
400
|
-
}
|
|
401
789
|
await runManager?.handleLLMNewToken(
|
|
402
|
-
generationChunk.text
|
|
790
|
+
generationChunk.text,
|
|
403
791
|
newTokenIndices,
|
|
404
792
|
undefined,
|
|
405
793
|
undefined,
|
|
@@ -427,9 +815,7 @@ export class ChatOpenAI extends OriginalChatOpenAI<t.ChatOpenAICallOptions> {
|
|
|
427
815
|
const generationChunk = new ChatGenerationChunk({
|
|
428
816
|
message: new AIMessageChunk({
|
|
429
817
|
content: '',
|
|
430
|
-
response_metadata: {
|
|
431
|
-
usage: { ...usage },
|
|
432
|
-
},
|
|
818
|
+
response_metadata: { usage: { ...usage } },
|
|
433
819
|
usage_metadata: {
|
|
434
820
|
input_tokens: usage.prompt_tokens,
|
|
435
821
|
output_tokens: usage.completion_tokens,
|
|
@@ -445,9 +831,17 @@ export class ChatOpenAI extends OriginalChatOpenAI<t.ChatOpenAICallOptions> {
|
|
|
445
831
|
text: '',
|
|
446
832
|
});
|
|
447
833
|
yield generationChunk;
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
834
|
+
await runManager?.handleLLMNewToken(
|
|
835
|
+
generationChunk.text,
|
|
836
|
+
{
|
|
837
|
+
prompt: 0,
|
|
838
|
+
completion: 0,
|
|
839
|
+
},
|
|
840
|
+
undefined,
|
|
841
|
+
undefined,
|
|
842
|
+
undefined,
|
|
843
|
+
{ chunk: generationChunk }
|
|
844
|
+
);
|
|
451
845
|
}
|
|
452
846
|
if (options.signal?.aborted === true) {
|
|
453
847
|
throw new Error('AbortError');
|
|
@@ -455,57 +849,28 @@ export class ChatOpenAI extends OriginalChatOpenAI<t.ChatOpenAICallOptions> {
|
|
|
455
849
|
}
|
|
456
850
|
}
|
|
457
851
|
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
super(fields);
|
|
464
|
-
this._lc_stream_delay = fields?._lc_stream_delay;
|
|
852
|
+
class LibreChatOpenAIResponses extends OriginalChatOpenAIResponses {
|
|
853
|
+
protected _getReasoningParams(
|
|
854
|
+
options?: this['ParsedCallOptions']
|
|
855
|
+
): OpenAIClient.Reasoning | undefined {
|
|
856
|
+
return getReasoningParams(this.reasoning, options);
|
|
465
857
|
}
|
|
466
858
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
return 'LibreChatAzureOpenAI';
|
|
859
|
+
_getClientOptions(
|
|
860
|
+
options?: OpenAICoreRequestOptions
|
|
861
|
+
): OpenAICoreRequestOptions {
|
|
862
|
+
return getCustomOpenAIClientOptions(this, options);
|
|
472
863
|
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
getReasoningParams(
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
class LibreChatAzureOpenAICompletions extends OriginalAzureChatOpenAICompletions {
|
|
867
|
+
protected _getReasoningParams(
|
|
478
868
|
options?: this['ParsedCallOptions']
|
|
479
869
|
): OpenAIClient.Reasoning | undefined {
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
}
|
|
870
|
+
return getGatedReasoningParams(this.model, this.reasoning, options);
|
|
871
|
+
}
|
|
483
872
|
|
|
484
|
-
|
|
485
|
-
let reasoning: OpenAIClient.Reasoning | undefined;
|
|
486
|
-
if (this.reasoning !== undefined) {
|
|
487
|
-
reasoning = {
|
|
488
|
-
...reasoning,
|
|
489
|
-
...this.reasoning,
|
|
490
|
-
};
|
|
491
|
-
}
|
|
492
|
-
if (options?.reasoning !== undefined) {
|
|
493
|
-
reasoning = {
|
|
494
|
-
...reasoning,
|
|
495
|
-
...options.reasoning,
|
|
496
|
-
};
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
return reasoning;
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
protected _getReasoningParams(
|
|
503
|
-
options?: this['ParsedCallOptions']
|
|
504
|
-
): OpenAIClient.Reasoning | undefined {
|
|
505
|
-
return this.getReasoningParams(options);
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
protected _getClientOptions(
|
|
873
|
+
_getClientOptions(
|
|
509
874
|
options: OpenAICoreRequestOptions | undefined
|
|
510
875
|
): OpenAICoreRequestOptions {
|
|
511
876
|
if (!(this.client as unknown as AzureOpenAIClient | undefined)) {
|
|
@@ -567,162 +932,133 @@ export class AzureChatOpenAI extends OriginalAzureChatOpenAI {
|
|
|
567
932
|
}
|
|
568
933
|
return requestOptions;
|
|
569
934
|
}
|
|
570
|
-
async *_streamResponseChunks(
|
|
571
|
-
messages: BaseMessage[],
|
|
572
|
-
options: this['ParsedCallOptions'],
|
|
573
|
-
runManager?: CallbackManagerForLLMRun
|
|
574
|
-
): AsyncGenerator<ChatGenerationChunk> {
|
|
575
|
-
if (!this._useResponseApi(options)) {
|
|
576
|
-
return yield* super._streamResponseChunks(messages, options, runManager);
|
|
577
|
-
}
|
|
578
|
-
const streamIterable = await this.responseApiWithRetry(
|
|
579
|
-
{
|
|
580
|
-
...this.invocationParams<'responses'>(options, { streaming: true }),
|
|
581
|
-
input: _convertMessagesToOpenAIResponsesParams(
|
|
582
|
-
messages,
|
|
583
|
-
this.model,
|
|
584
|
-
this.zdrEnabled
|
|
585
|
-
),
|
|
586
|
-
stream: true,
|
|
587
|
-
},
|
|
588
|
-
options
|
|
589
|
-
);
|
|
590
|
-
|
|
591
|
-
for await (const data of streamIterable) {
|
|
592
|
-
const chunk = _convertOpenAIResponsesDeltaToBaseMessageChunk(
|
|
593
|
-
data as ResponseReturnStreamEvents
|
|
594
|
-
);
|
|
595
|
-
if (chunk == null) continue;
|
|
596
|
-
yield chunk;
|
|
597
|
-
if (this._lc_stream_delay != null) {
|
|
598
|
-
await sleep(this._lc_stream_delay);
|
|
599
|
-
}
|
|
600
|
-
await runManager?.handleLLMNewToken(
|
|
601
|
-
chunk.text || '',
|
|
602
|
-
undefined,
|
|
603
|
-
undefined,
|
|
604
|
-
undefined,
|
|
605
|
-
undefined,
|
|
606
|
-
{ chunk }
|
|
607
|
-
);
|
|
608
|
-
}
|
|
609
935
|
|
|
610
|
-
|
|
936
|
+
async completionWithRetry(
|
|
937
|
+
request: OpenAIClient.Chat.ChatCompletionCreateParamsStreaming,
|
|
938
|
+
requestOptions?: OpenAICoreRequestOptions
|
|
939
|
+
): Promise<AsyncIterable<OpenAIChatCompletionChunk>>;
|
|
940
|
+
async completionWithRetry(
|
|
941
|
+
request: OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming,
|
|
942
|
+
requestOptions?: OpenAICoreRequestOptions
|
|
943
|
+
): Promise<OpenAIChatCompletion>;
|
|
944
|
+
async completionWithRetry(
|
|
945
|
+
request:
|
|
946
|
+
| OpenAIClient.Chat.ChatCompletionCreateParamsStreaming
|
|
947
|
+
| OpenAIClient.Chat.ChatCompletionCreateParamsNonStreaming,
|
|
948
|
+
requestOptions?: OpenAICoreRequestOptions
|
|
949
|
+
): Promise<AsyncIterable<OpenAIChatCompletionChunk> | OpenAIChatCompletion> {
|
|
950
|
+
return completionWithFilteredOpenAIStream(
|
|
951
|
+
request,
|
|
952
|
+
requestOptions,
|
|
953
|
+
super.completionWithRetry.bind(this) as OpenAIChatCompletionRetry
|
|
954
|
+
);
|
|
611
955
|
}
|
|
612
956
|
}
|
|
613
|
-
export class ChatDeepSeek extends OriginalChatDeepSeek {
|
|
614
|
-
public get exposedClient(): CustomOpenAIClient {
|
|
615
|
-
return this.client;
|
|
616
|
-
}
|
|
617
|
-
static lc_name(): 'LibreChatDeepSeek' {
|
|
618
|
-
return 'LibreChatDeepSeek';
|
|
619
|
-
}
|
|
620
957
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
958
|
+
class LibreChatAzureOpenAIResponses extends OriginalAzureChatOpenAIResponses {
|
|
959
|
+
protected _getReasoningParams(
|
|
960
|
+
options?: this['ParsedCallOptions']
|
|
961
|
+
): OpenAIClient.Reasoning | undefined {
|
|
962
|
+
return getGatedReasoningParams(this.model, this.reasoning, options);
|
|
625
963
|
}
|
|
626
964
|
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
965
|
+
_getClientOptions(
|
|
966
|
+
options: OpenAICoreRequestOptions | undefined
|
|
967
|
+
): OpenAICoreRequestOptions {
|
|
968
|
+
if (!(this.client as unknown as AzureOpenAIClient | undefined)) {
|
|
969
|
+
const openAIEndpointConfig: t.OpenAIEndpointConfig = {
|
|
970
|
+
azureOpenAIApiDeploymentName: this.azureOpenAIApiDeploymentName,
|
|
971
|
+
azureOpenAIApiInstanceName: this.azureOpenAIApiInstanceName,
|
|
972
|
+
azureOpenAIApiKey: this.azureOpenAIApiKey,
|
|
973
|
+
azureOpenAIBasePath: this.azureOpenAIBasePath,
|
|
974
|
+
azureADTokenProvider: this.azureADTokenProvider,
|
|
975
|
+
baseURL: this.clientConfig.baseURL,
|
|
976
|
+
};
|
|
633
977
|
|
|
634
|
-
|
|
635
|
-
return super._generate(messages, options ?? {}, runManager);
|
|
636
|
-
}
|
|
978
|
+
const endpoint = getEndpoint(openAIEndpointConfig);
|
|
637
979
|
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
{
|
|
646
|
-
|
|
647
|
-
...options?.options,
|
|
980
|
+
const params = {
|
|
981
|
+
...this.clientConfig,
|
|
982
|
+
baseURL: endpoint,
|
|
983
|
+
timeout: this.timeout,
|
|
984
|
+
maxRetries: 0,
|
|
985
|
+
};
|
|
986
|
+
|
|
987
|
+
if (!this.azureADTokenProvider) {
|
|
988
|
+
params.apiKey = openAIEndpointConfig.azureOpenAIApiKey;
|
|
648
989
|
}
|
|
649
|
-
);
|
|
650
990
|
|
|
651
|
-
|
|
991
|
+
if (params.baseURL == null) {
|
|
992
|
+
delete params.baseURL;
|
|
993
|
+
}
|
|
652
994
|
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
generation.generationInfo = {
|
|
661
|
-
...(part.finish_reason != null
|
|
662
|
-
? { finish_reason: part.finish_reason }
|
|
663
|
-
: {}),
|
|
664
|
-
...(part.logprobs ? { logprobs: part.logprobs } : {}),
|
|
995
|
+
const defaultHeaders = normalizeHeaders(params.defaultHeaders);
|
|
996
|
+
params.defaultHeaders = {
|
|
997
|
+
...params.defaultHeaders,
|
|
998
|
+
'User-Agent':
|
|
999
|
+
defaultHeaders['User-Agent'] != null
|
|
1000
|
+
? `${defaultHeaders['User-Agent']}: librechat-azure-openai-v2`
|
|
1001
|
+
: 'librechat-azure-openai-v2',
|
|
665
1002
|
};
|
|
666
|
-
|
|
1003
|
+
|
|
1004
|
+
this.client = new CustomAzureOpenAIClient({
|
|
1005
|
+
apiVersion: this.azureOpenAIApiVersion,
|
|
1006
|
+
azureADTokenProvider: this.azureADTokenProvider,
|
|
1007
|
+
...(params as t.AzureOpenAIInput),
|
|
1008
|
+
}) as unknown as CustomOpenAIClient;
|
|
667
1009
|
}
|
|
668
1010
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
}
|
|
678
|
-
|
|
1011
|
+
const requestOptions = {
|
|
1012
|
+
...this.clientConfig,
|
|
1013
|
+
...options,
|
|
1014
|
+
} as OpenAICoreRequestOptions;
|
|
1015
|
+
if (this.azureOpenAIApiKey != null) {
|
|
1016
|
+
requestOptions.headers = {
|
|
1017
|
+
'api-key': this.azureOpenAIApiKey,
|
|
1018
|
+
...requestOptions.headers,
|
|
1019
|
+
};
|
|
1020
|
+
requestOptions.query = {
|
|
1021
|
+
'api-version': this.azureOpenAIApiVersion,
|
|
1022
|
+
...requestOptions.query,
|
|
1023
|
+
};
|
|
1024
|
+
}
|
|
1025
|
+
return requestOptions;
|
|
679
1026
|
}
|
|
1027
|
+
}
|
|
680
1028
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
}));
|
|
693
|
-
|
|
694
|
-
const additional_kwargs: Record<string, unknown> = {};
|
|
695
|
-
if (rawToolCalls) {
|
|
696
|
-
additional_kwargs.tool_calls = rawToolCalls;
|
|
697
|
-
}
|
|
698
|
-
if (
|
|
699
|
-
'reasoning_content' in message &&
|
|
700
|
-
message.reasoning_content != null &&
|
|
701
|
-
message.reasoning_content !== ''
|
|
702
|
-
) {
|
|
703
|
-
additional_kwargs.reasoning_content = message.reasoning_content;
|
|
704
|
-
}
|
|
1029
|
+
function withLibreChatOpenAIFields(
|
|
1030
|
+
fields?: LibreChatOpenAIFields
|
|
1031
|
+
): LibreChatOpenAIFields {
|
|
1032
|
+
const nextFields = fields ?? {};
|
|
1033
|
+
return {
|
|
1034
|
+
...nextFields,
|
|
1035
|
+
completions:
|
|
1036
|
+
nextFields.completions ?? new LibreChatOpenAICompletions(nextFields),
|
|
1037
|
+
responses: nextFields.responses ?? new LibreChatOpenAIResponses(nextFields),
|
|
1038
|
+
};
|
|
1039
|
+
}
|
|
705
1040
|
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
total_tokens: data.usage.total_tokens,
|
|
715
|
-
}
|
|
716
|
-
: undefined,
|
|
717
|
-
response_metadata: {
|
|
718
|
-
model_name: data.model,
|
|
719
|
-
system_fingerprint: data.system_fingerprint,
|
|
720
|
-
finish_reason: choice.finish_reason,
|
|
721
|
-
},
|
|
722
|
-
});
|
|
1041
|
+
export class ChatOpenAI extends OriginalChatOpenAI<t.ChatOpenAICallOptions> {
|
|
1042
|
+
_lc_stream_delay?: number;
|
|
1043
|
+
|
|
1044
|
+
constructor(
|
|
1045
|
+
fields?: LibreChatOpenAIFields & t.OpenAIChatInput['modelKwargs']
|
|
1046
|
+
) {
|
|
1047
|
+
super(withLibreChatOpenAIFields(fields));
|
|
1048
|
+
this._lc_stream_delay = fields?._lc_stream_delay;
|
|
723
1049
|
}
|
|
724
1050
|
|
|
725
|
-
|
|
1051
|
+
public get exposedClient(): CustomOpenAIClient {
|
|
1052
|
+
return getExposedOpenAIClient(
|
|
1053
|
+
this.completions as OpenAIClientDelegate,
|
|
1054
|
+
this.responses as OpenAIClientDelegate,
|
|
1055
|
+
this._useResponsesApi(undefined)
|
|
1056
|
+
) as CustomOpenAIClient;
|
|
1057
|
+
}
|
|
1058
|
+
static lc_name(): string {
|
|
1059
|
+
return 'LibreChatOpenAI';
|
|
1060
|
+
}
|
|
1061
|
+
_getClientOptions(
|
|
726
1062
|
options?: OpenAICoreRequestOptions
|
|
727
1063
|
): OpenAICoreRequestOptions {
|
|
728
1064
|
if (!(this.client as OpenAIClient | undefined)) {
|
|
@@ -750,130 +1086,199 @@ export class ChatDeepSeek extends OriginalChatDeepSeek {
|
|
|
750
1086
|
return requestOptions;
|
|
751
1087
|
}
|
|
752
1088
|
|
|
1089
|
+
/**
|
|
1090
|
+
* Returns backwards compatible reasoning parameters from constructor params and call options
|
|
1091
|
+
* @internal
|
|
1092
|
+
*/
|
|
1093
|
+
getReasoningParams(
|
|
1094
|
+
options?: this['ParsedCallOptions']
|
|
1095
|
+
): OpenAIClient.Reasoning | undefined {
|
|
1096
|
+
return getReasoningParams(this.reasoning, options);
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
protected _getReasoningParams(
|
|
1100
|
+
options?: this['ParsedCallOptions']
|
|
1101
|
+
): OpenAIClient.Reasoning | undefined {
|
|
1102
|
+
return this.getReasoningParams(options);
|
|
1103
|
+
}
|
|
1104
|
+
|
|
753
1105
|
async *_streamResponseChunks(
|
|
754
1106
|
messages: BaseMessage[],
|
|
755
1107
|
options: this['ParsedCallOptions'],
|
|
756
1108
|
runManager?: CallbackManagerForLLMRun
|
|
757
1109
|
): AsyncGenerator<ChatGenerationChunk> {
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
1110
|
+
yield* delayStreamChunks(
|
|
1111
|
+
super._streamResponseChunks(messages, options, runManager),
|
|
1112
|
+
this._lc_stream_delay
|
|
1113
|
+
);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
762
1116
|
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
streaming: true,
|
|
766
|
-
}),
|
|
767
|
-
messages: messagesMapped,
|
|
768
|
-
stream: true as const,
|
|
769
|
-
};
|
|
770
|
-
let defaultRole: OpenAIRoleEnum | undefined;
|
|
1117
|
+
export class AzureChatOpenAI extends OriginalAzureChatOpenAI {
|
|
1118
|
+
_lc_stream_delay?: number;
|
|
771
1119
|
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
if (data.usage) {
|
|
779
|
-
usage = data.usage;
|
|
780
|
-
}
|
|
781
|
-
if (!choice) {
|
|
782
|
-
continue;
|
|
783
|
-
}
|
|
1120
|
+
constructor(fields?: LibreChatAzureOpenAIFields) {
|
|
1121
|
+
super(fields);
|
|
1122
|
+
this.completions = new LibreChatAzureOpenAICompletions(fields);
|
|
1123
|
+
this.responses = new LibreChatAzureOpenAIResponses(fields);
|
|
1124
|
+
this._lc_stream_delay = fields?._lc_stream_delay;
|
|
1125
|
+
}
|
|
784
1126
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
1127
|
+
public get exposedClient(): CustomOpenAIClient {
|
|
1128
|
+
return getExposedOpenAIClient(
|
|
1129
|
+
this.completions as OpenAIClientDelegate,
|
|
1130
|
+
this.responses as OpenAIClientDelegate,
|
|
1131
|
+
this._useResponsesApi(undefined)
|
|
1132
|
+
) as CustomOpenAIClient;
|
|
1133
|
+
}
|
|
1134
|
+
static lc_name(): 'LibreChatAzureOpenAI' {
|
|
1135
|
+
return 'LibreChatAzureOpenAI';
|
|
1136
|
+
}
|
|
1137
|
+
/**
|
|
1138
|
+
* Returns backwards compatible reasoning parameters from constructor params and call options
|
|
1139
|
+
* @internal
|
|
1140
|
+
*/
|
|
1141
|
+
getReasoningParams(
|
|
1142
|
+
options?: this['ParsedCallOptions']
|
|
1143
|
+
): OpenAIClient.Reasoning | undefined {
|
|
1144
|
+
return getGatedReasoningParams(this.model, this.reasoning, options);
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
protected _getReasoningParams(
|
|
1148
|
+
options?: this['ParsedCallOptions']
|
|
1149
|
+
): OpenAIClient.Reasoning | undefined {
|
|
1150
|
+
return this.getReasoningParams(options);
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
_getClientOptions(
|
|
1154
|
+
options: OpenAICoreRequestOptions | undefined
|
|
1155
|
+
): OpenAICoreRequestOptions {
|
|
1156
|
+
if (!(this.client as unknown as AzureOpenAIClient | undefined)) {
|
|
1157
|
+
const openAIEndpointConfig: t.OpenAIEndpointConfig = {
|
|
1158
|
+
azureOpenAIApiDeploymentName: this.azureOpenAIApiDeploymentName,
|
|
1159
|
+
azureOpenAIApiInstanceName: this.azureOpenAIApiInstanceName,
|
|
1160
|
+
azureOpenAIApiKey: this.azureOpenAIApiKey,
|
|
1161
|
+
azureOpenAIBasePath: this.azureOpenAIBasePath,
|
|
1162
|
+
azureADTokenProvider: this.azureADTokenProvider,
|
|
1163
|
+
baseURL: this.clientConfig.baseURL,
|
|
801
1164
|
};
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
generationInfo.model_name = data.model;
|
|
815
|
-
generationInfo.service_tier = data.service_tier;
|
|
1165
|
+
|
|
1166
|
+
const endpoint = getEndpoint(openAIEndpointConfig);
|
|
1167
|
+
|
|
1168
|
+
const params = {
|
|
1169
|
+
...this.clientConfig,
|
|
1170
|
+
baseURL: endpoint,
|
|
1171
|
+
timeout: this.timeout,
|
|
1172
|
+
maxRetries: 0,
|
|
1173
|
+
};
|
|
1174
|
+
|
|
1175
|
+
if (!this.azureADTokenProvider) {
|
|
1176
|
+
params.apiKey = openAIEndpointConfig.azureOpenAIApiKey;
|
|
816
1177
|
}
|
|
817
|
-
|
|
818
|
-
|
|
1178
|
+
|
|
1179
|
+
if (params.baseURL == null) {
|
|
1180
|
+
delete params.baseURL;
|
|
819
1181
|
}
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
1182
|
+
|
|
1183
|
+
const defaultHeaders = normalizeHeaders(params.defaultHeaders);
|
|
1184
|
+
params.defaultHeaders = {
|
|
1185
|
+
...params.defaultHeaders,
|
|
1186
|
+
'User-Agent':
|
|
1187
|
+
defaultHeaders['User-Agent'] != null
|
|
1188
|
+
? `${defaultHeaders['User-Agent']}: librechat-azure-openai-v2`
|
|
1189
|
+
: 'librechat-azure-openai-v2',
|
|
1190
|
+
};
|
|
1191
|
+
|
|
1192
|
+
this.client = new CustomAzureOpenAIClient({
|
|
1193
|
+
apiVersion: this.azureOpenAIApiVersion,
|
|
1194
|
+
azureADTokenProvider: this.azureADTokenProvider,
|
|
1195
|
+
...(params as t.AzureOpenAIInput),
|
|
1196
|
+
}) as unknown as CustomOpenAIClient;
|
|
834
1197
|
}
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
1198
|
+
|
|
1199
|
+
const requestOptions = {
|
|
1200
|
+
...this.clientConfig,
|
|
1201
|
+
...options,
|
|
1202
|
+
} as OpenAICoreRequestOptions;
|
|
1203
|
+
if (this.azureOpenAIApiKey != null) {
|
|
1204
|
+
requestOptions.headers = {
|
|
1205
|
+
'api-key': this.azureOpenAIApiKey,
|
|
1206
|
+
...requestOptions.headers,
|
|
843
1207
|
};
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
}),
|
|
848
|
-
...(usage.completion_tokens_details?.reasoning_tokens != null && {
|
|
849
|
-
reasoning: usage.completion_tokens_details.reasoning_tokens,
|
|
850
|
-
}),
|
|
1208
|
+
requestOptions.query = {
|
|
1209
|
+
'api-version': this.azureOpenAIApiVersion,
|
|
1210
|
+
...requestOptions.query,
|
|
851
1211
|
};
|
|
852
|
-
const generationChunk = new ChatGenerationChunk({
|
|
853
|
-
message: new AIMessageChunk({
|
|
854
|
-
content: '',
|
|
855
|
-
response_metadata: {
|
|
856
|
-
usage: { ...usage },
|
|
857
|
-
},
|
|
858
|
-
usage_metadata: {
|
|
859
|
-
input_tokens: usage.prompt_tokens,
|
|
860
|
-
output_tokens: usage.completion_tokens,
|
|
861
|
-
total_tokens: usage.total_tokens,
|
|
862
|
-
...(Object.keys(inputTokenDetails).length > 0 && {
|
|
863
|
-
input_token_details: inputTokenDetails,
|
|
864
|
-
}),
|
|
865
|
-
...(Object.keys(outputTokenDetails).length > 0 && {
|
|
866
|
-
output_token_details: outputTokenDetails,
|
|
867
|
-
}),
|
|
868
|
-
},
|
|
869
|
-
}),
|
|
870
|
-
text: '',
|
|
871
|
-
});
|
|
872
|
-
yield generationChunk;
|
|
873
1212
|
}
|
|
874
|
-
|
|
875
|
-
|
|
1213
|
+
return requestOptions;
|
|
1214
|
+
}
|
|
1215
|
+
async *_streamResponseChunks(
|
|
1216
|
+
messages: BaseMessage[],
|
|
1217
|
+
options: this['ParsedCallOptions'],
|
|
1218
|
+
runManager?: CallbackManagerForLLMRun
|
|
1219
|
+
): AsyncGenerator<ChatGenerationChunk> {
|
|
1220
|
+
yield* delayStreamChunks(
|
|
1221
|
+
super._streamResponseChunks(messages, options, runManager),
|
|
1222
|
+
this._lc_stream_delay
|
|
1223
|
+
);
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
export class ChatDeepSeek extends OriginalChatDeepSeek {
|
|
1227
|
+
_lc_stream_delay?: number;
|
|
1228
|
+
|
|
1229
|
+
constructor(
|
|
1230
|
+
fields?: ConstructorParameters<typeof OriginalChatDeepSeek>[0] & {
|
|
1231
|
+
_lc_stream_delay?: number;
|
|
876
1232
|
}
|
|
1233
|
+
) {
|
|
1234
|
+
super(fields);
|
|
1235
|
+
this._lc_stream_delay = fields?._lc_stream_delay;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
public get exposedClient(): CustomOpenAIClient {
|
|
1239
|
+
return this.client;
|
|
1240
|
+
}
|
|
1241
|
+
static lc_name(): 'LibreChatDeepSeek' {
|
|
1242
|
+
return 'LibreChatDeepSeek';
|
|
1243
|
+
}
|
|
1244
|
+
|
|
1245
|
+
_getClientOptions(
|
|
1246
|
+
options?: OpenAICoreRequestOptions
|
|
1247
|
+
): OpenAICoreRequestOptions {
|
|
1248
|
+
if (!(this.client as OpenAIClient | undefined)) {
|
|
1249
|
+
const openAIEndpointConfig: t.OpenAIEndpointConfig = {
|
|
1250
|
+
baseURL: this.clientConfig.baseURL,
|
|
1251
|
+
};
|
|
1252
|
+
|
|
1253
|
+
const endpoint = getEndpoint(openAIEndpointConfig);
|
|
1254
|
+
const params = {
|
|
1255
|
+
...this.clientConfig,
|
|
1256
|
+
baseURL: endpoint,
|
|
1257
|
+
timeout: this.timeout,
|
|
1258
|
+
maxRetries: 0,
|
|
1259
|
+
};
|
|
1260
|
+
if (params.baseURL == null) {
|
|
1261
|
+
delete params.baseURL;
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
this.client = new CustomOpenAIClient(params);
|
|
1265
|
+
}
|
|
1266
|
+
const requestOptions = {
|
|
1267
|
+
...this.clientConfig,
|
|
1268
|
+
...options,
|
|
1269
|
+
} as OpenAICoreRequestOptions;
|
|
1270
|
+
return requestOptions;
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
async *_streamResponseChunks(
|
|
1274
|
+
messages: BaseMessage[],
|
|
1275
|
+
options: this['ParsedCallOptions'],
|
|
1276
|
+
runManager?: CallbackManagerForLLMRun
|
|
1277
|
+
): AsyncGenerator<ChatGenerationChunk> {
|
|
1278
|
+
yield* delayStreamChunks(
|
|
1279
|
+
super._streamResponseChunks(messages, options, runManager),
|
|
1280
|
+
this._lc_stream_delay
|
|
1281
|
+
);
|
|
877
1282
|
}
|
|
878
1283
|
}
|
|
879
1284
|
|
|
@@ -896,242 +1301,17 @@ export interface XAIUsageMetadata
|
|
|
896
1301
|
}
|
|
897
1302
|
|
|
898
1303
|
export class ChatMoonshot extends ChatOpenAI {
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
return _convertMessagesToOpenAIParams(messages, this.model, {
|
|
1304
|
+
constructor(
|
|
1305
|
+
fields?: LibreChatOpenAIFields & t.OpenAIChatInput['modelKwargs']
|
|
1306
|
+
) {
|
|
1307
|
+
super({
|
|
1308
|
+
...fields,
|
|
905
1309
|
includeReasoningContent: true,
|
|
906
1310
|
});
|
|
907
1311
|
}
|
|
908
1312
|
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
options: this['ParsedCallOptions'],
|
|
912
|
-
runManager?: CallbackManagerForLLMRun
|
|
913
|
-
): Promise<ChatResult> {
|
|
914
|
-
const params = this.invocationParams(options);
|
|
915
|
-
|
|
916
|
-
if (params.stream === true) {
|
|
917
|
-
return super._generate(messages, options, runManager);
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
const messagesMapped = this._convertMessages(messages);
|
|
921
|
-
const data = await this.completionWithRetry(
|
|
922
|
-
{
|
|
923
|
-
...params,
|
|
924
|
-
stream: false,
|
|
925
|
-
messages: messagesMapped,
|
|
926
|
-
},
|
|
927
|
-
{
|
|
928
|
-
signal: options.signal,
|
|
929
|
-
...options.options,
|
|
930
|
-
}
|
|
931
|
-
);
|
|
932
|
-
|
|
933
|
-
const { completion_tokens, prompt_tokens, total_tokens } = data.usage ?? {};
|
|
934
|
-
|
|
935
|
-
const generations = [];
|
|
936
|
-
for (const part of data.choices ?? []) {
|
|
937
|
-
const text = part.message.content ?? '';
|
|
938
|
-
const generation: ChatGeneration = {
|
|
939
|
-
text: typeof text === 'string' ? text : '',
|
|
940
|
-
message: this._convertResponseToMessage(part, data),
|
|
941
|
-
};
|
|
942
|
-
generation.generationInfo = {
|
|
943
|
-
...(part.finish_reason ? { finish_reason: part.finish_reason } : {}),
|
|
944
|
-
...(part.logprobs ? { logprobs: part.logprobs } : {}),
|
|
945
|
-
};
|
|
946
|
-
generations.push(generation);
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
return {
|
|
950
|
-
generations,
|
|
951
|
-
llmOutput: {
|
|
952
|
-
tokenUsage: {
|
|
953
|
-
completionTokens: completion_tokens,
|
|
954
|
-
promptTokens: prompt_tokens,
|
|
955
|
-
totalTokens: total_tokens,
|
|
956
|
-
},
|
|
957
|
-
},
|
|
958
|
-
};
|
|
959
|
-
}
|
|
960
|
-
|
|
961
|
-
protected _convertResponseToMessage(
|
|
962
|
-
choice: OpenAIClient.Chat.Completions.ChatCompletion.Choice,
|
|
963
|
-
data: OpenAIClient.Chat.Completions.ChatCompletion
|
|
964
|
-
): AIMessage {
|
|
965
|
-
const { message } = choice;
|
|
966
|
-
const rawToolCalls = message.tool_calls;
|
|
967
|
-
const toolCalls = rawToolCalls?.map((tc) => ({
|
|
968
|
-
id: tc.id,
|
|
969
|
-
name: tc.function.name,
|
|
970
|
-
args: JSON.parse(tc.function.arguments || '{}'),
|
|
971
|
-
type: 'tool_call' as const,
|
|
972
|
-
}));
|
|
973
|
-
|
|
974
|
-
const additional_kwargs: Record<string, unknown> = {};
|
|
975
|
-
if (rawToolCalls) {
|
|
976
|
-
additional_kwargs.tool_calls = rawToolCalls;
|
|
977
|
-
}
|
|
978
|
-
if (
|
|
979
|
-
'reasoning_content' in message &&
|
|
980
|
-
message.reasoning_content != null &&
|
|
981
|
-
message.reasoning_content !== ''
|
|
982
|
-
) {
|
|
983
|
-
additional_kwargs.reasoning_content = message.reasoning_content;
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
return new AIMessage({
|
|
987
|
-
content: message.content ?? '',
|
|
988
|
-
tool_calls: toolCalls,
|
|
989
|
-
additional_kwargs,
|
|
990
|
-
usage_metadata: data.usage
|
|
991
|
-
? {
|
|
992
|
-
input_tokens: data.usage.prompt_tokens,
|
|
993
|
-
output_tokens: data.usage.completion_tokens,
|
|
994
|
-
total_tokens: data.usage.total_tokens,
|
|
995
|
-
}
|
|
996
|
-
: undefined,
|
|
997
|
-
response_metadata: {
|
|
998
|
-
model_name: data.model,
|
|
999
|
-
system_fingerprint: data.system_fingerprint,
|
|
1000
|
-
finish_reason: choice.finish_reason,
|
|
1001
|
-
},
|
|
1002
|
-
});
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
|
-
async *_streamResponseChunks(
|
|
1006
|
-
messages: BaseMessage[],
|
|
1007
|
-
options: this['ParsedCallOptions'],
|
|
1008
|
-
runManager?: CallbackManagerForLLMRun
|
|
1009
|
-
): AsyncGenerator<ChatGenerationChunk> {
|
|
1010
|
-
const messagesMapped: OpenAICompletionParam[] =
|
|
1011
|
-
_convertMessagesToOpenAIParams(messages, this.model, {
|
|
1012
|
-
includeReasoningContent: true,
|
|
1013
|
-
});
|
|
1014
|
-
|
|
1015
|
-
const params = {
|
|
1016
|
-
...this.invocationParams(options, {
|
|
1017
|
-
streaming: true,
|
|
1018
|
-
}),
|
|
1019
|
-
messages: messagesMapped,
|
|
1020
|
-
stream: true as const,
|
|
1021
|
-
};
|
|
1022
|
-
let defaultRole: OpenAIRoleEnum | undefined;
|
|
1023
|
-
|
|
1024
|
-
const streamIterable = await this.completionWithRetry(params, options);
|
|
1025
|
-
let usage: OpenAIClient.Completions.CompletionUsage | undefined;
|
|
1026
|
-
for await (const data of streamIterable) {
|
|
1027
|
-
const choice = data.choices[0] as
|
|
1028
|
-
| Partial<OpenAIClient.Chat.Completions.ChatCompletionChunk.Choice>
|
|
1029
|
-
| undefined;
|
|
1030
|
-
if (data.usage) {
|
|
1031
|
-
usage = data.usage;
|
|
1032
|
-
}
|
|
1033
|
-
if (!choice) {
|
|
1034
|
-
continue;
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
const { delta } = choice;
|
|
1038
|
-
if (!delta) {
|
|
1039
|
-
continue;
|
|
1040
|
-
}
|
|
1041
|
-
const chunk = this._convertOpenAIDeltaToBaseMessageChunk(
|
|
1042
|
-
delta,
|
|
1043
|
-
data,
|
|
1044
|
-
defaultRole
|
|
1045
|
-
);
|
|
1046
|
-
if ('reasoning_content' in delta) {
|
|
1047
|
-
chunk.additional_kwargs.reasoning_content = delta.reasoning_content;
|
|
1048
|
-
}
|
|
1049
|
-
defaultRole = delta.role ?? defaultRole;
|
|
1050
|
-
const newTokenIndices = {
|
|
1051
|
-
prompt: (options as OpenAIChatCallOptions).promptIndex ?? 0,
|
|
1052
|
-
completion: choice.index ?? 0,
|
|
1053
|
-
};
|
|
1054
|
-
if (typeof chunk.content !== 'string') {
|
|
1055
|
-
// eslint-disable-next-line no-console
|
|
1056
|
-
console.log(
|
|
1057
|
-
'[WARNING]: Received non-string content from OpenAI. This is currently not supported.'
|
|
1058
|
-
);
|
|
1059
|
-
continue;
|
|
1060
|
-
}
|
|
1061
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1062
|
-
const generationInfo: Record<string, any> = { ...newTokenIndices };
|
|
1063
|
-
if (choice.finish_reason != null) {
|
|
1064
|
-
generationInfo.finish_reason = choice.finish_reason;
|
|
1065
|
-
generationInfo.system_fingerprint = data.system_fingerprint;
|
|
1066
|
-
generationInfo.model_name = data.model;
|
|
1067
|
-
generationInfo.service_tier = data.service_tier;
|
|
1068
|
-
}
|
|
1069
|
-
if (this.logprobs == true) {
|
|
1070
|
-
generationInfo.logprobs = choice.logprobs;
|
|
1071
|
-
}
|
|
1072
|
-
const generationChunk = new ChatGenerationChunk({
|
|
1073
|
-
message: chunk,
|
|
1074
|
-
text: chunk.content,
|
|
1075
|
-
generationInfo,
|
|
1076
|
-
});
|
|
1077
|
-
yield generationChunk;
|
|
1078
|
-
if (this._lc_stream_delay != null) {
|
|
1079
|
-
await sleep(this._lc_stream_delay);
|
|
1080
|
-
}
|
|
1081
|
-
await runManager?.handleLLMNewToken(
|
|
1082
|
-
generationChunk.text || '',
|
|
1083
|
-
newTokenIndices,
|
|
1084
|
-
undefined,
|
|
1085
|
-
undefined,
|
|
1086
|
-
undefined,
|
|
1087
|
-
{ chunk: generationChunk }
|
|
1088
|
-
);
|
|
1089
|
-
}
|
|
1090
|
-
if (usage) {
|
|
1091
|
-
const inputTokenDetails = {
|
|
1092
|
-
...(usage.prompt_tokens_details?.audio_tokens != null && {
|
|
1093
|
-
audio: usage.prompt_tokens_details.audio_tokens,
|
|
1094
|
-
}),
|
|
1095
|
-
...(usage.prompt_tokens_details?.cached_tokens != null && {
|
|
1096
|
-
cache_read: usage.prompt_tokens_details.cached_tokens,
|
|
1097
|
-
}),
|
|
1098
|
-
};
|
|
1099
|
-
const outputTokenDetails = {
|
|
1100
|
-
...(usage.completion_tokens_details?.audio_tokens != null && {
|
|
1101
|
-
audio: usage.completion_tokens_details.audio_tokens,
|
|
1102
|
-
}),
|
|
1103
|
-
...(usage.completion_tokens_details?.reasoning_tokens != null && {
|
|
1104
|
-
reasoning: usage.completion_tokens_details.reasoning_tokens,
|
|
1105
|
-
}),
|
|
1106
|
-
};
|
|
1107
|
-
const generationChunk = new ChatGenerationChunk({
|
|
1108
|
-
message: new AIMessageChunk({
|
|
1109
|
-
content: '',
|
|
1110
|
-
response_metadata: {
|
|
1111
|
-
usage: { ...usage },
|
|
1112
|
-
},
|
|
1113
|
-
usage_metadata: {
|
|
1114
|
-
input_tokens: usage.prompt_tokens,
|
|
1115
|
-
output_tokens: usage.completion_tokens,
|
|
1116
|
-
total_tokens: usage.total_tokens,
|
|
1117
|
-
...(Object.keys(inputTokenDetails).length > 0 && {
|
|
1118
|
-
input_token_details: inputTokenDetails,
|
|
1119
|
-
}),
|
|
1120
|
-
...(Object.keys(outputTokenDetails).length > 0 && {
|
|
1121
|
-
output_token_details: outputTokenDetails,
|
|
1122
|
-
}),
|
|
1123
|
-
},
|
|
1124
|
-
}),
|
|
1125
|
-
text: '',
|
|
1126
|
-
});
|
|
1127
|
-
yield generationChunk;
|
|
1128
|
-
if (this._lc_stream_delay != null) {
|
|
1129
|
-
await sleep(this._lc_stream_delay);
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
if (options.signal?.aborted === true) {
|
|
1133
|
-
throw new Error('AbortError');
|
|
1134
|
-
}
|
|
1313
|
+
static lc_name(): 'LibreChatMoonshot' {
|
|
1314
|
+
return 'LibreChatMoonshot';
|
|
1135
1315
|
}
|
|
1136
1316
|
}
|
|
1137
1317
|
|
|
@@ -1168,7 +1348,7 @@ export class ChatXAI extends OriginalChatXAI {
|
|
|
1168
1348
|
return this.client;
|
|
1169
1349
|
}
|
|
1170
1350
|
|
|
1171
|
-
|
|
1351
|
+
_getClientOptions(
|
|
1172
1352
|
options?: OpenAICoreRequestOptions
|
|
1173
1353
|
): OpenAICoreRequestOptions {
|
|
1174
1354
|
if (!(this.client as OpenAIClient | undefined)) {
|
|
@@ -1201,166 +1381,9 @@ export class ChatXAI extends OriginalChatXAI {
|
|
|
1201
1381
|
options: this['ParsedCallOptions'],
|
|
1202
1382
|
runManager?: CallbackManagerForLLMRun
|
|
1203
1383
|
): AsyncGenerator<ChatGenerationChunk> {
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
...this.invocationParams(options, {
|
|
1209
|
-
streaming: true,
|
|
1210
|
-
}),
|
|
1211
|
-
messages: messagesMapped,
|
|
1212
|
-
stream: true as const,
|
|
1213
|
-
};
|
|
1214
|
-
let defaultRole: OpenAIRoleEnum | undefined;
|
|
1215
|
-
|
|
1216
|
-
const streamIterable = await this.completionWithRetry(params, options);
|
|
1217
|
-
let usage: OpenAIClient.Completions.CompletionUsage | undefined;
|
|
1218
|
-
for await (const data of streamIterable) {
|
|
1219
|
-
const choice = data.choices[0] as
|
|
1220
|
-
| Partial<OpenAIClient.Chat.Completions.ChatCompletionChunk.Choice>
|
|
1221
|
-
| undefined;
|
|
1222
|
-
if (data.usage) {
|
|
1223
|
-
usage = data.usage;
|
|
1224
|
-
}
|
|
1225
|
-
if (!choice) {
|
|
1226
|
-
continue;
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
|
-
const { delta } = choice;
|
|
1230
|
-
if (!delta) {
|
|
1231
|
-
continue;
|
|
1232
|
-
}
|
|
1233
|
-
const chunk = this._convertOpenAIDeltaToBaseMessageChunk(
|
|
1234
|
-
delta,
|
|
1235
|
-
data,
|
|
1236
|
-
defaultRole
|
|
1237
|
-
);
|
|
1238
|
-
if (chunk.usage_metadata != null) {
|
|
1239
|
-
chunk.usage_metadata = {
|
|
1240
|
-
input_tokens:
|
|
1241
|
-
(chunk.usage_metadata as Partial<UsageMetadata>).input_tokens ?? 0,
|
|
1242
|
-
output_tokens:
|
|
1243
|
-
(chunk.usage_metadata as Partial<UsageMetadata>).output_tokens ?? 0,
|
|
1244
|
-
total_tokens:
|
|
1245
|
-
(chunk.usage_metadata as Partial<UsageMetadata>).total_tokens ?? 0,
|
|
1246
|
-
};
|
|
1247
|
-
}
|
|
1248
|
-
if ('reasoning_content' in delta) {
|
|
1249
|
-
chunk.additional_kwargs.reasoning_content = delta.reasoning_content;
|
|
1250
|
-
}
|
|
1251
|
-
defaultRole = delta.role ?? defaultRole;
|
|
1252
|
-
const newTokenIndices = {
|
|
1253
|
-
prompt: (options as OpenAIChatCallOptions).promptIndex ?? 0,
|
|
1254
|
-
completion: choice.index ?? 0,
|
|
1255
|
-
};
|
|
1256
|
-
if (typeof chunk.content !== 'string') {
|
|
1257
|
-
// eslint-disable-next-line no-console
|
|
1258
|
-
console.log(
|
|
1259
|
-
'[WARNING]: Received non-string content from OpenAI. This is currently not supported.'
|
|
1260
|
-
);
|
|
1261
|
-
continue;
|
|
1262
|
-
}
|
|
1263
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1264
|
-
const generationInfo: Record<string, any> = { ...newTokenIndices };
|
|
1265
|
-
if (choice.finish_reason != null) {
|
|
1266
|
-
generationInfo.finish_reason = choice.finish_reason;
|
|
1267
|
-
// Only include system fingerprint in the last chunk for now
|
|
1268
|
-
// to avoid concatenation issues
|
|
1269
|
-
generationInfo.system_fingerprint = data.system_fingerprint;
|
|
1270
|
-
generationInfo.model_name = data.model;
|
|
1271
|
-
generationInfo.service_tier = data.service_tier;
|
|
1272
|
-
}
|
|
1273
|
-
if (this.logprobs == true) {
|
|
1274
|
-
generationInfo.logprobs = choice.logprobs;
|
|
1275
|
-
}
|
|
1276
|
-
const generationChunk = new ChatGenerationChunk({
|
|
1277
|
-
message: chunk,
|
|
1278
|
-
text: chunk.content,
|
|
1279
|
-
generationInfo,
|
|
1280
|
-
});
|
|
1281
|
-
yield generationChunk;
|
|
1282
|
-
if (this._lc_stream_delay != null) {
|
|
1283
|
-
await sleep(this._lc_stream_delay);
|
|
1284
|
-
}
|
|
1285
|
-
await runManager?.handleLLMNewToken(
|
|
1286
|
-
generationChunk.text || '',
|
|
1287
|
-
newTokenIndices,
|
|
1288
|
-
undefined,
|
|
1289
|
-
undefined,
|
|
1290
|
-
undefined,
|
|
1291
|
-
{ chunk: generationChunk }
|
|
1292
|
-
);
|
|
1293
|
-
}
|
|
1294
|
-
if (usage) {
|
|
1295
|
-
// Type assertion for xAI-specific usage structure
|
|
1296
|
-
const xaiUsage = usage as XAIUsageMetadata;
|
|
1297
|
-
const inputTokenDetails = {
|
|
1298
|
-
// Standard OpenAI fields
|
|
1299
|
-
...(usage.prompt_tokens_details?.audio_tokens != null && {
|
|
1300
|
-
audio: usage.prompt_tokens_details.audio_tokens,
|
|
1301
|
-
}),
|
|
1302
|
-
...(usage.prompt_tokens_details?.cached_tokens != null && {
|
|
1303
|
-
cache_read: usage.prompt_tokens_details.cached_tokens,
|
|
1304
|
-
}),
|
|
1305
|
-
// Add xAI-specific prompt token details if they exist
|
|
1306
|
-
...(xaiUsage.prompt_tokens_details?.text_tokens != null && {
|
|
1307
|
-
text: xaiUsage.prompt_tokens_details.text_tokens,
|
|
1308
|
-
}),
|
|
1309
|
-
...(xaiUsage.prompt_tokens_details?.image_tokens != null && {
|
|
1310
|
-
image: xaiUsage.prompt_tokens_details.image_tokens,
|
|
1311
|
-
}),
|
|
1312
|
-
};
|
|
1313
|
-
const outputTokenDetails = {
|
|
1314
|
-
// Standard OpenAI fields
|
|
1315
|
-
...(usage.completion_tokens_details?.audio_tokens != null && {
|
|
1316
|
-
audio: usage.completion_tokens_details.audio_tokens,
|
|
1317
|
-
}),
|
|
1318
|
-
...(usage.completion_tokens_details?.reasoning_tokens != null && {
|
|
1319
|
-
reasoning: usage.completion_tokens_details.reasoning_tokens,
|
|
1320
|
-
}),
|
|
1321
|
-
// Add xAI-specific completion token details if they exist
|
|
1322
|
-
...(xaiUsage.completion_tokens_details?.accepted_prediction_tokens !=
|
|
1323
|
-
null && {
|
|
1324
|
-
accepted_prediction:
|
|
1325
|
-
xaiUsage.completion_tokens_details.accepted_prediction_tokens,
|
|
1326
|
-
}),
|
|
1327
|
-
...(xaiUsage.completion_tokens_details?.rejected_prediction_tokens !=
|
|
1328
|
-
null && {
|
|
1329
|
-
rejected_prediction:
|
|
1330
|
-
xaiUsage.completion_tokens_details.rejected_prediction_tokens,
|
|
1331
|
-
}),
|
|
1332
|
-
};
|
|
1333
|
-
const generationChunk = new ChatGenerationChunk({
|
|
1334
|
-
message: new AIMessageChunk({
|
|
1335
|
-
content: '',
|
|
1336
|
-
response_metadata: {
|
|
1337
|
-
usage: { ...usage },
|
|
1338
|
-
// Include xAI-specific metadata if it exists
|
|
1339
|
-
...(xaiUsage.num_sources_used != null && {
|
|
1340
|
-
num_sources_used: xaiUsage.num_sources_used,
|
|
1341
|
-
}),
|
|
1342
|
-
},
|
|
1343
|
-
usage_metadata: {
|
|
1344
|
-
input_tokens: usage.prompt_tokens,
|
|
1345
|
-
output_tokens: usage.completion_tokens,
|
|
1346
|
-
total_tokens: usage.total_tokens,
|
|
1347
|
-
...(Object.keys(inputTokenDetails).length > 0 && {
|
|
1348
|
-
input_token_details: inputTokenDetails,
|
|
1349
|
-
}),
|
|
1350
|
-
...(Object.keys(outputTokenDetails).length > 0 && {
|
|
1351
|
-
output_token_details: outputTokenDetails,
|
|
1352
|
-
}),
|
|
1353
|
-
},
|
|
1354
|
-
}),
|
|
1355
|
-
text: '',
|
|
1356
|
-
});
|
|
1357
|
-
yield generationChunk;
|
|
1358
|
-
if (this._lc_stream_delay != null) {
|
|
1359
|
-
await sleep(this._lc_stream_delay);
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
if (options.signal?.aborted === true) {
|
|
1363
|
-
throw new Error('AbortError');
|
|
1364
|
-
}
|
|
1384
|
+
yield* delayStreamChunks(
|
|
1385
|
+
super._streamResponseChunks(messages, options, runManager),
|
|
1386
|
+
this._lc_stream_delay
|
|
1387
|
+
);
|
|
1365
1388
|
}
|
|
1366
1389
|
}
|