Publikováno 20. června 2026

Obchodnirejstrik-ai: když lepší AI model změnil architekturu, ne jen prompt

Článek o vývoji SAAS platformy na analýzu firem z věřejných registrů v ČR: od OCR mezivrstvy k přímé práci s PDF, strukturovaným datům, deterministickým kontrolám a provozní spolehlivosti.

obchodnirejstrik-ai stavím jako nástroj pro prověrku české firmy. Vstupem je IČO nebo výroční zpráva v PDF, výstupem finanční, rizikový a valuační report. Na papíře je to jednoduché. Ve skutečnosti jsou účetní závěrky rozeseté mezi Sbírkou listin a další registry, často mají několik let dat v jednom dokumentu a část důležitých informací vůbec není ve finančních výkazech.

Tahle verze projektu je už druhá architektura. Nejde o přepsání frontendu kvůli novému frameworku. Změnil se samotný předpoklad, na kterém stála první pipeline: co musí systém udělat předtím, než může model nad dokumentem rozumně pracovat.

Problém nebyl „přečíst PDF“

První verze začínala samostatným OCR krokem. PDF šlo do Mistral OCR, z něj přišel text a tabulky v Markdownu a až potom model extrahoval finanční data do strukturovaného výstupu. Tehdy to byl rozumný kompromis: výroční zprávy jsou často skeny, tabulky jsou složité a pouhé vytažení textové vrstvy PDF nestačí.

Za OCR následovalo dohledání dat z registrů, analýza modelem, výpočet rizik a generování reportu. Aplikace měla React/Vite a FastAPI, dlouhé úlohy běžely přes Celery a Redis, datovou páteř, autentizaci i soubory zajišťoval Supabase.

Největší problém nebyla jedna služba navíc. Byla to celá hranice mezi dokumentem a modelem: další externí volání, další účtování, další typ chyb a další transformace, jejíž kvalitu bylo nutné hlídat. OCR vrstva byla infrastrukturní nutnost, ne produktová výhoda.

Zlom: model převzal i OCR vrstvu

Současné multimodální modely umějí zpracovat PDF jako soubor přímo v API: vedle textové vrstvy pracují i s vizuální podobou stránek. To změnilo rozhodnutí od „vylepšit OCR“ na „zjednodušit celou cestu“.

V aktuálním backendu se PDF nahraje přes OpenAI Files API a do Responses API jde jako input_file společně s přesným zadáním. Model vrací JSON, ne hotový dokument. Konkrétní model v konfiguraci beru jako vyměnitelný detail — důležité je rozhraní, evaluační vzorky a kontrakt výstupu, ne marketingové tvrzení o jednom „nejnovějším“ modelu.

Tím odpadla jedna síťová závislost, vlastní meziformát i část latence. Neznamená to, že model bezchybně chápe každou závěrku. Znamená to, že jeden systém nese odpovědnost za porozumění dokumentu a že můžu testovat kvalitu přes stejné strukturované rozhraní místo ladění dvou nezávislých služeb.

Pipeline dnes: data nejdřív, text až potom

Přestavba skončila u monorepa: Next.js na webu, FastAPI v API, PostgreSQL přes SQLAlchemy a Alembic pro reprodukovatelné migrace, Redis a ARQ pro práci na pozadí. Analýza neběží v HTTP requestu; API vytvoří report, ověří vstup a předá práci workeru.

Typická hlubší analýza vypadá takto:

  1. Uživatel zadá IČO nebo nahraje PDF. Pokud má jen IČO, aplikace zkusí stáhnout relevantní účetní závěrky ze Sbírky listin.
  2. Worker doplní údaje o firmě a víceleté finanční hodnoty. Pro jeden rok může porovnat více podání: nový dokument má často úplnější aktuální sloupec, starší podání zase doplní chybějící cash flow nebo EBITDA.
  3. PDF se zpracuje přímo modelem do strukturovaných finančních dat a faktů z dokumentu. Výstup se parsuje a ukládá podle kanonického schématu, ne jako volný text.
  4. Paralelně přichází kontext z ARES, justice.cz, ADIS, eISIR, sankčních seznamů a dalších veřejných zdrojů; podle typu reportu také vlastnické vazby, lidé ve vedení nebo veřejné zakázky.
  5. Python spočítá valuaci pomocí násobků EV/EBITDA. Násobky jsou odvětvově citlivé, ne jeden globální koeficient pro všechny firmy.
  6. Teprve nad tím vznikají jednotlivé části reportu, zdroje a srozumitelné shrnutí. Výsledek lze zobrazit, sdílet přes read-only odkaz nebo exportovat do PDF.

