file opened

Pika PDF Merger: Pomysł, implementacja i wdrożenie

2026-09-02 ::5 min read

Zgodnie z wyborem z ankiety na LinkedIn, ten wpis jest o prostej apce, którą “zmontowałem” na szybko używając LLM - Pika PDF Merger. Aplikacja powstała iteracyjnie, czyli automatyzacja pracy z AI była połowiczna.

Jak zawsze: wszystko zaczęło się od pomysłu

Pomysł na aplikację istniał od dawna. Co do zasady nie robiłem tego, dlatego, że aby zrobić taką prostą apkę bez LLM trzeba było mieć i tak sporo czasu. Co nasuwa się samo: zwykła, prosta apka, więc jak można na to potrzebować dużo czasu? Miło, że pytasz, toteż spieszę z odpowiedzią. Dzieje się tak, ponieważ taka mała aplikacja jest kolejną z wielu zazwyczaj. W moim przypadku chodzi oczywiście o alokację czasu i zasobów (w tym kredytów AI) pomiędzy każdą taką dodatkową, małą aplikację, a PikaCloud. Psychologiczny “chwyt” w moim przypadku, to uzasadnienie sobie, że aplikacji będę używał (a jeszcze lepiej, jeśli ktoś z moich bliskich będzie), a jednocześnie mogę w ten sposób rozbudować funkcjonalność systemu (w domyśle PikaCloud). Jednocześnie, właściwym czynnikiem i motorem do działania była bezpośrednia prośba bliskiej mi osoby, że nigdy nie może znaleźć sobie takiej aplikacji online, a potrzebuje co jakiś czas. Wniosek prosty: montujemy, nie?

Projekt - UML? Nie, co to?

Projekt powstał w mojej głowie jakiś czas wcześniej. Miałem też elektroniczne szkice (notatki tekstowe) na laptopie, z których przygotowałem sobie zestaw instrukcji dla modelu. Pierwszym krokiem było zbudowanie szkieletu aplikacji w zadanej technologii (tutaj był to Laravel z Vue) razem z Dockerem, który by był łatwo “deployable” w moim ekosystemie. Chodziło przede wszystkim o to, aby było to pierwotnie rozłączne względem PikaCore czy innych komponentów systemu. Docelowo jednak zamysł był taki, aby backend nowego systemu był komaptybilny i migrowalny do roli wewnętrznego makroserwisu, a front-end mógł być łatwo zmigrowany jako integralna część UI PikaCore (stąd Vue na froncie). Backend został napisany w php głównie dlatego, że jest to dobrze mi znana technologia, którą lubię, dająca ogrom możliwości w operacji na plikach PDF, które są ostatecznie kluczowym punktem całej aplikacji. Nawiązujące do tytułu, nie posiadam UML do tego systemu, ale to wynika z mojego ogólnego planu na reorganizację i udokumentowanie całego systemu (forma podprojektu w ramach projektu “cloudu”). Zgodnie z tym, nie marnowałem tu na to tokenów, bo aplikacja mogła zmienić w trakcie pracy iteracyjnej relacje do reszty systemów, połączenia i krawędzie, do których następuje połączenie. Natomiast, zachęcam do projektowania używając następującego schematu: myśl -> notatka -> UML. Notatka i UML będą docelowo stanowić świetną dokumentację prywatnych projektów, a w przypadku projektów enterprise - zalążek tejże.

Implementacja - MMMP (Model Modelem Model Pogania)

Wstępną implementację tzw. szkieletu zrealizował GPT5.6 Sol poprzez ChatGPT. Kolejnym krokiem było zwyczajne skonfigurowanie pipeline’ów i workflow CI&CD na TeamCity. Stąd już GPT zaprojektował Dockerfile i compose tak, by ułatwić za równo lokalne testowanie, ale także deployment z użyciem lokalnego Docker Registry i TeamCity. Następnie rozpakowałem sobie archiwum od ChatGPT na laptopie, zweryfikowałem co otrzymałem w środku (kod, zamysł), a następnie podpiąłem pod projekt Github Copilota z modelem GPT5.5, gdzie zacząłem iteracyjnie “modelować” integrację ze swoim PikaCore w dwóch trybach. Jeden jest w trybie publicznym (dostęp do storage, storage2), ale także drugim, autoryzowanym, gdzie wskazujemy z dowolnego, widocznego dla nas bucketu plik/pliki. Standardowo, aplikacja też pozwala po prostu “wrzucić” swoje pliki lub bezpośrednie linki do pliku. W każdym wypadku to jest tylko zmiana “źródła”, gdzie oba pierwsze są wbudowane, ale już mój system jest traktowany jako “adapter”. Laravel ma to rozwiązane na własnym poziomie, gdzie można dodać sobie dowolne “filesystems”. Klasycznie jest oczywiście local, S3 itd, toteż moja aplikacja ma mój własny: PikaCore. Domyślnie, LLM mógłby tego nie połączyć, ale ja jasno wskazałem mu to w promptach już w 1. iteracji, a następne były coraz mniejsze i tańsze, dlatego, że coraz bardziej doprecyzowywałem działanie, nie architekturę. Klarowna architektura ułatwiła i mnie, i modelowi analizę w raz z osadzeniem systemu w konkretnym kontekście. Istotnym elementem tego procesu również było to, że model pracował na konkretnych plikach (nie na całych repo), posiadając plik konfiguracyjny co do stylu w kodzie Laravelowym, ale otrzymywał również konkretne, wskazane przeze mnie manualnie kontrolery, usługi czy adaptery z innego kodu. Te pliki były jasno opisane cd swojej roli wewnątrz PikaCore i jak ma je wykorzystać w ramach implementacji integracji z systemem. Ostatecznie, zrealizowałem całą aplikację włącznie z wdrożeniem z 2 wieczory, przy czym wynikało to głównie z tego, że rozpocząłem pracę pierwszego dnia dość późno, a sen jest przecież bardzo istotny.

Coś na koniec

Generalnie rzecz ujmując - mogłem to zrobić na 100% szybciej. W pełni zautomatyzować. Jednak mam dwa powody, dlaczego tak na razie nie robię.

Powód numer 1: Lubię proces iteracyjnej pracy, monitorowania, ew. zmian w pomyśle. Nie zmniejsza to mojej efektywności, bo mój flow i tak wygląda tak, że jeśli pracuję to na kilku rzeczach na raz, a jak przestaję to przestaję i nie czuję potrzeby, by coś się działo bez mojego nadzoru.

Powód numer 2: Pełna automatyzacja wymaga konfiguracji flow z użyciem dopasowanych modeli do konkretnych zadań co w przypadku użytkowania gotowych rozwiązań na bazie agentic tool jak Github Copilot będzie kosztowne. Ten powód przestaje być dla mnie ważny, gdyż skonfigurowałem sobie OpenCode z lokalnym modelem, który sobie troszkę ztweakowałem na poziomie manifestu, dzięki czemu mam troszkę dłużej “mielący” model, ale wyniki są zadowalające, więc mogę sobie powoli pozwolić na użytkowanie agenta z podagentami. Natomiast, to już jest temat na inny odcinek.