Grounding pipeline and recipe-search settings API #70
+14
-6
@@ -299,12 +299,20 @@ automatic** (D-021).
|
|||||||
recorded twice. Files written for a transaction that rolls back are
|
recorded twice. Files written for a transaction that rolls back are
|
||||||
removed by the caller (`RemovePhotoFiles`).
|
removed by the caller (`RemovePhotoFiles`).
|
||||||
- Grounding (`recipes.Grounder`) ties these together.
|
- Grounding (`recipes.Grounder`) ties these together.
|
||||||
`Ground(ctx, dishName, query)` searches for the top 5 candidates; if one
|
`Ground(ctx, dishName, query)` searches for the top 5 candidates and ranks
|
||||||
is already a stored `source_url`, the first such is returned without
|
them all, stored and new alike: a candidate whose `source_url` is already
|
||||||
fetching anything. Otherwise it ranks them and tries each ranked recipe
|
stored is scored on its stored recipe (title, ingredients, steps, times,
|
||||||
best first: download its photo, run `normalize_recipe`, then store the
|
photo source) and its page is never refetched; every other candidate is
|
||||||
photo, recipe, ingredients and steps in **one transaction** (an existing
|
fetched and extracted. Ranking alone decides between them. It then tries
|
||||||
`source_url` is updated in place). It returns `Grounded{recipe_id,
|
each ranked candidate best first. A stored one is returned as it is, so a
|
||||||
|
stored recipe is reused only when it ranks above every new candidate that
|
||||||
|
grounds. A new one is grounded in this order: (1) `DownloadPhoto` —
|
||||||
|
the download and validation step of photo caching — (2)
|
||||||
|
`normalize_recipe`, then (3) one **transaction** that runs `CachePhoto`
|
||||||
|
(scales and writes the photo files and records the `photos` row) and
|
||||||
|
stores the recipe, ingredients and steps (an existing `source_url` is
|
||||||
|
updated in place); files written for a rolled-back transaction are
|
||||||
|
removed. It returns `Grounded{recipe_id,
|
||||||
photo_id, method, minutes_total, difficulty, source_url, site_name}`. A
|
photo_id, method, minutes_total, difficulty, source_url, site_name}`. A
|
||||||
candidate whose photo fails or whose model output is unusable
|
candidate whose photo fails or whose model output is unusable
|
||||||
(`llm.ErrBadOutput`) is passed over; when none grounds, the error is a
|
(`llm.ErrBadOutput`) is passed over; when none grounds, the error is a
|
||||||
|
|||||||
@@ -319,6 +319,11 @@ func (g *Grounder) storedRecipe(ctx context.Context, sourceURL string) (storedRe
|
|||||||
// ground downloads r's photo, normalizes it and stores it as sourceURL's
|
// ground downloads r's photo, normalizes it and stores it as sourceURL's
|
||||||
// recipe. A problem with this recipe is returned as reason, so the caller
|
// recipe. A problem with this recipe is returned as reason, so the caller
|
||||||
// can try another; err is a failure that is not the recipe's.
|
// can try another; err is a failure that is not the recipe's.
|
||||||
|
//
|
||||||
|
// The order is fixed: the photo is downloaded and validated first, so a
|
||||||
|
// recipe without a usable photo never costs a normalize_recipe call; then
|
||||||
|
// normalize_recipe runs; then save records the photo (CachePhoto) and the
|
||||||
|
// recipe in one transaction.
|
||||||
func (g *Grounder) ground(ctx context.Context, sourceURL string, r Recipe) (gr Grounded, reason, err error) {
|
func (g *Grounder) ground(ctx context.Context, sourceURL string, r Recipe) (gr Grounded, reason, err error) {
|
||||||
photo, err := g.photos.DownloadPhoto(ctx, r.ImageURL)
|
photo, err := g.photos.DownloadPhoto(ctx, r.ImageURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user