Skip to content

Commit be8df5a

Browse files
authored
💄 style: Add cached token count to usage of GoogleAI and VertexAI (#8545)
1 parent b853a5c commit be8df5a

File tree

3 files changed

+56
-12
lines changed

3 files changed

+56
-12
lines changed

src/libs/model-runtime/utils/streams/google-ai.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,52 @@ describe('GoogleGenerativeAIStream', () => {
186186
]);
187187
});
188188

189+
it('should handle token count with cached token count', async () => {
190+
vi.spyOn(uuidModule, 'nanoid').mockReturnValueOnce('1');
191+
192+
const data = {
193+
candidates: [{ content: { role: 'model' }, finishReason: 'STOP', index: 0 }],
194+
usageMetadata: {
195+
promptTokenCount: 15725,
196+
candidatesTokenCount: 1053,
197+
totalTokenCount: 16778,
198+
cachedContentTokenCount: 14286,
199+
promptTokensDetails: [{ modality: 'TEXT', tokenCount: 15725 }],
200+
cacheTokensDetails: [{ modality: 'TEXT', tokenCount: 14286 }],
201+
},
202+
modelVersion: 'gemini-2.0-flash-exp',
203+
};
204+
205+
const mockGoogleStream = new ReadableStream({
206+
start(controller) {
207+
controller.enqueue(data);
208+
209+
controller.close();
210+
},
211+
});
212+
213+
const protocolStream = GoogleGenerativeAIStream(mockGoogleStream);
214+
215+
const decoder = new TextDecoder();
216+
const chunks = [];
217+
218+
// @ts-ignore
219+
for await (const chunk of protocolStream) {
220+
chunks.push(decoder.decode(chunk, { stream: true }));
221+
}
222+
223+
expect(chunks).toEqual([
224+
// stop
225+
'id: chat_1\n',
226+
'event: stop\n',
227+
`data: "STOP"\n\n`,
228+
// usage
229+
'id: chat_1\n',
230+
'event: usage\n',
231+
`data: {"inputCachedTokens":14286,"inputTextTokens":15725,"outputTextTokens":1053,"totalInputTokens":15725,"totalOutputTokens":1053,"totalTokens":16778}\n\n`,
232+
]);
233+
});
234+
189235
it('should handle stop with content', async () => {
190236
vi.spyOn(uuidModule, 'nanoid').mockReturnValueOnce('1');
191237

src/libs/model-runtime/utils/streams/google-ai.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ const transformGoogleGenerativeAIStream = (
3333
{ data: candidate.finishReason, id: context?.id, type: 'stop' },
3434
{
3535
data: {
36-
// TODO: Google SDK 0.24.0 don't have promptTokensDetails types
37-
inputImageTokens: usage.promptTokensDetails?.find((i: any) => i.modality === 'IMAGE')
36+
inputCachedTokens: usage.cachedContentTokenCount,
37+
inputImageTokens: usage.promptTokensDetails?.find((i) => i.modality === 'IMAGE')
3838
?.tokenCount,
39-
inputTextTokens: usage.promptTokensDetails?.find((i: any) => i.modality === 'TEXT')
39+
inputTextTokens: usage.promptTokensDetails?.find((i) => i.modality === 'TEXT')
4040
?.tokenCount,
4141
outputReasoningTokens: reasoningTokens,
4242
outputTextTokens,
@@ -79,7 +79,7 @@ const transformGoogleGenerativeAIStream = (
7979
// 首先检查是否为 reasoning 内容 (thought: true)
8080
if (Array.isArray(candidate.content?.parts) && candidate.content.parts.length > 0) {
8181
for (const part of candidate.content.parts) {
82-
if (part && part.text && (part as any).thought === true) {
82+
if (part && part.text && part.thought === true) {
8383
return { data: part.text, id: context.id, type: 'reasoning' };
8484
}
8585
}

src/libs/model-runtime/utils/streams/vertex-ai.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,11 @@ const transformVertexAIStream = (
3131
{ data: candidate.finishReason, id: context?.id, type: 'stop' },
3232
{
3333
data: {
34-
// TODO: Google SDK 0.24.0 don't have promptTokensDetails types
35-
inputImageTokens: (usage as any).promptTokensDetails?.find(
36-
(i: any) => i.modality === 'IMAGE',
37-
)?.tokenCount,
38-
inputTextTokens: (usage as any).promptTokensDetails?.find(
39-
(i: any) => i.modality === 'TEXT',
40-
)?.tokenCount,
34+
inputCachedTokens: usage.cachedContentTokenCount,
35+
inputImageTokens: usage.promptTokensDetails?.find((i) => i.modality === 'IMAGE')
36+
?.tokenCount,
37+
inputTextTokens: usage.promptTokensDetails?.find((i) => i.modality === 'TEXT')
38+
?.tokenCount,
4139
outputReasoningTokens,
4240
outputTextTokens,
4341
totalInputTokens: usage.promptTokenCount,
@@ -56,7 +54,7 @@ const transformVertexAIStream = (
5654
candidate.content.parts.length > 0
5755
) {
5856
for (const part of candidate.content.parts) {
59-
if (part && part.text && (part as any).thought === true) {
57+
if (part && part.text && part.thought === true) {
6058
return { data: part.text, id: context.id, type: 'reasoning' };
6159
}
6260
}

0 commit comments

Comments
 (0)