Remove Gemini evaluation budget
build-push / docker (push) Successful in 4m21s

This commit is contained in:
AI Assistant
2026-03-16 13:12:29 +09:00
parent 4b03cc41f7
commit d787f84799
3 changed files with 13 additions and 20 deletions
+10
View File
@@ -255,6 +255,16 @@
- backend debug broadcasts
## Recent Change Log
- Date: `2026-03-16`
- What changed:
- Removed the request-time budget from Gemini evaluation and supplemental exploration so the search pipeline now processes sequentially without the custom early-stop timeout branch.
- Why it changed:
- The user explicitly requested no tight Gemini evaluation cutoff and wanted purely sequential processing instead of budget-based truncation.
- How it was verified:
- code-path inspection of `/api/search` and `EvaluateAllCandidatesWithGemini(...)`
- What is still risky or incomplete:
- End-to-end search latency can now grow significantly, and upstream reverse proxies may still time out if their own request timeout is shorter than the full sequential pipeline.
- Date: `2026-03-16`
- What changed:
- If Gemini evaluation times out before producing any usable reviewed items, the API now returns a capped ranked fallback set instead of an empty result list.
+3 -7
View File
@@ -270,7 +270,6 @@ func (a *App) runDownload(recordID int64, url, start, end, quality, outputPath s
func (a *App) searchMedia(c *gin.Context) {
started := time.Now()
deadline := started.Add(22 * time.Second)
var req struct {
Query string `json:"query"`
Platforms []string `json:"platforms"`
@@ -322,16 +321,16 @@ func (a *App) searchMedia(c *gin.Context) {
scored := services.RankSearchResults(rankQuery, results)
a.debug("search ranked summary", summarizeSearchResults(scored, time.Since(started), services.GeminiCandidateLimit(len(scored)), ""))
a.Hub.Broadcast("progress", gin.H{"type": "search", "status": "analyzing all candidate visuals with Gemini Vision", "progress": 75})
recommended, geminiStats, geminiErr := services.EvaluateAllCandidatesWithGeminiBudget(a.GeminiService, req.Query, scored, deadline)
recommended, geminiStats, geminiErr := services.EvaluateAllCandidatesWithGemini(a.GeminiService, req.Query, scored)
a.debug("search gemini evaluation", geminiStats)
if services.NeedsSupplementalExploration(recommended) && time.Now().Before(deadline.Add(-4*time.Second)) {
if services.NeedsSupplementalExploration(recommended) {
a.Hub.Broadcast("progress", gin.H{"type": "search", "status": "Gemini 평가가 약해 추가 후보를 탐색하는 중", "progress": 82})
explorationQueries := buildSupplementalQueries(req.Query, queryVariants)
extraResults, extraErr := a.SearchService.SearchMedia(explorationQueries, enabledPlatforms)
if extraErr == nil && len(extraResults) > 0 {
results = mergeSearchResults(results, extraResults)
scored = services.RankSearchResults(strings.Join(explorationQueries[:min(len(explorationQueries), 3)], " "), results)
recommended, geminiStats, geminiErr = services.EvaluateAllCandidatesWithGeminiBudget(a.GeminiService, req.Query, scored, deadline)
recommended, geminiStats, geminiErr = services.EvaluateAllCandidatesWithGemini(a.GeminiService, req.Query, scored)
a.debug("search supplemental query variants", gin.H{"variants": explorationQueries, "variantCount": len(explorationQueries)})
a.debug("search gemini evaluation after supplemental search", geminiStats)
}
@@ -368,9 +367,6 @@ func (a *App) searchMedia(c *gin.Context) {
if geminiErr != nil {
warning = geminiErr.Error()
}
if geminiStats.TimedOut && warning == "" {
warning = "search returned partial Gemini-reviewed results before the gateway timeout budget"
}
a.debug("search complete summary", summarizeRecommendationResults(merged, time.Since(started), warning))
response := gin.H{"results": merged, "queries": queryVariants}
if warning != "" {
-13
View File
@@ -18,7 +18,6 @@ type GeminiBatchStats struct {
Failed int `json:"failed"`
SequentialRetried int `json:"sequentialRetried"`
RecommendedCount int `json:"recommendedCount"`
TimedOut bool `json:"timedOut,omitempty"`
Errors []string `json:"errors,omitempty"`
}
@@ -91,10 +90,6 @@ func GeminiCandidateLimit(total int) int {
}
func EvaluateAllCandidatesWithGemini(service *GeminiService, query string, ranked []SearchResult) ([]AIRecommendation, GeminiBatchStats, error) {
return EvaluateAllCandidatesWithGeminiBudget(service, query, ranked, time.Time{})
}
func EvaluateAllCandidatesWithGeminiBudget(service *GeminiService, query string, ranked []SearchResult, deadline time.Time) ([]AIRecommendation, GeminiBatchStats, error) {
if service == nil {
return nil, GeminiBatchStats{}, fmt.Errorf("gemini service is not configured")
}
@@ -112,10 +107,6 @@ func EvaluateAllCandidatesWithGeminiBudget(service *GeminiService, query string,
merged := make([]AIRecommendation, 0, len(ranked))
seen := map[string]bool{}
for idx := 0; idx < limit; idx++ {
if !deadline.IsZero() && time.Now().After(deadline) {
stats.TimedOut = true
break
}
recommendations, err := recoverGeminiCandidateSequentially(service, query, ranked[idx])
if err != nil {
stats.Failed++
@@ -140,10 +131,6 @@ func EvaluateAllCandidatesWithGeminiBudget(service *GeminiService, query string,
stats.RecommendedCount = len(merged)
switch {
case stats.TimedOut && len(merged) > 0:
return merged, stats, fmt.Errorf("gemini vision evaluation stopped early to avoid request timeout")
case stats.TimedOut && len(merged) == 0:
return nil, stats, fmt.Errorf("gemini vision evaluation timed out before any usable results were returned")
case len(merged) > 0 && stats.Failed == 0:
return merged, stats, nil
case len(merged) > 0 && stats.Failed > 0: