This commit is contained in:
@@ -147,6 +147,11 @@ func (g *GeminiService) ExpandImageQueries(query string) ([]string, error) {
|
||||
}
|
||||
jsonText, err := extractJSONObject(rawText)
|
||||
if err != nil {
|
||||
if looseQueries := parseLooseImageExpansionLines(rawText); len(looseQueries) == 5 {
|
||||
g.setCachedExpansion(cacheKey, looseQueries, 15*time.Minute)
|
||||
g.debug("gemini:image_expand_success", map[string]any{"query": trimmed, "queries": looseQueries, "mode": "loose_text"})
|
||||
return looseQueries, nil
|
||||
}
|
||||
g.debug("gemini:image_expand_parse_error", map[string]any{"query": trimmed, "error": err.Error()})
|
||||
g.setCachedExpansion(cacheKey, fallback, 15*time.Minute)
|
||||
return fallback, err
|
||||
@@ -801,6 +806,34 @@ func truncateForError(text string, limit int) string {
|
||||
return trimmed[:limit] + "..."
|
||||
}
|
||||
|
||||
func parseLooseImageExpansionLines(text string) []string {
|
||||
candidates := make([]string, 0, 8)
|
||||
for _, line := range strings.Split(text, "\n") {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
if trimmed == "" {
|
||||
continue
|
||||
}
|
||||
trimmed = strings.TrimPrefix(trimmed, "- ")
|
||||
trimmed = strings.TrimPrefix(trimmed, "* ")
|
||||
trimmed = strings.TrimPrefix(trimmed, "1. ")
|
||||
trimmed = strings.TrimPrefix(trimmed, "2. ")
|
||||
trimmed = strings.TrimPrefix(trimmed, "3. ")
|
||||
trimmed = strings.TrimPrefix(trimmed, "4. ")
|
||||
trimmed = strings.TrimPrefix(trimmed, "5. ")
|
||||
trimmed = strings.TrimSpace(strings.Trim(trimmed, "\"'`"))
|
||||
lower := strings.ToLower(trimmed)
|
||||
if strings.HasPrefix(lower, "here is") || strings.HasPrefix(lower, "json") || strings.HasPrefix(lower, "output") {
|
||||
continue
|
||||
}
|
||||
candidates = append(candidates, trimmed)
|
||||
}
|
||||
queries := normalizeImageExpansionQueries(candidates)
|
||||
if len(queries) < 5 {
|
||||
return nil
|
||||
}
|
||||
return queries[:5]
|
||||
}
|
||||
|
||||
func normalizeKoreanReason(reason string) string {
|
||||
trimmed := strings.TrimSpace(reason)
|
||||
if trimmed == "" {
|
||||
|
||||
@@ -145,6 +145,26 @@ func TestExpandImageQueriesFallsBackWhenGeminiFails(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpandImageQueriesAcceptsLoosePlainTextList(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"candidates":[{"content":{"parts":[{"text":"Here is the JSON requested\n1. cute cat\n2. cute cat gif\n3. cat reaction gif\n4. cat meme gif\n5. animated cat sticker"}]}}]}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
service := NewGeminiService("dummy-key", "gemini-2.5-flash")
|
||||
service.Client = &http.Client{Timeout: 2 * time.Second}
|
||||
service.GenerateEndpoint = server.URL
|
||||
|
||||
queries, err := service.ExpandImageQueries("고양이")
|
||||
if err != nil {
|
||||
t.Fatalf("expected loose plain-text list to be accepted, got %v", err)
|
||||
}
|
||||
if len(queries) != 5 || queries[0] != "cute cat" || queries[4] != "animated cat sticker" {
|
||||
t.Fatalf("unexpected loose parsed queries: %#v", queries)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelectUnevaluatedCandidatesSkipsReviewedLinks(t *testing.T) {
|
||||
ranked := []SearchResult{
|
||||
{Link: "https://a.example"},
|
||||
|
||||
@@ -168,7 +168,6 @@ func (s *GiphyService) SearchImages(query string, requestedMax int) (GiphySearch
|
||||
expandedQueries, expansionErr := s.expandQueries(response.OriginalQuery)
|
||||
response.ExpandedQueries = expandedQueries
|
||||
if expansionErr != nil {
|
||||
response.Warning = "Query expansion failed, using fallback search terms."
|
||||
s.debug("giphy:query_expansion_fallback", map[string]any{
|
||||
"query": response.OriginalQuery,
|
||||
"queries": expandedQueries,
|
||||
|
||||
Reference in New Issue
Block a user