use core::time::Duration;
use crate::multi::MultiLimiter;
use crate::throttle::Throttle;
const MINUTE: Duration = Duration::from_secs(60);
fn per_minute(requests: u32, input_tokens: u32, output_tokens: u32) -> MultiLimiter {
MultiLimiter::builder()
.dimension("requests", Throttle::per_duration(requests, MINUTE))
.dimension("input_tokens", Throttle::per_duration(input_tokens, MINUTE))
.dimension(
"output_tokens",
Throttle::per_duration(output_tokens, MINUTE),
)
.build()
}
pub mod anthropic {
use super::{MultiLimiter, per_minute};
#[must_use]
pub fn tier_1() -> MultiLimiter {
per_minute(50, 40_000, 8_000)
}
#[must_use]
pub fn tier_2() -> MultiLimiter {
per_minute(1_000, 80_000, 16_000)
}
#[must_use]
pub fn tier_4() -> MultiLimiter {
per_minute(4_000, 400_000, 80_000)
}
}
pub mod openai {
use super::{MultiLimiter, per_minute};
#[must_use]
pub fn tier_1() -> MultiLimiter {
per_minute(500, 30_000, 30_000)
}
#[must_use]
pub fn tier_2() -> MultiLimiter {
per_minute(5_000, 450_000, 450_000)
}
}
#[cfg(test)]
mod tests {
use super::{anthropic, openai};
#[test]
fn test_anthropic_tiers_have_the_three_dimensions() {
let limiter = anthropic::tier_2();
assert_eq!(limiter.available("requests"), Some(1_000));
assert_eq!(limiter.available("input_tokens"), Some(80_000));
assert_eq!(limiter.available("output_tokens"), Some(16_000));
}
#[test]
fn test_tiers_are_monotonic() {
assert!(
anthropic::tier_2().available("requests") >= anthropic::tier_1().available("requests")
);
assert!(
anthropic::tier_4().available("requests") >= anthropic::tier_2().available("requests")
);
assert!(openai::tier_2().available("requests") >= openai::tier_1().available("requests"));
}
#[test]
fn test_preset_admits_a_typical_call() {
let limiter = openai::tier_1();
assert!(limiter.try_acquire_costs(&[
("requests", 1),
("input_tokens", 1_000),
("output_tokens", 500),
]));
}
}