From 262fee3b4950637412e64d76b2735de4145d150d Mon Sep 17 00:00:00 2001 From: Jaakko Vanhala Date: Mon, 6 Apr 2026 08:16:36 +0300 Subject: [PATCH] GUIDE.md: opettavainen yhteenveto kielimalleista, tokeneista ja laadun parantamisesta MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kattaa: - Kielimallit ja parametrimäärät (135M → 1800B vertailu) - Tokenit: mitä ne ovat, miksi kieli vaikuttaa, token-budjetti - Prompttirakenne: system/agent/user/prefill + miksi englanniksi - Prefill-tekniikka: miten se toimii ja miksi se säästää tokeneita - Sampling: temperature, top-k, repetition penalty selitettyinä - Stop-sekvenssit: milloin generointi loppuu - Projekti-pipeline: agenttitiimin työnkulku kaaviona - Laadun parantaminen 10 eri keinolla: 1. Isompi malli 2. Paremmat promptit 3. Kontekstin hallinta 4. Iterointi (review-luuppi) 5. Erikoistetut system promptit 6. Few-shot esimerkit 7. Temperature-säätö tehtävän mukaan 8. Ensemble (sama prompti usealle mallille) 9. Post-processing 10. Fine-tuning (LoRA) - Välimuistiarkkitehtuuri: miksi toinen lataus on nopea - Käytännön lukuja: token-määrät, ajat, kustannukset Co-Authored-By: Claude Opus 4.6 (1M context) --- network-poc/GUIDE.md | 433 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 433 insertions(+) create mode 100644 network-poc/GUIDE.md diff --git a/network-poc/GUIDE.md b/network-poc/GUIDE.md new file mode 100644 index 0000000..669df75 --- /dev/null +++ b/network-poc/GUIDE.md @@ -0,0 +1,433 @@ +# Kipinä Agentic Studio — Opas + +Hajautettu AI-laskentaverkko jossa kielimallit ajavat koodia suoraan selaimessa. +Tämä opas selittää miten kielimallit toimivat, miten niitä ohjataan, ja miten +tuloksia voi parantaa. + +--- + +## Kielimallit ja niiden koot + +Kielimalli on neuroverkko joka ennustaa seuraavan sanan (tokenin) edellisten +perusteella. Mallin "koko" tarkoittaa parametrien (painojen) määrää: + +| Malli | Parametrit | Koko levyllä | Nopeus selaimessa | Koodinlaatu | +|-------|-----------|-------------|-------------------|-------------| +| SmolLM 135M | 135 miljoonaa | ~270 MB | ~5 tok/s | Yksinkertainen teksti | +| Qwen2.5-Coder 0.5B | 500 miljoonaa | ~990 MB | ~3-6 tok/s | Pienet funktiot | +| Qwen2.5-Coder 3B | 3 miljardia | ~6.2 GB | ~0.4 tok/s | Kokonaiset tiedostot | +| GPT-4 (vertailu) | ~1800 miljardia | ~3.6 TB | pilvipalvelu | Kokonaiset projektit | + +**Parametrien vaikutus:** Jokainen parametri on yksi liukuluku (float16 = 2 tavua) +joka tallentaa opittua tietoa. 0.5B-malli tietää perusrakenteet mutta tekee +loogisia virheitä. 3B-malli ymmärtää kontekstin paremmin. Ero on kuin sanakirjan +ja oppikirjan välillä. + +**Miksi selaimessa?** Malli ajetaan käyttäjän omalla laitteella WebAssemblyn +kautta. Data ei lähde koneelta, eikä tarvita pilvipalvelua. Haittapuoli on +hitaus — GPU-palvelimella sama 0.5B-malli tuottaa ~100 tok/s. + +--- + +## Tokenit — kielimallin "sanat" + +Malli ei näe tekstiä kirjaimina vaan **tokeneina**. Tokeni on yleensä +sanan osa, kokonainen sana tai välilyönti: + +``` +"print('Hello')" → ["print", "('", "Hello", "')"] = 4 tokenia +"tulosta('Hei')" → ["tul", "osta", "('", "He", "i", "')"] = 6 tokenia +``` + +**Miksi tällä on väliä?** + +1. **Kustannus:** Jokainen tokeni vaatii laskentaa. 100 tokenin vastaus + kestää 0.5B-mallilla ~15-30 sekuntia selaimessa. + +2. **Konteksti-ikkuna:** Malli näkee kerrallaan rajallisen määrän tokeneita. + Qwen2.5:ssa ikkuna on 32 768 tokenia. Tähän mahtuu prompti + vastaus. + +3. **Kielen tehokkuus:** Englanti tokenisoidaan tehokkaammin kuin suomi. + Sama lause vaatii suomeksi ~30-70% enemmän tokeneita. Siksi promptit + ovat englanniksi — malli saa enemmän informaatiota samassa token-budjetissa. + +**Token-budjetti tässä järjestelmässä:** + +| Osa | Tokeneita | Osuus | +|-----|-----------|-------| +| System prompt | ~30 | kiinteä | +| Agent prompt | ~25 | kiinteä | +| Konteksti (aiemmat tiedostot) | 0-300 | kasvaa | +| Käyttäjän prompti | ~20-50 | vaihtelee | +| **Syöte yhteensä** | **~75-400** | | +| Generoitu vastaus (max) | 512 | raja | +| **Yhteensä** | **~600-900** | /32 768 | + +Konteksti-ikkuna on reilusti riittävä. Pullonkaula ei ole ikkunan koko +vaan **mallin kyky ymmärtää pitkää kontekstia** — 0.5B-malli alkaa +"unohtaa" ohjeet kun konteksti kasvaa yli ~200 tokenin. + +--- + +## Promptit — miten mallia ohjataan + +### Kolmitasoinen prompttirakenne + +``` +┌─ System prompt (kiinteä, kovakoodattu) ─────────────────────┐ +│ "You are a coding assistant. Respond with ONLY code." │ +│ → Määrittää mallin roolin ja rajoitteet │ +│ → Tämä on tehokkain ohje koska malli priorisoi sen │ +└─────────────────────────────────────────────────────────────┘ + ↓ +┌─ Agent prompt (käyttäjän muokattavissa) ────────────────────┐ +│ "Olet kokenut ohjelmistokehittäjä. Kirjoita selkeää..." │ +│ → Agenttikohtainen persoonallisuus ja erikoisosaaminen │ +│ → Tallennetaan localStorageen, voi muokata UI:ssa │ +└─────────────────────────────────────────────────────────────┘ + ↓ +┌─ User prompt (vaihtelee joka kutsussa) ─────────────────────┐ +│ "Write ONLY the file main.py: FastAPI app with endpoints." │ +│ → Konkreettinen tehtävä tällä kerralla │ +│ → Sisältää kontekstin (aiemmat tiedostot) pipeline-tilassa │ +└─────────────────────────────────────────────────────────────┘ + ↓ +┌─ Prefill (pakottaa vastausformaatin) ───────────────────────┐ +│ ``` │ +│ → Malli luulee aloittaneensa koodiblokin ja jatkaa koodilla │ +│ → Estää "Sure! Here is..." -johdantotekstit │ +│ → Säästää ~10-20 tokenia per vastaus │ +└─────────────────────────────────────────────────────────────┘ +``` + +### Miksi promptit ovat englanniksi? + +Qwen2.5-Coder on harjoitettu pääosin englanninkielisellä koodilla ja +dokumentaatiolla. Suomenkielinen ohje kuluttaa enemmän tokeneita JA +malli ymmärtää sen huonommin. Agenttien nimet ja käyttöliittymä ovat +suomeksi, mutta tekniset ohjeet mallille englanniksi. + +Poikkeus: agenttipromptit ovat suomeksi koska ne menevät user-blokkiin +(ei system-blokkiin) ja niiden tarkoitus on enemmän "persoonallisuus" +kuin tekninen ohje. + +--- + +## Prefill-tekniikka + +Normaalisti malli päättää vapaasti miten vastaa: + +``` +Ilman prefilliä: + Malli: "Sure! Here is a Python program that prints Hello World:\n```python\nprint('Hello')\n```" + → 25 tokenia, joista 15 turhia + +Prefillin kanssa: + Me syötämme: ``` + Malli jatkaa: python\nprint('Hello')\n``` + → 5 tokenia, kaikki hyödyllisiä +``` + +Prefill on kuin aloittaisit lauseen toisen puolesta — malli jatkaa +siitä mihin jäit sen sijaan, että aloittaisi kohteliaalla johdannolla. + +**Sivuvaikutus:** Malli tuottaa kielitunnisteen (`python`, `rust`) ja +sulkevan ` ``` `:n. Nämä siivotaan jälkikäteen `strip_markdown_wrapper`-funktiolla. + +--- + +## Sampling — miten malli valitsee seuraavan tokenin + +Malli ei "tiedä" oikeaa vastausta. Se laskee jokaiselle mahdolliselle +seuraavalle tokenille todennäköisyyden ja valitsee yhden. Valintaa +ohjataan kolmella parametrilla: + +### Temperature (0.7) + +Kontrolloi "luovuutta" vs. "varmuutta": + +``` +Temperature 0.0 (greedy): Aina todennäköisin tokeni → "def fibonacci(n):" +Temperature 0.7 (oletus): Painottaa todennäköisiä mutta sallii vaihtelua +Temperature 1.5 (luova): Lähes satunnainen → "async lambda fib = ..." +``` + +0.7 on kompromissi: tarpeeksi determinististä tuottamaan toimivaa koodia, +mutta tarpeeksi vaihtelevaa välttämään toistoa. + +### Top-k (40) + +Rajaa valinnan 40 todennäköisimpään tokeniin. Estää mallia valitsemasta +täysin absurdeja vaihtoehtoja: + +``` +Ilman top-k: 150 936 vaihtoehtoa → voi valita minkä tahansa +Top-k 40: 40 vaihtoehtoa → järkevät vaihtoehdot +Top-k 1: 1 vaihtoehto → greedy (aina sama vastaus) +``` + +### Repetition penalty (1.15) + +Vähentää jo tuotettujen tokenien todennäköisyyttä. Estää mallia +juuttumasta luuppiin: + +``` +Ilman rangaistusta: "print print print print print..." +Penalty 1.15: "print('Hello')\nprint('World')" +``` + +1.15 on lievä rangaistus — estää pahimman toiston mutta sallii +saman avainsanan (esim. `return`) esiintymisen useasti. + +--- + +## Stop-sekvenssit — milloin generointi loppuu + +Malli generoi tokeneita kunnes jokin näistä tapahtuu: + +1. **EOS-tokeni** (151645): Mallin oma "loppu"-merkki +2. **Max tokens** (512): Kovakoodattu raja +3. **Stop-sekvenssi**: Malli alkaa tuottaa selitystä + +``` +fn fibonacci(n: usize) -> usize { + if n <= 1 { return n; } + fibonacci(n-1) + fibonacci(n-2) +} + ← Tähän asti koodia, ok +// Example usage: ← Stop! Tämä ei ole enää vastausta +let result = fibonacci(10); ← Ei generoida +``` + +Tunnistetut stop-sekvenssit: `### `, `Explanation`, `Note:`, `Output:`, +`// Example`, `# Example`. Generointi katkaistaan ja teksti trimmataan +stop-kohtaan. + +--- + +## Projekti-pipeline — miten agenttitiimi toimii + +``` +┌──────────┐ +│ Käyttäjä │ "FastAPI + SQLite REST API for users" +└────┬─────┘ + ↓ +┌──────────┐ "Pilko tiedostoiksi" +│ Manageri │ → models.py, main.py, pyproject.toml +└────┬─────┘ + ↓ (tiedostolista) +┌──────────┐ "Kirjoita models.py" +│ Koodari │ → from sqlalchemy import ... +└────┬─────┘ + ↓ (models.py kontekstina) +┌──────────┐ "Kirjoita main.py, käytä models.py:tä" +│ Koodari │ → from fastapi import ... +└────┬─────┘ + ↓ (kaikki tiedostot kontekstina) +┌──────────┐ "Kirjoita pyproject.toml" +│ Koodari │ → [project] dependencies = [...] +└────┬─────┘ + ↓ (kaikki tiedostot yhdessä) +┌──────────┐ "Review: onko bugeja?" +│ Testaaja │ → "Missing db.close(), no error handling" +└────┬─────┘ + ↓ (review-palaute + koodi) +┌──────────┐ "Korjaa nämä ongelmat" +│ Koodari │ → Korjattu koodi +└────┬─────┘ + ↓ +┌──────────┐ "Tarkista korjaukset" +│ Testaaja │ → "LGTM" tai lisäkorjauksia +└──────────┘ +``` + +**Kontekstin ketjutus** on kriittistä: kun koodari kirjoittaa `main.py`:tä, +se saa `models.py`:n sisällön promptissa. Ilman tätä se ei tietäisi +mitä luokkia importata. + +**Riippuvuusjärjestys:** Manageria pyydetään listaamaan riippuvuudet ensin +(models.py ennen main.py) jotta kontekstiketju toimii oikeaan suuntaan. + +--- + +## Laadun parantaminen + +### 1. Isompi malli (suurin vaikutus) + +| | 0.5B | 3B | Pilvi-API | +|---|---|---|---| +| Fibonacci | Joskus virheitä | Yleensä oikein | Aina oikein | +| FastAPI CRUD | Voi käyttää Flaskia | Oikea kirjasto | Täydellinen | +| Monimutkainen logiikka | Hallusinoi | Osaa perusasiat | Syvä ymmärrys | +| Nopeus (selain) | ~5 tok/s | ~0.4 tok/s | — | +| Latauksen koko | 990 MB | 6.2 GB | 0 (API) | + +**Käytännössä:** `kpn load 2` lataa 3B-mallin. Hitaampi mutta huomattavasti +parempi koodinlaatu. Suositus monimutkaisiin projekteihin. + +### 2. Paremmat promptit (ilmaista) + +**Huono:** `"tee fibonacci"` +- Malli ei tiedä kieltä, formaattia tai kontekstia + +**Hyvä:** `"Write a fibonacci function in Rust that returns Vec"` +- Kieli, palautustyyppi ja rakenne määritelty + +**Promptin säännöt:** +- Englanniksi (tehokkaampi tokenisointi, parempi ymmärrys) +- Konkreettinen (mainitse kieli, kirjastot, palautustyyppi) +- Lyhyt (jokainen sana kuluttaa tokenin konteksti-ikkunasta) +- Positiivinen ("Write X" ei "Don't write Y") + +### 3. Kontekstin hallinta (pipeline-taso) + +**Ongelma:** 0.5B-malli "unohtaa" promptin alun kun konteksti kasvaa. + +**Ratkaisu:** Pienet, kohdennetut promptit: +- Yksi tiedosto kerrallaan (ei "kirjoita koko projekti") +- Vain relevantit aiemmat tiedostot kontekstina +- Max 4 tiedostoa per projekti + +### 4. Iterointi (review-luuppi) + +Yksi generointikierros tuottaa harvoin virheetöntä koodia. +Pipeline-arkkitehtuuri mahdollistaa: + +1. **Generointi** — ensimmäinen versio +2. **Review** — testaaja löytää ongelmat +3. **Korjaus** — koodari saa palautteen ja korjaa +4. **Uusi review** — tarkistetaan korjaukset + +Nykyinen järjestelmä tekee max 1 korjauskierroksen. Useampi +iteraatio parantaisi laatua mutta kasvattaisi laskenta-aikaa. + +### 5. Erikoistetut system promptit + +Oletuspromptit ovat yleiskäyttöisiä. Projektikohtaiset promptit +parantavat laatua merkittävästi: + +``` +Oletus: "Olet kokenut ohjelmistokehittäjä." + +Parempi: "You are a Python backend developer specializing in FastAPI. +Always use Pydantic models for request/response schemas. +Always use dependency injection for database sessions. +Follow the repository pattern." +``` + +Agenttikohtaiset promptit voi muokata suoraan UI:ssa. + +### 6. Few-shot esimerkit + +Malli oppii parhaiten esimerkeistä. Sen sijaan, että sanot "kirjoita +FastAPI endpoint", näytä miltä haluat tuloksen näyttävän: + +``` +Write a GET endpoint like this example: + +@app.get("/items") +def list_items(): + db = SessionLocal() + return db.query(Item).all() + +Now write a similar endpoint for /users. +``` + +0.5B-malli jäljittelee rakennetta tehokkaasti — se on parempi kopioimaan +kuin keksimään. Nykyinen pyproject.toml-esimerkki promptissa on tätä tekniikkaa. + +### 7. Temperature-säätö tehtävän mukaan + +Nykyinen temperature 0.7 on kompromissi. Eri tehtävät hyötyisivät eri arvoista: + +| Tehtävä | Paras temperature | Miksi | +|---------|-------------------|-------| +| Tarkka koodi (CRUD, boilerplate) | 0.2-0.4 | Determinismi tärkeää | +| Luova koodi (algoritmit, arkkitehtuuri) | 0.6-0.8 | Vaihtelu löytää ratkaisuja | +| Vapaa teksti (kommentit, dokumentaatio) | 0.8-1.0 | Luonnollisempi kieli | + +Järjestelmä voisi valita temperaturen automaattisesti tehtävätyypin perusteella. + +### 8. Ensemble — sama prompti usealle mallille + +Lähetetään sama tehtävä kahdelle solmulle ja valitaan parempi vastaus. +Nykyinen Proof of Compute -arkkitehtuuri tukee tätä periaatteessa: +hub voisi reitittää saman task_id:n kahdelle solmulle ja verrata tuloksia. + +Käytännössä tämä kaksinkertaistaa laskenta-ajan mutta parantaa laatua +merkittävästi — virheellinen vastaus harvoin on sama kahdella ajolla +koska sampling on stokastinen. + +### 9. Post-processing (nykyinen) + +Mallin raakavastaus siivotaan: +1. Kielitunniste poistetaan (`python`, `rust`, ...) +2. Sulkeva ` ``` ` poistetaan +3. Johdantolauseet poistetaan ("Sure!", "Here is...") +4. Selityskommentit poistetaan ("# This is a simple...") +5. Stop-sekvenssit katkaisevat generoinnin + +Tämä ei paranna mallin ajattelua mutta poistaa turhan roskan. + +### 10. Mallin hienosäätö (fine-tuning) + +Qwen2.5-Coder on yleiskäyttöinen koodimalli. Jos sitä hienosäätäisi +omalla koodiaineistolla (esim. yrityksen koodikanta, tietty framework), +se tuottaisi huomattavasti parempaa koodia juuri siihen kontekstiin. + +LoRA-hienosäätö 0.5B-mallille vaatii ~4 GB GPU-muistia ja muutaman +tunnin harjoittelua. Tulos on erikoistunut malli joka osaa tuottaa +esimerkiksi juuri FastAPI + SQLAlchemy -koodia luotettavasti. + +--- + +## Välimuistiarkkitehtuuri — miksi toinen lataus on nopea + +``` +Ensimmäinen lataus (hidas): + Verkko (HuggingFace CDN) → IndexedDB → RAM → Mallin rakennus + ~990 MB lataus, ~30-60s + +Toinen lataus samalla sivulatauksella (nopea): + RAM-cache → Mallia ei rakenneta uusiksi, vain KV-cache nollataan + ~0ms + +Refresh jälkeen (keskitaso): + IndexedDB → RAM → Mallin rakennus + ~0 MB lataus, ~2-5s rakennus + +Uusi selain/laite (hidas): + Verkko → IndexedDB → RAM → Mallin rakennus + Kuten ensimmäinen lataus +``` + +**KV-cache:** Mallin sisäinen muisti joka tallentaa aiempien tokenien +laskenta tulokset. Nollataan (`clear_kv_cache()`) jokaisen promptin +välillä jotta edellinen vastaus ei vuoda seuraavaan. + +--- + +## Lukuja käytännöstä + +**Yksittäinen funktio** (esim. fibonacci): +- Input: ~80 tokenia +- Output: ~50-100 tokenia +- Aika: ~10-20s (0.5B, selain) +- Laatu: Yleensä toimiva, joskus loogisia virheitä + +**3 tiedoston projekti** (esim. FastAPI CRUD): +- Manageri: ~30 tok out +- Koodari (3x): ~100-150 tok out per tiedosto +- Testeri: ~50 tok out +- Korjaukset: ~100 tok out (jos tarpeen) +- **Yhteensä: ~500-700 tokenia, ~3-5 min** +- Laatu: Rakenne oikein, yksittäisiä bugeja + +**Token-kustannus vs. pilvipalvelu:** +- Tässä järjestelmässä: 0 euroa (laskenta omalla koneella) +- GPT-4 API: ~700 tokenia x $0.03/1K = ~$0.02 per projekti +- Claude API: ~700 tokenia x $0.015/1K = ~$0.01 per projekti + +Selaimessa ajettava malli on ilmainen mutta huomattavasti hitaampi +ja heikompilaatuinen kuin pilvi-API. Sopii oppimiseen, prototypointiin +ja tilanteisiin joissa data ei saa lähteä omalta koneelta.