Skip to content

Commit a1a53a5

Browse files
committed
token counts
1 parent df4ba73 commit a1a53a5

4 files changed

Lines changed: 32 additions & 10 deletions

File tree

dev-packages/node-integration-tests/suites/tracing/google-genai/scenario-embeddings.mjs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ function startMockGoogleGenAIServer() {
66
const app = express();
77
app.use(express.json());
88

9-
app.post('/v1beta/models/:model\\:embedContent', (req, res) => {
9+
app.post('/v1beta/models/:model\\:batchEmbedContents', (req, res) => {
1010
const model = req.params.model;
1111

1212
if (model === 'error-model') {
@@ -18,14 +18,11 @@ function startMockGoogleGenAIServer() {
1818
embeddings: [
1919
{
2020
values: [0.1, 0.2, 0.3, 0.4, 0.5],
21-
statistics: {
22-
tokenCount: 8,
23-
truncated: false,
24-
},
2521
},
2622
],
27-
metadata: {
28-
billableCharacterCount: 30,
23+
usageMetadata: {
24+
promptTokenCount: 8,
25+
totalTokenCount: 8,
2926
},
3027
});
3128
});

packages/core/src/tracing/google-genai/embeddings.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,27 @@ export function addEmbeddingsRequestAttributes(span: Span, params: Record<string
3838

3939
/**
4040
* Add response attributes from the Google GenAI embedContent response.
41-
* The EmbedContentResponse has no usageMetadata/candidates/modelVersion.
42-
* Token counts come from embeddings[].statistics.tokenCount.
41+
* Token counts come from usageMetadata (Gemini API) or embeddings[].statistics.tokenCount (Vertex AI).
4342
* @see https://ai.google.dev/api/embeddings#EmbedContentResponse
4443
*/
4544
export function addEmbedContentResponseAttributes(span: Span, response: unknown): void {
4645
if (!response || typeof response !== 'object') return;
4746

4847
const embedResponse = response as GoogleGenAIEmbedContentResponse;
4948

49+
// Try usageMetadata first (same shape as GenerateContentResponse)
50+
if (embedResponse.usageMetadata && typeof embedResponse.usageMetadata === 'object') {
51+
const usage = embedResponse.usageMetadata;
52+
if (typeof usage.promptTokenCount === 'number') {
53+
span.setAttribute(GEN_AI_USAGE_INPUT_TOKENS_ATTRIBUTE, usage.promptTokenCount);
54+
}
55+
if (typeof usage.totalTokenCount === 'number') {
56+
span.setAttribute(GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE, usage.totalTokenCount);
57+
}
58+
return;
59+
}
60+
61+
// Fallback: sum token counts from individual embedding statistics (Vertex AI)
5062
if (Array.isArray(embedResponse.embeddings)) {
5163
let totalTokenCount = 0;
5264
for (const embedding of embedResponse.embeddings) {

packages/core/src/tracing/google-genai/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,13 @@ import { buildMethodPath, extractSystemInstructions, getFinalOperationName, getS
3131
import { CHAT_PATH, CHATS_CREATE_METHOD, GOOGLE_GENAI_SYSTEM_NAME } from './constants';
3232
import { addEmbedContentResponseAttributes, addEmbeddingsRequestAttributes } from './embeddings';
3333
import { instrumentStream } from './streaming';
34-
import type { Candidate, ContentPart, GoogleGenAIIstrumentedMethod, GoogleGenAIOptions, GoogleGenAIResponse } from './types';
34+
import type {
35+
Candidate,
36+
ContentPart,
37+
GoogleGenAIIstrumentedMethod,
38+
GoogleGenAIOptions,
39+
GoogleGenAIResponse,
40+
} from './types';
3541
import type { ContentListUnion, ContentUnion, Message, PartListUnion } from './utils';
3642
import { contentUnionToMessages, isEmbeddingsMethod, isStreamingMethod, shouldInstrument } from './utils';
3743

packages/core/src/tracing/google-genai/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,13 @@ export type GoogleGenAIEmbedContentResponse = {
210210
/** Billable character count. */
211211
billableCharacterCount?: number;
212212
};
213+
/** Usage metadata (same shape as GenerateContentResponse). */
214+
usageMetadata?: {
215+
/** Number of tokens in the request. */
216+
promptTokenCount?: number;
217+
/** Total token count. */
218+
totalTokenCount?: number;
219+
};
213220
};
214221

215222
// Export the response type for use in instrumentation

0 commit comments

Comments
 (0)