feat(search): P3.1 filters and multi-query merge
Native include/exclude domains, time_range, topic, exact_match, min_score, and up to 4 queries fused with RRF. Honesty notes stay off the Warn/fail path. Tavily keeps include_answer false and sets auto_parameters false. Cache key is canonical JSON. CLI flags and skill recipe included.
This commit is contained in:
+18
-10
@@ -59,7 +59,7 @@ func (s *SearxNG) Name() string { return NameSearxNG }
|
||||
func (s *SearxNG) Ready() bool { return s != nil && s.Client.Ready() }
|
||||
func (s *BraveLLM) Ready() bool { return s != nil && s.Client.Ready() }
|
||||
|
||||
func (s *SearxNG) Search(ctx context.Context, query string, k int) SourceOut {
|
||||
func (s *SearxNG) Search(ctx context.Context, query string, k int, f Filter) SourceOut {
|
||||
if s == nil || s.Client == nil {
|
||||
return SourceOut{Warn: NameSearxNG + ": error"}
|
||||
}
|
||||
@@ -71,10 +71,17 @@ func (s *SearxNG) Search(ctx context.Context, query string, k int) SourceOut {
|
||||
if err != nil {
|
||||
return SourceOut{Warn: warnErr(NameSearxNG, err)}
|
||||
}
|
||||
qtext, notes := searxQueryAndNotes(query, f)
|
||||
q := u.Query()
|
||||
q.Set("q", query)
|
||||
q.Set("q", qtext)
|
||||
q.Set("format", "json")
|
||||
q.Set("pageno", "1")
|
||||
if f.TimeRange != "" {
|
||||
q.Set("time_range", f.TimeRange)
|
||||
}
|
||||
if f.Topic == "news" {
|
||||
q.Set("categories", "news")
|
||||
}
|
||||
u.RawQuery = q.Encode()
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
|
||||
if err != nil {
|
||||
@@ -92,10 +99,11 @@ func (s *SearxNG) Search(ctx context.Context, query string, k int) SourceOut {
|
||||
}
|
||||
var env struct {
|
||||
Results []struct {
|
||||
URL string `json:"url"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Score float64 `json:"score"`
|
||||
URL string `json:"url"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Score float64 `json:"score"`
|
||||
PublishedDate string `json:"publishedDate"`
|
||||
} `json:"results"`
|
||||
}
|
||||
if err := readJSON(resp, &env); err != nil {
|
||||
@@ -107,9 +115,9 @@ func (s *SearxNG) Search(ctx context.Context, query string, k int) SourceOut {
|
||||
if r.URL == "" {
|
||||
continue
|
||||
}
|
||||
hits = append(hits, Hit{URL: r.URL, Title: r.Title, Snippet: r.Content, Score: r.Score, Source: NameSearxNG})
|
||||
hits = append(hits, Hit{URL: r.URL, Title: r.Title, Snippet: r.Content, Score: r.Score, Source: NameSearxNG, PublishedDate: r.PublishedDate})
|
||||
}
|
||||
return SourceOut{Hits: hits}
|
||||
return SourceOut{Hits: hits, Notes: notes}
|
||||
}
|
||||
|
||||
// BraveLLM is GET {url}?q= with X-Subscription-Token.
|
||||
@@ -120,7 +128,7 @@ type BraveLLM struct {
|
||||
|
||||
func (s *BraveLLM) Name() string { return NameBraveLLM }
|
||||
|
||||
func (s *BraveLLM) Search(ctx context.Context, query string, k int) SourceOut {
|
||||
func (s *BraveLLM) Search(ctx context.Context, query string, k int, f Filter) SourceOut {
|
||||
if s == nil || s.Client == nil {
|
||||
return SourceOut{Warn: NameBraveLLM + ": error"}
|
||||
}
|
||||
@@ -159,7 +167,7 @@ func (s *BraveLLM) Search(ctx context.Context, query string, k int) SourceOut {
|
||||
if len(hits) >= 0 {
|
||||
credits = 1
|
||||
}
|
||||
return SourceOut{Hits: hits, Credits: credits}
|
||||
return SourceOut{Hits: hits, Credits: credits, Notes: braveNotes(f)}
|
||||
}
|
||||
|
||||
func mapBrave(raw []byte) []Hit {
|
||||
|
||||
Reference in New Issue
Block a user