TUI inc
This commit is contained in:
@@ -6,6 +6,7 @@ use tokio_tungstenite::tungstenite::Message;
|
||||
|
||||
mod inference;
|
||||
mod tui;
|
||||
mod tui_dashboard;
|
||||
|
||||
/// GPU-tietorakenne — yhtenäinen kaikille valmistajille
|
||||
struct GpuInfo {
|
||||
@@ -268,10 +269,24 @@ fn format_optional<T: std::fmt::Display>(val: Option<T>, suffix: &str) -> String
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let file_appender = tracing_appender::rolling::never(".", "native-node.log");
|
||||
let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender);
|
||||
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter("native_node=debug")
|
||||
.with_writer(non_blocking)
|
||||
.init();
|
||||
|
||||
// Hookataan paniikkitilanteet palauttamaan terminaalin raw-moodista
|
||||
let original_hook = std::panic::take_hook();
|
||||
std::panic::set_hook(Box::new(move |panic_info| {
|
||||
tui_dashboard::restore_terminal();
|
||||
original_hook(panic_info);
|
||||
}));
|
||||
|
||||
let tui_state = std::sync::Arc::new(tokio::sync::RwLock::new(tui_dashboard::DashboardState::new()));
|
||||
let (cmd_tx, mut cmd_rx) = tokio::sync::mpsc::unbounded_channel::<String>();
|
||||
|
||||
let hub_url = std::env::var("HUB_URL").unwrap_or_else(|_| "ws://hub:3000/ws".to_string());
|
||||
let allocated_gb: u32 = std::env::var("ALLOCATED_GB")
|
||||
.ok()
|
||||
@@ -287,6 +302,18 @@ async fn main() {
|
||||
sys["cpu_cores"],
|
||||
sys["ram_total_mb"]
|
||||
);
|
||||
|
||||
{
|
||||
let mut st = tui_state.write().await;
|
||||
st.sys_info = format!("{} | {} | {} ydintä | {} MB RAM",
|
||||
sys["hostname"].as_str().unwrap_or("?"),
|
||||
sys["os"].as_str().unwrap_or("?"),
|
||||
sys["cpu_cores"],
|
||||
sys["ram_total_mb"]
|
||||
);
|
||||
let i = st.sys_info.clone();
|
||||
st.push_log("System", format!("Järjestelmä: {}", i), None);
|
||||
}
|
||||
|
||||
let gpus = collect_all_gpus();
|
||||
if gpus.is_empty() {
|
||||
@@ -328,6 +355,20 @@ async fn main() {
|
||||
|
||||
let active_model = llm.as_ref().map(|e| e.model_name()).unwrap_or_else(|| "unknown".to_string());
|
||||
tracing::info!("Käytettävä kielimalli konfiguroitu (selected_task): {}", active_model);
|
||||
|
||||
{
|
||||
let mut st = tui_state.write().await;
|
||||
st.model_name = active_model.clone();
|
||||
st.push_log("System", format!("Malli valmis: {}", active_model), None);
|
||||
}
|
||||
|
||||
// Käynnistetään graafinen TUI vasta kun TUI:n Prompt (LlmEngine::load) on ohitettu!
|
||||
let ui_state = tui_state.clone();
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = tui_dashboard::run_dashboard(ui_state, cmd_tx).await {
|
||||
tracing::error!("Pääluupin TUI kaatui: {}", e);
|
||||
}
|
||||
});
|
||||
|
||||
// Haetaan paikalliset mallit hubille lähetettäväksi
|
||||
let mut available_models = None;
|
||||
@@ -355,22 +396,28 @@ async fn main() {
|
||||
continue;
|
||||
}
|
||||
|
||||
use tokio::io::AsyncBufReadExt;
|
||||
let mut stdin_lines = tokio::io::BufReader::new(tokio::io::stdin()).lines();
|
||||
|
||||
loop {
|
||||
tokio::select! {
|
||||
line = stdin_lines.next_line() => {
|
||||
if let Ok(Some(text)) = line {
|
||||
let t = text.trim();
|
||||
if t == "p" || t == "pause" {
|
||||
cmd = cmd_rx.recv() => {
|
||||
if let Some(cmd_str) = cmd {
|
||||
if cmd_str == "pause" {
|
||||
tracing::info!("Tauotetaan solmun suoritus (Hub ei lähetä tehtäviä)...");
|
||||
let req = json!({"type": "status_update", "status": "paused"});
|
||||
let _ = write.send(Message::Text(req.to_string())).await;
|
||||
} else if t == "r" || t == "resume" || t == "s" {
|
||||
{
|
||||
let mut st = tui_state.write().await;
|
||||
st.status = "PAUSED".to_string();
|
||||
st.push_log("Network", "Solmu siirretty taukotilaan".to_string(), None);
|
||||
}
|
||||
} else if cmd_str == "resume" {
|
||||
tracing::info!("Jatketaan solmun suoritusta...");
|
||||
let req = json!({"type": "status_update", "status": "active"});
|
||||
let _ = write.send(Message::Text(req.to_string())).await;
|
||||
{
|
||||
let mut st = tui_state.write().await;
|
||||
st.status = "ACTIVE".to_string();
|
||||
st.push_log("System", "Suoritus jatkuu...".to_string(), None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -385,10 +432,32 @@ async fn main() {
|
||||
tracing::info!("Hub pakotti solmun tauolle (Pause)");
|
||||
let req = json!({"type": "status_update", "status": "paused"});
|
||||
let _ = write.send(Message::Text(req.to_string())).await;
|
||||
{
|
||||
let mut st = tui_state.write().await;
|
||||
st.status = "PAUSED".to_string();
|
||||
st.push_log("Network", "Hub kytki solmun tauolle".to_string(), None);
|
||||
}
|
||||
} else if action == "resume" {
|
||||
tracing::info!("Hub aktivoi solmun suorituksen (Resume)");
|
||||
let req = json!({"type": "status_update", "status": "active"});
|
||||
let _ = write.send(Message::Text(req.to_string())).await;
|
||||
{
|
||||
let mut st = tui_state.write().await;
|
||||
st.status = "ACTIVE".to_string();
|
||||
st.push_log("Network", "Hub palautti solmun töihin".to_string(), None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Verkon globaali tila
|
||||
if text.contains(r#""type":"network_status""#) {
|
||||
if let Ok(status) = serde_json::from_str::<serde_json::Value>(&text) {
|
||||
if let Some(nodes) = status.get("active_nodes").and_then(|v| v.as_u64()) {
|
||||
if let Some(tasks) = status.get("tasks").and_then(|v| v.as_u64()) {
|
||||
let mut st = tui_state.write().await;
|
||||
st.network_active_nodes = nodes as usize;
|
||||
st.network_total_tasks = tasks;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -407,17 +476,35 @@ async fn main() {
|
||||
let prompt_lines = prompt.lines().count();
|
||||
let prompt_last: String = prompt.lines().last().unwrap_or("").chars().take(60).collect();
|
||||
tracing::info!("→ task_id:{} | {}r prompti | \"{}...\"", task_id, prompt_lines, prompt_last);
|
||||
{
|
||||
let mut st = tui_state.write().await;
|
||||
st.cur_task_id = Some(task_id.to_string());
|
||||
st.cur_prompt = Some(format!("→ {} riviä | \"{}...\"", prompt_lines, prompt_last));
|
||||
// Ei login puskemista vielä tässä! Yhdistetään se valmiin lohkoon yhdelle riville.
|
||||
}
|
||||
|
||||
let model_name = engine.model_name();
|
||||
match engine.generate(prompt, max_tokens).await {
|
||||
Ok(result) => {
|
||||
let tokens_sec = (result.tokens_per_sec * 10.0).round() / 10.0;
|
||||
tracing::info!(
|
||||
"✓ {} | {} tok | {:.0}ms | {:.1} tok/s",
|
||||
model_name,
|
||||
result.tokens_generated,
|
||||
result.duration_ms,
|
||||
result.tokens_per_sec,
|
||||
tokens_sec,
|
||||
);
|
||||
{
|
||||
let mut st = tui_state.write().await;
|
||||
st.tasks_completed += 1;
|
||||
st.last_tokens_sec = tokens_sec as f64;
|
||||
st.cur_task_id = None;
|
||||
st.cur_prompt = None;
|
||||
|
||||
let msg_type = if task_id == "status-check" { "Ping" } else { "Task" };
|
||||
let msg_text = format!("{} ({} tok)", task_id, result.tokens_generated);
|
||||
st.push_log(msg_type, msg_text, Some(tokens_sec as f64));
|
||||
}
|
||||
let prompt_short: String = prompt.lines().last().unwrap_or("").chars().take(100).collect();
|
||||
let done = json!({
|
||||
"type": "llm_done",
|
||||
@@ -426,7 +513,7 @@ async fn main() {
|
||||
"response": result.text,
|
||||
"tokens_generated": result.tokens_generated,
|
||||
"duration_ms": result.duration_ms,
|
||||
"tokens_per_sec": (result.tokens_per_sec * 10.0).round() / 10.0,
|
||||
"tokens_per_sec": tokens_sec,
|
||||
"load_time_ms": 0,
|
||||
"task_id": task_id,
|
||||
});
|
||||
@@ -434,6 +521,12 @@ async fn main() {
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("Inferenssivirhe: {}", e);
|
||||
{
|
||||
let mut st = tui_state.write().await;
|
||||
st.cur_task_id = None;
|
||||
st.cur_prompt = None;
|
||||
st.push_log("System", format!("Virhe inferenssissä: {}", e), None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -449,7 +542,12 @@ async fn main() {
|
||||
tracing::info!("Vaihdetaan malli: {}", new_model);
|
||||
engine.set_model(new_model.to_string());
|
||||
match engine.ensure_model().await {
|
||||
Ok(()) => tracing::info!("Malli {} valmis!", new_model),
|
||||
Ok(()) => {
|
||||
tracing::info!("Malli {} valmis!", new_model);
|
||||
let mut st = tui_state.write().await;
|
||||
st.model_name = new_model.to_string();
|
||||
st.push_log("System", format!("Malli {} ladattu & valmis!", new_model), None);
|
||||
}
|
||||
Err(e) => tracing::error!("Mallin lataus epäonnistui: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user