Improve Vertex search result extraction
Some checks are pending
build-push / docker (push) Waiting to run
Some checks are pending
build-push / docker (push) Waiting to run
This commit is contained in:
@@ -263,6 +263,10 @@ func (a *App) searchMedia(c *gin.Context) {
|
||||
c.JSON(http.StatusBadGateway, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
if len(results) == 0 {
|
||||
c.JSON(http.StatusOK, gin.H{"results": []services.AIRecommendation{}, "warning": "Vertex AI Search returned no renderable results. Check your website indexing fields and thumbnails."})
|
||||
return
|
||||
}
|
||||
|
||||
recommended, err := a.GeminiService.Recommend(req.Query, results)
|
||||
if err != nil {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
neturl "net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -121,15 +122,33 @@ func (s *SearchService) searchLite(query string, imageSearch bool) ([]SearchResu
|
||||
|
||||
results := make([]SearchResult, 0, len(payload.Results))
|
||||
for _, item := range payload.Results {
|
||||
link := firstString(item.Document.StructData, "link", "url", "uri")
|
||||
title := firstString(item.Document.StructData, "title", "name")
|
||||
displayLink := firstString(item.Document.StructData, "site_name", "displayLink")
|
||||
snippet := firstString(item.Document.DerivedStructData, "snippets", "snippet")
|
||||
thumb := firstString(item.Document.DerivedStructData, "link", "thumbnail", "image", "image_url")
|
||||
link := firstNonEmpty(
|
||||
firstString(item.Document.DerivedStructData, "link", "url", "uri"),
|
||||
firstString(item.Document.StructData, "link", "url", "uri"),
|
||||
)
|
||||
title := firstNonEmpty(
|
||||
firstString(item.Document.DerivedStructData, "title", "name"),
|
||||
firstString(item.Document.StructData, "title", "name"),
|
||||
)
|
||||
displayLink := firstNonEmpty(
|
||||
firstString(item.Document.DerivedStructData, "displayLink", "site_name"),
|
||||
firstString(item.Document.StructData, "displayLink", "site_name"),
|
||||
)
|
||||
snippet := firstNonEmpty(
|
||||
firstString(item.Document.DerivedStructData, "snippets", "snippet", "extractive_answers"),
|
||||
firstString(item.Document.StructData, "snippets", "snippet", "description"),
|
||||
)
|
||||
thumb := firstNonEmpty(
|
||||
firstString(item.Document.DerivedStructData, "thumbnail", "image", "image_url", "link"),
|
||||
firstString(item.Document.StructData, "thumbnail", "image", "image_url"),
|
||||
)
|
||||
if thumb == "" {
|
||||
thumb = firstString(item.Document.StructData, "thumbnail", "image", "image_url")
|
||||
thumb = deriveThumbnail(link)
|
||||
}
|
||||
if thumb == "" || link == "" {
|
||||
if title == "" {
|
||||
title = displayLink
|
||||
}
|
||||
if link == "" {
|
||||
continue
|
||||
}
|
||||
results = append(results, SearchResult{
|
||||
@@ -144,6 +163,15 @@ func (s *SearchService) searchLite(query string, imageSearch bool) ([]SearchResu
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func firstNonEmpty(values ...string) string {
|
||||
for _, value := range values {
|
||||
if strings.TrimSpace(value) != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func firstString(values map[string]any, keys ...string) string {
|
||||
for _, key := range keys {
|
||||
value, ok := values[key]
|
||||
@@ -161,13 +189,13 @@ func firstString(values map[string]any, keys ...string) string {
|
||||
return text
|
||||
}
|
||||
if mapped, ok := item.(map[string]any); ok {
|
||||
if text := firstString(mapped, "snippet", "htmlSnippet", "url"); text != "" {
|
||||
if text := firstString(mapped, "snippet", "htmlSnippet", "url", "link", "value", "content"); text != "" {
|
||||
return text
|
||||
}
|
||||
}
|
||||
}
|
||||
case map[string]any:
|
||||
if text := firstString(typed, "snippet", "htmlSnippet", "url"); text != "" {
|
||||
if text := firstString(typed, "snippet", "htmlSnippet", "url", "link", "value", "content"); text != "" {
|
||||
return text
|
||||
}
|
||||
}
|
||||
@@ -175,6 +203,30 @@ func firstString(values map[string]any, keys ...string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func deriveThumbnail(link string) string {
|
||||
if link == "" {
|
||||
return ""
|
||||
}
|
||||
if videoID := extractYouTubeID(link); videoID != "" {
|
||||
return "https://i.ytimg.com/vi/" + videoID + "/hqdefault.jpg"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func extractYouTubeID(link string) string {
|
||||
patterns := []*regexp.Regexp{
|
||||
regexp.MustCompile(`(?:v=|\/shorts\/|\/embed\/)([A-Za-z0-9_-]{11})`),
|
||||
regexp.MustCompile(`youtu\.be\/([A-Za-z0-9_-]{11})`),
|
||||
}
|
||||
for _, pattern := range patterns {
|
||||
matches := pattern.FindStringSubmatch(link)
|
||||
if len(matches) == 2 {
|
||||
return matches[1]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func inferSource(displayLink string) string {
|
||||
switch {
|
||||
case strings.Contains(displayLink, "youtube"):
|
||||
|
||||
Reference in New Issue
Block a user