use serde::Serialize;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[serde(rename_all = "kebab-case")]
pub enum BatchStrategy {
Speed,
MinTokens,
}
impl BatchStrategy {
pub const ALL: [BatchStrategy; 2] = [BatchStrategy::Speed, BatchStrategy::MinTokens];
pub fn as_str(self) -> &'static str {
match self {
BatchStrategy::Speed => "speed",
BatchStrategy::MinTokens => "min-tokens",
}
}
pub fn parse(s: &str) -> Option<Self> {
match s {
"speed" => Some(BatchStrategy::Speed),
"min-tokens" => Some(BatchStrategy::MinTokens),
_ => None,
}
}
}
pub fn waves(strategy: BatchStrategy, n: usize) -> Vec<Vec<usize>> {
if n == 0 {
return Vec::new();
}
match strategy {
BatchStrategy::Speed => vec![(0..n).collect()],
BatchStrategy::MinTokens => {
if n == 1 {
vec![vec![0]]
} else {
vec![vec![0], (1..n).collect()]
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn strategy_token_round_trips_for_every_variant() {
for s in BatchStrategy::ALL {
assert_eq!(BatchStrategy::parse(s.as_str()), Some(s));
}
assert_eq!(BatchStrategy::parse("nope"), None);
assert_eq!(
serde_json::to_string(&BatchStrategy::MinTokens).unwrap(),
"\"min-tokens\""
);
assert_eq!(
serde_json::to_string(&BatchStrategy::Speed).unwrap(),
"\"speed\""
);
}
#[test]
fn speed_is_always_a_single_wave_of_everything() {
assert_eq!(waves(BatchStrategy::Speed, 1), vec![vec![0]]);
assert_eq!(waves(BatchStrategy::Speed, 3), vec![vec![0, 1, 2]]);
assert_eq!(waves(BatchStrategy::Speed, 5), vec![vec![0, 1, 2, 3, 4]]);
}
#[test]
fn min_tokens_warms_one_then_fans_the_rest() {
assert_eq!(waves(BatchStrategy::MinTokens, 1), vec![vec![0]]);
assert_eq!(waves(BatchStrategy::MinTokens, 2), vec![vec![0], vec![1]]);
assert_eq!(
waves(BatchStrategy::MinTokens, 4),
vec![vec![0], vec![1, 2, 3]]
);
assert_eq!(waves(BatchStrategy::MinTokens, 4)[0].len(), 1);
}
#[test]
fn zero_prompts_yields_no_waves_for_either_strategy() {
assert!(waves(BatchStrategy::Speed, 0).is_empty());
assert!(waves(BatchStrategy::MinTokens, 0).is_empty());
}
#[test]
fn waves_cover_every_index_exactly_once() {
for strategy in BatchStrategy::ALL {
for n in 0..6 {
let mut seen: Vec<usize> = waves(strategy, n).into_iter().flatten().collect();
seen.sort_unstable();
assert_eq!(
seen,
(0..n).collect::<Vec<_>>(),
"strategy {strategy:?} n {n}"
);
}
}
}
}