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.

326 lines 11.6 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var generate_exports = {}; __export(generate_exports, { generateTelemetry: () => generateTelemetry }); module.exports = __toCommonJS(generate_exports); var import_api = require("@opentelemetry/api"); var import_crypto = require("crypto"); var import_genkit = require("genkit"); var import_logging = require("genkit/logging"); var import_tracing = require("genkit/tracing"); var import_metrics = require("../metrics.js"); var import_utils = require("../utils.js"); class GenerateTelemetry { /** * Wraps the declared metrics in a Genkit-specific, internal namespace. */ _N = import_metrics.internalMetricNamespaceWrap.bind(null, "ai"); actionCounter = new import_metrics.MetricCounter(this._N("generate/requests"), { description: "Counts calls to genkit generate actions.", valueType: import_api.ValueType.INT }); latencies = new import_metrics.MetricHistogram(this._N("generate/latency"), { description: "Latencies when interacting with a Genkit model.", valueType: import_api.ValueType.DOUBLE, unit: "ms" }); inputCharacters = new import_metrics.MetricCounter( this._N("generate/input/characters"), { description: "Counts input characters to any Genkit model.", valueType: import_api.ValueType.INT } ); inputTokens = new import_metrics.MetricCounter(this._N("generate/input/tokens"), { description: "Counts input tokens to a Genkit model.", valueType: import_api.ValueType.INT }); inputImages = new import_metrics.MetricCounter(this._N("generate/input/images"), { description: "Counts input images to a Genkit model.", valueType: import_api.ValueType.INT }); outputCharacters = new import_metrics.MetricCounter( this._N("generate/output/characters"), { description: "Counts output characters from a Genkit model.", valueType: import_api.ValueType.INT } ); outputTokens = new import_metrics.MetricCounter(this._N("generate/output/tokens"), { description: "Counts output tokens from a Genkit model.", valueType: import_api.ValueType.INT }); thinkingTokens = new import_metrics.MetricCounter( this._N("generate/thinking/tokens"), { description: "Counts thinking tokens from a Genkit model.", valueType: import_api.ValueType.INT } ); outputImages = new import_metrics.MetricCounter(this._N("generate/output/images"), { description: "Count output images from a Genkit model.", valueType: import_api.ValueType.INT }); tick(span, logInputAndOutput, projectId) { const attributes = span.attributes; const modelName = (0, import_utils.truncate)(attributes["genkit:name"], 1024); const path = attributes["genkit:path"] || ""; const input = "genkit:input" in attributes ? JSON.parse( attributes["genkit:input"] ) : void 0; const output = "genkit:output" in attributes ? JSON.parse( attributes["genkit:output"] ) : void 0; const errName = (0, import_utils.extractErrorName)(span.events); let featureName = (0, import_utils.truncate)( attributes["genkit:metadata:flow:name"] || (0, import_utils.extractOuterFeatureNameFromPath)(path) ); if (!featureName || featureName === "<unknown>") { featureName = "generate"; } const sessionId = attributes["genkit:sessionId"]; const threadName = attributes["genkit:threadName"]; if (input) { this.recordGenerateActionMetrics(modelName, featureName, path, { response: output, errName }); this.recordGenerateActionConfigLogs( span, modelName, featureName, path, input, projectId, sessionId, threadName ); if (logInputAndOutput) { this.recordGenerateActionInputLogs( span, modelName, featureName, path, input, projectId, sessionId, threadName ); } } if (output && logInputAndOutput) { this.recordGenerateActionOutputLogs( span, modelName, featureName, path, output, projectId, sessionId, threadName ); } } recordGenerateActionMetrics(modelName, featureName, path, opts) { this.doRecordGenerateActionMetrics(modelName, opts.response?.usage || {}, { featureName, path, latencyMs: opts.response?.latencyMs, errName: opts.errName, source: "ts", sourceVersion: import_genkit.GENKIT_VERSION }); } recordGenerateActionConfigLogs(span, model, featureName, qualifiedPath, input, projectId, sessionId, threadName) { const path = (0, import_utils.truncatePath)((0, import_tracing.toDisplayPath)(qualifiedPath)); const sharedMetadata = { ...(0, import_utils.createCommonLogAttributes)(span, projectId), model, path, qualifiedPath, featureName, sessionId, threadName }; import_logging.logger.logStructured(`Config[${path}, ${model}]`, { ...sharedMetadata, maxOutputTokens: input.config?.maxOutputTokens, stopSequences: input.config?.stopSequences, // array source: "ts", sourceVersion: import_genkit.GENKIT_VERSION }); } recordGenerateActionInputLogs(span, model, featureName, qualifiedPath, input, projectId, sessionId, threadName) { const path = (0, import_utils.truncatePath)((0, import_tracing.toDisplayPath)(qualifiedPath)); const sharedMetadata = { ...(0, import_utils.createCommonLogAttributes)(span, projectId), model, path, qualifiedPath, featureName, sessionId, threadName }; const messages = input.messages.length; input.messages.forEach((msg, msgIdx) => { const parts = msg.content.length; msg.content.forEach((part, partIdx) => { const partCounts = this.toPartCounts(partIdx, parts, msgIdx, messages); import_logging.logger.logStructured(`Input[${path}, ${model}] ${partCounts}`, { ...sharedMetadata, content: this.toPartLogContent(part), role: msg.role, partIndex: partIdx, totalParts: parts, messageIndex: msgIdx, totalMessages: messages }); }); }); } recordGenerateActionOutputLogs(span, model, featureName, qualifiedPath, output, projectId, sessionId, threadName) { const path = (0, import_utils.truncatePath)((0, import_tracing.toDisplayPath)(qualifiedPath)); const sharedMetadata = { ...(0, import_utils.createCommonLogAttributes)(span, projectId), model, path, qualifiedPath, featureName, sessionId, threadName }; const message = output.message || output.candidates?.[0]?.message; if (message?.content) { const parts = message.content.length; message.content.forEach((part, partIdx) => { const partCounts = this.toPartCounts(partIdx, parts, 0, 1); const initial = output.finishMessage ? { finishMessage: (0, import_utils.truncate)(output.finishMessage) } : {}; import_logging.logger.logStructured(`Output[${path}, ${model}] ${partCounts}`, { ...initial, ...sharedMetadata, content: this.toPartLogContent(part), role: message.role, partIndex: partIdx, totalParts: parts, candidateIndex: 0, totalCandidates: 1, messageIndex: 0, finishReason: output.finishReason }); }); } } toPartCounts(partOrdinal, parts, msgOrdinal, messages) { if (parts > 1 && messages > 1) { return `(part ${this.xOfY(partOrdinal, parts)} in message ${this.xOfY( msgOrdinal, messages )})`; } if (parts > 1) { return `(part ${this.xOfY(partOrdinal, parts)})`; } if (messages > 1) { return `(message ${this.xOfY(msgOrdinal, messages)})`; } return ""; } xOfY(x, y) { return `${x + 1} of ${y}`; } toPartLogContent(part) { if (part.text) { return (0, import_utils.truncate)(part.text); } if (part.data) { return (0, import_utils.truncate)(JSON.stringify(part.data)); } if (part.media) { return this.toPartLogMedia(part); } if (part.toolRequest) { return this.toPartLogToolRequest(part); } if (part.toolResponse) { return this.toPartLogToolResponse(part); } if (part.custom) { return (0, import_utils.truncate)(JSON.stringify(part.custom)); } return "<unknown format>"; } toPartLogMedia(part) { if (part.media.url.startsWith("data:")) { const splitIdx = part.media.url.indexOf("base64,"); if (splitIdx < 0) { return "<unknown media format>"; } const prefix = part.media.url.substring(0, splitIdx + 7); const hashedContent = (0, import_crypto.createHash)("sha256").update(part.media.url.substring(splitIdx + 7)).digest("hex"); return `${prefix}<sha256(${hashedContent})>`; } return (0, import_utils.truncate)(part.media.url); } toPartLogToolRequest(part) { const inputText = typeof part.toolRequest.input === "string" ? part.toolRequest.input : JSON.stringify(part.toolRequest.input); return (0, import_utils.truncate)( `Tool request: ${part.toolRequest.name}, ref: ${part.toolRequest.ref}, input: ${inputText}` ); } toPartLogToolResponse(part) { const outputText = typeof part.toolResponse.output === "string" ? part.toolResponse.output : JSON.stringify(part.toolResponse.output); return (0, import_utils.truncate)( `Tool response: ${part.toolResponse.name}, ref: ${part.toolResponse.ref}, output: ${outputText}` ); } /** * Records all metrics associated with performing a GenerateAction. */ doRecordGenerateActionMetrics(modelName, usage, dimensions) { const shared = { modelName, featureName: dimensions.featureName, path: dimensions.path, source: dimensions.source, sourceVersion: dimensions.sourceVersion, status: dimensions.errName ? "failure" : "success" }; this.actionCounter.add(1, { error: dimensions.errName, ...shared }); this.latencies.record(dimensions.latencyMs, shared); this.inputTokens.add(usage.inputTokens, shared); this.inputCharacters.add(usage.inputCharacters, shared); this.inputImages.add(usage.inputImages, shared); this.outputTokens.add(usage.outputTokens, shared); this.outputCharacters.add(usage.outputCharacters, shared); this.outputImages.add(usage.outputImages, shared); this.thinkingTokens.add(usage.thoughtsTokens, shared); } } const generateTelemetry = new GenerateTelemetry(); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { generateTelemetry }); //# sourceMappingURL=generate.js.map