Web Worker: WASM-inferenssi erillisessä säikeessä, UI ei jäädy

- Poistettu kaikki web_sys::window() -kutsut Rust WASM:sta
- Uudet Worker-yhteensopivat apufunktiot: perf_now(), worker_fetch(), sleep_ms()
- worker.js lataa ja ajaa WASM-moduulin erillisessä säikeessä
- ensureCoderNode käynnistää Workerin pääsäikeen sijaan
- Selaimen UI pysyy responsiivisena inferenssin aikana

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-06 19:59:09 +03:00
parent fc95cf8c1b
commit b3646ae5d3
6 changed files with 129 additions and 70 deletions

View File

@@ -24,10 +24,7 @@ async fn ensure_cached(key: &str, url: &str, ws: &Rc<RefCell<WebSocket>>) -> Res
console_log!("[Qwen] Ladataan {}...", key);
let window = web_sys::window().unwrap();
let resp_val = wasm_bindgen_futures::JsFuture::from(window.fetch_with_str(url))
.await.map_err(|e| format!("Fetch epäonnistui: {:?}", e))?;
let resp: web_sys::Response = resp_val.dyn_into().map_err(|_| "Ei Response".to_string())?;
let resp = crate::worker_fetch(url).await?;
if !resp.ok() { return Err(format!("HTTP {}", resp.status())); }
let total_size: usize = resp.headers()
@@ -71,7 +68,7 @@ async fn ensure_cached(key: &str, url: &str, ws: &Rc<RefCell<WebSocket>>) -> Res
}
pub async fn run_qwen_inference(prompt: String, ws: Rc<RefCell<WebSocket>>) {
let perf = web_sys::window().unwrap().performance().unwrap();
// performance via crate::perf_now()
let tok_bytes = match ensure_cached("qwen05b-tokenizer.json", TOKENIZER_URL, &ws).await {
Ok(b) => b,
@@ -88,7 +85,7 @@ pub async fn run_qwen_inference(prompt: String, ws: Rc<RefCell<WebSocket>>) {
};
console_log!("[Qwen] Rakennetaan mallia...");
let start_load = perf.now();
let start_load = crate::perf_now();
let device = Device::Cpu;
let dtype = DType::F32;
@@ -120,7 +117,7 @@ pub async fn run_qwen_inference(prompt: String, ws: Rc<RefCell<WebSocket>>) {
Err(e) => { console_log!("[Qwen] Mallin lataus: {}", e); return; }
};
let load_time = perf.now() - start_load;
let load_time = crate::perf_now() - start_load;
console_log!("[Qwen] Malli ladattu ({:.0}ms). Generoidaan...", load_time);
let encoding = match tokenizer.encode(prompt.as_str(), true) {
@@ -131,7 +128,7 @@ pub async fn run_qwen_inference(prompt: String, ws: Rc<RefCell<WebSocket>>) {
let input_len = input_ids.len();
console_log!("[Qwen] Syöte: {} tokenia", input_len);
let start_gen = perf.now();
let start_gen = crate::perf_now();
let max_new_tokens = 32;
let mut generated_text = String::new();
let mut tokens_generated: usize = 0;
@@ -202,7 +199,7 @@ pub async fn run_qwen_inference(prompt: String, ws: Rc<RefCell<WebSocket>>) {
crate::sleep_ms(0).await;
}
let gen_time = perf.now() - start_gen;
let gen_time = crate::perf_now() - start_gen;
let tokens_per_sec = if gen_time > 0.0 { (tokens_generated as f64 / gen_time) * 1000.0 } else { 0.0 };
console_log!("[Qwen] {} tokenia | {:.0}ms | {:.1} tok/s", tokens_generated, gen_time, tokens_per_sec);