hyvä siitä tulee

This commit is contained in:
2026-04-02 18:16:41 +03:00
parent 6cdd695a3b
commit 31995fb278
8 changed files with 272 additions and 89 deletions

View File

@@ -25,7 +25,7 @@ const ALLOWED_ORIGINS: &[&str] = &[
];
// Sallitut viestityyypit clientilta
const ALLOWED_MSG_TYPES: &[&str] = &["auth", "result", "pair_done", "llm_chunk", "llm_done", "download_progress", "user_text"];
const ALLOWED_MSG_TYPES: &[&str] = &["auth", "result", "pair_done", "llm_chunk", "llm_done", "download_progress", "user_text", "single_tokenize_done"];
struct AppState {
next_node_id: Mutex<u64>,
@@ -158,7 +158,7 @@ async function load() {
].map(s => `<div class="stat-card"><div class="val">${s.v}</div><div class="label">${s.l}</div></div>`).join('');
// Sessions — lajittelu: 1) aktiiviset nodet (online + ei viewer), 2) katsojat (online + viewer), 3) offline
const taskNames = {'tokenize':'Tokenisaatio','smollm-135m':'SmolLM 135M','qwen-05b':'Qwen2.5 0.5B','phi3-mini':'Phi-3 Mini','qwen-coder-05b':'Coder 0.5B','qwen-coder-3b':'Coder 3B','viewer':'Katsoja'};
const taskNames = {'tokenize':'Tokenisaatio','smollm-135m':'SmolLM 135M','qwen-05b':'Qwen2.5 0.5B','phi3-mini':'Phi-3 Mini','qwen-coder-05b':'Coder 0.5B','qwen-coder-3b':'Coder 3B','viewer':'Katsoja','codelab-viewer':'Koodilabra'};
sessions.sort((a, b) => {
const aOnline = !a.disconnected_at;
const bOnline = !b.disconnected_at;
@@ -321,28 +321,9 @@ async fn main() {
});
let _ = state_for_task.stats_tx.send(phi3_msg.to_string());
// Coder-promptit — pieniä Python-tehtäviä
let code_prompts = vec![
"Write a Python function that checks if a number is prime.",
"Write a Python function that reverses a string without using slicing.",
"Write a Python function to find the factorial of a number using recursion.",
"Write a Python function that returns the Fibonacci sequence up to n numbers.",
"Write a Python function to check if a string is a palindrome.",
"Write a Python function that sorts a list using bubble sort.",
"Write a Python function to count the occurrences of each character in a string.",
"Write a Python function that flattens a nested list.",
"Write a Python function to find the greatest common divisor of two numbers.",
"Write a Python function that converts Celsius to Fahrenheit.",
];
let code_idx = (rng_state as usize / 13) % code_prompts.len();
let coder_msg = serde_json::json!({
"type": "llm_prompt",
"prompt": code_prompts[code_idx],
"model": "qwen-coder",
});
let _ = state_for_task.stats_tx.send(coder_msg.to_string());
// Coder ei saa automaattisia tehtäviä — vain käyttäjän user_text
tracing::debug!("Tehtävät lähetetty: pair + smollm + qwen + phi3 + coder");
tracing::debug!("Tehtävät lähetetty: pair + smollm + qwen + phi3");
}
});
@@ -617,11 +598,21 @@ async fn handle_socket(socket: WebSocket, state: Arc<AppState>, ip: IpAddr) {
map.insert(node_id, allocated);
}
// Tallennetaan sessiotieto tietokantaan
state.db.insert_session(node_id, &ip.to_string(), node_type, &json);
// Tallennetaan valittu tehtävä muistiin reititystä varten
let selected_task = json.get("selected_task").and_then(|v| v.as_str()).unwrap_or("tokenize").to_string();
let is_viewer = selected_task == "viewer" || selected_task == "codelab-viewer";
let existing = state.node_tasks.lock().unwrap().contains_key(&node_id);
if existing {
// Sama yhteys, eri tehtävä → päivitetään
state.db.update_session_task(node_id, &selected_task);
tracing::info!("Solmu {} päivitti tehtävän → {}", node_id, selected_task);
} else {
// Uusi yhteys — suljetaan saman IP:n viewer-sessiot jos tämä on aktiivinen node
if !is_viewer {
state.db.close_viewers_by_ip(&ip.to_string());
}
state.db.insert_session(node_id, &ip.to_string(), node_type, &json);
}
state.node_tasks.lock().unwrap().insert(node_id, selected_task);
if node_type == "native" {
@@ -726,6 +717,14 @@ async fn handle_socket(socket: WebSocket, state: Arc<AppState>, ip: IpAddr) {
}
broadcast_stats(&state).await;
}
} else if msg_type == "single_tokenize_done" {
{
let mut json = json.clone();
if let Some(obj) = json.as_object_mut() {
obj.insert("node_id".to_string(), serde_json::json!(node_id));
}
let _ = state.stats_tx.send(json.to_string());
}
} else if msg_type == "llm_chunk" {
{
let mut json = json;
@@ -770,14 +769,11 @@ async fn handle_socket(socket: WebSocket, state: Arc<AppState>, ip: IpAddr) {
tracing::info!("Solmu {} lähetti oman tekstin ({}): \"{}\"", node_id, task_type, &text[..text.len().min(80)]);
match task_type {
"tokenize" => {
// Tokenisoidaan käyttäjän teksti EN-puolella, FI jätetään tyhjäksi
let pair = serde_json::json!({
"type": "pair_task",
"en": text,
"fi": text,
"user_submitted": true,
let msg = serde_json::json!({
"type": "single_tokenize",
"text": text,
});
let _ = state.stats_tx.send(pair.to_string());
let _ = state.stats_tx.send(msg.to_string());
}
_ => {
// LLM-prompti