From 4d8d317c50cdf3cc7de5a90153789fe6fd535919 Mon Sep 17 00:00:00 2001 From: AI Assistant Date: Fri, 13 Mar 2026 10:53:27 +0900 Subject: [PATCH] Tune Gemini prompts for stock media search --- backend/handlers/api.go | 22 ++++++++++++++++++++-- backend/services/gemini.go | 16 ++++++++++++---- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/backend/handlers/api.go b/backend/handlers/api.go index d7d95a7..17ff413 100644 --- a/backend/handlers/api.go +++ b/backend/handlers/api.go @@ -351,6 +351,14 @@ func min(a, b int) int { func rankSearchResults(query string, results []services.SearchResult) []services.SearchResult { queryTerms := strings.Fields(strings.ToLower(query)) + positiveTerms := []string{ + "b-roll", "b roll", "stock", "stock footage", "footage", "cinematic", "editorial", + "establishing", "4k", "hd", "drone", "ambient", "scene", "urban", "cityscape", + } + negativeTerms := []string{ + "shocking", "amazing", "crazy", "must watch", "reaction", "gossip", "celebrity", + "thumbnail", "meme", "prank", "drama", "breaking", "viral", + } type scoredResult struct { item services.SearchResult score int @@ -365,6 +373,16 @@ func rankSearchResults(query string, results []services.SearchResult) []services score += 3 } } + for _, term := range positiveTerms { + if strings.Contains(text, term) { + score += 2 + } + } + for _, term := range negativeTerms { + if strings.Contains(text, term) { + score -= 4 + } + } if result.ThumbnailURL != "" { score += 2 } @@ -372,9 +390,9 @@ func rankSearchResults(query string, results []services.SearchResult) []services case "Google Video": score += 3 case "Envato": - score += 2 + score += 4 case "Artgrid": - score += 2 + score += 4 } scored = append(scored, scoredResult{item: result, score: score}) } diff --git a/backend/services/gemini.go b/backend/services/gemini.go index 057f97e..1cd4b27 100644 --- a/backend/services/gemini.go +++ b/backend/services/gemini.go @@ -48,8 +48,12 @@ func (g *GeminiService) ExpandQuery(query string) ([]string, error) { "parts": []map[string]string{ { "text": `Return JSON only in this shape: {"querywords":["..."]}. -Generate at most 4 concise search variations for media discovery across Google Video, Envato, and Artgrid. -Keep the original language when possible. User query: ` + query, +Generate at most 10 concise search variations for media discovery across Google Video, Envato, and Artgrid. +If the user query is in Korean, include strong English search variants that a stock footage editor would use. +Prioritize media, video footage, stock footage, cinematic b-roll, editorial footage, and scene-based search terms. +Avoid celebrity gossip, reaction-style phrasing, clickbait phrasing, and generic web search wording. +Mix Korean and English when useful, but make sure several queries are clean English production keywords. +User query: ` + query, }, }, }, @@ -57,7 +61,7 @@ Keep the original language when possible. User query: ` + query, "generationConfig": map[string]any{ "responseMimeType": "application/json", "temperature": 0.2, - "maxOutputTokens": 120, + "maxOutputTokens": 220, }, } @@ -125,7 +129,11 @@ func (g *GeminiService) Recommend(query string, candidates []SearchResult) ([]AI { "text": `Analyze the provided images for the user's search intent. Return JSON only in this shape: {"recommendations":[{"index":0,"reason":"short reason","recommended":true}]} -Mark only the best matches as recommended=true. Keep reasons concise. Recommend up to 8 items. User query: ` + query, +Mark only the best matches as recommended=true. Keep reasons concise. Recommend up to 8 items. +Prefer cinematic b-roll, stock footage, editorial footage, clean composition, usable establishing shots, and professional media thumbnails. +Avoid clickbait faces, exaggerated expressions, meme aesthetics, low-information thumbnails, sensational text overlays, or gossip-style imagery. +Favor thumbnails that look directly useful for media editing and footage sourcing. +User query: ` + query, }, }