#[non_exhaustive]pub struct TokenLimits {
pub context_window: Option<u32>,
pub max_output: Option<u32>,
pub source: LimitSource,
pub context_window_source: Option<LimitSource>,
pub max_output_source: Option<LimitSource>,
}Expand description
一个模型的 token 限额。
两个字段都是 Option:拿不到就是拿不到,不填一个猜的数字。
调用方遇到 None 应当让用户手填,而不是自己兜一个默认值 ——
那正是要避免的「硬编码回落」。
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.context_window: Option<u32>上下文窗口(输入 + 输出的总上限)。
用途:裁历史消息。注意它是总量,留给输出的部分要从中扣除。
max_output: Option<u32>单次输出上限。
用途:填请求里的 max_tokens。此前各应用普遍硬编码 4096 ——
对支持 64K 输出的模型来说白白浪费了大半能力。
source: LimitSource整条的来源:优先级最高、真正起作用的那一层,见 LimitSource。
两个值可能来自不同的层(用户只填了窗口、输出上限由预置补),
要分别标注请用 Self::context_window_source / Self::max_output_source。
context_window_source: Option<LimitSource>context_window 这个值来自哪一层;值为 None 时也为 None。
max_output_source: Option<LimitSource>max_output 这个值来自哪一层;值为 None 时也为 None。
Implementations§
Source§impl TokenLimits
impl TokenLimits
Sourcepub const fn from_endpoint(
context_window: Option<u32>,
max_output: Option<u32>,
) -> Self
pub const fn from_endpoint( context_window: Option<u32>, max_output: Option<u32>, ) -> Self
端点上报的限额。
Sourcepub const fn from_preset(
context_window: Option<u32>,
max_output: Option<u32>,
) -> Self
pub const fn from_preset( context_window: Option<u32>, max_output: Option<u32>, ) -> Self
预置静态兜底。
Sourcepub const fn from_user(
context_window: Option<u32>,
max_output: Option<u32>,
) -> Self
pub const fn from_user( context_window: Option<u32>, max_output: Option<u32>, ) -> Self
用户手填的限额。
Sourcepub const fn with_source(
context_window: Option<u32>,
max_output: Option<u32>,
source: LimitSource,
) -> Self
pub const fn with_source( context_window: Option<u32>, max_output: Option<u32>, source: LimitSource, ) -> Self
按来源构造 —— 调用方从存储里读回 (窗口, 输出, 来源) 时用。
两个值都记为同一来源;逐字段来源只在 Self::or 合并不同层时才会不同。
Sourcepub const fn or(self, fallback: TokenLimits) -> TokenLimits
pub const fn or(self, fallback: TokenLimits) -> TokenLimits
逐字段回退:自己缺的字段从 fallback 补,值和它的来源一起补。
整条的 source 取自己的(只要自己至少有一个字段)—— 它标的是优先级最高、
真正起作用的那一层。自己全空时整个换成 fallback。
每个值实际来自哪一层看 context_window_source / max_output_source。
🔴 为什么要逐字段:用户常常只知道窗口大小(文档写了),不知道输出上限。 整条替换的话,填了窗口就丢了预置里的输出上限,等于填了反而变差。
let user = TokenLimits::from_user(Some(64_000), None);
let preset = TokenLimits::from_preset(Some(128_000), Some(8192));
let l = user.or(preset);
assert_eq!(l.context_window, Some(64_000)); // 用户的
assert_eq!(l.max_output, Some(8192)); // 预置补的
assert_eq!(l.source, LimitSource::User);Sourcepub fn input_budget(&self, reserve_output: u32) -> Option<u32>
pub fn input_budget(&self, reserve_output: u32) -> Option<u32>
留给输入的预算 = 上下文窗口 − 为输出预留的量。
这是裁历史时真正要用的数字。reserve_output 传本次请求实际要用的
max_tokens,而不是模型的输出上限 —— 用上限会把预算压得过小。
上下文窗口未知时返回 None:不猜。
let l = TokenLimits::from_endpoint(Some(128_000), Some(8192));
assert_eq!(l.input_budget(4096), Some(123_904));
// 预留量比窗口还大 —— 返回 0 而不是下溢
let tiny = TokenLimits::from_preset(Some(1000), None);
assert_eq!(tiny.input_budget(4096), Some(0));
// 不知道窗口就是不知道
assert_eq!(TokenLimits::from_preset(None, None).input_budget(4096), None);