| import { GoogleGenAI, Type, Schema } from "@google/genai"; |
| import { AnalysisReport } from "../types"; |
|
|
| |
| |
| const ai = new GoogleGenAI({ apiKey: process.env.API_KEY }); |
|
|
| const MODEL_NAME = "gemini-2.5-flash"; |
|
|
| const analysisSchema: Schema = { |
| type: Type.OBJECT, |
| properties: { |
| isCompliant: { type: Type.BOOLEAN, description: "Whether the image is suitable for a public lock screen." }, |
| overallScore: { type: Type.INTEGER, description: "A quality score from 0 to 100." }, |
| checks: { |
| type: Type.ARRAY, |
| items: { |
| type: Type.OBJECT, |
| properties: { |
| name: { type: Type.STRING, description: "The name of the criterion being checked." }, |
| passed: { type: Type.BOOLEAN, description: "Whether the check passed." }, |
| reason: { type: Type.STRING, description: "Brief explanation of the result." } |
| }, |
| required: ["name", "passed", "reason"] |
| } |
| } |
| }, |
| required: ["isCompliant", "overallScore", "checks"] |
| }; |
|
|
| |
| |
| |
| const fileToGenerativePart = async (file: File): Promise<string> => { |
| return new Promise((resolve, reject) => { |
| const reader = new FileReader(); |
| reader.onloadend = () => { |
| const base64String = reader.result as string; |
| |
| const base64Data = base64String.split(',')[1]; |
| resolve(base64Data); |
| }; |
| reader.onerror = reject; |
| reader.readAsDataURL(file); |
| }); |
| }; |
|
|
| export const analyzeLockScreen = async (file: File): Promise<AnalysisReport> => { |
| try { |
| const base64Data = await fileToGenerativePart(file); |
|
|
| const systemPrompt = ` |
| You are Prism, an AI expert for Samsung Glance lock screen compliance. |
| Analyze the provided image against the following strict criteria: |
| 1. Image Quality: Must be high resolution, not blurry, no artifacts. |
| 2. Ribbon Detection: Ensure no promotional ribbons, watermarks, or text overlays covering the subject. |
| 3. Text Legibility: If there is text, is it legible? (Prefer no text for wallpapers). |
| 4. Safe Content: No offensive, violent, or adult content. |
| 5. Subject Centering: The main subject should be well-positioned for a mobile lock screen (portrait aspect). |
| |
| Return the result as a structured JSON object. |
| `; |
|
|
| const response = await ai.models.generateContent({ |
| model: MODEL_NAME, |
| contents: { |
| parts: [ |
| { inlineData: { mimeType: file.type, data: base64Data } }, |
| { text: systemPrompt } |
| ] |
| }, |
| config: { |
| responseMimeType: "application/json", |
| responseSchema: analysisSchema, |
| temperature: 0.2, |
| } |
| }); |
|
|
| if (response.text) { |
| return JSON.parse(response.text) as AnalysisReport; |
| } else { |
| throw new Error("No response text from Gemini."); |
| } |
|
|
| } catch (error) { |
| console.error("Gemini Analysis Failed:", error); |
| |
| return { |
| isCompliant: false, |
| overallScore: 0, |
| checks: [ |
| { name: "System Error", passed: false, reason: "Failed to connect to AI service." } |
| ] |
| }; |
| } |
| }; |