Repository navigation
Ranker v2: judged quality prior, featured home layout, evals - #38
Merged
Merged
Conversation
Replace the feed ranker's calorie/ingredient heuristics with a per-food quality rating (role + appeal), and measure ranking with an offline eval. Ranking - food_quality.py: role/appeal per food from data/food_labels.json (2,021 judged foods, hand-editable); unseen foods rated by a small numpy-only linear model. No API calls at ranking time. - ranker.py: gate out toppings/condiments/plain staples, score by appeal + rarity + favorites + taste affinity + student interest. Up to 3 dishes per station; the best 20 per hall and meal are flagged `featured`. - Taste affinity sums per-favorite similarity (z-scored against the day's menu) and is normalized by sqrt(#favorites). - Student interest counts distinct students per dish (home-feed views count half) and gains weight as the app gathers evidence. Bug fixes - Scraper set `frequency` on one meal-period row only (UpdateOne), and the ranker treated a missing value as a rotating special. - Feed de-duplicated rec_nums across halls and meals, hiding dishes served at both lunch and dinner. - item_views/search_queries timestamps are BSON dates but were compared to ISO strings, so view popularity, recent views and trending searches matched nothing. - Trending required only one favorite. iOS - Home feed lays out by `featured` (legacy 5x3 fallback when absent); See More reveals the rest. Removed the substring name filter that hid dishes like "Butternut ..." and "... w/ Ranch". Versioned the feed cache. Evals - evals/run_eval.py replays 14 days of menus and grades what the home screen shows; pytest gates fail CI on a ranking regression. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Replaces the home-feed ranker and adds an offline eval so ranking changes are measured instead of guessed.
data/food_labels.json(2,021 judged foods, hand-editable). Unseen foods are rated by a 189 KB numpy-only model. No API calls at ranking time.featured.featured(falls back to 5 stations × 3 when the API doesn't send it); See More reveals the rest; removed the substring name filter; versioned the feed cache.Bugs fixed
frequencyto one meal-period row only → 88% of dinner rows had none, and the ranker treated that as a "rotating special".Results (14 days of real menus, guest view)
python evals/run_eval.pyprints the scorecard;pytestgates it.After merge
POST /api/backfill-frequencyonce (admin) to repair existing menu rows.UpdateManyfix.🤖 Generated with Claude Code