UNPKG

@genkit-ai/google-cloud

Version:

Genkit AI framework plugin for Google Cloud Platform including Firestore trace/state store and deployment helpers for Cloud Functions for Firebase.

1 lines 19.4 kB
{"version":3,"sources":["../../src/telemetry/generate.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ValueType } from '@opentelemetry/api';\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-base';\nimport { createHash } from 'crypto';\nimport {\n GENKIT_VERSION,\n type GenerateRequestData,\n type GenerateResponseData,\n type GenerationUsage,\n type MediaPart,\n type Part,\n type ToolRequestPart,\n type ToolResponsePart,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { toDisplayPath } from 'genkit/tracing';\nimport {\n MetricCounter,\n MetricHistogram,\n internalMetricNamespaceWrap,\n type Telemetry,\n} from '../metrics.js';\nimport {\n createCommonLogAttributes,\n extractErrorName,\n extractOuterFeatureNameFromPath,\n truncate,\n truncatePath,\n} from '../utils.js';\n\ntype SharedDimensions = {\n modelName?: string;\n featureName?: string;\n path?: string;\n status?: string;\n source?: string;\n sourceVersion?: string;\n};\n\nclass GenerateTelemetry implements Telemetry {\n /**\n * Wraps the declared metrics in a Genkit-specific, internal namespace.\n */\n private _N = internalMetricNamespaceWrap.bind(null, 'ai');\n\n private actionCounter = new MetricCounter(this._N('generate/requests'), {\n description: 'Counts calls to genkit generate actions.',\n valueType: ValueType.INT,\n });\n\n private latencies = new MetricHistogram(this._N('generate/latency'), {\n description: 'Latencies when interacting with a Genkit model.',\n valueType: ValueType.DOUBLE,\n unit: 'ms',\n });\n\n private inputCharacters = new MetricCounter(\n this._N('generate/input/characters'),\n {\n description: 'Counts input characters to any Genkit model.',\n valueType: ValueType.INT,\n }\n );\n\n private inputTokens = new MetricCounter(this._N('generate/input/tokens'), {\n description: 'Counts input tokens to a Genkit model.',\n valueType: ValueType.INT,\n });\n\n private inputImages = new MetricCounter(this._N('generate/input/images'), {\n description: 'Counts input images to a Genkit model.',\n valueType: ValueType.INT,\n });\n\n private outputCharacters = new MetricCounter(\n this._N('generate/output/characters'),\n {\n description: 'Counts output characters from a Genkit model.',\n valueType: ValueType.INT,\n }\n );\n\n private outputTokens = new MetricCounter(this._N('generate/output/tokens'), {\n description: 'Counts output tokens from a Genkit model.',\n valueType: ValueType.INT,\n });\n\n private thinkingTokens = new MetricCounter(\n this._N('generate/thinking/tokens'),\n {\n description: 'Counts thinking tokens from a Genkit model.',\n valueType: ValueType.INT,\n }\n );\n\n private outputImages = new MetricCounter(this._N('generate/output/images'), {\n description: 'Count output images from a Genkit model.',\n valueType: ValueType.INT,\n });\n\n tick(\n span: ReadableSpan,\n logInputAndOutput: boolean,\n projectId?: string\n ): void {\n const attributes = span.attributes;\n const modelName = truncate(attributes['genkit:name'] as string, 1024);\n const path = (attributes['genkit:path'] as string) || '';\n const input =\n 'genkit:input' in attributes\n ? (JSON.parse(\n attributes['genkit:input']! as string\n ) as GenerateRequestData)\n : undefined;\n const output =\n 'genkit:output' in attributes\n ? (JSON.parse(\n attributes['genkit:output']! as string\n ) as GenerateResponseData)\n : undefined;\n\n const errName = extractErrorName(span.events);\n let featureName = truncate(\n (attributes['genkit:metadata:flow:name'] ||\n extractOuterFeatureNameFromPath(path)) as string\n );\n if (!featureName || featureName === '<unknown>') {\n featureName = 'generate';\n }\n\n const sessionId = attributes['genkit:sessionId'] as string;\n const threadName = attributes['genkit:threadName'] as string;\n\n if (input) {\n this.recordGenerateActionMetrics(modelName, featureName, path, {\n response: output,\n errName,\n });\n this.recordGenerateActionConfigLogs(\n span,\n modelName,\n featureName,\n path,\n input,\n projectId,\n sessionId,\n threadName\n );\n\n if (logInputAndOutput) {\n this.recordGenerateActionInputLogs(\n span,\n modelName,\n featureName,\n path,\n input,\n projectId,\n sessionId,\n threadName\n );\n }\n }\n\n if (output && logInputAndOutput) {\n this.recordGenerateActionOutputLogs(\n span,\n modelName,\n featureName,\n path,\n output,\n projectId,\n sessionId,\n threadName\n );\n }\n }\n\n private recordGenerateActionMetrics(\n modelName: string,\n featureName: string,\n path: string,\n opts: {\n response?: GenerateResponseData;\n errName?: string;\n }\n ) {\n this.doRecordGenerateActionMetrics(modelName, opts.response?.usage || {}, {\n featureName,\n path,\n latencyMs: opts.response?.latencyMs,\n errName: opts.errName,\n source: 'ts',\n sourceVersion: GENKIT_VERSION,\n });\n }\n\n private recordGenerateActionConfigLogs(\n span: ReadableSpan,\n model: string,\n featureName: string,\n qualifiedPath: string,\n input: GenerateRequestData,\n projectId?: string,\n sessionId?: string,\n threadName?: string\n ) {\n const path = truncatePath(toDisplayPath(qualifiedPath));\n const sharedMetadata = {\n ...createCommonLogAttributes(span, projectId),\n model,\n path,\n qualifiedPath,\n featureName,\n sessionId,\n threadName,\n };\n logger.logStructured(`Config[${path}, ${model}]`, {\n ...sharedMetadata,\n maxOutputTokens: input.config?.maxOutputTokens,\n stopSequences: input.config?.stopSequences, // array\n source: 'ts',\n sourceVersion: GENKIT_VERSION,\n });\n }\n\n private recordGenerateActionInputLogs(\n span: ReadableSpan,\n model: string,\n featureName: string,\n qualifiedPath: string,\n input: GenerateRequestData,\n projectId?: string,\n sessionId?: string,\n threadName?: string\n ) {\n const path = truncatePath(toDisplayPath(qualifiedPath));\n const sharedMetadata = {\n ...createCommonLogAttributes(span, projectId),\n model,\n path,\n qualifiedPath,\n featureName,\n sessionId,\n threadName,\n };\n\n const messages = input.messages.length;\n input.messages.forEach((msg, msgIdx) => {\n const parts = msg.content.length;\n msg.content.forEach((part, partIdx) => {\n const partCounts = this.toPartCounts(partIdx, parts, msgIdx, messages);\n logger.logStructured(`Input[${path}, ${model}] ${partCounts}`, {\n ...sharedMetadata,\n content: this.toPartLogContent(part),\n role: msg.role,\n partIndex: partIdx,\n totalParts: parts,\n messageIndex: msgIdx,\n totalMessages: messages,\n });\n });\n });\n }\n\n private recordGenerateActionOutputLogs(\n span: ReadableSpan,\n model: string,\n featureName: string,\n qualifiedPath: string,\n output: GenerateResponseData,\n projectId?: string,\n sessionId?: string,\n threadName?: string\n ) {\n const path = truncatePath(toDisplayPath(qualifiedPath));\n const sharedMetadata = {\n ...createCommonLogAttributes(span, projectId),\n model,\n path,\n qualifiedPath,\n featureName,\n sessionId,\n threadName,\n };\n const message = output.message || output.candidates?.[0]?.message!;\n\n if (message?.content) {\n const parts = message.content.length;\n message.content.forEach((part, partIdx) => {\n const partCounts = this.toPartCounts(partIdx, parts, 0, 1);\n const initial = output.finishMessage\n ? { finishMessage: truncate(output.finishMessage) }\n : {};\n logger.logStructured(`Output[${path}, ${model}] ${partCounts}`, {\n ...initial,\n ...sharedMetadata,\n content: this.toPartLogContent(part),\n role: message.role,\n partIndex: partIdx,\n totalParts: parts,\n candidateIndex: 0,\n totalCandidates: 1,\n messageIndex: 0,\n finishReason: output.finishReason,\n });\n });\n }\n }\n\n private toPartCounts(\n partOrdinal: number,\n parts: number,\n msgOrdinal: number,\n messages: number\n ): string {\n if (parts > 1 && messages > 1) {\n return `(part ${this.xOfY(partOrdinal, parts)} in message ${this.xOfY(\n msgOrdinal,\n messages\n )})`;\n }\n if (parts > 1) {\n return `(part ${this.xOfY(partOrdinal, parts)})`;\n }\n if (messages > 1) {\n return `(message ${this.xOfY(msgOrdinal, messages)})`;\n }\n return '';\n }\n\n private xOfY(x: number, y: number): string {\n return `${x + 1} of ${y}`;\n }\n\n private toPartLogContent(part: Part): string {\n if (part.text) {\n return truncate(part.text);\n }\n if (part.data) {\n return truncate(JSON.stringify(part.data));\n }\n if (part.media) {\n return this.toPartLogMedia(part);\n }\n if (part.toolRequest) {\n return this.toPartLogToolRequest(part);\n }\n if (part.toolResponse) {\n return this.toPartLogToolResponse(part);\n }\n if (part.custom) {\n return truncate(JSON.stringify(part.custom));\n }\n return '<unknown format>';\n }\n\n private toPartLogMedia(part: MediaPart): string {\n if (part.media.url.startsWith('data:')) {\n const splitIdx = part.media.url.indexOf('base64,');\n if (splitIdx < 0) {\n return '<unknown media format>';\n }\n const prefix = part.media.url.substring(0, splitIdx + 7);\n const hashedContent = createHash('sha256')\n .update(part.media.url.substring(splitIdx + 7))\n .digest('hex');\n return `${prefix}<sha256(${hashedContent})>`;\n }\n return truncate(part.media.url);\n }\n\n private toPartLogToolRequest(part: ToolRequestPart): string {\n const inputText =\n typeof part.toolRequest.input === 'string'\n ? part.toolRequest.input\n : JSON.stringify(part.toolRequest.input);\n return truncate(\n `Tool request: ${part.toolRequest.name}, ref: ${part.toolRequest.ref}, input: ${inputText}`\n );\n }\n\n private toPartLogToolResponse(part: ToolResponsePart): string {\n const outputText =\n typeof part.toolResponse.output === 'string'\n ? part.toolResponse.output\n : JSON.stringify(part.toolResponse.output);\n return truncate(\n `Tool response: ${part.toolResponse.name}, ref: ${part.toolResponse.ref}, output: ${outputText}`\n );\n }\n\n /**\n * Records all metrics associated with performing a GenerateAction.\n */\n private doRecordGenerateActionMetrics(\n modelName: string,\n usage: GenerationUsage,\n dimensions: {\n featureName?: string;\n path?: string;\n latencyMs?: number;\n errName?: string;\n source?: string;\n sourceVersion: string;\n }\n ) {\n const shared: SharedDimensions = {\n modelName: modelName,\n featureName: dimensions.featureName,\n path: dimensions.path,\n source: dimensions.source,\n sourceVersion: dimensions.sourceVersion,\n status: dimensions.errName ? 'failure' : 'success',\n };\n\n this.actionCounter.add(1, {\n error: dimensions.errName,\n ...shared,\n });\n\n this.latencies.record(dimensions.latencyMs, shared);\n\n // inputs\n this.inputTokens.add(usage.inputTokens, shared);\n this.inputCharacters.add(usage.inputCharacters, shared);\n this.inputImages.add(usage.inputImages, shared);\n\n // outputs\n this.outputTokens.add(usage.outputTokens, shared);\n this.outputCharacters.add(usage.outputCharacters, shared);\n this.outputImages.add(usage.outputImages, shared);\n\n // thoughts\n this.thinkingTokens.add(usage.thoughtsTokens, shared);\n }\n}\n\nconst generateTelemetry = new GenerateTelemetry();\nexport { generateTelemetry };\n"],"mappings":"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","names":[]}