Technologie

Jak Dreamalizing provozuje jazykový model bez cloudu

Sen je to nejvíce osobní věc, kterou může člověk zapsat. Proto text snu v Dreamalizing nikdy neposíláme do externí služby AI. Tento článek popisuje, jak to technicky funguje, jaká rozhodnutí s tím souvisela a co se cestou pokazilo.

Je napsán pro vývojáře a pro každého, kdo chce ověřit, zda příslib soukromí je víc než jen věta na úvodní stránce.

Příslib v jedné větě

Váš text snu zpracovává náš vlastní jazykový model na serverech v Evropské unii. Vaše údaje jsou ukládány šifrovaně a text snu není odesílán do externích služeb AI.

Tato věta je v aplikaci, v obchodech a na tomto webu. Vše pod tímto článkem slouží k tomu, aby byla splněna, i když někdo udělá překlep v konfiguračním souboru.

Řetězec od telefonu k modelu

Aplikace (React Native, Expo) komunikuje s API (NestJS, PostgreSQL) na pronajatém serveru v EU. Tento server nemá jazykový model. Přes WireGuard tunel se připojuje k bráně (gateway) na vlastním hardwaru, a ta pak komunikuje s modelem.

Model je Gemma 4 se 26 miliardami parametrů v architektuře mixture-of-experts, přičemž přibližně 4 miliardy jsou aktivní na každý token, v 8bitové kvantizaci. Jeden model dělá vše: otázky, analýzu i strukturovanou extrakci. Kontextové okno je pevně nastaveno na 32 768 tokenů, protože nejnáročnější analýza dosud využívala 13 671 tokenů a výstup může mít až 8 192 tokenů.

Do srpna běžely dva modely: jeden těžší pro otázky a analýzu a druhý lehčí pro extrakci. To se ukázalo jako dražší, než to přineslo úspory. Dva modely se navzájem vytlačovaly v paměti, což znamenalo, že se u každého snu musel model načítat třikrát, což trvalo 7 až 10 sekund. Těžší model provádí extrakci o 3,7 sekundy pomaleji, ale ušetří 27 sekund času při načítání.

Lokální režim jako dohled, nikoliv jako záměr

API má směrovací vrstvu, která může směrovat požadavky k více poskytovatelům. To je užitečné při vývoji, ale nebezpečné v produkci. Proto máme tři pojistky.

První je tvrdá vlajka (flag) v runtime. Pokud je zapnutá, API odmítne jakýkoli požadavek obsahující text snu směřující k ne-lokálnímu poskytovateli. Existuje nouzové tlačítko, ale je omezeno maximálně čtrnácti dny a automaticky vyprší; neplatné nebo příliš vzdálené datum je ignorováno a dohled zůstane aktivní.

Druhá je brána (gateway). Každé ID modelu, které API vyžaduje, začíná prefixem local-. Brána to přečte jako lokální režim a takový požadavek odmítne doručit cloudovému poskytovateli, i když na něj ukazuje záložní řetězec.

Třetí jsou testy. Jeden test vynucuje, aby API nikdy neodstraňovalo prefix, druhý zajišťuje, aby konfigurace modelu v testovacím a produkčním prostředí byla identická. První test existuje proto, že API prefix do konce srpna skutečně odstraňovalo. To znamenalo, že záložní mechanismus brány by teoreticky mohl poslat text snu do cloudu se stavem 200 a bez varování. Aplikace nebyla tehdy ještě spuštěna a mimo nás neměla žádné aktivní uživatele. Cestu jsme uzavřeli a test přidali, aby to již nešlo, ani nepozorovaně.

Čekací doba je rozhodnutí o designu

Lokální model na jednom stroji je pomalejší než cloudové API. Otázky jsou vyřízeny za 20 až 40 sekund, analýza za 30 až 60. To nebudeme skrývat; aplikace říká, co se děje a jak dlouho to přibližně potrvá.

Sekvence je podle toho nastavena. Nejdříve jdou otázky do aplikace na surový text snu. Poté, paralelně, druhý požadavek buduje strukturovaná data, která bude analýza později potřebovat. Snilící mezitím odpovídá na otázky a o tomto druhém požadavku neví.

Na stroji běží omezovač, který pro každého uživatele dovoluje jeden požadavek najednou a zajistí, že volitelné požadavky nikdy nebudou přednostně zpracovány před povinnými. To jsme se naučili z incidentu v produkci: volitelný požadavek vytlačil ten povinný a snilící na nic nečekal.

Úložiště a offline režim

Texty snů a odpovědi jsou pro každého uživatele ukládány šifrovaně pomocí AES-256-GCM s vlastním klíčem pro každého uživatele, který je zase chráněn hlavním klíčem. V telefonu je fronta ještě neodeslaných snů uložena v šifrované databázi SQLCipher s klíčem v zabezpečeném úložišti zařízení.

Každá zápisová operace nese stabilní ID operace. Pokud spojení vypadne po odeslání, ale před obdržením odpovědi, opakování vrátí tentýž sen, nikoliv druhý. Deník těchto ID nikdy neobsahuje text snu, pouze typ akce, hash a výsledek.

Kolik to stojí

Jeden stroj představuje strop. Při současných uživatelích se požadavky hromadí a čekací doba roste. To je cena za absenci cloudu a důvod, proč jsme začali v Nizozemsku a ne globálně.

Druhou cenou je, že model není tak dobrý jako největší cloudové modely. Proto proto měříme změny v promptech vždy na lokálním modelu, nikdy ne na cloudovém modelu; to, co funguje na větším modelu, zde nemusí automaticky fungovat.

Co následuje

Otázky ohledně architektury jsou vítány. To, co je zde uvedeno, je stav k září 2026; pokud se něco změní, tento článek se změní spolu s ním.