Java jako język do produkcji w obszarze sztucznej inteligencji: Spring Boot, RAG i pgvector
Praktyczna mapa budowania usług RAG na JVM przy użyciu Spring AI lub LangChain4j, wyboru magazynu wektorów oraz zarządzania dzierżawą, kosztami, oceną i rozwiązaniami awaryjnymi.
Python służy do trenowania modeli, natomiast Java stopniowo staje się językiem, który umożliwia ich wdrożenie. Przez około trzy lata środowisko AI przypominało konferencję poświęconą Pythonowi, tylko z większym budżetem: dema w notatnikach, tutoriale rozpoczynające się od pip install, a także diagramy architektury, na których mała ramka o nazwie „Python LLM service” znajdowała się obok rzeczywistego backendu. Tym rzeczywistym backendem zazwyczaj był Spring Boot, który już zajmował się autoryzacją, fakturowaniem, logami audytowymi oraz bazą danych.
Mała ramka nie jest już obowiązkowa. Spring AI przekroczył wersję 1.0 i znajduje się teraz na poziomie 2.0. LangChain4j to pełnoprawna biblioteka JVM z ponad dwudziestoma dostawcami modeli oraz ponad trzydziestoma magazynami wektorowymi. PostgreSQL przechowuje embeddingi za pomocą pgvector. Usługa Spring Boot, którą już uruchamiasz, może wywołać model LLM, pobrać odpowiedni kontekst, użyć różnych narzędzi, przesyłać tokeny oraz publikować metryki Micrometer, wszystko to wewnątrz JVM.
Czy to czyni z Javy nowego króla sztucznej inteligencji? Nie w sensie zwykłych walk językowych. Nikt nie zastępuje PyTorchem Javy. To, w czym Java odnosi sukcesy, to obszar, gdzie jest pieniądz: aplikacje biznesowe, które muszą być poprawne, przejrzyste i jednocześnie jak najmniej atrakcyjne. Jeśli pracujesz w tym obszarze, zwycięzcą jest to, co już uruchamia twój klastr produkcyjny, a coraz częściej jest to Java.
Pozostała część tego artykułu opisuje tę zmianę. Omawia, dlaczego do niej doszło, jak wygląda usługa RAG w Spring Boot, jak wybrać magazyn wektorów oraz jakie szczegóły produkcyjne odróżniają wersję demonstracyjną od rozwiązania, któremu można zaufać przy przechowywaniu danych klientów.
Zaletą Pythona zawsze były badania naukowe
Python zdominował dziedzinę badań naukowych z uzasadnionych powodów, które nadal obowiązują: NumPy, PyTorch, Hugging Face, Jupyter oraz cała generacja inżynierów biegle posługujących się tensorami. Dostosowywanie modeli, testowanie nowych architektur embeddingów czy szkolenie na kartach graficznych nadal odbywa się w Pythonie.
Rozwój produktów to zupełnie inna sprawa. Większość firm nigdy nie szkoli modeli podstawowych. Wzywają takie modele, a dopiero wtedy zaczyna się prawdziwa praca: pobieranie dokumentów, wprowadzanie zasad działania, oddzielanie użytkowników, rejestrowanie zapytań, kontrolowanie wydatków oraz upewnianie się, że nikt nie wymyśli fałszywej kwoty zwrotu. To właśnie projektowanie API, dostęp do danych, bezpieczeństwo i zarządzanie operacjami – obszary, którymi Spring Boot zajmuje się od 2014 roku.
Popularne rozwiązanie polegające na umieszczeniu modelu za pomocą FastAPI wiązało się z dodatkowymi kosztami:
- dwa języki w jednym produkcie
- oddzielne procesy wdrażania
- oddzielne systemy monitoringu
Ludzie to akceptowali, ponieważ Java nie posiadało solidnych narzędzi do pracy z LLM. Do 2025 roku sytuacja się zmieniła. Spring AI 1.0 stał się powszechnie dostępny w maju 2025 roku, a wersja 2.0 pojawiła się w czerwcu 2026 roku razem z Spring Boot 4. LangChain4j osiągnął wersję 1.0 w tym samym okresie. Stosunek JVM już nie jest w tyle. Dla zespołów już korzystających ze Spring to rozsądny standard.
Co oznacza „dodanie AI” w aplikacji Spring
Nie jest to konieczne przepisywanie kodu, wystarczą trzy funkcjonalności.
- Szyna czatowa.
ChatClientw Spring AI lubAiServicew LangChain4j przekształca prompt oraz historię wiadomości na odpowiedź modelu. Strumieniowanie danych jest standardem, a ustrukturyzowany wynik może zostać przechowywany w rekordzie Java, co oszczędza czas potrzebny na przetwarzanie JSON z tekstu za pomocą regularnych wyrażeń. - Dostęp do własnych danych. Obliczasz embeddingi i przechowujesz je w bazie wektorowej, dzięki czemu odpowiedzi pochodzą z twoich polityk, faktur, instrukcji obsługi oraz dokumentacji produktu, a nie z tego, co model półpamięta. To właśnie jest Retrieval-Augmented Generation (RAG).
- Wywoływanie narzędzi. Model może wykorzystywać metody Java zgodnie z twoimi regułami autoryzacji, na przykład do wyszukiwania zamówień, otwierania przypadków lub sprawdzania salda. W tym przypadku system typów oraz usługi, które już posiadasz, okazują się przydatne. Model nie jest twoim źródłem prawdy – on tylko na jego podstawie wyciąga wnioski.
Z użyciem Spring Security, Spring Data, Actuator oraz PostgreSQL mamy tu kolejny typ klienta, podobnie jak wtedy, gdy pojawiły się Redis czy Kafka.
RAG, wyjaśnione dla programisty Java
Gdy usuniemy otoczkę tajemniczości, RAG to pipeline wyszukiwania kończący się modelem językowym. Kroki są następujące:
- Rozdzielamy dokumenty na fragmenty.
- Każdy fragment przekształcamy w embedding – wektor liczb zmiennoprzecinkowych, który koduje jego znaczenie.
- Zapisujemy te wektory wraz z metadanymi, takimi jak identyfikator użytkownika, ID dokumentu, adres źródłowy i data.
- Gdy pojawia się pytanie, embeddingujemy je i szukamy najbliższych fragmentów.
- wstawiamy te fragmenty do promptu.
- polecamy modelowi, aby odpowiedział wyłącznie na podstawie tych fragmentów oraz przyznał, gdy nie zawierają one odpowiedzi.
Baza danych wektorowych nie zastępuje bazy transakcyjnej. Jest to indeks semantyczny, nieco podobny do Elasticsearch, ale z bardziej zaawansowaną leksyką.
Dla projektów opartych na Spring Boot zazwyczaj punktem wyjścia jest PostgreSQL w połączeniu z pgvector. Postgres jest już wdrożony, zapewniony o kopie zapasowe i zarządzany jako zasób puli, więc dodanie jednej rozszerzenia kosztuje mniej niż natychmiastowe wdrożenie Pinecone, Weaviate lub Qdrant. Specjalistyczne silniki są korzystne, gdy skalowanie jest ekstremalne lub potrzebna jest hybrydowa wyszukiwarka, jednak większość wewnętrznych aplikacji RAG funkcjonuje daleko poniżej takich wymagań.
Skelet, który działa
Poniższa konfiguracja łączy Spring AI 2.0 z Boot 4; w przypadku Boot 3.4 lub 3.5 należy użyć wersji 1.1.x. Najpierw należy dodać plik BOM, aby wszystkie elementy startowe były na tej samej wersji:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>1.1.8</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Następnie podaj tylko te zależności, które są potrzebne:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-pgvector</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
JDBC został umieszczony tam celowo. Narzędzie pgvector starter działa poprzez JdbcTemplate, a zapomnienie o tej zależności jest zaskakująco częstą przyczyną nieudanego uruchomienia.
Ustawienia znajdują się w pliku application.yml. W tym właśnie polega idea Spring AI: model powinien być konfigurowany tak samo jak źródło danych.
spring:
datasource:
url: jdbc:postgresql://localhost:5432/app
username: app
password: ${DB_PASSWORD}
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: gpt-4o-mini
temperature: 0.2
embedding:
options:
model: text-embedding-3-small
vectorstore:
pgvector:
initialize-schema: true
index-type: HNSW
distance-type: COSINE_DISTANCE
dimensions: 1536
Dwa aspekty w tym pliku są ważniejsze, niż się wydaje. Wymiar embeddingu musi być taki sam jak ten generowany przez model embeddingowy, a text-embedding-3-small wytwarza wartość 1536. Jeśli zmienisz model i zapomnisz o tej liczbie, wyszukiwanie podobieństw będzie działać gorzej, choć bez żadnych błędów. Drugim istotnym elementem jest niska temperatura w przypadku RAG – chcesz bowiem, aby wynik był bliski pobranemu tekstu, a nie kreatywną wersją bilansu.
Traktuj proces przyjmowania danych jako odrębną usługę, a nie prosty skrypt kontrolny. Funkcja VectorStore.add(...) przyjmuje fragmenty typu Document, a każdy z tych fragmentów powinien zawierać metadane, na których później będziesz filtrować, takie jak tenantId, source, docType oraz effectiveDate. Bez filtrów wyszukiwanie semantyczne może pokazać umowę jednego klienta w odpowiedzi innego klienta.
Zapytania są równie proste w użyciu. QuestionAnswerAdvisor w Spring AI to określona wersja tego procesu: pobieranie danych, dodawanie kontekstu oraz wywoływanie modelu. Gdy potrzebujesz filtrów, ponownego sortowania lub cytatów, użyj sam similaritySearch i traktuj filterExpression jako klauzulę WHERE, ponieważ to właśnie jest jego zadaniem.
Wybór magazynu wektorowego bez dogmatów
Będziesz miał do wyboru cztery opcje:
- Postgres z pgvector. To rozsądny standard, dobrze znany pod względem operacyjnym. Dzięki indeksowaniu HNSW, monitorowaniu dokładności wyników oraz kompaktowym blokom danych radzi sobie z dziesiątkami milionów wektorów. Okazuje się niewystarczający, gdy potrzebujesz zaawansowanego hybrydowego wyszukiwania lub zespołu zajmującego się utrzymaniem infrastruktury do szukania najbliższych sąsiadów.
Sposób podejmowania decyzji jest prosty, i to jego mocna strona. Zacznij od pgvector, gdy Postgres już działa w środowisku produkcyjnym. Zmień strategię, gdy szybkość odpowiedzi, opóźnienia lub wyszukiwanie hybrydowe nie spełniają rzeczywistych standardów jakości, a nie dlatego, że jakaś prezentacja twierdziła, iż zaawansowane aplikacje AI używają danego produktu. Pamiętaj również o przechowywaniu odniesienia do oryginalnego zapisu obok każdego wektora, abyś mógł go ponownie włączyć w razie zmiany zasad.
To ostatnie punkt jest pomijany w tutorialach. Modele do włączania są zastępowane, metody dzielenia na fragmenty stają się bardziej zaawansowane, a dokumenty prawne są modyfikowane. Zadanie importu, które jest idempotentne i oparte na wersji dokumentu, pozwala uniknąć problemów związanych z próbami ustalenia, dlaczego bot korzysta z zeszłorocznego harmonogramu opłat.
Spring AI kontra LangChain4j
Oba są gotowe do użycia w środowisku produkcyjnym. To, który się nadaje, zależy od aktualnego poziomu rozwoju twojego zespołu.
Spring AI bierze znany z Springa koncepcję przenośnych abstrakcji i stosuje ją do modeli. Jeśli wyobrażysz to sobie jako Spring Data dla LLM, będzie to naturalne – autokonfiguracja, ChatClient, doradcy, Actuator oraz Micrometer doskonale pasują do tego podejścia. Używaj wersji 2.0 z Boot 4. W przypadku Boot 3 należy pozostać przy wersji 1.1.x, ponieważ 2.0 nie będzie mogła zostać bezpośrednio zainstalowana.
LangChain4j został napisany przede wszystkim dla Javy i oferuje dodatkowo starter Spring. Obsługuje większą liczbę dostawców, jego typowane AiServices przypominają klienty Feign skierowane do modeli, a nadaje się dla zespołów używających również Quarkus lub zwykłej Javy. Osoby, które chcą mieć pełną kontrolę nad pętlą agenta, zazwyczaj wybierają tę opcję.
Nic nie stoi na przeszkodzie, by używać obu rozwiązań jednocześnie. Jednym sprawdzonym podziałem jest wykorzystanie Spring AI do rozmów i RAG w usługach skierowanych do klientów, przy czym LangChain4j może uzupełniać braki w przypadku konkretnego dostawcy lub wzorca agenta. Trzeba utrzymywać ich komponenty oddzielnie i nigdy nie pozwalać dwóm różnym modelom embeddingowym zapisywać niekompatybilnych wektorów do jednej tabeli.
Infrastruktura oparta wyłącznie na Spring Boot, która może przeprowadzić aktualizację na Boot 4, powinna korzystać z Spring AI. Środowisko mieszane z JVM lub takie, które od roku pozostaje na wersji Boot 3, prawdopodobnie okaże się bardziej zależne od wersji frameworka, dlatego lepiej wybrać LangChain4j.
To w produkcji JVM pokazuje swoją przewagę
Każdy może zaprezentować przykład odpowiedzi. Produkt natomiast musi wytrzymać audyt. Oto obszary, które należy uwzględnić:
- Związywanie z kontekstem i odrzucanie żądań. Ogranicz model do uzyskanego kontekstu i podawaj odniesienia. Gdy wyniki porównania podobieństwa spadną poniżej określonego progu, odpowiedź powinna brzmieć „to nie znajduje się w bazie wiedzy”, a nie być domysłem. W sektorach finansowym, operacyjnym i opieki zdrowotnej błąd popełniony z przekonaniem kosztuje więcej niż proste odrzucenie żądania.
- Wynajem i cenzura. Filtruj wektory według poszczególnych użytkowników oraz usuwaj poufne informacje z zapytań. Unikaj umieszczania numerów kart, numerów kont i danych zdrowotnych w surowych zapisach zapytań. Jeśli konieczne jest ich zapisanie w celu debugowania, najpierw tokenizuj je i przechowuj zgodnie z zasadami przechowywania stosowanymi przez system źródłowy.
- Budżety na koszty i opóźnienia. Tokeny kosztują pieniędzy, dlatego rejestruj tokeny wejściowe, tokeny wyjściowe, czas pobierania danych oraz czas pracy modelu. Ustal maksymalną liczbę tokenów na każde wezwanie, przechowuj w pamięci tymczasowej embeddingi dokumentów, które się powtarzają, oraz przesyłaj zadania klasyfikacji lub kierowania do mniejszego modelu, używając większego tylko w razie potrzeby.
To wszystko to znajome zadania w Springu: otoczenie odległego wywołania, oznaczenie metryki, odrzucenie nieautoryzowanych żądań. LLM to nowa zależność o gorszych warunkach SLA, więc należy nią zarządzać tak samo jak innymi zależnościami.
Gdzie stwierdzenie „Java jest królem” jest prawdziwe
Java stanowi lepszy punkt wyjścia, gdy system danych już działa na JVM, gdy funkcja AI musi dzielić identyfikator, kontekst użytkownika oraz dane audytowe z istniejącymi API, gdy potrzebne jest wywoływanie wewnętrznych usług Java jako narzędzi, gdy wymogi regulacyjne nie pozwalają na użycie alternatywnego stacku Python, oraz gdy osoby pełniące dyżur o 2 w nocy już znają Spring Boot.
Python nadal przewyższa w przypadku szkolenia lub dopracowywania modeli, gdy potrzebna jest biblioteka badawcza w tydzień po jej wydaniu, lub gdy sam model jest produktem, a nie tylko jedną z funkcji w większym oprogramowaniu.
To są odrębne zadania, a przez dwa lata branża zachowywała się tak, jakby nie istniały. Skutkiem tego było pojawienie się mnóstwa architektur wykorzystujących Pythona jako narzędzie pomocnicze, wraz z nadzieją, że jego specyfikacja pozostanie niezmieniona. Wzorzec, który wydaje się interesujący na rok 2026, jest zmienny: Python lub hostowany laboratorium modeli zajmuje się szkoleniem i oceną, Java służy do obsługi, wyszukiwanie wektorowe funkcjonuje obok danych operacyjnych, model pochodzi od dostawcy, a logika biznesowa pozostaje w twoich rękach.
Rozsądny pierwszy projekt
Nie zaczynaj od nieograniczonego chatbota dla całej firmy. Wybierz wąski, cenny zakres treści oraz pytanie, które można ocenić. Oto kilka przykładów skutecznych rozwiązań:
- Podręcznik z pytaniami i odpowiedziami dla inżynierów pełniących dyżury, powiązany z odpowiednią stroną źródłową
- Pomocnik do zarządzania politykami, który przytacza dokładne postanowienia
- Pytania i odpowiedzi dotyczące faktury lub wykazu, który użytkownik właśnie przesłał
Zastosuj to za zautoryzowanym API, które już posiadasz: rejestruj każde pobranie, wyświetlaj cytaty w interfejsie użytkownika, dodaj funkcję wyłączania konfiguracji oraz sprawdź koszt za zapytanie przed rozszerzaniem zbioru danych. Pierwszy projekt uczy dzielenia na fragmenty, metadanych, oceny oraz kontroli zmian w promptach – te umiejętności są przydatne później, natomiast nazwa frameworku nie ma takiego znaczenia.
Sprzęt, któremu już ufasz
Zdanie „Java to nowy król sztucznej inteligencji” nadaje się jako nagłówek, ale nie jako teza. Java nie zwyciężyło w dziedzinie uczenia maszynowego – raczej wprowadziło zastosowania sztucznej inteligencji na platformę, która już obsługuje światowe systemy transakcyjne.
Inżynier Spring Boot nie potrzebuje żadnej zgody, by tu pracować, ani dyplomu z nauk o danych. Potrzebny jest dostawca modeli, model embeddingowy, indeks wektorowy oraz ta sama staranność operacyjna stosowana przy transakcjach płatniczych i komunikacji. Python nadal szkoli „gwiazdy” laboratorium. Java staje się liderem na drodze od laboratorium do rejestru, gdzie odpowiedzi muszą mieć podstawy, wywołania narzędzi wymagają autoryzacji, a każda rachunek potrzebuje wyjaśnienia. Dla większości zespołów to jedyna godna posiadania korona.
Jeśli Twój serwis Spring Boot już kontroluje tożsamość, pieniądze i ślady audytowe, nie ma powodu, by czekać na dodatkowe narzędzie. Wybierz w tym tygodniu jeden wąski zbiór danych, umieść ChatClient przed pgvector i wymagaj od modelu podawania źródeł.
Literatura pokrewna
- Spring AI kontra LangChain4j: ten sam RAG, różne ukryte opcje — Twój przewodnik po Twin Java RAG pokazuje, że różnice w liczbie wierszy zmniejszają się po integracji z Springiem, a błędna odpowiedź ujawnia domyślne ustawienia fragmentowania.
- Wskazówki praktyczne: Spring AI + MCP – udostępnianie twoich narzędzi Javy każdemu klientowi AI — Szczegółowy przewodnik po wskazówkach praktycznych dotyczących Spring AI + MCP: udostępnianie narzędzi Javy każdemu klientowi AI, w tym informacje o kontraktach, sprawdzaniach oraz gotowych fragmentach kodu dla zespołów wdrażających ten model.