Backfill partial Gemini results and restore modal iframe
build-push / docker (push) Successful in 4m13s
build-push / docker (push) Successful in 4m13s
This commit is contained in:
@@ -460,6 +460,21 @@
|
|||||||
- There is one known local commit that has not been pushed because the remote repo reported an unpacker error.
|
- There is one known local commit that has not been pushed because the remote repo reported an unpacker error.
|
||||||
|
|
||||||
## Recent Change Log
|
## Recent Change Log
|
||||||
|
- Date: `2026-03-16`
|
||||||
|
- What changed:
|
||||||
|
- When Gemini batch evaluation is only partially successful, the API now explicitly backfills the final list with preview-capable ranked candidates instead of leaving the visible result set too thin.
|
||||||
|
- Result modal behavior was switched so Envato and Artgrid open their actual item webpages inside the modal iframe again, while Google Video still uses the YouTube embed path.
|
||||||
|
- Frontend asset version was bumped again to force clients off stale preview-handling code.
|
||||||
|
- Why it changed:
|
||||||
|
- The new debug log showed `recommendedCount: 2` plus one failed Gemini batch, but the final visible list still collapsed to `6` items even though the raw pool was `25`.
|
||||||
|
- The user wants in-modal login/download for Envato and Artgrid rather than preview-only media mode.
|
||||||
|
- How it was verified:
|
||||||
|
- log review from `ai-media-hub-2026-03-16T06-00-31-359Z.log`
|
||||||
|
- code inspection of post-Gemini backfill and modal rendering path
|
||||||
|
- What is still risky or incomplete:
|
||||||
|
- Artgrid candidate volume is still often low because SearXNG is returning many `0`-result queries for current Artgrid query templates.
|
||||||
|
- If a browser still holds older frontend assets, a hard refresh may be required before the latest modal/preview behavior appears.
|
||||||
|
|
||||||
- Date: `2026-03-16`
|
- Date: `2026-03-16`
|
||||||
- What changed:
|
- What changed:
|
||||||
- Significantly increased backend debug logging volume and routed it into the existing WebSocket `debug` stream so the in-app `Logs` panel captures much deeper request, search, preview, Gemini, and ranking traces.
|
- Significantly increased backend debug logging volume and routed it into the existing WebSocket `debug` stream so the in-app `Logs` panel captures much deeper request, search, preview, Gemini, and ranking traces.
|
||||||
|
|||||||
@@ -458,6 +458,14 @@ func (a *App) searchMedia(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
merged := services.MergeRecommendations(recommended, scored, 20)
|
merged := services.MergeRecommendations(recommended, scored, 20)
|
||||||
|
if geminiErr != nil {
|
||||||
|
merged = services.BackfillRecommendations(
|
||||||
|
merged,
|
||||||
|
scored,
|
||||||
|
12,
|
||||||
|
"Gemini 배치 일부가 실패해 미리보기 가능한 상위 후보를 보강했습니다.",
|
||||||
|
)
|
||||||
|
}
|
||||||
merged = services.RandomizeTopRecommendations(merged, 8)
|
merged = services.RandomizeTopRecommendations(merged, 8)
|
||||||
warning := ""
|
warning := ""
|
||||||
if geminiErr != nil {
|
if geminiErr != nil {
|
||||||
|
|||||||
@@ -355,6 +355,38 @@ func MergeRecommendations(recommended []AIRecommendation, ranked []SearchResult,
|
|||||||
return merged
|
return merged
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BackfillRecommendations(existing []AIRecommendation, ranked []SearchResult, limit int, reason string) []AIRecommendation {
|
||||||
|
merged := make([]AIRecommendation, 0, min(limit, len(ranked)))
|
||||||
|
seen := map[string]bool{}
|
||||||
|
for _, item := range existing {
|
||||||
|
if item.Link == "" || seen[item.Link] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seen[item.Link] = true
|
||||||
|
merged = append(merged, item)
|
||||||
|
}
|
||||||
|
for _, item := range ranked {
|
||||||
|
if len(merged) >= limit || item.Link == "" || seen[item.Link] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(item.ThumbnailURL) == "" && strings.TrimSpace(item.PreviewVideoURL) == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seen[item.Link] = true
|
||||||
|
merged = append(merged, AIRecommendation{
|
||||||
|
Title: item.Title,
|
||||||
|
Link: item.Link,
|
||||||
|
Snippet: item.Snippet,
|
||||||
|
ThumbnailURL: item.ThumbnailURL,
|
||||||
|
PreviewVideoURL: item.PreviewVideoURL,
|
||||||
|
Source: item.Source,
|
||||||
|
Reason: reason,
|
||||||
|
Recommended: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return merged
|
||||||
|
}
|
||||||
|
|
||||||
func max(a, b int) int {
|
func max(a, b int) int {
|
||||||
if a > b {
|
if a > b {
|
||||||
return a
|
return a
|
||||||
|
|||||||
+1
-3
@@ -513,10 +513,8 @@ function openResultModal(item) {
|
|||||||
resetResultModalMedia();
|
resetResultModalMedia();
|
||||||
if (item.source === "Google Video") {
|
if (item.source === "Google Video") {
|
||||||
showResultModalFrame(buildResultModalEmbedURL(item));
|
showResultModalFrame(buildResultModalEmbedURL(item));
|
||||||
} else if (item.previewVideoUrl) {
|
|
||||||
showResultModalVideo(item.previewVideoUrl);
|
|
||||||
} else {
|
} else {
|
||||||
showResultModalThumbnail(item.thumbnailUrl, item.title || "");
|
showResultModalFrame(item.link || "about:blank");
|
||||||
}
|
}
|
||||||
showModal(resultModal);
|
showModal(resultModal);
|
||||||
logEvent("result:modal:open", { title: item.title, source: item.source, link: item.link });
|
logEvent("result:modal:open", { title: item.title, source: item.source, link: item.link });
|
||||||
|
|||||||
+1
-1
@@ -202,6 +202,6 @@
|
|||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script src="/app.js?v=20260316e" defer></script>
|
<script src="/app.js?v=20260316f" defer></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user