Toto pořadí je záměr. Nechci, aby model nejdřív napsal přesvědčivý příběh a systém pak hledal, čím ho podložit. Nejdřív vznikne datový základ a důkazy; narativ je až jeho interpretace.

Proč nestačí říct „analyzuj firmu“

Report nevzniká jedním volným promptem. Model extrahuje data do kanonického schématu a interpretuje ověřená data, ale nemá pravomoc vytvářet finanční fakta ani předpoklady valuace. Aplikace extrahovaná data validuje a deterministicky řídí výpočty, rizikové příznaky, grafy, pořadí sekcí, renderování i zdrojové důkazy.

Výstup je pevná sada sekcí renderovaná z validovaných dat, takže se dá znovu vytvořit a zkontrolovat. Valuace používá centrálně spravované, sektorově citlivé násobky a benchmarky s deterministickými pravidly použití a mantinely. Model je nemůže domýšlet ani měnit.

Kde končí model a začíná software

Nejdůležitější architektonické rozhodnutí je hranice důvěry. Model je dobrý ve čtení nehomogenních dokumentů, extrakci a vysvětlení souvislostí. Není zdrojem pravdy pro věci, které musí být reprodukovatelné nebo mají právní a finanční dopad.

Proto držím v kódu:

  • datové schéma a validaci odpovědí;
  • výpočty finančních ukazatelů, valuace a benchmarků;
  • tvrdé rizikové příznaky, například aktivní insolvence nebo nespolehlivý plátce DPH;
  • pořadí a renderování reportu, grafy a evidence zdrojů;
  • přístupová pravidla, kredity a audit spotřeby modelu po jednotlivých reportech.

Model může popsat, proč je pokles marže zajímavý. Nemá však sám rozhodnout, zda firma splňuje pravidlo pro rizikový flag, ani „vymyslet“ číslo do valuace. Tento rozpad také výrazně zjednodušuje debugging: špatná hodnota je problém extrakce nebo vstupu, špatný výpočet problém finanční logiky a špatné zobrazení problém rendereru. Neřeším jeden neurčitý výsledek modelu.

Co znamená provozovat AI feature

Nejtěžší části nebyly prompty. Byla to provozní disciplína okolo drahých a pomalých operací.

Každý report prochází frontou ARQ místo toho, aby držel otevřený HTTP request několik minut. Worker ukládá stav a postup práce, retryuje přechodná selhání a u opakovaného spuštění umí využít už vytvořené sekce reportu. Při problému s jedním veřejným registrem aplikace raději označí zdroj jako nedostupný, než aby zrušila celý placený report — ale kritický nedostatek vstupních dat umí analýzu zastavit dřív, než se utratí peníze za generování.

AI náklad není jen prostá položka v dashboardu poskytovatele. Při volání Responses API měřím vstupní i výstupní tokeny pro konkrétní report. Kreditový systém zapisuje operace do účetní knihy; odečet, vrácení kreditu při selhání a kontrola zůstatku jsou explicitní workflow, ne vedlejší efekt jednoho requestu.

Pro observabilitu používám self-hosted službu kompatibilní se Sentry (Bugsink). Zachytává chyby API, trvale neúspěšné joby a health checky workeru, aniž by chybová data musela opouštět VPS. Pro malý produkt je to pragmatický kompromis: menší vendor footprint za cenu toho, že provoz a aktualizace infrastruktury jsou moje odpovědnost.

Co bych dnes udělal stejně

Přestavba mě utvrdila ve dvou věcech. První: když se fundamentálně změní schopnost modelu, je někdy správnější přehodnotit systémovou hranici než lepit původní pipeline. Mistral OCR nebyl omyl; byl to správný krok pro tehdejší schopnosti modelů. Jen přestal být nejlepší architekturou.

Druhá: důvěryhodná AI aplikace nevznikne tím, že model dostane více volnosti. Vznikne tím, že dostane přesně vymezenou práci, ověřitelný datový kontrakt a software okolo, který zvládne chyby poskytovatele, neúplná data i cenu každého běhu. To je část obchodnirejstrik-ai, která mě zajímá nejvíc — ne samotné volání modelu, ale hranice, jež z něj dělají použitelný produkt.