Judge each post with a brief of the product, and let a fitted model decide who is a lead - #96
Merged
Merged
Conversation
…ecide who is a lead The product reading now also writes a brief, in the same Muse call on high effort. It holds the product's precise kind, the neighbouring kinds it is not, who pays and who only talks, and example asks on each side of the line. It is kept apart from the profile because it may use what the site does not say. Projects made before briefs get one from a `brief` job at boot, and a profile edit queues one. The job then queues the rescore. The judge asks about one post per request (0.843 AUC one at a time against 0.828 ten at a time). It asks five narrow signal questions beside its own and, where there is a brief, three built from it: which kind of thing the person wants among the product and its neighbours, which group they are in, and whether the post reads like the brief's good asks rather than its near misses. The gates no longer decide from fit and intent. After the shared reading has found a buyer with an open need, a logistic model over every answer decides. It was fitted on 2,362 posts labelled against 172 products' sites, and the feed is sorted by it. Out of fold, at the gates' own recall, it shows 69% good and 5% bad leads against 62% and 7%. On the 442 leads labelled 2026-09-22 end to end, the buyer lane goes from 38% good and 18% bad to 51% and 10%. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…d model on those briefs On high effort the onboarding reading took a median 75s against 32s on low, while the user watches it. Through the scan's own pipeline on 2,256 labelled posts, low-effort briefs give 68% good and 7% bad leads against 70% and 6% on high, so both the reading and the brief job now use the default low effort, and the effort option is gone. The lead model with a brief is refitted on answers judged against low-effort briefs. Out of fold it shows 67% good and 7% bad at the old gates' recall. On the 442 leads labelled 2026-09-22 end to end, the buyer lane shows 146 posts, 49% good and 13% bad, keeping 71 of 106 good leads. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts: # drizzle/meta/0028_snapshot.json # drizzle/meta/_journal.json
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.
Why
After #94, production buyer leads were 38% good and 18% bad on the 442 leads labelled 2026-09-22. Experiments on 2,362 labelled posts traced this to how Jev was used, not to Jev itself. Ten posts per request distracted the model. Similarity was asked as broad yes/no questions. The market knowledge Jev can't infer, such as price tier and adjacent products, was never in its state. Answers were combined with hand-set 0.5 cutoffs.
What
Brief. The onboarding reading (one Muse call, still on low effort) also writes a brief:
It is stored in
projects.briefand never shown as the profile, because it may use what the site doesn't say.briefjob. It's seeded at boot, starting 3 minutes in and spaced 5 seconds apart, so the outgoing revision can't claim it.briefjob too.Judge. One post per request (
SCORE_BATCH_SIZE1; the shared reading stays at 10). It asks five narrow signal questions, plus three built from the brief:wanted_kind: a choice between the product's kind and its neighbours;author_group: which buyer or non-buyer group the author belongs to;is_lead_like: a yes/no whose criteria carry the brief's good asks and near misses as examples.Decision. Seller, helper, resolved and no-need are still settled by the shared reading. After that, a logistic model over every answer decides whether someone is a lead. Its weights are in
leadModelWeights.ts: one set with a brief, one without. The feed score is built from the same model.SCORER_VERSIONis now2026-09-22.2.Measured
Out of fold, grouped by product, on 2,362 posts labelled against 172 products' own sites (2,257 of them with a brief), at the old gates' own recall:
End to end with
scorer:evalon the 442 leads labelled 2026-09-22 (in-sample for the weights):Effort. Timed and scored through this PR's pipeline on 167 sites and 2,256 posts:
Low adds about 3 seconds to onboarding. The brief job for older projects runs on low too, and the weights are fitted on low-effort briefs.
Cost.
Tests
vitestpasses all 547 tests.jobs.test.ts"seeds a scan" now has a 60s timeout, because it walks every project in the test database.🤖 Generated with Claude Code