forked from xai-org/x-algorithm
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscorer.rs
More file actions
65 lines (59 loc) · 2.29 KB
/
Copy pathscorer.rs
File metadata and controls
65 lines (59 loc) · 2.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use crate::candidate_pipeline::{PipelineCandidate, PipelineQuery};
use crate::util;
use std::any::type_name_of_val;
use tonic::async_trait;
use tracing::warn;
/// Scorers update candidate fields (like a score field) and run sequentially
#[async_trait]
pub trait Scorer<Q, C>: Send + Sync
where
Q: PipelineQuery,
C: PipelineCandidate,
{
/// Decide if this scorer should run for the given query
fn enable(&self, _query: &Q) -> bool {
true
}
#[xai_stats_macro::receive_stats]
#[tracing::instrument(skip_all, name = "scorer", fields(name = self.name()))]
async fn run(&self, query: &Q, candidates: &[C]) -> Vec<Result<C, String>> {
let scored = self.score(query, candidates).await;
let expected_len = candidates.len();
if scored.len() == expected_len {
scored
} else {
let message = format!(
"Scorer length_mismatch expected={} got={}",
expected_len,
scored.len()
);
warn!(
"Skipped: length_mismatch expected={} got={}",
expected_len,
scored.len()
);
vec![Err(message); expected_len]
}
}
/// Score candidates by performing async operations.
/// Returns candidates with this scorer's fields populated.
///
/// IMPORTANT: The returned vector must have the same candidates in the same order as the input.
/// Dropping candidates in a hydrator is not allowed - use a filter stage instead.
async fn score(&self, query: &Q, candidates: &[C]) -> Vec<Result<C, String>>;
/// Update a single candidate with the scored fields.
/// Only the fields this scorer is responsible for should be copied.
fn update(&self, candidate: &mut C, scored: C);
/// Update all successfully scored candidates with the fields from `scored`.
/// Default implementation iterates and calls `update` for each pair.
fn update_all(&self, candidates: &mut [C], scored: Vec<Result<C, String>>) {
for (candidate, scored) in candidates.iter_mut().zip(scored) {
if let Ok(scored) = scored {
self.update(candidate, scored);
}
}
}
fn name(&self) -> &'static str {
util::short_type_name(type_name_of_val(self))
}
}