Compare commits
42 Commits
8aed9f97a2
...
v0.2.4
| Author | SHA1 | Date | |
|---|---|---|---|
| afc7f9bcee | |||
| 5d2027b2ca | |||
| 8a4d515eed | |||
| 987a370a05 | |||
| f75e7f07e9 | |||
| eb6f720fcc | |||
| e25d0ea8f2 | |||
| 4d1e89da34 | |||
| bf535b6256 | |||
| 29e1c440c6 | |||
| 560bee1369 | |||
| b074e0cb49 | |||
| 9307c75516 | |||
| 86191fbb6c | |||
| a6a94f7688 | |||
| 8d5c5440d2 | |||
| a12bd7ce7f | |||
| 9ac90aa540 | |||
| 32065d5818 | |||
| 321943ee3c | |||
| 1b75c89320 | |||
| 01622a960f | |||
| 4e4efda67d | |||
| f5db2eb034 | |||
| 77c8d46e7b | |||
| f14eba1b49 | |||
| 6d15298418 | |||
| cea1961183 | |||
| 21a8015ea3 | |||
| c3991193d9 | |||
| 02c6d67218 | |||
| de1cf009fa | |||
| 060f36f479 | |||
| e2ec0fa43d | |||
| 8752c0f465 | |||
| 8c95282654 | |||
| a1bc1af646 | |||
| 6b27cbbade | |||
| 4d9c51a86f | |||
| 66d1e8c4b1 | |||
| 2eeac255f6 | |||
| 6097cfc263 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -34,3 +34,6 @@ Cargo.lock
|
|||||||
*.pdb
|
*.pdb
|
||||||
|
|
||||||
# End of https://www.toptal.com/developers/gitignore/api/rust,linux
|
# End of https://www.toptal.com/developers/gitignore/api/rust,linux
|
||||||
|
|
||||||
|
# Ajonaikaiset tietokannat
|
||||||
|
*.db
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ RUN apt-get update && apt-get install -y \
|
|||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY Cargo.toml Cargo.lock ./
|
COPY Cargo.toml ./
|
||||||
|
COPY Cargo.loc[k] ./
|
||||||
COPY hub/Cargo.toml hub/Cargo.toml
|
COPY hub/Cargo.toml hub/Cargo.toml
|
||||||
COPY node/Cargo.toml node/Cargo.toml
|
COPY node/Cargo.toml node/Cargo.toml
|
||||||
COPY native-node/Cargo.toml native-node/Cargo.toml
|
COPY native-node/Cargo.toml native-node/Cargo.toml
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
services:
|
services:
|
||||||
# NVIDIA GPU -solmu
|
# Ollama NVIDIA GPU:lla
|
||||||
native-node-nvidia:
|
ollama-nvidia:
|
||||||
build:
|
image: ollama/ollama:latest
|
||||||
context: .
|
container_name: kipina-ollama
|
||||||
dockerfile: Dockerfile.native-node
|
ports:
|
||||||
container_name: kipina-node-nvidia
|
- "11434:11434"
|
||||||
environment:
|
volumes:
|
||||||
- HUB_URL=wss://kipina.studio/ws
|
- ollama-models:/root/.ollama
|
||||||
- ALLOCATED_GB=4
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
@@ -16,6 +15,65 @@ services:
|
|||||||
- driver: nvidia
|
- driver: nvidia
|
||||||
count: all
|
count: all
|
||||||
capabilities: [gpu]
|
capabilities: [gpu]
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
aliases:
|
||||||
|
- ollama
|
||||||
|
profiles:
|
||||||
|
- nvidia
|
||||||
|
|
||||||
|
# Ollama AMD ROCm GPU:lla
|
||||||
|
ollama-amd:
|
||||||
|
image: ollama/ollama:rocm
|
||||||
|
container_name: kipina-ollama
|
||||||
|
ports:
|
||||||
|
- "11434:11434"
|
||||||
|
volumes:
|
||||||
|
- ollama-models:/root/.ollama
|
||||||
|
restart: unless-stopped
|
||||||
|
devices:
|
||||||
|
- /dev/kfd:/dev/kfd
|
||||||
|
- /dev/dri:/dev/dri
|
||||||
|
group_add:
|
||||||
|
- video
|
||||||
|
- render
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
aliases:
|
||||||
|
- ollama
|
||||||
|
profiles:
|
||||||
|
- amd
|
||||||
|
|
||||||
|
# Ollama CPU:lla
|
||||||
|
ollama-cpu:
|
||||||
|
image: ollama/ollama:latest
|
||||||
|
container_name: kipina-ollama
|
||||||
|
ports:
|
||||||
|
- "11434:11434"
|
||||||
|
volumes:
|
||||||
|
- ollama-models:/root/.ollama
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
default:
|
||||||
|
aliases:
|
||||||
|
- ollama
|
||||||
|
profiles:
|
||||||
|
- cpu
|
||||||
|
|
||||||
|
# NVIDIA GPU -solmu
|
||||||
|
native-node-nvidia:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile.native-node
|
||||||
|
container_name: kipina-node-nvidia
|
||||||
|
environment:
|
||||||
|
- HUB_URL=wss://kipina.studio/ws
|
||||||
|
- OLLAMA_URL=http://ollama:11434
|
||||||
|
- OLLAMA_MODEL=qwen2.5-coder:7b
|
||||||
|
- ALLOCATED_GB=4
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- ollama-nvidia
|
||||||
profiles:
|
profiles:
|
||||||
- nvidia
|
- nvidia
|
||||||
|
|
||||||
@@ -27,14 +85,12 @@ services:
|
|||||||
container_name: kipina-node-amd
|
container_name: kipina-node-amd
|
||||||
environment:
|
environment:
|
||||||
- HUB_URL=wss://kipina.studio/ws
|
- HUB_URL=wss://kipina.studio/ws
|
||||||
|
- OLLAMA_URL=http://ollama:11434
|
||||||
|
- OLLAMA_MODEL=qwen2.5-coder:7b
|
||||||
- ALLOCATED_GB=4
|
- ALLOCATED_GB=4
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
devices:
|
depends_on:
|
||||||
- /dev/kfd:/dev/kfd
|
- ollama-amd
|
||||||
- /dev/dri:/dev/dri
|
|
||||||
group_add:
|
|
||||||
- video
|
|
||||||
- render
|
|
||||||
profiles:
|
profiles:
|
||||||
- amd
|
- amd
|
||||||
|
|
||||||
@@ -46,7 +102,14 @@ services:
|
|||||||
container_name: kipina-node-cpu
|
container_name: kipina-node-cpu
|
||||||
environment:
|
environment:
|
||||||
- HUB_URL=wss://kipina.studio/ws
|
- HUB_URL=wss://kipina.studio/ws
|
||||||
|
- OLLAMA_URL=http://ollama:11434
|
||||||
|
- OLLAMA_MODEL=qwen2.5-coder:7b
|
||||||
- ALLOCATED_GB=2
|
- ALLOCATED_GB=2
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
- ollama-cpu
|
||||||
profiles:
|
profiles:
|
||||||
- cpu
|
- cpu
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
ollama-models:
|
||||||
|
|||||||
@@ -11,21 +11,19 @@ services:
|
|||||||
# Käännetään aina käynnistyksen yhteydessä varmuuden vuoksi Wasm uusimmista koodeista, ja päälle pyöräytetään Hub!
|
# Käännetään aina käynnistyksen yhteydessä varmuuden vuoksi Wasm uusimmista koodeista, ja päälle pyöräytetään Hub!
|
||||||
command: bash -c "cd node && wasm-pack build --release --target web --out-dir ../static/pkg && cd ../hub && cargo run"
|
command: bash -c "cd node && wasm-pack build --release --target web --out-dir ../static/pkg && cd ../hub && cargo run"
|
||||||
|
|
||||||
# Ollama — LLM-inferenssi GPU:lla (NVIDIA/AMD/Apple)
|
# Ollama — LLM-inferenssi
|
||||||
|
# NVIDIA: vaihda image → ollama/ollama:latest ja lisää deploy.resources (ks. README)
|
||||||
|
# CPU: vaihda image → ollama/ollama:latest ja poista devices
|
||||||
ollama:
|
ollama:
|
||||||
image: ollama/ollama:latest
|
image: ollama/ollama:rocm
|
||||||
container_name: kipina_ollama
|
container_name: kipina_ollama
|
||||||
ports:
|
ports:
|
||||||
- "11434:11434"
|
- "11434:11434"
|
||||||
volumes:
|
volumes:
|
||||||
- ollama-models:/root/.ollama
|
- ollama-models:/root/.ollama
|
||||||
deploy:
|
devices:
|
||||||
resources:
|
- /dev/kfd
|
||||||
reservations:
|
- /dev/dri
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: all
|
|
||||||
capabilities: [gpu]
|
|
||||||
profiles:
|
profiles:
|
||||||
- native
|
- native
|
||||||
|
|
||||||
@@ -36,12 +34,11 @@ services:
|
|||||||
dockerfile: Dockerfile.native-node
|
dockerfile: Dockerfile.native-node
|
||||||
container_name: kipina_native_node
|
container_name: kipina_native_node
|
||||||
environment:
|
environment:
|
||||||
- HUB_URL=ws://agentic-poc:3000/ws
|
- HUB_URL=wss://kipina.studio/ws
|
||||||
- OLLAMA_URL=http://ollama:11434
|
- OLLAMA_URL=http://ollama:11434
|
||||||
- OLLAMA_MODEL=qwen2.5-coder:7b
|
- OLLAMA_MODEL=qwen2.5-coder:7b
|
||||||
- ALLOCATED_GB=4
|
- ALLOCATED_GB=4
|
||||||
depends_on:
|
depends_on:
|
||||||
- agentic-poc
|
|
||||||
- ollama
|
- ollama
|
||||||
profiles:
|
profiles:
|
||||||
- native
|
- native
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "hub"
|
name = "hub"
|
||||||
version = "0.2.1"
|
version = "0.2.4"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@@ -16,3 +16,4 @@ futures = "0.3"
|
|||||||
rusqlite = { version = "0.31", features = ["bundled"] }
|
rusqlite = { version = "0.31", features = ["bundled"] }
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
base64 = "0.22"
|
base64 = "0.22"
|
||||||
|
reqwest = { version = "0.12", features = ["json"] }
|
||||||
|
|||||||
Binary file not shown.
@@ -386,6 +386,7 @@ async fn main() {
|
|||||||
.route("/api/v1/chat/completions", axum::routing::post(api_chat_completions))
|
.route("/api/v1/chat/completions", axum::routing::post(api_chat_completions))
|
||||||
.route("/api/v1/model", axum::routing::post(api_change_model))
|
.route("/api/v1/model", axum::routing::post(api_change_model))
|
||||||
.route("/api/v1/hardware", get(api_hardware))
|
.route("/api/v1/hardware", get(api_hardware))
|
||||||
|
.route("/api/v1/ollama/tags", get(api_ollama_tags))
|
||||||
.route("/admin", get(admin_page))
|
.route("/admin", get(admin_page))
|
||||||
.nest_service("/", {
|
.nest_service("/", {
|
||||||
let static_dir = std::env::var("STATIC_DIR").unwrap_or_else(|_| "../static".to_string());
|
let static_dir = std::env::var("STATIC_DIR").unwrap_or_else(|_| "../static".to_string());
|
||||||
@@ -960,6 +961,20 @@ struct ChatCompletionResponse {
|
|||||||
tokens_generated: u64,
|
tokens_generated: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn api_ollama_tags() -> axum::response::Response {
|
||||||
|
let ollama_url = std::env::var("OLLAMA_URL").unwrap_or_else(|_| "http://ollama:11434".to_string());
|
||||||
|
match reqwest::get(format!("{}/api/tags", ollama_url)).await {
|
||||||
|
Ok(resp) => {
|
||||||
|
if let Ok(body) = resp.json::<serde_json::Value>().await {
|
||||||
|
axum::Json(body).into_response()
|
||||||
|
} else {
|
||||||
|
axum::Json(serde_json::json!({ "models": [] })).into_response()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => axum::Json(serde_json::json!({ "models": [] })).into_response(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn api_hardware(
|
async fn api_hardware(
|
||||||
axum::extract::State(state): axum::extract::State<Arc<AppState>>,
|
axum::extract::State(state): axum::extract::State<Arc<AppState>>,
|
||||||
) -> axum::response::Response {
|
) -> axum::response::Response {
|
||||||
@@ -969,17 +984,34 @@ async fn api_hardware(
|
|||||||
s.get("node_type").and_then(|v| v.as_str()) == Some("native")
|
s.get("node_type").and_then(|v| v.as_str()) == Some("native")
|
||||||
});
|
});
|
||||||
|
|
||||||
let (vram_mb, gpu_name, ram_mb) = if let Some(s) = native {
|
let (mut vram_mb, mut gpu_name, ram_mb) = if let Some(s) = native {
|
||||||
let gpus = s.get("gpus").and_then(|v| v.as_array());
|
let gpus = s.get("gpus").and_then(|v| v.as_array());
|
||||||
let gpu = gpus.and_then(|g| g.first());
|
let gpu = gpus.and_then(|g| g.first());
|
||||||
let vram = gpu.and_then(|g| g.get("vram_total_mb")).and_then(|v| v.as_u64()).unwrap_or(0);
|
let vram = gpu.and_then(|g| g.get("vram_total_mb")).and_then(|v| v.as_u64()).unwrap_or(0);
|
||||||
let name = gpu.and_then(|g| g.get("name")).and_then(|v| v.as_str()).unwrap_or("?");
|
let name = gpu.and_then(|g| g.get("name")).and_then(|v| v.as_str()).unwrap_or("").to_string();
|
||||||
let ram = s.get("system").and_then(|v| v.get("ram_total_mb")).and_then(|v| v.as_u64()).unwrap_or(0);
|
let ram = s.get("system").and_then(|v| v.get("ram_total_mb")).and_then(|v| v.as_u64()).unwrap_or(0);
|
||||||
(vram, name.to_string(), ram)
|
(vram, name, ram)
|
||||||
} else {
|
} else {
|
||||||
(0, "ei natiivisolmua".to_string(), 0)
|
(0, String::new(), 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Fallback: kysytään Ollamalta onko malleja ladattu (= Ollama on käynnissä)
|
||||||
|
if vram_mb == 0 {
|
||||||
|
let ollama_url = std::env::var("OLLAMA_URL").unwrap_or_else(|_| "http://ollama:11434".to_string());
|
||||||
|
if let Ok(resp) = reqwest::get(format!("{}/api/tags", ollama_url)).await {
|
||||||
|
if let Ok(body) = resp.json::<serde_json::Value>().await {
|
||||||
|
let models = body["models"].as_array().map(|a| a.len()).unwrap_or(0);
|
||||||
|
if models > 0 {
|
||||||
|
gpu_name = "Ollama (GPU/CPU)".to_string();
|
||||||
|
// Natiivisolmun RAM fallbackina
|
||||||
|
vram_mb = if ram_mb > 0 { ram_mb } else { 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if gpu_name.is_empty() { gpu_name = "ei natiivisolmua".to_string(); }
|
||||||
|
|
||||||
axum::Json(serde_json::json!({
|
axum::Json(serde_json::json!({
|
||||||
"gpu_name": gpu_name,
|
"gpu_name": gpu_name,
|
||||||
"vram_mb": vram_mb,
|
"vram_mb": vram_mb,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "native-node"
|
name = "native-node"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@@ -8,17 +8,47 @@ pub struct LlmEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LlmEngine {
|
impl LlmEngine {
|
||||||
pub fn load() -> Result<Self, String> {
|
pub async fn load() -> Result<Self, String> {
|
||||||
let ollama_url = std::env::var("OLLAMA_URL").unwrap_or_else(|_| "http://localhost:11434".to_string());
|
|
||||||
let model = std::env::var("OLLAMA_MODEL").unwrap_or_else(|_| "qwen2.5-coder:7b".to_string());
|
let model = std::env::var("OLLAMA_MODEL").unwrap_or_else(|_| "qwen2.5-coder:7b".to_string());
|
||||||
|
|
||||||
tracing::info!("Ollama backend: {} | malli: {}", ollama_url, model);
|
|
||||||
|
|
||||||
let client = reqwest::Client::builder()
|
let client = reqwest::Client::builder()
|
||||||
.timeout(std::time::Duration::from_secs(600))
|
.timeout(std::time::Duration::from_secs(600))
|
||||||
|
.connect_timeout(std::time::Duration::from_secs(3))
|
||||||
.build()
|
.build()
|
||||||
.map_err(|e| format!("HTTP client: {}", e))?;
|
.map_err(|e| format!("HTTP client: {}", e))?;
|
||||||
|
|
||||||
|
// Jos OLLAMA_URL on asetettu, käytetään sitä suoraan
|
||||||
|
let ollama_url = if let Ok(url) = std::env::var("OLLAMA_URL") {
|
||||||
|
tracing::info!("Ollama backend (env): {}", url);
|
||||||
|
url
|
||||||
|
} else {
|
||||||
|
// Haistellaan Ollamaa tunnetuista osoitteista
|
||||||
|
let candidates = [
|
||||||
|
"http://localhost:11434",
|
||||||
|
"http://127.0.0.1:11434",
|
||||||
|
"http://ollama:11434",
|
||||||
|
"http://host.docker.internal:11434",
|
||||||
|
];
|
||||||
|
let mut found = None;
|
||||||
|
for url in &candidates {
|
||||||
|
let probe = reqwest::Client::builder()
|
||||||
|
.connect_timeout(std::time::Duration::from_secs(2))
|
||||||
|
.build().unwrap_or(client.clone());
|
||||||
|
if let Ok(resp) = probe.get(format!("{}/api/version", url)).send().await {
|
||||||
|
if resp.status().is_success() {
|
||||||
|
tracing::info!("Ollama löytyi osoitteesta: {}", url);
|
||||||
|
found = Some(url.to_string());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
found.unwrap_or_else(|| {
|
||||||
|
tracing::warn!("Ollamaa ei löytynyt — käytetään oletusta http://localhost:11434");
|
||||||
|
"http://localhost:11434".to_string()
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
tracing::info!("Ollama backend: {} | malli: {}", ollama_url, model);
|
||||||
Ok(LlmEngine { ollama_url, model: RefCell::new(model), client })
|
Ok(LlmEngine { ollama_url, model: RefCell::new(model), client })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +79,7 @@ impl LlmEngine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn generate(&self, prompt: &str, max_tokens: usize) -> Result<GenerateResult, String> {
|
pub async fn generate(&self, prompt: &str, max_tokens: usize) -> Result<GenerateResult, String> {
|
||||||
let system = "You are a coding assistant. Respond with ONLY code. No explanations, no markdown, no comments unless asked.";
|
let system = "You are a coding assistant. Respond with ONLY code. Use proper newlines and indentation. No explanations, no markdown fences, no comments unless asked.";
|
||||||
let model = self.model.borrow().clone();
|
let model = self.model.borrow().clone();
|
||||||
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ async fn main() {
|
|||||||
|
|
||||||
// Ollama-backend
|
// Ollama-backend
|
||||||
tracing::info!("Alustetaan Ollama-yhteyttä...");
|
tracing::info!("Alustetaan Ollama-yhteyttä...");
|
||||||
let llm = match inference::LlmEngine::load() {
|
let llm = match inference::LlmEngine::load().await {
|
||||||
Ok(engine) => {
|
Ok(engine) => {
|
||||||
// Varmistetaan malli (ollama pull) — odotetaan kunnes valmis
|
// Varmistetaan malli (ollama pull) — odotetaan kunnes valmis
|
||||||
match engine.ensure_model().await {
|
match engine.ensure_model().await {
|
||||||
|
|||||||
@@ -118,6 +118,27 @@ async fn run_ai_tensor_inference(difficulty: usize) -> String {
|
|||||||
format!("PoC {} Matmul ({}x{}) >> {}", backend_name, active_workload_size, active_workload_size, result)
|
format!("PoC {} Matmul ({}x{}) >> {}", backend_name, active_workload_size, active_workload_size, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// JS-exportti: tokenisoi tekstin ja palauttaa JSON-merkkijonon
|
||||||
|
/// Tokenizer ladataan IndexedDB:stä (täytyy olla ladattu aiemmin)
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub async fn tokenize_js(text: String) -> Result<String, JsValue> {
|
||||||
|
let cached_tok = storage::load_from_idb("tokenizer.json").await.unwrap_or(None);
|
||||||
|
let Some(bytes) = cached_tok else {
|
||||||
|
// Yritetään ladata verkosta
|
||||||
|
let resp = reqwest::get("https://huggingface.co/Qwen/Qwen2.5-Coder-0.5B/resolve/main/tokenizer.json").await
|
||||||
|
.map_err(|e| JsValue::from_str(&format!("Tokenizer-lataus epäonnistui: {}", e)))?;
|
||||||
|
let bytes = resp.bytes().await
|
||||||
|
.map_err(|e| JsValue::from_str(&format!("Tokenizer-lataus epäonnistui: {}", e)))?;
|
||||||
|
let _ = storage::save_to_idb("tokenizer.json", &bytes).await;
|
||||||
|
let tokenizer = tokenizers::Tokenizer::from_bytes(&bytes)
|
||||||
|
.map_err(|e| JsValue::from_str(&format!("Tokenizer-parsinta: {}", e)))?;
|
||||||
|
return Ok(tokenize_text(&tokenizer, &text).to_string());
|
||||||
|
};
|
||||||
|
let tokenizer = tokenizers::Tokenizer::from_bytes(&bytes)
|
||||||
|
.map_err(|e| JsValue::from_str(&format!("Tokenizer-parsinta: {}", e)))?;
|
||||||
|
Ok(tokenize_text(&tokenizer, &text).to_string())
|
||||||
|
}
|
||||||
|
|
||||||
/// Tokenisoi yhden tekstin ja palauttaa metriikat
|
/// Tokenisoi yhden tekstin ja palauttaa metriikat
|
||||||
fn tokenize_text(tokenizer: &tokenizers::Tokenizer, text: &str) -> serde_json::Value {
|
fn tokenize_text(tokenizer: &tokenizers::Tokenizer, text: &str) -> serde_json::Value {
|
||||||
let char_count = text.chars().count();
|
let char_count = text.chars().count();
|
||||||
|
|||||||
@@ -36,29 +36,13 @@ sanan osa, kokonainen sana tai välilyönti. Tokenisaatio tehdään
|
|||||||
BPE-algoritmilla (Byte Pair Encoding) joka oppii yleisimmät
|
BPE-algoritmilla (Byte Pair Encoding) joka oppii yleisimmät
|
||||||
merkkijonot harjoitusdatasta.
|
merkkijonot harjoitusdatasta.
|
||||||
|
|
||||||
### Esimerkki: koodi
|
|
||||||
|
|
||||||
```
|
|
||||||
"print('Hello')" → [print] [(' ] [Hello] [')] = 4 tokenia
|
|
||||||
"tulosta('Hei')" → [tul] [osta] [(' ] [He] [i] [')] = 6 tokenia
|
|
||||||
```
|
|
||||||
|
|
||||||
Koodi tokenisoidaan tehokkaasti koska `print`, `def`, `return` yms.
|
|
||||||
ovat kokonaisia tokeneita. Suomenkielinen `tulosta` joudutaan pilkkomaan
|
|
||||||
osiin koska se ei esiinny harjoitusdatassa kokonaisena.
|
|
||||||
|
|
||||||
### Esimerkki: suomi vs. englanti
|
### Esimerkki: suomi vs. englanti
|
||||||
|
|
||||||
Sama lause kahdella kielellä Qwen2.5-Coder -tokenisaattorilla:
|
Alla oikea tokenisointitulos Qwen2.5-Coder-tokenisaattorilla. Jokainen
|
||||||
|
värikoodattu lohko on yksi tokeni — huomaa miten suomi vaatii enemmän
|
||||||
|
tokeneita saman merkityksen välittämiseen:
|
||||||
|
|
||||||
| | Teksti | Tokenit | Määrä | Merkkejä/token |
|

|
||||||
|---|---|---|---|---|
|
|
||||||
| EN | The cat sat on the mat | [The] [ cat] [ sat] [ on] [ the] [ mat] | **6** | 3.7 |
|
|
||||||
| FI | Kissa istui matolla | [K] [issa] [ ist] [ui] [ mat] [olla] | **6** | 3.2 |
|
|
||||||
| EN | Distributed computing in the browser | [Dist] [ributed] [ computing] [ in] [ the] [ browser] | **6** | 6.0 |
|
|
||||||
| FI | Hajautettu laskenta selaimessa | [H] [aj] [au] [tettu] [ las] [kenta] [ sel] [aim] [essa] | **9** | 3.3 |
|
|
||||||
| EN | Write a function that sorts a list | [Write] [ a] [ function] [ that] [ sorts] [ a] [ list] | **7** | 5.0 |
|
|
||||||
| FI | Kirjoita funktio joka lajittelee listan | [K] [irj] [oita] [ funkt] [io] [ joka] [ laj] [ittel] [ee] [ listan] | **10** | 4.0 |
|
|
||||||
|
|
||||||
**Huomaa miten:**
|
**Huomaa miten:**
|
||||||
- Englannin yleiset sanat (`the`, `in`, `a`, `function`) ovat kokonaisia tokeneita
|
- Englannin yleiset sanat (`the`, `in`, `a`, `function`) ovat kokonaisia tokeneita
|
||||||
|
|||||||
BIN
network-poc/static/images/tokenization-example.png
Normal file
BIN
network-poc/static/images/tokenization-example.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 104 KiB |
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user