use regex::Regex;
use std::sync::LazyLock;
fn compile(pattern: &str) -> Regex {
Regex::new(pattern).expect("invalid regex pattern")
}
pub static LLAMA_START: LazyLock<Regex> = LazyLock::new(|| {
compile(r"(?i)(llama.*server|ggml\s+version)")
});
pub static LOADING_MODEL: LazyLock<Regex> = LazyLock::new(|| {
compile(r"(?i)llama_model_loader")
});
pub static LOADED_META: LazyLock<Regex> = LazyLock::new(|| {
compile(r"(?i)(loaded\s+\d+\s+meta|meta\s+data)")
});
pub static LOAD_TENSORS: LazyLock<Regex> = LazyLock::new(|| {
compile(r"(?i)load tensors:")
});
pub static SERVER_LISTENING: LazyLock<Regex> = LazyLock::new(|| {
compile(r"(?i)(server listening|http server listening|load_model:\s*initializing\s+slots)")
});
pub static LOADING_TENSOR: LazyLock<Regex> =
LazyLock::new(|| compile(r"(?i)loading tensor\s+(\d+)\s+(?:of|out of)\s+(\d+)"));
pub static OFFLOADING_LAYERS: LazyLock<Regex> =
LazyLock::new(|| compile(r"(?i)offloading\s+(\d+)\s+repeating layers"));
pub static OFFLOADED_LAYERS: LazyLock<Regex> = LazyLock::new(|| {
compile(r"(?i)offloaded\s+(\d+)\s*(?:out\s+of|/)\s*(\d+)\s*layers")
});
pub static MODEL_BUFFER_SIZE: LazyLock<Regex> = LazyLock::new(|| {
compile(r"(?i)((?:vulkan\d|roc\d|cuda|cpu|metal)?(?:\s*))model buffer size\s*=\s*([\d.]+)\s*MiB")
});
pub static KV_BUFFER_SIZE: LazyLock<Regex> = LazyLock::new(|| {
compile(r"(?i)kv buffer size\s*=\s*([\d.]+)\s*MiB")
});
pub static ERROR_OOM: LazyLock<Regex> =
LazyLock::new(|| compile(r"(?i)(out\s+of\s+(device\s+)?memory|outof(devic)?memory|vk\s*outofmemory)"));
pub static ERROR_GENERIC: LazyLock<Regex> = LazyLock::new(|| {
compile(r"(?i)(error|failed\s+to\s+load|exception|vk::systemerror)")
});
fn normalize(msg: &str) -> String {
msg.chars()
.map(|c| if c.is_ascii_alphanumeric() || c.is_ascii_whitespace() { c } else { ' ' })
.collect()
}
pub fn is_loading_error(msg: &str) -> bool {
let n = normalize(msg);
ERROR_OOM.is_match(&n) || ERROR_GENERIC.is_match(&n)
}
pub fn is_oom_error(msg: &str) -> bool {
let n = normalize(msg);
ERROR_OOM.is_match(&n)
}