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:
@@ -125,6 +125,16 @@ pub fn load_profile(path: &Path) -> anyhow::Result<ProfileFile> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Load the exact standing-interest union used in the system prompt.
|
||||
pub fn load_standing_interests(
|
||||
opml_path: &Path,
|
||||
profile_path: &Path,
|
||||
) -> anyhow::Result<Vec<String>> {
|
||||
let opml = parse_interests(opml_path)?;
|
||||
let profile = load_profile(profile_path)?;
|
||||
Ok(union_interests(opml, profile.interests))
|
||||
}
|
||||
|
||||
fn union_interests(opml: Vec<String>, profile: Vec<String>) -> Vec<String> {
|
||||
let mut seen = BTreeSet::new();
|
||||
let mut out = Vec::new();
|
||||
|
||||
Reference in New Issue
Block a user