feat: MPS-24 Phase 2 — auto-suggest tags from title + description
Operator with 481 untagged products (printableprompts.com) gets a one-click path to a usable categorization without hand-tagging each product. Strictly suggest-then-approve — nothing writes Tag or ProductTag rows until the operator clicks Apply on a cluster. - lib/tag_suggest.py: pure-function clusterer. Tokenize title (weight 3) + description (weight 1, capped at 100 unique tokens per product), strip markdown / URLs / HTML, English + per-shop stopwords, simple suffix-strip stemmer, group by stem, drop stems matching existing tag slugs, rank by product count, label each cluster with the most frequent original word for its stem. No new deps, no ML. - scripts/backfill_tags.py: CLI preview + --apply for a single shop. - views/shop.py: shop_tags gains action=apply_suggestion (creates tag + bulk-attaches every product in cluster) and action=dismiss_suggestion (adds the cluster's words to shop.tag_stopwords_json so it never resurfaces). ?show_suggestions=1 triggers the cluster compute. - templates/shop_tags.j2: "Suggest categories from titles + descriptions" button + suggestions well with per-cluster sample titles, Apply, and Dismiss buttons. - 15 new tests (11 unit over tokenize / stem / cluster + 4 functional over the suggest/apply/dismiss flow). 1064 total passing. On a printableprompts-style sample the clusterer surfaces Math, Reading, Literacy, Seasonal, Novel, Activities, Comprehension — matching what an operator would manually pick.
This commit is contained in:
parent
c03ca53fb4
commit
5dbbe697b6
11 changed files with 884 additions and 29 deletions
14
CLAUDE.md
14
CLAUDE.md
|
|
@ -477,9 +477,17 @@ filters on no-JS. With JS, `static/js/tag_filter.js` intercepts clicks
|
|||
and filters the grid in place via `data-tag-slugs` attribute on
|
||||
`.serp-item`, zero network cost, fewer clicks to purchase.
|
||||
|
||||
Phase 2 (this ticket, follow-on commit): sectioned-lane layout (`==2`)
|
||||
+ deterministic auto-tagger script (`scripts/backfill_tags.py`) that
|
||||
clusters by shared title keywords minus stopwords.
|
||||
Phase 2 (shipped): deterministic title-plus-description auto-tagger
|
||||
in `lib/tag_suggest.py`. Title tokens weight × 3, description × 1 (capped
|
||||
at 100 unique tokens per product). Pipeline: tokenize → English + per-shop
|
||||
stopwords → suffix-strip stem → group by stem → drop stems matching
|
||||
existing tag slugs → rank by product count → label = most frequent
|
||||
original word for that stem. Surface: button on `/s/{id}/tags` →
|
||||
"Suggested categories" well with one-click Apply / Dismiss per cluster
|
||||
(`action=apply_suggestion` / `action=dismiss_suggestion`). CLI:
|
||||
`python -m make_post_sell.scripts.backfill_tags data/development.ini
|
||||
--shop=<id> [--apply]`. **Never auto-commits** — operator approves
|
||||
every cluster.
|
||||
|
||||
Phase 3 (this ticket, gated): ML categorization via uncloseai endpoint
|
||||
behind `app.features.ml_categorization.enabled` kill switch (mirror MPS-22).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue