UNPKG

@sconedev/ai_toolkit

Version:

Simplify AI integration in web apps with local and offline model support

102 lines (101 loc) 4.68 kB
import { GoogleGenerativeAI } from "@google/generative-ai"; export class GeminiProvider { constructor(apiKey, model) { if (!apiKey) { throw new Error('API key is required for Gemini provider'); } this.genAI = new GoogleGenerativeAI(apiKey); this.defaultModel = model || 'gemini-1.5-flash'; } async chat(messages, options) { try { // Ensure we have messages if (!messages || messages.length === 0) { throw new Error('No messages provided to Gemini chat'); } console.log(`Using Gemini model: ${options?.model || this.defaultModel}`); // Extract system message if present as first message let systemPrompt; let chatMessages = [...messages]; if (messages[0]?.role === 'system') { systemPrompt = messages[0].content; chatMessages = messages.slice(1); } // Ensure we have at least one user message if (chatMessages.length === 0 || chatMessages[chatMessages.length - 1].role !== 'user') { throw new Error('The last message must be from the user for Gemini'); } // Prepare conversation history const history = chatMessages.slice(0, -1).map(m => ({ role: m.role === 'user' ? 'user' : 'model', parts: [{ text: m.content }] })); // Get the last user message const lastMessage = chatMessages[chatMessages.length - 1]; // Configure generation parameters const generationConfig = { temperature: options?.temperature || 0.7, topP: options?.topP || 0.95, topK: options?.topK || 40, maxOutputTokens: options?.maxTokens || 1024, ...options?.generationConfig }; // Initialize the model with proper configuration const model = this.genAI.getGenerativeModel({ model: options?.model || this.defaultModel, // systemInstruction: systemPrompt, // Removed as it is not a valid property generationConfig }); // Start chat session with history console.log('Starting Gemini chat with history length:', history.length); const chat = model.startChat({ history, generationConfig }); // Send the message and get response console.log('Sending message to Gemini:', lastMessage.content.substring(0, 100) + '...'); const result = await chat.sendMessage(lastMessage.content); if (!result || !result.response) { throw new Error('Empty response from Gemini'); } const responseText = result.response.text(); console.log('Received response from Gemini:', responseText.substring(0, 100) + '...'); return responseText; } catch (error) { // Enhanced error handling console.error('Gemini API error:', error); if (error instanceof Error) { // Check for specific error types if (error.message.includes('API key')) { throw new Error('Invalid Gemini API key or authentication error'); } else if (error.message.includes('quota')) { throw new Error('Gemini API quota exceeded'); } else if (error.message.includes('blocked') || error.message.includes('safety')) { throw new Error('Content blocked by Gemini safety filters'); } throw new Error(`Gemini error: ${error.message}`); } throw new Error('Unknown error occurred with Gemini provider'); } } async generateImage(description, options) { try { const model = this.genAI.getGenerativeModel({ model: "gemini-pro-vision" }); // Check if the model supports image generation const result = await model.generateContent([description]); const response = await result.response; const text = response.text(); if (!text) { throw new Error('Empty response from Gemini image description'); } return text; } catch (error) { console.error('Gemini image generation error:', error); throw new Error('Gemini does not support direct image generation. Use text instructions instead.'); } } }