This commit is contained in:
233
geminiService.ts
Normal file
233
geminiService.ts
Normal file
@@ -0,0 +1,233 @@
|
||||
|
||||
import { GoogleGenAI, Type, Part } from "@google/genai";
|
||||
import { ProductPackage, AspectRatio, ImageSize, ProductType, CreativityLevel } from "./types";
|
||||
|
||||
const creativityMap: Record<CreativityLevel, number> = {
|
||||
"Literal": 0.2,
|
||||
"Balanced": 0.7,
|
||||
"Artistic": 1.1,
|
||||
"Avant-Garde": 1.6,
|
||||
"Conservative": 0.3,
|
||||
"Wild": 1.4
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// SYSTEM PERSONA DEFINITION
|
||||
// ---------------------------------------------------------
|
||||
const SYSTEM_INSTRUCTION = `
|
||||
You are an elite AI Fusion Entity possessing the combined expertise of:
|
||||
1. Global Etsy E-commerce Strategist (Market Trends 2024-2025)
|
||||
2. Senior Art Director & Creative Lead (Impeccable Taste)
|
||||
3. Neuromarketing Expert (Dopamine & Serotonin Visual Triggers)
|
||||
4. SEO Visual Specialist (Search Intent Optimization)
|
||||
5. Nano Banana / Stable Diffusion Prompt Engineer (Tag & Weight Mastery)
|
||||
|
||||
OBJECTIVE:
|
||||
Translate raw user ideas into a "Commercial Masterpiece" Digital Product Package.
|
||||
|
||||
CORE ANALYSIS WORKFLOW (Internal Monologue):
|
||||
Before generating output, perform this split-second analysis:
|
||||
1. Market Fit: Identify the trending style for this niche (e.g. Boho, Minimalist, Dark Academia).
|
||||
2. Neuro-Trigger: Define the emotion to sell (Calm, Joy, Nostalgia).
|
||||
3. Composition: Plan the perfect thumbnail click composition.
|
||||
|
||||
PROMPT FORMULA (Strict Adherence):
|
||||
The 'imagePrompt' MUST be a comma-separated string following this 'Nano Banana' structure:
|
||||
[Quality & Neuro Boosters], [Subject with Art Direction], [Environment & Context], [Artistic Medium & Style], [Color Palette & Lighting], [Tech Specs]
|
||||
|
||||
MANDATORY BOOSTERS TO START:
|
||||
(masterpiece:1.4), (best quality), (ultra-detailed), (commercial photography), (professional color grading), 8k resolution, (sharp focus), aesthetic, trending on etsy
|
||||
|
||||
EXAMPLE OUTPUT PROMPT:
|
||||
"(masterpiece:1.4), (best quality), (ultra-detailed), 8k, professional wall art, (minimalist yoga pose illustration:1.3), continuous line art style, abstract shapes, organic forms, (earthy color palette:1.2), terracotta and beige tones, soft textured paper background, zen atmosphere, (calming aesthetic), clean composition, interior design mockup style, soft studio lighting, 300 dpi"
|
||||
`;
|
||||
|
||||
/**
|
||||
* MODULE 1: Generates the specialized SEO and Prompt package using the 5-Layer Persona.
|
||||
*/
|
||||
export const generateProductPackage = async (
|
||||
niche: string,
|
||||
productType: ProductType,
|
||||
creativity: CreativityLevel,
|
||||
referenceImages?: string[]
|
||||
): Promise<ProductPackage> => {
|
||||
const ai = new GoogleGenAI({ apiKey: process.env.API_KEY });
|
||||
|
||||
const parts: Part[] = [
|
||||
{ text: SYSTEM_INSTRUCTION },
|
||||
{
|
||||
text: `
|
||||
TASK: Architect a High-Conversion ${productType} for the niche: "${niche}".
|
||||
|
||||
OUTPUT REQUIREMENTS (JSON):
|
||||
1. imagePrompt: The Nano Banana optimized tag string (English).
|
||||
2. seoTitle: Ultra-SEO optimized title (English).
|
||||
3. keywords: 13 golden tags (English).
|
||||
4. description: Neuro-marketing copy (English).
|
||||
5. suggestedPrice: Competitive Etsy pricing.
|
||||
6. printingGuide: Technical setup (English).
|
||||
` }
|
||||
];
|
||||
|
||||
if (referenceImages && referenceImages.length > 0) {
|
||||
referenceImages.forEach(b64 => {
|
||||
parts.push({ inlineData: { data: b64.split(',')[1], mimeType: 'image/png' } });
|
||||
});
|
||||
}
|
||||
|
||||
const response = await ai.models.generateContent({
|
||||
model: "gemini-2.0-flash", // HYBRID STRATEGY: Flash Brain (Cost Optimized)
|
||||
contents: { parts },
|
||||
config: {
|
||||
temperature: creativityMap[creativity],
|
||||
responseMimeType: "application/json",
|
||||
responseSchema: {
|
||||
type: Type.OBJECT,
|
||||
properties: {
|
||||
imagePrompt: { type: Type.STRING },
|
||||
seoTitle: { type: Type.STRING },
|
||||
keywords: { type: Type.ARRAY, items: { type: Type.STRING } },
|
||||
description: { type: Type.STRING },
|
||||
suggestedPrice: { type: Type.STRING },
|
||||
printingGuide: { type: Type.STRING }
|
||||
},
|
||||
required: ["imagePrompt", "seoTitle", "keywords", "description", "suggestedPrice", "printingGuide"]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return JSON.parse(response.text || "{}");
|
||||
};
|
||||
|
||||
/**
|
||||
* MODULE 2: MASTER ASSET GENERATION
|
||||
* Uses the Optimized Prompt to generate the visual.
|
||||
*/
|
||||
export const generateImage = async (
|
||||
prompt: string,
|
||||
aspectRatio: AspectRatio,
|
||||
size: ImageSize,
|
||||
productType: ProductType,
|
||||
referenceImages?: string[]
|
||||
): Promise<string> => {
|
||||
const ai = new GoogleGenAI({ apiKey: process.env.API_KEY });
|
||||
|
||||
// Apply Product-Specific Composition Rules as a "Guidance Layer" on top of the prompt
|
||||
let compositionGuidance = "";
|
||||
if (productType === "Sticker") compositionGuidance = "Ensure the subject is isolated on a clean white background with a thick white sticker border (die-cut style). No drop shadows.";
|
||||
if (productType === "Bookmark") compositionGuidance = "Ensure a narrow vertical composition suitable for a bookmark. Decorative borders.";
|
||||
|
||||
const masterPrompt = `
|
||||
Act as the Senior Art Director & Visual Engine.
|
||||
|
||||
INPUT PROMPT (Nano Banana Format):
|
||||
${prompt}
|
||||
|
||||
ADDITIONAL TECHNICAL GUIDANCE:
|
||||
${compositionGuidance}
|
||||
|
||||
EXECUTION:
|
||||
Generate the image adhering strictly to the aesthetic quality defined in the prompt tags.
|
||||
`;
|
||||
|
||||
const parts: Part[] = [{ text: masterPrompt }];
|
||||
|
||||
if (referenceImages && referenceImages.length > 0) {
|
||||
referenceImages.forEach(b64 => parts.push({ inlineData: { data: b64.split(',')[1], mimeType: 'image/png' } }));
|
||||
}
|
||||
|
||||
const response = await ai.models.generateContent({
|
||||
model: 'gemini-2.5-flash-image', // Or 'gemini-3-pro-image-preview' if available/preferred
|
||||
contents: { parts },
|
||||
config: { imageConfig: { aspectRatio, imageSize: size } }
|
||||
});
|
||||
|
||||
const part = response.candidates?.[0]?.content?.parts?.find(p => p.inlineData);
|
||||
return part?.inlineData ? `data:image/png;base64,${part.inlineData.data}` : "";
|
||||
};
|
||||
|
||||
/**
|
||||
* MODULE 3: MOCKUP SCENARIOS
|
||||
*/
|
||||
export const MOCKUP_SCENARIOS: Record<ProductType, string[]> = {
|
||||
"Wall Art": ["Luxury penthouse gallery wall", "Modern kitchen breakfast nook", "Studio easel"],
|
||||
"Bookmark": ["Tucked in a vintage book", "Flatlay with coffee", "Held in a journal"],
|
||||
"Sticker": ["On a laptop lid", "On a hydroflask", "In a planner spread"],
|
||||
"Planner": ["On a high-end tablet", "Minimalist desk setup", "Hand-held digital view"],
|
||||
"Phone Wallpaper": ["Smartphone lifestyle photo", "Marble nightstand", "Lockscreen preview"],
|
||||
"Social Media Kit": ["Grid preview", "Marketing agency desk", "Mobile profile layout"],
|
||||
"Label": ["Product bottle mockup", "Jar label display", "Package shelf"]
|
||||
};
|
||||
|
||||
/**
|
||||
* MODULE 4: GENERATE SINGLE MOCKUP
|
||||
*/
|
||||
export const generateSingleMockup = async (base64Image: string, productType: ProductType, scenario: string): Promise<string> => {
|
||||
const ai = new GoogleGenAI({ apiKey: process.env.API_KEY });
|
||||
const response = await ai.models.generateContent({
|
||||
model: 'gemini-2.5-flash-image',
|
||||
contents: {
|
||||
parts: [
|
||||
{ inlineData: { data: base64Image.split(',')[1], mimeType: 'image/png' } },
|
||||
{ text: `Mockup Scenario: This ${productType} asset used in a ${scenario}. Realistic, professional commercial photography, soft studio lighting, 8k, highly detailed.` }
|
||||
]
|
||||
}
|
||||
});
|
||||
const part = response.candidates?.[0]?.content?.parts?.find(p => p.inlineData);
|
||||
return part?.inlineData ? `data:image/png;base64,${part.inlineData.data}` : "";
|
||||
};
|
||||
|
||||
/**
|
||||
* MODULE 5: PRECISION REVISION
|
||||
* Maintains the Expert Persona for revisions.
|
||||
*/
|
||||
export const performPrecisionRevision = async (base64Image: string, revisionBrief: string): Promise<{ image: string, optimizedPrompt: string }> => {
|
||||
const ai = new GoogleGenAI({ apiKey: process.env.API_KEY });
|
||||
|
||||
// 1. Translate and Optimize
|
||||
const translationResponse = await ai.models.generateContent({
|
||||
model: 'gemini-2.0-flash', // Cost Optimized Brain
|
||||
contents: `
|
||||
You are the "Nano Banana Prompt Engineer".
|
||||
|
||||
TASK: Translate the revision brief: "${revisionBrief}" into a comma-separated English tag list (Nano Banana format).
|
||||
It should describe the NEW DESIRED STATE of the image.
|
||||
|
||||
Keep the original specific style tags unless the brief explicitly changes them.
|
||||
Output ONLY the tag string.
|
||||
`
|
||||
});
|
||||
const optimizedPrompt = translationResponse.text || revisionBrief;
|
||||
|
||||
// 2. Perform the Edit
|
||||
const editResponse = await ai.models.generateContent({
|
||||
model: 'gemini-2.5-flash-image',
|
||||
contents: {
|
||||
parts: [
|
||||
{ inlineData: { data: base64Image.split(',')[1], mimeType: 'image/png' } },
|
||||
{ text: `Precision Edit Instruction: Based on these tags: ${optimizedPrompt}. Maintain high fidelity and consistent art style.` }
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
const part = editResponse.candidates?.[0]?.content?.parts.find(p => p.inlineData);
|
||||
const newImage = part?.inlineData ? `data:image/png;base64,${part.inlineData.data}` : base64Image;
|
||||
|
||||
return { image: newImage, optimizedPrompt };
|
||||
};
|
||||
|
||||
/**
|
||||
* MODULE 6: COMPETITOR ANALYSIS
|
||||
*/
|
||||
export const analyzeCompetitors = async (niche: string): Promise<{ text: string; sources: any[] }> => {
|
||||
const ai = new GoogleGenAI({ apiKey: process.env.API_KEY });
|
||||
const response = await ai.models.generateContent({
|
||||
model: 'gemini-3-flash-preview',
|
||||
contents: `Act as an E-commerce Market Specialist. Analyze current Etsy trends for: "${niche}". Focus on visual style, color palettes, and top-selling themes.`,
|
||||
config: { tools: [{ googleSearch: {} }] }
|
||||
});
|
||||
return {
|
||||
text: response.text || "",
|
||||
sources: response.candidates?.[0]?.groundingMetadata?.groundingChunks || []
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user