@chatluna/v1-shared-adapter 1.0.28 → 1.0.30
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/lib/index.cjs +106 -48
- package/lib/index.mjs +103 -46
- package/lib/requester.d.ts +0 -8
- package/lib/types.d.ts +19 -5
- package/lib/utils.d.ts +14 -3
- package/package.json +2 -2
package/lib/index.cjs
CHANGED
|
@@ -27,6 +27,7 @@ __export(index_exports, {
|
|
|
27
27
|
convertMessageToMessageChunk: () => convertMessageToMessageChunk,
|
|
28
28
|
createEmbeddings: () => createEmbeddings,
|
|
29
29
|
createRequestContext: () => createRequestContext,
|
|
30
|
+
createUsageMetadata: () => createUsageMetadata,
|
|
30
31
|
expandReasoningEffortModelVariants: () => expandReasoningEffortModelVariants,
|
|
31
32
|
fetchFileLikeUrl: () => fetchFileLikeUrl,
|
|
32
33
|
fetchImageUrl: () => fetchImageUrl,
|
|
@@ -39,9 +40,9 @@ __export(index_exports, {
|
|
|
39
40
|
langchainMessageToOpenAIMessage: () => langchainMessageToOpenAIMessage,
|
|
40
41
|
messageTypeToOpenAIRole: () => messageTypeToOpenAIRole,
|
|
41
42
|
normalizeOpenAIModelName: () => normalizeOpenAIModelName,
|
|
43
|
+
openAIUsageToUsageMetadata: () => openAIUsageToUsageMetadata,
|
|
42
44
|
parseOpenAIModelNameWithReasoningEffort: () => parseOpenAIModelNameWithReasoningEffort,
|
|
43
|
-
|
|
44
|
-
processReasoningContent: () => processReasoningContent,
|
|
45
|
+
processInterleavedThinkMessages: () => processInterleavedThinkMessages,
|
|
45
46
|
processResponse: () => processResponse,
|
|
46
47
|
processStreamResponse: () => processStreamResponse,
|
|
47
48
|
reasoningEffortModelSuffixes: () => reasoningEffortModelSuffixes,
|
|
@@ -164,6 +165,8 @@ var imageModelMatchers = [
|
|
|
164
165
|
"qwen*-omni",
|
|
165
166
|
"qwen-omni",
|
|
166
167
|
"qwen*-vl",
|
|
168
|
+
"qwen-3.5",
|
|
169
|
+
"qwen3.5",
|
|
167
170
|
"qvq",
|
|
168
171
|
"o1",
|
|
169
172
|
"o3",
|
|
@@ -191,10 +194,40 @@ var import_messages = require("@langchain/core/messages");
|
|
|
191
194
|
var import_zod_to_json_schema = require("zod-to-json-schema");
|
|
192
195
|
var import_string = require("koishi-plugin-chatluna/utils/string");
|
|
193
196
|
var import_types = require("@langchain/core/utils/types");
|
|
197
|
+
function createUsageMetadata(data) {
|
|
198
|
+
const inputTokenDetails = {
|
|
199
|
+
...data.inputAudioTokens != null ? { audio: data.inputAudioTokens } : {},
|
|
200
|
+
...data.cacheReadTokens != null ? { cache_read: data.cacheReadTokens } : {},
|
|
201
|
+
...data.cacheCreationTokens != null ? { cache_creation: data.cacheCreationTokens } : {}
|
|
202
|
+
};
|
|
203
|
+
const outputTokenDetails = {
|
|
204
|
+
...data.outputAudioTokens != null ? { audio: data.outputAudioTokens } : {},
|
|
205
|
+
...data.reasoningTokens != null ? { reasoning: data.reasoningTokens } : {}
|
|
206
|
+
};
|
|
207
|
+
return {
|
|
208
|
+
input_tokens: data.inputTokens,
|
|
209
|
+
output_tokens: data.outputTokens,
|
|
210
|
+
total_tokens: data.totalTokens,
|
|
211
|
+
...Object.keys(inputTokenDetails).length > 0 ? { input_token_details: inputTokenDetails } : {},
|
|
212
|
+
...Object.keys(outputTokenDetails).length > 0 ? { output_token_details: outputTokenDetails } : {}
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
__name(createUsageMetadata, "createUsageMetadata");
|
|
216
|
+
function openAIUsageToUsageMetadata(usage) {
|
|
217
|
+
return createUsageMetadata({
|
|
218
|
+
inputTokens: usage.prompt_tokens,
|
|
219
|
+
outputTokens: usage.completion_tokens,
|
|
220
|
+
totalTokens: usage.total_tokens,
|
|
221
|
+
inputAudioTokens: usage.prompt_tokens_details?.audio_tokens,
|
|
222
|
+
outputAudioTokens: usage.completion_tokens_details?.audio_tokens,
|
|
223
|
+
cacheReadTokens: usage.prompt_tokens_details?.cached_tokens,
|
|
224
|
+
reasoningTokens: usage.completion_tokens_details?.reasoning_tokens
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
__name(openAIUsageToUsageMetadata, "openAIUsageToUsageMetadata");
|
|
194
228
|
async function langchainMessageToOpenAIMessage(messages, plugin, model, supportImageInputType, removeSystemMessage) {
|
|
195
229
|
const result = [];
|
|
196
230
|
const normalizedModel = model ? normalizeOpenAIModelName(model) : model;
|
|
197
|
-
const isDeepseekThinkModel = normalizedModel?.includes("deepseek-reasoner");
|
|
198
231
|
for (const rawMessage of messages) {
|
|
199
232
|
const role = messageTypeToOpenAIRole(rawMessage.getType());
|
|
200
233
|
const msg = {
|
|
@@ -309,13 +342,10 @@ async function langchainMessageToOpenAIMessage(messages, plugin, model, supportI
|
|
|
309
342
|
if (removeSystemMessage) {
|
|
310
343
|
return transformSystemMessages(result);
|
|
311
344
|
}
|
|
312
|
-
|
|
313
|
-
return processDeepSeekThinkMessages(result, messages);
|
|
314
|
-
}
|
|
315
|
-
return result;
|
|
345
|
+
return processInterleavedThinkMessages(result, messages);
|
|
316
346
|
}
|
|
317
347
|
__name(langchainMessageToOpenAIMessage, "langchainMessageToOpenAIMessage");
|
|
318
|
-
function
|
|
348
|
+
function processInterleavedThinkMessages(convertedMessages, originalMessages) {
|
|
319
349
|
if (originalMessages.length === 0) {
|
|
320
350
|
return convertedMessages;
|
|
321
351
|
}
|
|
@@ -344,7 +374,7 @@ function processDeepSeekThinkMessages(convertedMessages, originalMessages) {
|
|
|
344
374
|
return message;
|
|
345
375
|
});
|
|
346
376
|
}
|
|
347
|
-
__name(
|
|
377
|
+
__name(processInterleavedThinkMessages, "processInterleavedThinkMessages");
|
|
348
378
|
function transformSystemMessages(messages) {
|
|
349
379
|
const mappedMessage = [];
|
|
350
380
|
for (let i = 0; i < messages.length; i++) {
|
|
@@ -537,8 +567,12 @@ function convertMessageToMessageChunk(message) {
|
|
|
537
567
|
const toolCallChunks = [];
|
|
538
568
|
if (Array.isArray(message.tool_calls)) {
|
|
539
569
|
for (const rawToolCall of message.tool_calls) {
|
|
570
|
+
let name = rawToolCall.function?.name;
|
|
571
|
+
if (name != null && name.length < 1) {
|
|
572
|
+
name = void 0;
|
|
573
|
+
}
|
|
540
574
|
toolCallChunks.push({
|
|
541
|
-
name
|
|
575
|
+
name,
|
|
542
576
|
args: rawToolCall.function?.arguments,
|
|
543
577
|
id: rawToolCall.id
|
|
544
578
|
});
|
|
@@ -577,10 +611,6 @@ function convertDeltaToMessageChunk(delta, defaultRole) {
|
|
|
577
611
|
additionalKwargs = {
|
|
578
612
|
function_call: delta.function_call
|
|
579
613
|
};
|
|
580
|
-
} else if (delta.tool_calls) {
|
|
581
|
-
additionalKwargs = {
|
|
582
|
-
tool_calls: delta.tool_calls
|
|
583
|
-
};
|
|
584
614
|
} else {
|
|
585
615
|
additionalKwargs = {};
|
|
586
616
|
}
|
|
@@ -593,12 +623,16 @@ function convertDeltaToMessageChunk(delta, defaultRole) {
|
|
|
593
623
|
const toolCallChunks = [];
|
|
594
624
|
if (Array.isArray(delta.tool_calls)) {
|
|
595
625
|
for (const rawToolCall of delta.tool_calls) {
|
|
596
|
-
|
|
626
|
+
const toolCall = {
|
|
597
627
|
name: rawToolCall.function?.name,
|
|
598
628
|
args: rawToolCall.function?.arguments,
|
|
599
629
|
id: rawToolCall.id,
|
|
600
630
|
index: rawToolCall.index
|
|
601
|
-
}
|
|
631
|
+
};
|
|
632
|
+
if (toolCall.name != null && toolCall.name.length < 1) {
|
|
633
|
+
delete toolCall.name;
|
|
634
|
+
}
|
|
635
|
+
toolCallChunks.push(toolCall);
|
|
602
636
|
}
|
|
603
637
|
}
|
|
604
638
|
return new import_messages.AIMessageChunk({
|
|
@@ -678,25 +712,14 @@ async function buildChatCompletionParams(params, plugin, enableGoogleSearch, sup
|
|
|
678
712
|
return (0, import_object.deepAssign)({}, base, params.overrideRequestParams ?? {});
|
|
679
713
|
}
|
|
680
714
|
__name(buildChatCompletionParams, "buildChatCompletionParams");
|
|
681
|
-
function processReasoningContent(delta, reasoningState) {
|
|
682
|
-
if (delta.reasoning_content) {
|
|
683
|
-
reasoningState.content += delta.reasoning_content;
|
|
684
|
-
if (reasoningState.time === 0) {
|
|
685
|
-
reasoningState.time = Date.now();
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
if ((delta.reasoning_content == null || delta.reasoning_content === "") && delta.content && delta.content.length > 0 && reasoningState.time > 0 && !reasoningState.isSet) {
|
|
689
|
-
const reasoningTime = Date.now() - reasoningState.time;
|
|
690
|
-
reasoningState.time = reasoningTime;
|
|
691
|
-
reasoningState.isSet = true;
|
|
692
|
-
return reasoningTime;
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
__name(processReasoningContent, "processReasoningContent");
|
|
696
715
|
async function* processStreamResponse(requestContext, iterator) {
|
|
697
716
|
let defaultRole = "assistant";
|
|
698
717
|
let errorCount = 0;
|
|
699
|
-
const reasoningState = {
|
|
718
|
+
const reasoningState = {
|
|
719
|
+
content: "",
|
|
720
|
+
startedAt: Date.now(),
|
|
721
|
+
endedAt: void 0
|
|
722
|
+
};
|
|
700
723
|
for await (const event of iterator) {
|
|
701
724
|
const chunk = event.data;
|
|
702
725
|
if (chunk === "[DONE]") break;
|
|
@@ -711,26 +734,38 @@ async function* processStreamResponse(requestContext, iterator) {
|
|
|
711
734
|
}
|
|
712
735
|
const choice = data.choices?.[0];
|
|
713
736
|
if (data.usage) {
|
|
737
|
+
const usageMetadata = openAIUsageToUsageMetadata(data.usage);
|
|
714
738
|
yield new import_outputs.ChatGenerationChunk({
|
|
739
|
+
generationInfo: {
|
|
740
|
+
usage_metadata: usageMetadata
|
|
741
|
+
},
|
|
715
742
|
message: new import_messages2.AIMessageChunk({
|
|
716
743
|
content: "",
|
|
717
|
-
|
|
718
|
-
tokenUsage: {
|
|
719
|
-
promptTokens: data.usage.prompt_tokens,
|
|
720
|
-
completionTokens: data.usage.completion_tokens,
|
|
721
|
-
totalTokens: data.usage.total_tokens
|
|
722
|
-
}
|
|
723
|
-
}
|
|
744
|
+
usage_metadata: usageMetadata
|
|
724
745
|
}),
|
|
725
746
|
text: ""
|
|
726
747
|
});
|
|
727
748
|
}
|
|
728
749
|
if (!choice) continue;
|
|
729
750
|
const { delta } = choice;
|
|
730
|
-
const
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
751
|
+
const hasResult = (delta.content?.length ?? 0) > 0 || (delta.tool_calls?.length ?? 0) > 0 || delta.function_call != null;
|
|
752
|
+
if (reasoningState.endedAt == null && hasResult) {
|
|
753
|
+
reasoningState.endedAt = Date.now();
|
|
754
|
+
}
|
|
755
|
+
if (reasoningState.endedAt == null && !hasResult && delta.reasoning_content) {
|
|
756
|
+
reasoningState.content += delta.reasoning_content;
|
|
757
|
+
}
|
|
758
|
+
const messageChunk = convertDeltaToMessageChunk(
|
|
759
|
+
{
|
|
760
|
+
...delta,
|
|
761
|
+
reasoning_content: void 0
|
|
762
|
+
},
|
|
763
|
+
defaultRole
|
|
764
|
+
);
|
|
765
|
+
const hasMessageChunk = (typeof messageChunk.content === "string" ? messageChunk.content.length > 0 : Array.isArray(messageChunk.content) && messageChunk.content.length > 0) || messageChunk instanceof import_messages2.AIMessageChunk && (messageChunk.tool_call_chunks?.length ?? 0) > 0 || messageChunk.additional_kwargs.function_call != null;
|
|
766
|
+
if (!hasMessageChunk) {
|
|
767
|
+
defaultRole = (delta.role?.length ?? 0) > 0 ? delta.role : defaultRole;
|
|
768
|
+
continue;
|
|
734
769
|
}
|
|
735
770
|
defaultRole = (delta.role?.length ?? 0) > 0 ? delta.role : defaultRole;
|
|
736
771
|
yield new import_outputs.ChatGenerationChunk({
|
|
@@ -738,6 +773,13 @@ async function* processStreamResponse(requestContext, iterator) {
|
|
|
738
773
|
text: messageChunk.content
|
|
739
774
|
});
|
|
740
775
|
} catch (e) {
|
|
776
|
+
if (chunk.includes("tool_calls") || chunk.includes("function_call") || chunk.includes("tool_call_id")) {
|
|
777
|
+
requestContext.modelRequester.logger.error(
|
|
778
|
+
"error with chunk",
|
|
779
|
+
chunk
|
|
780
|
+
);
|
|
781
|
+
throw new import_error.ChatLunaError(import_error.ChatLunaErrorCode.API_REQUEST_FAILED, e);
|
|
782
|
+
}
|
|
741
783
|
if (errorCount > 5) {
|
|
742
784
|
requestContext.modelRequester.logger.error(
|
|
743
785
|
"error with chunk",
|
|
@@ -749,8 +791,19 @@ async function* processStreamResponse(requestContext, iterator) {
|
|
|
749
791
|
}
|
|
750
792
|
}
|
|
751
793
|
if (reasoningState.content.length > 0) {
|
|
794
|
+
const reasoningTime = (reasoningState.endedAt ?? Date.now()) - reasoningState.startedAt;
|
|
795
|
+
yield new import_outputs.ChatGenerationChunk({
|
|
796
|
+
message: new import_messages2.AIMessageChunk({
|
|
797
|
+
content: "",
|
|
798
|
+
additional_kwargs: {
|
|
799
|
+
reasoning_content: reasoningState.content,
|
|
800
|
+
...reasoningTime != null ? { reasoning_time: reasoningTime } : {}
|
|
801
|
+
}
|
|
802
|
+
}),
|
|
803
|
+
text: ""
|
|
804
|
+
});
|
|
752
805
|
requestContext.modelRequester.logger.debug(
|
|
753
|
-
`
|
|
806
|
+
`Reasoning Content: ${reasoningState.content}. Thought for: ${(reasoningTime ?? 0) / 1e3}s`
|
|
754
807
|
);
|
|
755
808
|
}
|
|
756
809
|
}
|
|
@@ -785,11 +838,15 @@ async function processResponse(requestContext, response) {
|
|
|
785
838
|
);
|
|
786
839
|
}
|
|
787
840
|
const messageChunk = convertMessageToMessageChunk(choice.message);
|
|
841
|
+
const usageMetadata = data.usage ? openAIUsageToUsageMetadata(data.usage) : void 0;
|
|
842
|
+
if (messageChunk instanceof import_messages2.AIMessageChunk) {
|
|
843
|
+
messageChunk.usage_metadata = usageMetadata;
|
|
844
|
+
}
|
|
788
845
|
return new import_outputs.ChatGenerationChunk({
|
|
789
846
|
message: messageChunk,
|
|
790
847
|
text: (0, import_string2.getMessageContent)(messageChunk.content),
|
|
791
|
-
generationInfo: {
|
|
792
|
-
|
|
848
|
+
generationInfo: usageMetadata == null ? void 0 : {
|
|
849
|
+
usage_metadata: usageMetadata
|
|
793
850
|
}
|
|
794
851
|
});
|
|
795
852
|
} catch (e) {
|
|
@@ -957,6 +1014,7 @@ __name(createRequestContext, "createRequestContext");
|
|
|
957
1014
|
convertMessageToMessageChunk,
|
|
958
1015
|
createEmbeddings,
|
|
959
1016
|
createRequestContext,
|
|
1017
|
+
createUsageMetadata,
|
|
960
1018
|
expandReasoningEffortModelVariants,
|
|
961
1019
|
fetchFileLikeUrl,
|
|
962
1020
|
fetchImageUrl,
|
|
@@ -969,9 +1027,9 @@ __name(createRequestContext, "createRequestContext");
|
|
|
969
1027
|
langchainMessageToOpenAIMessage,
|
|
970
1028
|
messageTypeToOpenAIRole,
|
|
971
1029
|
normalizeOpenAIModelName,
|
|
1030
|
+
openAIUsageToUsageMetadata,
|
|
972
1031
|
parseOpenAIModelNameWithReasoningEffort,
|
|
973
|
-
|
|
974
|
-
processReasoningContent,
|
|
1032
|
+
processInterleavedThinkMessages,
|
|
975
1033
|
processResponse,
|
|
976
1034
|
processStreamResponse,
|
|
977
1035
|
reasoningEffortModelSuffixes,
|
package/lib/index.mjs
CHANGED
|
@@ -114,6 +114,8 @@ var imageModelMatchers = [
|
|
|
114
114
|
"qwen*-omni",
|
|
115
115
|
"qwen-omni",
|
|
116
116
|
"qwen*-vl",
|
|
117
|
+
"qwen-3.5",
|
|
118
|
+
"qwen3.5",
|
|
117
119
|
"qvq",
|
|
118
120
|
"o1",
|
|
119
121
|
"o3",
|
|
@@ -155,10 +157,40 @@ import {
|
|
|
155
157
|
isMessageContentImageUrl
|
|
156
158
|
} from "koishi-plugin-chatluna/utils/string";
|
|
157
159
|
import { isZodSchemaV3 } from "@langchain/core/utils/types";
|
|
160
|
+
function createUsageMetadata(data) {
|
|
161
|
+
const inputTokenDetails = {
|
|
162
|
+
...data.inputAudioTokens != null ? { audio: data.inputAudioTokens } : {},
|
|
163
|
+
...data.cacheReadTokens != null ? { cache_read: data.cacheReadTokens } : {},
|
|
164
|
+
...data.cacheCreationTokens != null ? { cache_creation: data.cacheCreationTokens } : {}
|
|
165
|
+
};
|
|
166
|
+
const outputTokenDetails = {
|
|
167
|
+
...data.outputAudioTokens != null ? { audio: data.outputAudioTokens } : {},
|
|
168
|
+
...data.reasoningTokens != null ? { reasoning: data.reasoningTokens } : {}
|
|
169
|
+
};
|
|
170
|
+
return {
|
|
171
|
+
input_tokens: data.inputTokens,
|
|
172
|
+
output_tokens: data.outputTokens,
|
|
173
|
+
total_tokens: data.totalTokens,
|
|
174
|
+
...Object.keys(inputTokenDetails).length > 0 ? { input_token_details: inputTokenDetails } : {},
|
|
175
|
+
...Object.keys(outputTokenDetails).length > 0 ? { output_token_details: outputTokenDetails } : {}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
__name(createUsageMetadata, "createUsageMetadata");
|
|
179
|
+
function openAIUsageToUsageMetadata(usage) {
|
|
180
|
+
return createUsageMetadata({
|
|
181
|
+
inputTokens: usage.prompt_tokens,
|
|
182
|
+
outputTokens: usage.completion_tokens,
|
|
183
|
+
totalTokens: usage.total_tokens,
|
|
184
|
+
inputAudioTokens: usage.prompt_tokens_details?.audio_tokens,
|
|
185
|
+
outputAudioTokens: usage.completion_tokens_details?.audio_tokens,
|
|
186
|
+
cacheReadTokens: usage.prompt_tokens_details?.cached_tokens,
|
|
187
|
+
reasoningTokens: usage.completion_tokens_details?.reasoning_tokens
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
__name(openAIUsageToUsageMetadata, "openAIUsageToUsageMetadata");
|
|
158
191
|
async function langchainMessageToOpenAIMessage(messages, plugin, model, supportImageInputType, removeSystemMessage) {
|
|
159
192
|
const result = [];
|
|
160
193
|
const normalizedModel = model ? normalizeOpenAIModelName(model) : model;
|
|
161
|
-
const isDeepseekThinkModel = normalizedModel?.includes("deepseek-reasoner");
|
|
162
194
|
for (const rawMessage of messages) {
|
|
163
195
|
const role = messageTypeToOpenAIRole(rawMessage.getType());
|
|
164
196
|
const msg = {
|
|
@@ -273,13 +305,10 @@ async function langchainMessageToOpenAIMessage(messages, plugin, model, supportI
|
|
|
273
305
|
if (removeSystemMessage) {
|
|
274
306
|
return transformSystemMessages(result);
|
|
275
307
|
}
|
|
276
|
-
|
|
277
|
-
return processDeepSeekThinkMessages(result, messages);
|
|
278
|
-
}
|
|
279
|
-
return result;
|
|
308
|
+
return processInterleavedThinkMessages(result, messages);
|
|
280
309
|
}
|
|
281
310
|
__name(langchainMessageToOpenAIMessage, "langchainMessageToOpenAIMessage");
|
|
282
|
-
function
|
|
311
|
+
function processInterleavedThinkMessages(convertedMessages, originalMessages) {
|
|
283
312
|
if (originalMessages.length === 0) {
|
|
284
313
|
return convertedMessages;
|
|
285
314
|
}
|
|
@@ -308,7 +337,7 @@ function processDeepSeekThinkMessages(convertedMessages, originalMessages) {
|
|
|
308
337
|
return message;
|
|
309
338
|
});
|
|
310
339
|
}
|
|
311
|
-
__name(
|
|
340
|
+
__name(processInterleavedThinkMessages, "processInterleavedThinkMessages");
|
|
312
341
|
function transformSystemMessages(messages) {
|
|
313
342
|
const mappedMessage = [];
|
|
314
343
|
for (let i = 0; i < messages.length; i++) {
|
|
@@ -501,8 +530,12 @@ function convertMessageToMessageChunk(message) {
|
|
|
501
530
|
const toolCallChunks = [];
|
|
502
531
|
if (Array.isArray(message.tool_calls)) {
|
|
503
532
|
for (const rawToolCall of message.tool_calls) {
|
|
533
|
+
let name = rawToolCall.function?.name;
|
|
534
|
+
if (name != null && name.length < 1) {
|
|
535
|
+
name = void 0;
|
|
536
|
+
}
|
|
504
537
|
toolCallChunks.push({
|
|
505
|
-
name
|
|
538
|
+
name,
|
|
506
539
|
args: rawToolCall.function?.arguments,
|
|
507
540
|
id: rawToolCall.id
|
|
508
541
|
});
|
|
@@ -541,10 +574,6 @@ function convertDeltaToMessageChunk(delta, defaultRole) {
|
|
|
541
574
|
additionalKwargs = {
|
|
542
575
|
function_call: delta.function_call
|
|
543
576
|
};
|
|
544
|
-
} else if (delta.tool_calls) {
|
|
545
|
-
additionalKwargs = {
|
|
546
|
-
tool_calls: delta.tool_calls
|
|
547
|
-
};
|
|
548
577
|
} else {
|
|
549
578
|
additionalKwargs = {};
|
|
550
579
|
}
|
|
@@ -557,12 +586,16 @@ function convertDeltaToMessageChunk(delta, defaultRole) {
|
|
|
557
586
|
const toolCallChunks = [];
|
|
558
587
|
if (Array.isArray(delta.tool_calls)) {
|
|
559
588
|
for (const rawToolCall of delta.tool_calls) {
|
|
560
|
-
|
|
589
|
+
const toolCall = {
|
|
561
590
|
name: rawToolCall.function?.name,
|
|
562
591
|
args: rawToolCall.function?.arguments,
|
|
563
592
|
id: rawToolCall.id,
|
|
564
593
|
index: rawToolCall.index
|
|
565
|
-
}
|
|
594
|
+
};
|
|
595
|
+
if (toolCall.name != null && toolCall.name.length < 1) {
|
|
596
|
+
delete toolCall.name;
|
|
597
|
+
}
|
|
598
|
+
toolCallChunks.push(toolCall);
|
|
566
599
|
}
|
|
567
600
|
}
|
|
568
601
|
return new AIMessageChunk({
|
|
@@ -642,25 +675,14 @@ async function buildChatCompletionParams(params, plugin, enableGoogleSearch, sup
|
|
|
642
675
|
return deepAssign({}, base, params.overrideRequestParams ?? {});
|
|
643
676
|
}
|
|
644
677
|
__name(buildChatCompletionParams, "buildChatCompletionParams");
|
|
645
|
-
function processReasoningContent(delta, reasoningState) {
|
|
646
|
-
if (delta.reasoning_content) {
|
|
647
|
-
reasoningState.content += delta.reasoning_content;
|
|
648
|
-
if (reasoningState.time === 0) {
|
|
649
|
-
reasoningState.time = Date.now();
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
if ((delta.reasoning_content == null || delta.reasoning_content === "") && delta.content && delta.content.length > 0 && reasoningState.time > 0 && !reasoningState.isSet) {
|
|
653
|
-
const reasoningTime = Date.now() - reasoningState.time;
|
|
654
|
-
reasoningState.time = reasoningTime;
|
|
655
|
-
reasoningState.isSet = true;
|
|
656
|
-
return reasoningTime;
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
__name(processReasoningContent, "processReasoningContent");
|
|
660
678
|
async function* processStreamResponse(requestContext, iterator) {
|
|
661
679
|
let defaultRole = "assistant";
|
|
662
680
|
let errorCount = 0;
|
|
663
|
-
const reasoningState = {
|
|
681
|
+
const reasoningState = {
|
|
682
|
+
content: "",
|
|
683
|
+
startedAt: Date.now(),
|
|
684
|
+
endedAt: void 0
|
|
685
|
+
};
|
|
664
686
|
for await (const event of iterator) {
|
|
665
687
|
const chunk = event.data;
|
|
666
688
|
if (chunk === "[DONE]") break;
|
|
@@ -675,26 +697,38 @@ async function* processStreamResponse(requestContext, iterator) {
|
|
|
675
697
|
}
|
|
676
698
|
const choice = data.choices?.[0];
|
|
677
699
|
if (data.usage) {
|
|
700
|
+
const usageMetadata = openAIUsageToUsageMetadata(data.usage);
|
|
678
701
|
yield new ChatGenerationChunk({
|
|
702
|
+
generationInfo: {
|
|
703
|
+
usage_metadata: usageMetadata
|
|
704
|
+
},
|
|
679
705
|
message: new AIMessageChunk2({
|
|
680
706
|
content: "",
|
|
681
|
-
|
|
682
|
-
tokenUsage: {
|
|
683
|
-
promptTokens: data.usage.prompt_tokens,
|
|
684
|
-
completionTokens: data.usage.completion_tokens,
|
|
685
|
-
totalTokens: data.usage.total_tokens
|
|
686
|
-
}
|
|
687
|
-
}
|
|
707
|
+
usage_metadata: usageMetadata
|
|
688
708
|
}),
|
|
689
709
|
text: ""
|
|
690
710
|
});
|
|
691
711
|
}
|
|
692
712
|
if (!choice) continue;
|
|
693
713
|
const { delta } = choice;
|
|
694
|
-
const
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
714
|
+
const hasResult = (delta.content?.length ?? 0) > 0 || (delta.tool_calls?.length ?? 0) > 0 || delta.function_call != null;
|
|
715
|
+
if (reasoningState.endedAt == null && hasResult) {
|
|
716
|
+
reasoningState.endedAt = Date.now();
|
|
717
|
+
}
|
|
718
|
+
if (reasoningState.endedAt == null && !hasResult && delta.reasoning_content) {
|
|
719
|
+
reasoningState.content += delta.reasoning_content;
|
|
720
|
+
}
|
|
721
|
+
const messageChunk = convertDeltaToMessageChunk(
|
|
722
|
+
{
|
|
723
|
+
...delta,
|
|
724
|
+
reasoning_content: void 0
|
|
725
|
+
},
|
|
726
|
+
defaultRole
|
|
727
|
+
);
|
|
728
|
+
const hasMessageChunk = (typeof messageChunk.content === "string" ? messageChunk.content.length > 0 : Array.isArray(messageChunk.content) && messageChunk.content.length > 0) || messageChunk instanceof AIMessageChunk2 && (messageChunk.tool_call_chunks?.length ?? 0) > 0 || messageChunk.additional_kwargs.function_call != null;
|
|
729
|
+
if (!hasMessageChunk) {
|
|
730
|
+
defaultRole = (delta.role?.length ?? 0) > 0 ? delta.role : defaultRole;
|
|
731
|
+
continue;
|
|
698
732
|
}
|
|
699
733
|
defaultRole = (delta.role?.length ?? 0) > 0 ? delta.role : defaultRole;
|
|
700
734
|
yield new ChatGenerationChunk({
|
|
@@ -702,6 +736,13 @@ async function* processStreamResponse(requestContext, iterator) {
|
|
|
702
736
|
text: messageChunk.content
|
|
703
737
|
});
|
|
704
738
|
} catch (e) {
|
|
739
|
+
if (chunk.includes("tool_calls") || chunk.includes("function_call") || chunk.includes("tool_call_id")) {
|
|
740
|
+
requestContext.modelRequester.logger.error(
|
|
741
|
+
"error with chunk",
|
|
742
|
+
chunk
|
|
743
|
+
);
|
|
744
|
+
throw new ChatLunaError(ChatLunaErrorCode.API_REQUEST_FAILED, e);
|
|
745
|
+
}
|
|
705
746
|
if (errorCount > 5) {
|
|
706
747
|
requestContext.modelRequester.logger.error(
|
|
707
748
|
"error with chunk",
|
|
@@ -713,8 +754,19 @@ async function* processStreamResponse(requestContext, iterator) {
|
|
|
713
754
|
}
|
|
714
755
|
}
|
|
715
756
|
if (reasoningState.content.length > 0) {
|
|
757
|
+
const reasoningTime = (reasoningState.endedAt ?? Date.now()) - reasoningState.startedAt;
|
|
758
|
+
yield new ChatGenerationChunk({
|
|
759
|
+
message: new AIMessageChunk2({
|
|
760
|
+
content: "",
|
|
761
|
+
additional_kwargs: {
|
|
762
|
+
reasoning_content: reasoningState.content,
|
|
763
|
+
...reasoningTime != null ? { reasoning_time: reasoningTime } : {}
|
|
764
|
+
}
|
|
765
|
+
}),
|
|
766
|
+
text: ""
|
|
767
|
+
});
|
|
716
768
|
requestContext.modelRequester.logger.debug(
|
|
717
|
-
`
|
|
769
|
+
`Reasoning Content: ${reasoningState.content}. Thought for: ${(reasoningTime ?? 0) / 1e3}s`
|
|
718
770
|
);
|
|
719
771
|
}
|
|
720
772
|
}
|
|
@@ -749,11 +801,15 @@ async function processResponse(requestContext, response) {
|
|
|
749
801
|
);
|
|
750
802
|
}
|
|
751
803
|
const messageChunk = convertMessageToMessageChunk(choice.message);
|
|
804
|
+
const usageMetadata = data.usage ? openAIUsageToUsageMetadata(data.usage) : void 0;
|
|
805
|
+
if (messageChunk instanceof AIMessageChunk2) {
|
|
806
|
+
messageChunk.usage_metadata = usageMetadata;
|
|
807
|
+
}
|
|
752
808
|
return new ChatGenerationChunk({
|
|
753
809
|
message: messageChunk,
|
|
754
810
|
text: getMessageContent(messageChunk.content),
|
|
755
|
-
generationInfo: {
|
|
756
|
-
|
|
811
|
+
generationInfo: usageMetadata == null ? void 0 : {
|
|
812
|
+
usage_metadata: usageMetadata
|
|
757
813
|
}
|
|
758
814
|
});
|
|
759
815
|
} catch (e) {
|
|
@@ -920,6 +976,7 @@ export {
|
|
|
920
976
|
convertMessageToMessageChunk,
|
|
921
977
|
createEmbeddings,
|
|
922
978
|
createRequestContext,
|
|
979
|
+
createUsageMetadata,
|
|
923
980
|
expandReasoningEffortModelVariants,
|
|
924
981
|
fetchFileLikeUrl,
|
|
925
982
|
fetchImageUrl,
|
|
@@ -932,9 +989,9 @@ export {
|
|
|
932
989
|
langchainMessageToOpenAIMessage,
|
|
933
990
|
messageTypeToOpenAIRole,
|
|
934
991
|
normalizeOpenAIModelName,
|
|
992
|
+
openAIUsageToUsageMetadata,
|
|
935
993
|
parseOpenAIModelNameWithReasoningEffort,
|
|
936
|
-
|
|
937
|
-
processReasoningContent,
|
|
994
|
+
processInterleavedThinkMessages,
|
|
938
995
|
processResponse,
|
|
939
996
|
processStreamResponse,
|
|
940
997
|
reasoningEffortModelSuffixes,
|
package/lib/requester.d.ts
CHANGED
|
@@ -37,14 +37,6 @@ export declare function buildChatCompletionParams(params: ModelRequestParams, pl
|
|
|
37
37
|
include_usage: boolean;
|
|
38
38
|
};
|
|
39
39
|
} & Record<string, any>>;
|
|
40
|
-
export declare function processReasoningContent(delta: {
|
|
41
|
-
reasoning_content?: string;
|
|
42
|
-
content?: string;
|
|
43
|
-
}, reasoningState: {
|
|
44
|
-
content: string;
|
|
45
|
-
time: number;
|
|
46
|
-
isSet: boolean;
|
|
47
|
-
}): number;
|
|
48
40
|
export declare function processStreamResponse<T extends ClientConfig, R extends ChatLunaPlugin.Config>(requestContext: RequestContext<T, R>, iterator: AsyncGenerator<SSEEvent, string, unknown>): AsyncGenerator<ChatGenerationChunk, void, unknown>;
|
|
49
41
|
export declare function processResponse<T extends ClientConfig, R extends ChatLunaPlugin.Config>(requestContext: RequestContext<T, R>, response: Response): Promise<ChatGenerationChunk>;
|
|
50
42
|
export declare function completionStream<T extends ClientConfig, R extends ChatLunaPlugin.Config>(requestContext: RequestContext<T, R>, params: ModelRequestParams, completionUrl?: string, enableGoogleSearch?: boolean, supportImageInput?: boolean): AsyncGenerator<ChatGenerationChunk>;
|
package/lib/types.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export interface ChatCompletionResponse {
|
|
|
7
7
|
role?: string;
|
|
8
8
|
reasoning_content?: string;
|
|
9
9
|
function_call?: ChatCompletionRequestMessageToolCall;
|
|
10
|
+
tool_calls?: ChatCompletionRequestMessageToolCall[];
|
|
10
11
|
};
|
|
11
12
|
message: ChatCompletionResponseMessage;
|
|
12
13
|
}[];
|
|
@@ -14,11 +15,24 @@ export interface ChatCompletionResponse {
|
|
|
14
15
|
object: string;
|
|
15
16
|
created: number;
|
|
16
17
|
model: string;
|
|
17
|
-
usage
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
usage?: ChatCompletionUsage;
|
|
19
|
+
}
|
|
20
|
+
export interface ChatCompletionPromptTokensDetails {
|
|
21
|
+
audio_tokens?: number;
|
|
22
|
+
cached_tokens?: number;
|
|
23
|
+
}
|
|
24
|
+
export interface ChatCompletionCompletionTokensDetails {
|
|
25
|
+
reasoning_tokens?: number;
|
|
26
|
+
audio_tokens?: number;
|
|
27
|
+
accepted_prediction_tokens?: number;
|
|
28
|
+
rejected_prediction_tokens?: number;
|
|
29
|
+
}
|
|
30
|
+
export interface ChatCompletionUsage {
|
|
31
|
+
prompt_tokens: number;
|
|
32
|
+
completion_tokens: number;
|
|
33
|
+
total_tokens: number;
|
|
34
|
+
prompt_tokens_details?: ChatCompletionPromptTokensDetails;
|
|
35
|
+
completion_tokens_details?: ChatCompletionCompletionTokensDetails;
|
|
22
36
|
}
|
|
23
37
|
export interface ChatCompletionTextPart {
|
|
24
38
|
type: 'text';
|
package/lib/utils.d.ts
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
|
-
import { AIMessageChunk, BaseMessage, ChatMessageChunk, FunctionMessageChunk, HumanMessageChunk, MessageContentComplex, MessageContentImageUrl, MessageType, SystemMessageChunk, ToolMessageChunk } from '@langchain/core/messages';
|
|
1
|
+
import { AIMessageChunk, BaseMessage, ChatMessageChunk, FunctionMessageChunk, HumanMessageChunk, MessageContentComplex, MessageContentImageUrl, MessageType, SystemMessageChunk, ToolMessageChunk, type UsageMetadata } from '@langchain/core/messages';
|
|
2
2
|
import { StructuredTool } from '@langchain/core/tools';
|
|
3
3
|
import { JsonSchema7Type } from 'zod-to-json-schema';
|
|
4
|
-
import { ChatCompletionResponseMessage, ChatCompletionResponseMessageRoleEnum, ChatCompletionTool } from './types';
|
|
4
|
+
import { ChatCompletionResponseMessage, ChatCompletionResponseMessageRoleEnum, ChatCompletionTool, ChatCompletionUsage } from './types';
|
|
5
5
|
import { ChatLunaPlugin } from 'koishi-plugin-chatluna/services/chat';
|
|
6
|
+
export declare function createUsageMetadata(data: {
|
|
7
|
+
inputTokens: number;
|
|
8
|
+
outputTokens: number;
|
|
9
|
+
totalTokens: number;
|
|
10
|
+
inputAudioTokens?: number;
|
|
11
|
+
outputAudioTokens?: number;
|
|
12
|
+
cacheReadTokens?: number;
|
|
13
|
+
cacheCreationTokens?: number;
|
|
14
|
+
reasoningTokens?: number;
|
|
15
|
+
}): UsageMetadata;
|
|
16
|
+
export declare function openAIUsageToUsageMetadata(usage: ChatCompletionUsage): UsageMetadata;
|
|
6
17
|
export declare function langchainMessageToOpenAIMessage(messages: BaseMessage[], plugin: ChatLunaPlugin, model?: string, supportImageInputType?: boolean, removeSystemMessage?: boolean): Promise<ChatCompletionResponseMessage[]>;
|
|
7
|
-
export declare function
|
|
18
|
+
export declare function processInterleavedThinkMessages(convertedMessages: ChatCompletionResponseMessage[], originalMessages: BaseMessage[]): ChatCompletionResponseMessage[];
|
|
8
19
|
export declare function transformSystemMessages(messages: ChatCompletionResponseMessage[]): ChatCompletionResponseMessage[];
|
|
9
20
|
export declare function fetchImageUrl(plugin: ChatLunaPlugin, content: MessageContentImageUrl): Promise<string>;
|
|
10
21
|
type MessageContentFileLike = MessageContentComplex & ({
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chatluna/v1-shared-adapter",
|
|
3
3
|
"description": "chatluna shared adapter",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.30",
|
|
5
5
|
"main": "lib/index.cjs",
|
|
6
6
|
"module": "lib/index.mjs",
|
|
7
7
|
"typings": "lib/index.d.ts",
|
|
@@ -70,6 +70,6 @@
|
|
|
70
70
|
},
|
|
71
71
|
"peerDependencies": {
|
|
72
72
|
"koishi": "^4.18.9",
|
|
73
|
-
"koishi-plugin-chatluna": "^1.3.
|
|
73
|
+
"koishi-plugin-chatluna": "^1.3.33"
|
|
74
74
|
}
|
|
75
75
|
}
|