UNPKG

contaigents

Version:

Modular AI Content Ecosystem with Audio Generation

159 lines (158 loc) 6.64 kB
import { BaseLLM } from "./BaseLLM.js"; export class GoogleProvider extends BaseLLM { constructor() { super(GoogleProvider.providerConfig); } async executePrompt(prompt, options = {}) { if (!(await this.isConfigured())) { throw new Error("Google provider is not configured"); } const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${this.config.model}:generateContent?key=${this.config.apiKey}`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ contents: [{ parts: [{ text: prompt }] }], generationConfig: { temperature: options.temperature ?? 0.7, maxOutputTokens: options.maxTokens, }, }), }); if (!response.ok) { const error = await response.json(); throw new Error(`Google API error: ${error.error?.message || "Unknown error"}`); } const data = await response.json(); // Validate response structure with better error handling if (!data.candidates || !Array.isArray(data.candidates) || data.candidates.length === 0) { throw new Error(`Google API returned no candidates. Response: ${JSON.stringify(data)}`); } const candidate = data.candidates[0]; // Check if response was truncated due to token limit if (candidate && candidate.finishReason === 'MAX_TOKENS') { throw new Error(`Google API response was truncated due to MAX_TOKENS limit. Consider increasing maxTokens parameter.`); } if (!candidate || !candidate.content || !candidate.content.parts || !Array.isArray(candidate.content.parts) || candidate.content.parts.length === 0) { throw new Error(`Google API candidate has invalid content structure. Candidate: ${JSON.stringify(candidate)}`); } const text = candidate.content.parts[0].text; if (typeof text !== 'string') { throw new Error(`Google API returned non-string text. Parts: ${JSON.stringify(candidate.content.parts)}`); } return { content: text, raw: data, }; } async executeConversation(messages, options = {}) { if (!(await this.isConfigured())) { throw new Error("Google provider is not configured"); } // Extract system message for systemInstruction const systemMessage = messages.find(msg => msg.role === 'system'); // Convert conversation messages to Google format (excluding system messages) const contents = messages .filter(msg => msg.role !== 'system') .map(msg => { const parts = [{ text: msg.content }]; // Add image attachments if present if (msg.images && msg.images.length > 0) { for (const image of msg.images) { parts.push({ inline_data: { mime_type: image.mimeType, data: image.base64Data } }); } } return { role: msg.role === 'assistant' ? 'model' : 'user', parts }; }); // Build request body const requestBody = { contents, generationConfig: { temperature: options.temperature ?? 0.7, maxOutputTokens: options.maxTokens, }, }; // Add system instruction if system message exists if (systemMessage) { requestBody.systemInstruction = { parts: [{ text: systemMessage.content }] }; } const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${this.config.model}:generateContent?key=${this.config.apiKey}`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(requestBody), }); if (!response.ok) { const error = await response.json(); throw new Error(`Google API error: ${error.error?.message || "Unknown error"}`); } const data = await response.json(); // Validate response structure with better error handling if (!data.candidates || !Array.isArray(data.candidates) || data.candidates.length === 0) { throw new Error(`Google API returned no candidates. Response: ${JSON.stringify(data)}`); } const candidate = data.candidates[0]; // Check if response was truncated due to token limit if (candidate && candidate.finishReason === 'MAX_TOKENS') { throw new Error(`Google API response was truncated due to MAX_TOKENS limit. Consider increasing maxTokens parameter.`); } if (!candidate || !candidate.content || !candidate.content.parts || !Array.isArray(candidate.content.parts) || candidate.content.parts.length === 0) { throw new Error(`Google API candidate has invalid content structure. Candidate: ${JSON.stringify(candidate)}`); } const text = candidate.content.parts[0].text; if (typeof text !== 'string') { throw new Error(`Google API returned non-string text. Parts: ${JSON.stringify(candidate.content.parts)}`); } return { content: text, raw: data, }; } supportsConversation() { return true; } getCapabilities() { return { supportsConversation: true, supportsSystemMessages: true, // Google supports system messages via systemInstruction supportsToolCalls: true, // Enable tool calls for agentic behavior customFormat: 'gemini', maxContextLength: 1000000, }; } } GoogleProvider.providerConfig = { name: "Google", configFields: [ { name: "apiKey", required: true, }, { name: "model", required: true, options: [ "gemini-2.5-flash", "gemini-2.0-flash", "gemini-2.0-flash-lite-preview-02-05", "gemini-1.5-flash", "gemini-1.5-flash-8b", "gemini-1.5-pro", "gemini-1.0-pro", ], default: "gemini-2.5-flash", }, ], };