PRISM2.0 / frontend /services /geminiService.ts
devranx's picture
Initial deploy with LFS images and audio
d790e98
raw
history blame
3.36 kB
import { GoogleGenAI, Type, Schema } from "@google/genai";
import { AnalysisReport } from "../types";
// Initialize Gemini Client
// Note: API Key is injected via process.env.API_KEY
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"]
};
/**
* Converts a File object to a Base64 string for the API.
*/
const fileToGenerativePart = async (file: File): Promise<string> => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => {
const base64String = reader.result as string;
// Remove data url prefix (e.g. "data:image/jpeg;base64,")
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, // Low temperature for consistent, objective analysis
}
});
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);
// Fallback mock error for UI stability if API fails completely
return {
isCompliant: false,
overallScore: 0,
checks: [
{ name: "System Error", passed: false, reason: "Failed to connect to AI service." }
]
};
}
};