///|
/// 一次文本生成所采用的 sampling strategy。
///
/// 具体变体留在包内,调用者通过 `SamplingStrategy::greedy` 或
/// `SamplingStrategy::random` 构造策略。
pub enum SamplingStrategy {
  Greedy
  Random(seed~ : UInt?, temperature~ : Double, top_k~ : Int, top_p~ : Double)
} derive(@debug.Debug)

///|
/// 创建 greedy sampling strategy。
pub fn SamplingStrategy::greedy() -> SamplingStrategy {
  Greedy
}

///|
/// 创建第一版 random sampling strategy。
///
/// `seed=None` 表示使用非固定 seed;llama.cpp 将 `0xFFFFFFFFU` 保留为同一
/// 语义,因此显式传入 `@uint.MAX_VALUE` 也会规范化为 `None`。负 temperature
/// 规范化为 `0.0`,负 top-k 规范化为 `0`,top-p 限制到 `[0.0, 1.0]`;
/// temperature 或 top-p 为 `NaN` 时分别回落到默认值 `0.8` 与 `0.95`。
pub fn SamplingStrategy::random(
  seed? : UInt,
  temperature? : Double = 0.8,
  top_k? : Int = 40,
  top_p? : Double = 0.95,
) -> SamplingStrategy {
  let seed = match seed {
    Some(value) if value == @uint.MAX_VALUE => None
    other => other
  }
  let temperature = if temperature.is_nan() {
    0.8
  } else if temperature < 0.0 {
    0.0
  } else {
    temperature
  }
  let top_k = if top_k < 0 { 0 } else { top_k }
  let top_p = if top_p.is_nan() {
    0.95
  } else if top_p < 0.0 {
    0.0
  } else if top_p > 1.0 {
    1.0
  } else {
    top_p
  }
  Random(seed~, temperature~, top_k~, top_p~)
}

///|
/// 一次文本生成的配置。
///
/// 字段保持私有,调用者通过 `GenerationOptions::new` 构造完整配置。
#warnings("-unused_field")
pub struct GenerationOptions {
  priv max_tokens : Int
  priv strategy : SamplingStrategy
}

///|
/// 创建一次文本生成的配置。
///
/// 负数会统一规范化为 `-1`,表示不设置由调用者指定的 token 数量上限;`0`
/// 表示不生成新 token;正数表示最多生成对应数量的新 token。
pub fn GenerationOptions::new(
  max_tokens~ : Int,
  strategy? : SamplingStrategy = SamplingStrategy::greedy(),
) -> GenerationOptions {
  let max_tokens = if max_tokens < 0 { -1 } else { max_tokens }
  { max_tokens, strategy }
}