Miten Dreamalizing ajaa kielimallia ilman pilvipalvelua
Uni on henkilökohtaisinta, mitä kukaan voi kirjoittaa ylös. Siksi Dreamalizingissa unitekstiä ei koskaan lähetetä ulkoiseen tekoälypalveluun. Tässä artikkelissa kuvataan tekninen toteutus, siitä seuranneet valinnat ja se, mikä matkan varrella meni pieleen.
Teksti on kirjoitettu kehittäjille ja kaikille, jotka haluavat varmistaa, että tietosuojalupaus on muutakin kuin pelkkä lause kotisivulla.
Lupaus yhden lauseen muodossa
Unitekstisi käsitellään omalla kielimallillamme Euroopan unionin sisällä olevilla palvelimilla. Tietosi tallennetaan salattuina, eikä unitekstiäsi lähetetä ulkoisiin tekoälypalveluihin.
Tämä lause löytyy sovelluksesta, sovelluskaupoista ja tältä sivustolta. Kaikki alla oleva on olemassa toteuttaakseen tämän lupauksen, vaikka joku tekisi kirjoitusvirheen konfiguraatiotiedostoon.
Ketju puhelimesta malliin
Sovellus (React Native, Expo) keskustelee API:n (NestJS, PostgreSQL) kanssa EU:ssa sijaitsevalla vuokratimella. Tällä palvelimella ei ole kielimallia. Se saavuttaa WireGuard-tunnelin kautta gatewayn omalla laitteistolla, ja tämä gateway keskustelee mallin kanssa.
Malli on Gemma 4, jossa on 26 miljardia parametria mixture-of-experts-rakenteessa, josta noin 4 miljardia on aktiivisena per token, 8-bittisessä kvantisoinnissa. Yksi malli hoitaa kaiken: kysymykset, analyysin ja jäsennellyn tiedon erottelun. Konteksti-ikkuna on kiinteästi 32 768 tokenia, koska raskain analyysi käytti tähän asti 13 671 tokenia ja tuloste saa olla enintään 8 192 tokenia.
Elokuun asti käytössä oli kaksi mallia: raskaampi kysymyksiin ja analyysiin sekä kevyempi tiedon erotteluun. Tämä osoittautui kalliimmaksi kuin mitä se tuotti. Kaksi mallia syrjäytti toisensa muistissa, jolloin malli ladattiin kolme kertaa per uni, mikä vei 7–10 sekuntia. Raskaampi malli tekee erottelun 3,7 sekuntia hitaammin, mutta säästää 27 sekuntia latausaikaa.
Paikallinen valvonta, ei tarkoituksena
API:ssa on reitityskerros, joka voi ohjata pyynnöt useille tarjoajille. Se on hyödyllinen kehitysvaiheessa, mutta vaarallinen tuotannossa. Siksi on olemassa kolme lukkoa.
Ensinnäkin runtime-tasolla oleva tiukka lippu. Jos se on päällä, API kieltää jokaisen unisisältöä sisältävän kutsun, joka kohdistuu ei-paikalliseen tarjoajaan. Hätäventtiili on olemassa, mutta se on sidottu enintään neljätoista päivän pituiseen päättymispäivään ja se vanhenee automaattisesti; virheellinen tai liian kaukainen päivämäärä ohitetaan ja valvonta pysyy suljettuna.
Toiseksi gateway. Jokainen API:n pyytämä malli-id alkaa etuliitteellä local-. Gateway lukee tämän paikalliseksi (local-only) ja kieltää tällaisen pyynnön toimittamisen pilvitarjoajalle, vaikka sinne osoittaisi varareitti.
Kolmanneksi testit. Testi pakottaa API:n olemaan poistamatta etuliitettä koskaan, ja toinen testi varmistaa, että testaus- ja tuotantoympäristöjen mallikonfiguraatiot ovat identtiset. Ensimmäinen testi on olemassa, koska API poisti etuliitteen elokuun loppuun asti. Tämän vuoksi gatewayn varareitti olisi teoriassa voinut lähettää unitekstiä pilveen status 200 -vastauksella ilman varoitusta. Sovellus ei ollut tuolloin vielä julkaistu, eikä meillä ollut muita aktiivisia käyttäjiä. Suljimme polun ja lisäsimme testin, jotta se ei ole enää mahdollista, edes huomaamatta.
Odotusaika on suunnitteluvalinta
Paikallinen malli yhdellä koneella on hitaampi kuin pilvi-API. Vastaukset tulevat 20–40 sekunnin kuluttua, analyysi 30–60 sekunnin kuluttua. Emme peittele tätä; sovellus kertoo, mitä tapahtuu ja kuinka kauan se suunnilleen kestää.
Järjestys on säädetty tätä varten. Ensin kysymykset lähetetään sovellukseen raa'asta unitekstistä. Sen jälkeen, rinnakkain, toinen kutsu rakentaa jäsennellyt tiedot, joita analyysi tarvitsee myöhemmin. Sillä välin uneksija vastaa kysymyksiin eikä huomaa toista kutsua.
Koneella pyörii rajoitin, joka sallii yhden kutsu per käyttäjä kerrallaan ja varmistaa, ettei valinnaisia kutsuja koskaan lähetetä ennen pakollisia. Viimeksi opimme tämän tuotanto-ongelmasta: valinnainen kutsu syrjäytti pakollisen, eikä uneksija odottanut mitään.
Tallennus ja offline-tila
Unitekstit ja vastaukset tallennetaan käyttäjäkohtaisesti salattuina AES-256-GCM-menetelmällä ja jokaisella käyttäjällä on oma avaimensa, joka puolestaan on pääavaimen alla. Puhelimessa vielä lähettämättömien unien jono on salatussa SQLCipher-tietokannassa, jonka avain on laitteen suojatussa tallennustilassa.
Jokainen kirjoitusoperaatio kantaa vakaata operaatio-id:tä. Jos yhteys katkeaa lähetyksen jälkeen mutta ennen vastausta, uudelleenyritys tuottaa saman unen, ei toista. Näiden id:iden loki ei sisällä unitekstiä, vain toiminnon tyypin, hashin ja tuloksen.
Mitä se maksaa
Yksi kone on yksi katto. Samanaikaisilla käyttäjillä kutsut kertyvät ja odotusaika kasvaa. Tämä on hinta siitä, ettei käytetä pilveä, ja syy siihen, miksi aloitimme Alankomaista emmekä maailmanlaajuisesti.
Toinen hinta on se, että malli ei ole yhtä hyvä kuin suurimmat pilvimallit. Siksi mittaamme promptimuutokset aina paikallisella mallilla, emme koskaan pilvimallilla; se, mikä toimii suuremmalla mallilla, ei toimi täällä automaattisesti.
Mitä seuraavaksi
Kysymykset arkkitehtuurista ovat tervetulleita. Tässä oleva tieto on syyskuun 2026 tilanne; jos jokin muuttuu, tämä artikkeli päivittyy.