interests backfill: use cached vectors when the Voyage key is unset

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K9PrjtUS16PAQve8D4bHgc
This commit is contained in:
2026-09-13 05:55:06 +00:00
co-authored by Claude Fable 5.1
parent 57ba47a5a0
commit 7063b835db
+17 -10
View File
@@ -638,12 +638,19 @@ async fn cmd_interests_backfill(config: &Config, db: &Db) -> Result<String> {
.into_iter() .into_iter()
.map(|interest| (interest.name, interest.id)) .map(|interest| (interest.name, interest.id))
.collect::<HashMap<_, _>>(); .collect::<HashMap<_, _>>();
let service = if config.voyage.enabled { // Like the pipeline: a missing key means cached vectors only, not a failure.
embedding::EmbeddingService::real(db.clone(), config.voyage.clone()) let service = match config.voyage.enabled {
.context("building the Voyage client")? true => match embedding::EmbeddingService::real(db.clone(), config.voyage.clone()) {
} else { Ok(service) => Some(service),
embedding::EmbeddingService::cached_only(db.clone(), config.voyage.clone()) Err(embedding::EmbeddingError::MissingApiKey) => None,
Err(error) => return Err(error).context("building the Voyage client"),
},
false => None,
}; };
let cached_only = service.is_none();
let service = service.unwrap_or_else(|| {
embedding::EmbeddingService::cached_only(db.clone(), config.voyage.clone())
});
let interest_embeddings = service.interests(&names).await?; let interest_embeddings = service.interests(&names).await?;
let mut matches = curate::signals::interest_matches(&article_embeddings, &interest_embeddings) let mut matches = curate::signals::interest_matches(&article_embeddings, &interest_embeddings)
.into_iter() .into_iter()
@@ -653,12 +660,12 @@ async fn cmd_interests_backfill(config: &Config, db: &Db) -> Result<String> {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
matches.sort_by_key(|(article_id, _)| *article_id); matches.sort_by_key(|(article_id, _)| *article_id);
let inserted = interests::insert_matches_if_absent(db, &matches, &ids).await?; let inserted = interests::insert_matches_if_absent(db, &matches, &ids).await?;
if config.voyage.enabled { if cached_only {
Ok(format!("wrote {inserted} interest match rows"))
} else {
Ok(format!( Ok(format!(
"voyage disabled; used cached interest vectors and wrote {inserted} interest match rows" "no Voyage client; used cached interest vectors and wrote {inserted} interest match rows"
)) ))
} else {
Ok(format!("wrote {inserted} interest match rows"))
} }
} }
@@ -1827,7 +1834,7 @@ mod tests {
let message = cmd_interests_backfill(&config, &db).await.unwrap(); let message = cmd_interests_backfill(&config, &db).await.unwrap();
assert_eq!( assert_eq!(
message, message,
"voyage disabled; used cached interest vectors and wrote 1 interest match rows" "no Voyage client; used cached interest vectors and wrote 1 interest match rows"
); );
let rows = sqlx::query( let rows = sqlx::query(
"SELECT article_id, interest_id, run_id, cos, z "SELECT article_id, interest_id, run_id, cos, z