Curation v2 step 3: Voyage embeddings, cheap signals, candidate telemetry
- embedding.rs: EmbeddingBackend + VoyageBackend, batched bounded-concurrency client with its own UsageMeter, f32 BLOB codec, article/interest embedding cache keyed by model, dimension and sha256 of the embedded text. - signals.rs: z-scored interest match, decayed rated-neighbour preference with the knn gate, feed affinity with the feed gate, social, text heuristic without social terms, mid-rank percentile normalizer, preliminary blend. - telemetry.rs: candidate_runs writer with §7.5 signals_json, explain and near-misses renderers, prune. - [voyage] and the full [curation.ranking] config with validation. - CLI: explain, features backfill|prune, generate --skip-embeddings. - Pipeline: hygiene rows, embed and signals stages before the old prefilter; same-date regeneration no longer excludes its own picks. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A1rCLQeKBgnBo3oTgHuTMe
This commit is contained in:
+24
-1
@@ -90,7 +90,7 @@ impl PrefilterContext {
|
||||
let since = today
|
||||
.checked_sub(jiff::Span::new().days(STALE_LOOKBACK_DAYS))
|
||||
.unwrap_or(today);
|
||||
let already_published = db.previously_published_ids().await?;
|
||||
let already_published = db.previously_published_ids_before(today).await?;
|
||||
let recently_rejected = db.recently_low_scored_ids(STALE_LOW_SCORE, since).await?;
|
||||
tracing::debug!(
|
||||
published = already_published.len(),
|
||||
@@ -197,6 +197,29 @@ pub fn social_points(social_score: f64) -> f64 {
|
||||
MAX_SOCIAL_POINTS * (social_score / SOCIAL_SATURATION).min(1.0).sqrt()
|
||||
}
|
||||
|
||||
/// Text-only heuristic used by personalized ranking (§9.3).
|
||||
pub fn text_heuristic(article: &Article) -> f64 {
|
||||
longform_points(article.word_count)
|
||||
- excerpt_only_penalty(article)
|
||||
- roundup_penalty(&article.title)
|
||||
}
|
||||
|
||||
pub fn excerpt_only_penalty(article: &Article) -> f64 {
|
||||
if article.excerpt_only {
|
||||
EXCERPT_ONLY_PENALTY
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn roundup_penalty(title: &str) -> f64 {
|
||||
if looks_like_roundup(title) {
|
||||
ROUNDUP_TITLE_PENALTY
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Score one article 0–100 from word count, social proof, source signals,
|
||||
/// and the excerpt/roundup/blocklist penalties (§3.5).
|
||||
pub fn score_article(article: &Article, _ctx: &PrefilterContext, cfg: &Config) -> f64 {
|
||||
|
||||
Reference in New Issue
Block a user