@librechat/agents 2.4.55 → 2.4.56
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/llm/openai/index.cjs +106 -2
- package/dist/cjs/llm/openai/index.cjs.map +1 -1
- package/dist/cjs/llm/openai/utils/index.cjs +55 -0
- package/dist/cjs/llm/openai/utils/index.cjs.map +1 -1
- package/dist/esm/llm/openai/index.mjs +107 -3
- package/dist/esm/llm/openai/index.mjs.map +1 -1
- package/dist/esm/llm/openai/utils/index.mjs +56 -2
- package/dist/esm/llm/openai/utils/index.mjs.map +1 -1
- package/dist/types/llm/openai/index.d.ts +3 -2
- package/package.json +1 -1
- package/src/llm/openai/index.ts +145 -5
package/src/llm/openai/index.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { AzureOpenAI as AzureOpenAIClient } from 'openai';
|
|
2
|
+
import { AIMessageChunk } from '@langchain/core/messages';
|
|
2
3
|
import { ChatXAI as OriginalChatXAI } from '@langchain/xai';
|
|
3
|
-
import {
|
|
4
|
+
import { ChatGenerationChunk } from '@langchain/core/outputs';
|
|
4
5
|
import { ToolDefinition } from '@langchain/core/language_models/base';
|
|
6
|
+
import { isLangChainTool } from '@langchain/core/utils/function_calling';
|
|
7
|
+
import { ChatDeepSeek as OriginalChatDeepSeek } from '@langchain/deepseek';
|
|
8
|
+
import { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
|
|
5
9
|
import {
|
|
6
10
|
getEndpoint,
|
|
7
11
|
OpenAIClient,
|
|
@@ -9,19 +13,26 @@ import {
|
|
|
9
13
|
ChatOpenAI as OriginalChatOpenAI,
|
|
10
14
|
AzureChatOpenAI as OriginalAzureChatOpenAI,
|
|
11
15
|
} from '@langchain/openai';
|
|
12
|
-
import type { ChatGenerationChunk } from '@langchain/core/outputs';
|
|
13
|
-
import { isLangChainTool } from '@langchain/core/utils/function_calling';
|
|
14
|
-
import { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';
|
|
15
16
|
import type { BindToolsInput } from '@langchain/core/language_models/chat_models';
|
|
16
17
|
import type { OpenAIEndpointConfig } from '@langchain/openai/dist/utils/azure';
|
|
17
18
|
import type { BaseMessage } from '@langchain/core/messages';
|
|
18
19
|
import type * as t from '@langchain/openai';
|
|
19
20
|
import {
|
|
21
|
+
_convertMessagesToOpenAIParams,
|
|
20
22
|
_convertMessagesToOpenAIResponsesParams,
|
|
21
23
|
_convertOpenAIResponsesDeltaToBaseMessageChunk,
|
|
22
24
|
type ResponseReturnStreamEvents,
|
|
23
25
|
} from './utils';
|
|
24
26
|
|
|
27
|
+
// TODO import from SDK when available
|
|
28
|
+
type OpenAIRoleEnum =
|
|
29
|
+
| 'system'
|
|
30
|
+
| 'developer'
|
|
31
|
+
| 'assistant'
|
|
32
|
+
| 'user'
|
|
33
|
+
| 'function'
|
|
34
|
+
| 'tool';
|
|
35
|
+
|
|
25
36
|
type HeaderValue = string | undefined | null;
|
|
26
37
|
export type HeadersLike =
|
|
27
38
|
| Headers
|
|
@@ -78,6 +89,9 @@ export function normalizeHeaders(
|
|
|
78
89
|
return Object.fromEntries(output.entries());
|
|
79
90
|
}
|
|
80
91
|
|
|
92
|
+
type OpenAICompletionParam =
|
|
93
|
+
OpenAIClient.Chat.Completions.ChatCompletionMessageParam;
|
|
94
|
+
|
|
81
95
|
type OpenAICoreRequestOptions = OpenAIClient.RequestOptions;
|
|
82
96
|
|
|
83
97
|
function createAbortHandler(controller: AbortController): () => void {
|
|
@@ -229,7 +243,7 @@ export class ChatOpenAI extends OriginalChatOpenAI<t.ChatOpenAICallOptions> {
|
|
|
229
243
|
runManager?: CallbackManagerForLLMRun
|
|
230
244
|
): AsyncGenerator<ChatGenerationChunk> {
|
|
231
245
|
if (!this._useResponseApi(options)) {
|
|
232
|
-
return yield*
|
|
246
|
+
return yield* this._streamResponseChunks2(messages, options, runManager);
|
|
233
247
|
}
|
|
234
248
|
const streamIterable = await this.responseApiWithRetry(
|
|
235
249
|
{
|
|
@@ -262,6 +276,132 @@ export class ChatOpenAI extends OriginalChatOpenAI<t.ChatOpenAICallOptions> {
|
|
|
262
276
|
|
|
263
277
|
return;
|
|
264
278
|
}
|
|
279
|
+
|
|
280
|
+
async *_streamResponseChunks2(
|
|
281
|
+
messages: BaseMessage[],
|
|
282
|
+
options: this['ParsedCallOptions'],
|
|
283
|
+
runManager?: CallbackManagerForLLMRun
|
|
284
|
+
): AsyncGenerator<ChatGenerationChunk> {
|
|
285
|
+
const messagesMapped: OpenAICompletionParam[] =
|
|
286
|
+
_convertMessagesToOpenAIParams(messages, this.model);
|
|
287
|
+
|
|
288
|
+
const params = {
|
|
289
|
+
...this.invocationParams(options, {
|
|
290
|
+
streaming: true,
|
|
291
|
+
}),
|
|
292
|
+
messages: messagesMapped,
|
|
293
|
+
stream: true as const,
|
|
294
|
+
};
|
|
295
|
+
let defaultRole: OpenAIRoleEnum | undefined;
|
|
296
|
+
|
|
297
|
+
const streamIterable = await this.completionWithRetry(params, options);
|
|
298
|
+
let usage: OpenAIClient.Completions.CompletionUsage | undefined;
|
|
299
|
+
for await (const data of streamIterable) {
|
|
300
|
+
const choice = data.choices[0] as
|
|
301
|
+
| Partial<OpenAIClient.Chat.Completions.ChatCompletionChunk.Choice>
|
|
302
|
+
| undefined;
|
|
303
|
+
if (data.usage) {
|
|
304
|
+
usage = data.usage;
|
|
305
|
+
}
|
|
306
|
+
if (!choice) {
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const { delta } = choice;
|
|
311
|
+
if (!delta) {
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
const chunk = this._convertOpenAIDeltaToBaseMessageChunk(
|
|
315
|
+
delta,
|
|
316
|
+
data,
|
|
317
|
+
defaultRole
|
|
318
|
+
);
|
|
319
|
+
if ('reasoning_content' in delta) {
|
|
320
|
+
chunk.additional_kwargs.reasoning_content = delta.reasoning_content;
|
|
321
|
+
}
|
|
322
|
+
defaultRole = delta.role ?? defaultRole;
|
|
323
|
+
const newTokenIndices = {
|
|
324
|
+
prompt: options.promptIndex ?? 0,
|
|
325
|
+
completion: choice.index ?? 0,
|
|
326
|
+
};
|
|
327
|
+
if (typeof chunk.content !== 'string') {
|
|
328
|
+
// eslint-disable-next-line no-console
|
|
329
|
+
console.log(
|
|
330
|
+
'[WARNING]: Received non-string content from OpenAI. This is currently not supported.'
|
|
331
|
+
);
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
335
|
+
const generationInfo: Record<string, any> = { ...newTokenIndices };
|
|
336
|
+
if (choice.finish_reason != null) {
|
|
337
|
+
generationInfo.finish_reason = choice.finish_reason;
|
|
338
|
+
// Only include system fingerprint in the last chunk for now
|
|
339
|
+
// to avoid concatenation issues
|
|
340
|
+
generationInfo.system_fingerprint = data.system_fingerprint;
|
|
341
|
+
generationInfo.model_name = data.model;
|
|
342
|
+
generationInfo.service_tier = data.service_tier;
|
|
343
|
+
}
|
|
344
|
+
if (this.logprobs == true) {
|
|
345
|
+
generationInfo.logprobs = choice.logprobs;
|
|
346
|
+
}
|
|
347
|
+
const generationChunk = new ChatGenerationChunk({
|
|
348
|
+
message: chunk,
|
|
349
|
+
text: chunk.content,
|
|
350
|
+
generationInfo,
|
|
351
|
+
});
|
|
352
|
+
yield generationChunk;
|
|
353
|
+
await runManager?.handleLLMNewToken(
|
|
354
|
+
generationChunk.text || '',
|
|
355
|
+
newTokenIndices,
|
|
356
|
+
undefined,
|
|
357
|
+
undefined,
|
|
358
|
+
undefined,
|
|
359
|
+
{ chunk: generationChunk }
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
if (usage) {
|
|
363
|
+
const inputTokenDetails = {
|
|
364
|
+
...(usage.prompt_tokens_details?.audio_tokens != null && {
|
|
365
|
+
audio: usage.prompt_tokens_details.audio_tokens,
|
|
366
|
+
}),
|
|
367
|
+
...(usage.prompt_tokens_details?.cached_tokens != null && {
|
|
368
|
+
cache_read: usage.prompt_tokens_details.cached_tokens,
|
|
369
|
+
}),
|
|
370
|
+
};
|
|
371
|
+
const outputTokenDetails = {
|
|
372
|
+
...(usage.completion_tokens_details?.audio_tokens != null && {
|
|
373
|
+
audio: usage.completion_tokens_details.audio_tokens,
|
|
374
|
+
}),
|
|
375
|
+
...(usage.completion_tokens_details?.reasoning_tokens != null && {
|
|
376
|
+
reasoning: usage.completion_tokens_details.reasoning_tokens,
|
|
377
|
+
}),
|
|
378
|
+
};
|
|
379
|
+
const generationChunk = new ChatGenerationChunk({
|
|
380
|
+
message: new AIMessageChunk({
|
|
381
|
+
content: '',
|
|
382
|
+
response_metadata: {
|
|
383
|
+
usage: { ...usage },
|
|
384
|
+
},
|
|
385
|
+
usage_metadata: {
|
|
386
|
+
input_tokens: usage.prompt_tokens,
|
|
387
|
+
output_tokens: usage.completion_tokens,
|
|
388
|
+
total_tokens: usage.total_tokens,
|
|
389
|
+
...(Object.keys(inputTokenDetails).length > 0 && {
|
|
390
|
+
input_token_details: inputTokenDetails,
|
|
391
|
+
}),
|
|
392
|
+
...(Object.keys(outputTokenDetails).length > 0 && {
|
|
393
|
+
output_token_details: outputTokenDetails,
|
|
394
|
+
}),
|
|
395
|
+
},
|
|
396
|
+
}),
|
|
397
|
+
text: '',
|
|
398
|
+
});
|
|
399
|
+
yield generationChunk;
|
|
400
|
+
}
|
|
401
|
+
if (options.signal?.aborted === true) {
|
|
402
|
+
throw new Error('AbortError');
|
|
403
|
+
}
|
|
404
|
+
}
|
|
265
405
|
}
|
|
266
406
|
|
|
267
407
|
export class AzureChatOpenAI extends OriginalAzureChatOpenAI {
|