Add SearXNG and Brave recipe search providers with ranking
recipes.SearchProvider.Search(ctx, query, n) returns []Candidate{URL,
Title, Snippet}, appending " recipe" when the query lacks the word.
SearXNG calls {MEALQUEST_SEARXNG_URL}/search?q=…&format=json&categories=general
directly (the configured endpoint may be internal); Brave calls the Web
Search API with the key decrypted from recipe_search_settings. Redirects
are not followed; 401/403, 429, other non-2xx and malformed bodies map to
distinct errors.
recipes.Rank fetches and extracts the top 5 candidates, rejects those
without ingredients or an image, and scores the rest by
harness.Similarity of the recipe title to the dish name plus
completeness (ingredients, image, steps, minutes). harness.Similarity
exposes the existing Jaccard score used by Similar.
Maestro task 10c25cb5-3774-419c-87e1-3f87a3d1391d.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -239,6 +239,24 @@ automatic** (D-021).
|
||||
with two is `ErrManyRecipes`; a shape schema.org does not allow — such as
|
||||
a non-ISO-8601 duration like "20 minutes" or an empty one, or an image
|
||||
`@id` no node has — is `ErrMalformedRecipe`, never guessed at.
|
||||
- Recipe search (`recipes.SearchProvider`: `Search(ctx, query, n)` →
|
||||
`[]Candidate{URL, Title, Snippet}`, n 1–20) appends " recipe" to a query
|
||||
without that word. SearXNG is called at
|
||||
`{MEALQUEST_SEARXNG_URL}/search?q=…&format=json&categories=general` —
|
||||
directly, not through the Fetcher, since this configured endpoint may be
|
||||
on the internal network; Brave calls the Brave Web Search API with the
|
||||
key decrypted from `recipe_search_settings.api_key_ct`
|
||||
(`recipes.NewSearchProvider`). Redirects are not followed; 401/403 is
|
||||
`ErrSearchRefused`, 429 `ErrSearchRateLimited`, other non-2xx a
|
||||
`SearchStatusError`, and a body that is not the provider's JSON, over
|
||||
1 MB or with a result lacking an absolute http(s) URL `ErrSearchResponse`.
|
||||
- Ranking (`recipes.Rank`) fetches and extracts the top 5 candidates
|
||||
concurrently, rejects any whose recipe lacks ingredients or an image, and
|
||||
orders the rest by the token similarity of the recipe's title to the dish
|
||||
name (`harness.Similarity`, 0–1) plus a quarter for each of ingredients,
|
||||
image, steps and total minutes; ties keep search order. When every
|
||||
candidate is rejected the error is `ErrNoUsableRecipe` joined with each
|
||||
reason.
|
||||
- Photos are cached locally (`photos`) and processed with
|
||||
`golang.org/x/image`.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user