UNPKG

prompt-version-manager

Version:

Centralized prompt management system for Human Behavior AI agents

197 lines 8.7 kB
"use strict"; /** * Google provider implementation for TypeScript. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.GoogleProvider = void 0; const generative_ai_1 = require("@google/generative-ai"); const exceptions_1 = require("../core/exceptions"); const base_1 = require("./base"); class GoogleProvider extends base_1.BaseProvider { genAI; // Google Gemini pricing per 1K tokens (updated with latest models) static PRICING = { // Legacy models 'gemini-1.0-pro': { input: 0.0005, output: 0.0015 }, 'gemini-pro': { input: 0.0005, output: 0.0015 }, // Alias for gemini-1.0-pro 'gemini-pro-vision': { input: 0.00025, output: 0.0005 }, // Gemini 1.5 series 'gemini-1.5-pro': { input: 0.00125, output: 0.005 }, 'gemini-1.5-flash': { input: 0.000075, output: 0.0003 }, // Gemini 2.0 series (estimated pricing - adjust as needed) 'gemini-2.0-flash': { input: 0.0001, output: 0.0004 }, 'gemini-2.0-flash-lite': { input: 0.00005, output: 0.0002 }, // Gemini 2.5 series (estimated pricing - adjust as needed) 'gemini-2.5-pro': { input: 0.002, output: 0.008 }, 'gemini-2.5-flash': { input: 0.0001, output: 0.0004 }, 'gemini-2.5-flash-lite': { input: 0.00005, output: 0.0002 }, 'gemini-live-2.5-flash-preview': { input: 0.0001, output: 0.0004 } }; constructor(apiKey, config = {}) { super(apiKey, config); if (!this.apiKey) { throw new exceptions_1.APIKeyError('Google API key is required'); } this.genAI = new generative_ai_1.GoogleGenerativeAI(this.apiKey); } get name() { return 'google'; } get supportedModels() { return Object.keys(GoogleProvider.PRICING); } async chatCompletion(model, messages, options = {}) { if (!this.supportsModel(model)) { const available = this.supportedModels.join(', '); throw new exceptions_1.ProviderError(`Model ${model} not supported by Google. Available: ${available}`); } try { // Initialize generation config const generationConfig = {}; if (options.temperature !== undefined) { generationConfig.temperature = options.temperature; } if (options.maxTokens !== undefined) { generationConfig.maxOutputTokens = options.maxTokens; } // Safety settings - moderate default const safetySettings = [ { category: generative_ai_1.HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: generative_ai_1.HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, }, { category: generative_ai_1.HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: generative_ai_1.HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, }, { category: generative_ai_1.HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold: generative_ai_1.HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, }, { category: generative_ai_1.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold: generative_ai_1.HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, }, ]; // Handle structured output configuration let modelConfig = { model, generationConfig, safetySettings }; // Add structured output support if (options.responseMimeType && options.responseSchema) { modelConfig = { ...modelConfig, generationConfig: { ...generationConfig, responseMimeType: options.responseMimeType, responseSchema: options.responseSchema } }; } const geminiModel = this.genAI.getGenerativeModel(modelConfig); // Convert PVM messages to Gemini format // Gemini chat expects alternating user/model messages const geminiHistory = []; let systemInstruction; // Extract system message if present const currentMessages = []; for (const msg of messages) { if (msg.role === 'system') { systemInstruction = msg.content; } else { currentMessages.push(msg); } } // Build conversation history (all but last message) if (currentMessages.length > 1) { for (let i = 0; i < currentMessages.length - 1; i++) { const msg = currentMessages[i]; const role = msg.role === 'user' ? 'user' : 'model'; geminiHistory.push({ role, parts: [{ text: msg.content }] }); } } // Get the final message to send let finalMessage = currentMessages.length > 0 ? currentMessages[currentMessages.length - 1].content : ''; // Prepend system instruction if present if (systemInstruction) { finalMessage = `${systemInstruction}\n\n${finalMessage}`; } // Start chat session const chat = geminiModel.startChat({ history: geminiHistory }); // Make API call const startTime = new Date(); const result = await chat.sendMessage(finalMessage); const endTime = new Date(); // Calculate latency const latency = endTime.getTime() - startTime.getTime(); // Extract response data const response = await result.response; const content = response.text(); // Extract usage (Gemini provides token counts) const usageMetadata = response.usageMetadata; const tokenUsage = { input: usageMetadata?.promptTokenCount || 0, output: usageMetadata?.candidatesTokenCount || 0, total: usageMetadata?.totalTokenCount || 0 }; // Calculate cost const cost = this.calculateCost(model, tokenUsage); // Determine finish reason let finishReason = 'stop'; if (response.candidates && response.candidates[0]?.finishReason) { finishReason = response.candidates[0].finishReason.toLowerCase(); } return { content, tokens: tokenUsage, model, provider: this.name, latency, cost, timestamp: startTime, finishReason, rawResponse: { text: content, usageMetadata: { promptTokenCount: usageMetadata?.promptTokenCount || 0, candidatesTokenCount: usageMetadata?.candidatesTokenCount || 0, totalTokenCount: usageMetadata?.totalTokenCount || 0 }, candidates: response.candidates?.map(candidate => ({ finishReason: candidate.finishReason || null, safetyRatings: candidate.safetyRatings?.map(rating => ({ category: rating.category, probability: rating.probability })) || [] })) || [] } }; } catch (error) { // Google API doesn't have specific rate limit errors, check message if (error.message?.toLowerCase().includes('quota') || error.message?.toLowerCase().includes('rate')) { throw new exceptions_1.RateLimitError(`Google rate limit exceeded: ${error.message}`); } throw new exceptions_1.ProviderError(`Unexpected error calling Google: ${error.message}`); } } calculateCost(model, tokens) { const pricing = GoogleProvider.PRICING[model]; if (!pricing) { return 0.0; } const inputCost = (tokens.input / 1000) * pricing.input; const outputCost = (tokens.output / 1000) * pricing.output; return inputCost + outputCost; } } exports.GoogleProvider = GoogleProvider; //# sourceMappingURL=google.js.map