Clarify ranked minimal candidate selection

This commit is contained in:
fawney19
2026-04-27 15:11:02 +08:00
parent 517e84e5ae
commit f10f5f071d
6 changed files with 37 additions and 35 deletions

View File

@@ -1,7 +1,7 @@
use aether_data::DataLayerError; use aether_data::DataLayerError;
use aether_data_contracts::repository::candidate_selection::StoredMinimalCandidateSelectionRow; use aether_data_contracts::repository::candidate_selection::StoredMinimalCandidateSelectionRow;
use aether_scheduler_core::{ use aether_scheduler_core::{
auth_constraints_allow_api_format, build_minimal_candidate_selection, auth_constraints_allow_api_format, build_ranked_minimal_candidate_selection,
collect_global_model_names_for_required_capability, enumerate_minimal_candidate_selection, collect_global_model_names_for_required_capability, enumerate_minimal_candidate_selection,
normalize_api_format, resolve_requested_global_model_name, row_supports_requested_model, normalize_api_format, resolve_requested_global_model_name, row_supports_requested_model,
BuildMinimalCandidateSelectionInput, SchedulerAuthConstraints, BuildMinimalCandidateSelectionInput, SchedulerAuthConstraints,
@@ -161,7 +161,7 @@ pub(crate) async fn read_minimal_candidate_selection_with_priority_mode_and_affi
return Ok(Vec::new()); return Ok(Vec::new());
}; };
let auth_constraints = auth_snapshot.map(auth_snapshot_constraints); let auth_constraints = auth_snapshot.map(auth_snapshot_constraints);
build_minimal_candidate_selection(BuildMinimalCandidateSelectionInput { build_ranked_minimal_candidate_selection(BuildMinimalCandidateSelectionInput {
rows, rows,
normalized_api_format: &normalized_api_format, normalized_api_format: &normalized_api_format,
requested_model_name, requested_model_name,

View File

@@ -24,7 +24,7 @@ use aether_data_contracts::repository::video_tasks::{
UpsertVideoTask, VideoTaskLookupKey, VideoTaskStatus, VideoTaskWriteRepository, UpsertVideoTask, VideoTaskLookupKey, VideoTaskStatus, VideoTaskWriteRepository,
}; };
use aether_scheduler_core::{ use aether_scheduler_core::{
build_minimal_candidate_selection, BuildMinimalCandidateSelectionInput, build_ranked_minimal_candidate_selection, BuildMinimalCandidateSelectionInput,
SchedulerAuthConstraints, SchedulerPriorityMode, SchedulerAuthConstraints, SchedulerPriorityMode,
}; };
use serde_json::json; use serde_json::json;
@@ -622,7 +622,7 @@ async fn data_state_reads_minimal_candidate_selection_with_auth_filters() {
.map(|items| items.to_vec()), .map(|items| items.to_vec()),
}; };
let selection = build_minimal_candidate_selection(BuildMinimalCandidateSelectionInput { let selection = build_ranked_minimal_candidate_selection(BuildMinimalCandidateSelectionInput {
rows, rows,
normalized_api_format: "openai:chat", normalized_api_format: "openai:chat",
requested_model_name: "gpt-4.1", requested_model_name: "gpt-4.1",

View File

@@ -186,7 +186,7 @@ fn scheduler_candidate_runtime_paths_depend_on_scheduler_core_and_state_trait()
"candidate/mod.rs should depend on core minimal candidate DTO" "candidate/mod.rs should depend on core minimal candidate DTO"
); );
assert!( assert!(
!candidate_mod.contains("build_minimal_candidate_selection"), !candidate_mod.contains("build_ranked_minimal_candidate_selection"),
"candidate/mod.rs should not own the core minimal candidate builder anymore" "candidate/mod.rs should not own the core minimal candidate builder anymore"
); );
assert!( assert!(
@@ -487,7 +487,7 @@ fn scheduler_candidate_runtime_paths_depend_on_scheduler_core_and_state_trait()
let core_candidate_selection = let core_candidate_selection =
read_workspace_file("crates/aether-scheduler-core/src/candidate/selection.rs"); read_workspace_file("crates/aether-scheduler-core/src/candidate/selection.rs");
for expected in [ for expected in [
"build_minimal_candidate_selection", "build_ranked_minimal_candidate_selection",
"apply_scheduler_candidate_ranking", "apply_scheduler_candidate_ranking",
] { ] {
assert!( assert!(
@@ -571,7 +571,7 @@ fn scheduler_candidate_runtime_paths_depend_on_scheduler_core_and_state_trait()
"data/candidate_selection.rs should depend on core requested-model resolver" "data/candidate_selection.rs should depend on core requested-model resolver"
); );
assert!( assert!(
candidate_selection.contains("build_minimal_candidate_selection"), candidate_selection.contains("build_ranked_minimal_candidate_selection"),
"data/candidate_selection.rs should depend on core minimal candidate builder" "data/candidate_selection.rs should depend on core minimal candidate builder"
); );
assert!( assert!(

View File

@@ -14,7 +14,7 @@ pub use selectability::{
auth_api_key_concurrency_limit_reached, candidate_is_selectable_with_runtime_state, auth_api_key_concurrency_limit_reached, candidate_is_selectable_with_runtime_state,
candidate_runtime_skip_reason_with_state, CandidateRuntimeSelectabilityInput, candidate_runtime_skip_reason_with_state, CandidateRuntimeSelectabilityInput,
}; };
pub use selection::build_minimal_candidate_selection; pub use selection::build_ranked_minimal_candidate_selection;
pub use types::{ pub use types::{
BuildMinimalCandidateSelectionInput, SchedulerMinimalCandidateSelectionCandidate, BuildMinimalCandidateSelectionInput, SchedulerMinimalCandidateSelectionCandidate,
SchedulerPriorityMode, SchedulerPriorityMode,
@@ -33,7 +33,7 @@ mod tests {
use aether_data_contracts::repository::provider_catalog::StoredProviderCatalogKey; use aether_data_contracts::repository::provider_catalog::StoredProviderCatalogKey;
use super::{ use super::{
auth_api_key_concurrency_limit_reached, build_minimal_candidate_selection, auth_api_key_concurrency_limit_reached, build_ranked_minimal_candidate_selection,
candidate_is_selectable_with_runtime_state, candidate_supports_required_capability, candidate_is_selectable_with_runtime_state, candidate_supports_required_capability,
collect_global_model_names_for_required_capability, BuildMinimalCandidateSelectionInput, collect_global_model_names_for_required_capability, BuildMinimalCandidateSelectionInput,
CandidateRuntimeSelectabilityInput, SchedulerMinimalCandidateSelectionCandidate, CandidateRuntimeSelectabilityInput, SchedulerMinimalCandidateSelectionCandidate,
@@ -186,18 +186,19 @@ mod tests {
allowed_api_formats: Some(vec!["OPENAI:CHAT".to_string()]), allowed_api_formats: Some(vec!["OPENAI:CHAT".to_string()]),
allowed_models: Some(vec!["gpt-5".to_string()]), allowed_models: Some(vec!["gpt-5".to_string()]),
}; };
let candidates = build_minimal_candidate_selection(BuildMinimalCandidateSelectionInput { let candidates =
rows: vec![sample_row("1"), disallowed], build_ranked_minimal_candidate_selection(BuildMinimalCandidateSelectionInput {
normalized_api_format: "openai:chat", rows: vec![sample_row("1"), disallowed],
requested_model_name: "gpt-5", normalized_api_format: "openai:chat",
resolved_global_model_name: "gpt-5", requested_model_name: "gpt-5",
require_streaming: false, resolved_global_model_name: "gpt-5",
required_capabilities: None, require_streaming: false,
auth_constraints: Some(&constraints), required_capabilities: None,
affinity_key: None, auth_constraints: Some(&constraints),
priority_mode: SchedulerPriorityMode::Provider, affinity_key: None,
}) priority_mode: SchedulerPriorityMode::Provider,
.expect("candidate selection should build"); })
.expect("candidate selection should build");
assert_eq!(candidates.len(), 1); assert_eq!(candidates.len(), 1);
assert_eq!(candidates[0].provider_id, "provider-1"); assert_eq!(candidates[0].provider_id, "provider-1");
@@ -264,18 +265,19 @@ mod tests {
matching_capability.provider_priority = 10; matching_capability.provider_priority = 10;
let required_capabilities = serde_json::json!({"cache_1h": true}); let required_capabilities = serde_json::json!({"cache_1h": true});
let candidates = build_minimal_candidate_selection(BuildMinimalCandidateSelectionInput { let candidates =
rows: vec![missing_capability, matching_capability], build_ranked_minimal_candidate_selection(BuildMinimalCandidateSelectionInput {
normalized_api_format: "openai:chat", rows: vec![missing_capability, matching_capability],
requested_model_name: "gpt-5", normalized_api_format: "openai:chat",
resolved_global_model_name: "gpt-5", requested_model_name: "gpt-5",
require_streaming: false, resolved_global_model_name: "gpt-5",
required_capabilities: Some(&required_capabilities), require_streaming: false,
auth_constraints: None, required_capabilities: Some(&required_capabilities),
affinity_key: None, auth_constraints: None,
priority_mode: SchedulerPriorityMode::Provider, affinity_key: None,
}) priority_mode: SchedulerPriorityMode::Provider,
.expect("candidate selection should build"); })
.expect("candidate selection should build");
assert_eq!(candidates.len(), 2); assert_eq!(candidates.len(), 2);
assert_eq!(candidates[0].key_id, "key-2"); assert_eq!(candidates[0].key_id, "key-2");

View File

@@ -8,7 +8,7 @@ use super::types::{
BuildMinimalCandidateSelectionInput, SchedulerMinimalCandidateSelectionCandidate, BuildMinimalCandidateSelectionInput, SchedulerMinimalCandidateSelectionCandidate,
}; };
pub fn build_minimal_candidate_selection( pub fn build_ranked_minimal_candidate_selection(
input: BuildMinimalCandidateSelectionInput<'_>, input: BuildMinimalCandidateSelectionInput<'_>,
) -> Result<Vec<SchedulerMinimalCandidateSelectionCandidate>, DataLayerError> { ) -> Result<Vec<SchedulerMinimalCandidateSelectionCandidate>, DataLayerError> {
let priority_mode = input.priority_mode; let priority_mode = input.priority_mode;

View File

@@ -16,7 +16,7 @@ pub use auth::{
auth_constraints_allow_provider, provider_matches_allowed_value, SchedulerAuthConstraints, auth_constraints_allow_provider, provider_matches_allowed_value, SchedulerAuthConstraints,
}; };
pub use candidate::{ pub use candidate::{
auth_api_key_concurrency_limit_reached, build_minimal_candidate_selection, auth_api_key_concurrency_limit_reached, build_ranked_minimal_candidate_selection,
candidate_is_selectable_with_runtime_state, candidate_runtime_skip_reason_with_state, candidate_is_selectable_with_runtime_state, candidate_runtime_skip_reason_with_state,
candidate_supports_required_capability, collect_global_model_names_for_required_capability, candidate_supports_required_capability, collect_global_model_names_for_required_capability,
enumerate_minimal_candidate_selection, requested_capability_priority_for_candidate, enumerate_minimal_candidate_selection, requested_capability_priority_for_candidate,