File size: 3,588 Bytes
065d164 bc4db62 065d164 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
import { GoogleGenerativeAI } from "@google/generative-ai";
// Initialize the Gemini API with the API key
const apiKey = process.env.GEMINI_API_KEY;
const genAI = new GoogleGenerativeAI(apiKey);
// Maximum number of retries for API calls
const MAX_RETRIES = 3;
// Delay between retries (in milliseconds)
const RETRY_DELAY = 1000;
// Helper function to wait between retries
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const { image, prompt } = req.body;
if (!image) {
return res.status(400).json({ error: 'Image data is required' });
}
// Remove the data URL prefix
const base64Image = image.replace(/^data:image\/(png|jpeg|jpg);base64,/, '');
// Initialize the Gemini 2.0 Flash model
const model = genAI.getGenerativeModel({ model: "gemini-2.0-flash" });
// Use the custom prompt if provided, otherwise use the default
const promptText = prompt || "μ΄ μ΄λ―Έμ§λ₯Ό λ³΄κ³ (λ³΄μΌ μλ μλ μμ΄λ μκ°λ½μ 무μν μ±) μ€λ‘μ§ playing cardsλ§ μλ³νμΈμ. μλ³λ μΉ΄λμ μ νν μ λ³΄λ§ μΆλ ₯νμΈμ(μ, A μ€νμ΄λ, 10 ννΈ, J λ€μ΄μλͺ¬λ";
// Prepare the image part for the model
const imagePart = {
inlineData: {
data: base64Image,
mimeType: "image/jpeg",
},
};
// Implement retry logic with exponential backoff
let lastError = null;
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
try {
// Generate content with the image
const result = await model.generateContent([promptText, imagePart]);
const response = await result.response;
const text = response.text();
return res.status(200).json({ thought: text });
} catch (error) {
console.error(`Attempt ${attempt + 1} failed:`, error.message);
lastError = error;
// Check if error is related to throttling or service unavailability
if (error.message.includes('503 Service Unavailable') ||
error.message.includes('THROTTLED') ||
error.message.includes('overloaded')) {
// Wait before retrying with exponential backoff
await sleep(RETRY_DELAY * Math.pow(2, attempt));
continue;
} else {
// For other errors, don't retry
break;
}
}
}
// If we've exhausted all retries or encountered a non-retryable error
console.error('All attempts failed or non-retryable error:', lastError);
// Provide a user-friendly error message based on the error type
if (lastError.message.includes('THROTTLED') || lastError.message.includes('overloaded')) {
return res.status(503).json({
error: 'The AI service is currently busy. Please try again in a moment.',
fallbackThought: "π€"
});
} else if (lastError.message.includes('quota')) {
return res.status(429).json({
error: 'API quota exceeded. Please try again later.',
fallbackThought: "π€"
});
} else {
return res.status(500).json({
error: 'Something went wrong while analyzing your image.',
fallbackThought: "π€"
});
}
} catch (error) {
console.error('Unexpected error:', error);
return res.status(500).json({
error: 'An unexpected error occurred',
fallbackThought: "π€"
});
}
} |