Skip to main content

smoke/
smoke.rs

1//! End-to-end smoke test — downloads the model (first run only) and
2//! runs one fill-in-the-middle completion. Verifies the whole path:
3//! HF download → cache → candle load → FIM inference → decode.
4//!
5//!   cargo run --release --example smoke
6//!
7//! First run downloads ~1 GB to the shared cache; later runs just load.
8
9use std::time::Instant;
10
11fn main() {
12    let cache = fim_engine::default_cache_dir();
13    let choice = fim_engine::ModelChoice::Qwen1_5B;
14    eprintln!("cache dir: {}", cache.display());
15    eprintln!(
16        "model cached: {}",
17        fim_engine::is_model_cached(&cache, choice)
18    );
19
20    let t0 = Instant::now();
21    let mut engine = match fim_engine::FimEngine::load(&cache, choice, &|p| {
22        let pct = p
23            .total
24            .map(|t| format!("{}%", p.received * 100 / t.max(1)))
25            .unwrap_or_else(|| format!("{} bytes", p.received));
26        eprintln!("  download {} … {pct}", p.label);
27    }) {
28        Ok(e) => e,
29        Err(e) => {
30            eprintln!("LOAD FAILED: {e}");
31            std::process::exit(1);
32        }
33    };
34    eprintln!("loaded in {:.1}s", t0.elapsed().as_secs_f64());
35
36    // A classic FIM hole — the body of an `add` function.
37    let prefix = "fn add(a: i32, b: i32) -> i32 {\n    ";
38    let suffix = "\n}\n";
39    let t1 = Instant::now();
40    match engine.complete(prefix, suffix, 32) {
41        Ok(completion) => {
42            eprintln!("completion in {} ms", t1.elapsed().as_millis());
43            eprintln!("--- prefix ---\n{prefix}");
44            eprintln!("--- COMPLETION ---\n{completion}");
45            eprintln!("--- suffix ---\n{suffix}");
46        }
47        Err(e) => {
48            eprintln!("COMPLETE FAILED: {e}");
49            std::process::exit(1);
50        }
51    }
52}