///|
/// 一次文本生成所采用的 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 }
}