Java как язык для производственных систем ИИ: Spring Boot, RAG и pgvector
Практическая карта по созданию сервисов RAG на JVM с использованием Spring AI или LangChain4j, выбору хранилища векторов, а также управлению арендой ресурсов, затратами, оценкой качества и резервными решениями.
Python используется для обучения моделей, в то время как Java постепенно становится языком, с помощью которого они выпускаются в продакшн. Примерно три года сфера ИИ казалась своего рода конференцией Python с более большим бюджетом: демонстрации в ноутбуках, учебные материалы, начинающиеся с команды pip install, и диаграммы архитектуры, на которых небольшой блок под названием «Python LLM service» находился отдельно от реального бэкенда. Этим реальным бэкендом обычно был Spring Boot, уже отвечавший за аутентификацию, финансовый учет, журналы аудита и базу данных.
Теперь наличие этого небольшого блока уже не является обязательным. Spring AI вышел за версию 1.0 и теперь находится на уровне 2.0. LangChain4j — это полноценная библиотека для JVM с более чем двадцатью поставщиками моделей и более тридцатью хранилищами векторов. PostgreSQL хранит эмбеддинги с помощью модуля pgvector. Сервис Spring Boot, который уже работает у вас, может вызывать LLM, получать контекстную информацию, использовать различные инструменты, передавать токены и публиковать метрики Micrometer — всё это внутри JVM.
Становится ли это причиной того, что Java становится новым королем ИИ? Не в смысле обычных споров между языками программирования. Никто не собирается заменять PyTorch на Java. Java выигрывает там, где находятся деньги: в бизнес-приложениях, которые должны быть корректными, надежными и максимально простыми в использовании. Если вы работаете в этой сфере, победителем остается тот язык, который уже используется в вашем производственном кластере, причем все чаще это Java.
В остальной части статьи рассматривается эта трансформация. Там объясняется, почему это произошло, как выглядит сервис RAG в Spring Boot, как выбрать хранилище векторов и какие производственные аспекты отличают демо-версию от решения, которое можно использовать с клиентскими данными.
Преимущество Python всегда заключалось в исследованиях
Python остался лидером в исследовательской сфере по веским причинам, которые актуальны и сейчас: NumPy, PyTorch, Hugging Face, Jupyter, а также целое поколение инженеров, владеющих технологиями тензоров. Настройка модели, тестирование новых архитектур вкладок или обучение на GPU по-прежнему осуществляется с использованием Python.
Реализация продукта — это совершенно другая задача. Большинство компаний не обучают базовые модели. Они просто вызывают готовую модель, после чего начинается настоящая работа: загрузка документов, применение правил, разделение пользователей, логирование запросов, контроль расходов и проверка на отсутствие ошибок при расчете возвратов средств. Это задачи проектирования API, доступа к данным, безопасности и операционного управления, которыми с 2014 года занимается Spring Boot.
Популярный способ размещения модели через FastAPI сопровождался постоянными дополнительными затратами:
- два языка в одном продукте
- отдельные процессы развертывания
- отдельные системы мониторинга
Люди соглашались на это из-за отсутствия серьезных инструментов для работы с LLM в Java. К 2025 году это уже не было правдой. Spring AI 1.0 стал общедоступен в мае 2025 года, а версия 2.0 появилась в июне 2026 года вместе с Spring Boot 4. LangChain4j достиг версии 1.0 в тот же период. Теперь стек JVM уже не отстает. Для команд, уже использующих Spring, это разумный стандарт.
Что означает «добавление ИИ» в приложении Spring
Не требуется переписывание кода — достаточно трех функций.
- Слой чата. Класс
ChatClientв Spring AI или классAiServiceв LangChain4j преобразуют вводные запросы и историю сообщений в ответ модели. Потоковая обработка является стандартной, а структурированный результат может храниться в объекте типа Java record, что позволяет избежать необходимости обработки JSON из текста с помощью регулярных выражений. - Доступ к собственным данным. Вы вычисляете эмбеддинги и храните их в хранилище векторов, так что ответы формируются на основе ваших правил, счетов-фактур, руководств по эксплуатации и документации к продукту, а не на основе того, что модель еле помнит. Это и есть технология Retrieval-Augmented Generation (RAG).
- Вызовы инструментов. При соблюдении установленных правил авторизации модель может вызывать методы на языке Java, например для поиска заказа, открытия заявки или получения информации о балансе. Здесь оказываются полезны система типов и уже имеющиеся у вас сервисы. Модель не является источником истины — она делает выводы на основе уже существующих данных.
После настройки Spring Security, Spring Data, Actuator и PostgreSQL появляется ещё один тип клиента, подобно тому, как это было с Redis или Kafka.
RAG: объяснение для разработчика на Java
Если убрать всю таинственность, RAG — это пайплайн поиска, заканчивающийся использованием языковой модели. Этапы:
- Разбиваем документы на фрагменты.
- Преобразуем каждый фрагмент в эмбеддинг — вектор из чисел с плавающей точкой, кодирующий его смысл.
- Сохраняем эти векторы вместе с метаданными: информацией о пользователе, идентификатором документа, исходным URI и датой.
- При поступлении вопроса его также преобразуем в эмбеддинг и находим наиболее близкие фрагменты.
- Вставляем эти фрагменты в запрос к модели.
- Указываем модели отвечать исключительно на основе этих фрагментов и признавать, когда в них нет ответа.
База данных векторов не заменяет вашу транзакционную базу данных. Это семантический индекс, похожий на Elasticsearch, но с более сложной структурой данных.
Для проектов на Spring Boot обычно начинают с PostgreSQL вместе с pgvector. Postgres уже развернут, имеет резервные копии и пулы подключений, поэтому установка одного расширения обходится дешевле, чем сразу внедрение Pinecone, Weaviate или Qdrant. Специализированные движки действительно имеют преимущества при крайне высоких нагрузках или при необходимости гибридного поиска, однако большинство внутренних приложений типа RAG работают в условиях, где это не требуется.
Основа для работы
В приведённой ниже конфигурации используются Spring AI 2.0 в сочетании с Boot 4; для версий Boot 3.4 или 3.5 следует применять версию 1.1.x. Сначала необходимо добавить BOM, чтобы все стартовые компоненты использовали одну и ту же версию:
<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>
Далее укажите только те зависимости, которые вам нужны:
<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 указан намеренно. Стартовый пакет pgvector работает через JdbcTemplate, и забывание об этой зависимости — довольно частая причина сбоя при запуске.
Настройки находятся в файле application.yml. В этом и заключается суть Spring AI: модель должна настраиваться так же, как и источник данных.
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
Два аспекта в этом файле имеют большее значение, чем кажется на первый взгляд. Размер эмбеддинга должен совпадать с тем, который генерирует модель эмбеддингов; text-embedding-3-small генерирует значение 1536. Если изменить модель и забыть об этом числе, поиск по сходству будет работать хуже, но без каких-либо ошибок. Второй важный момент — низкая температура при использовании RAG, поскольку необходимо, чтобы результаты соответствовали полученному тексту, а не являлись творческой переработкой информации из отчета.
Рассматривайте процесс ввода данных как отдельную службу, а не просто одну строку кода для управления. Метод VectorStore.add(...) принимает фрагменты документов типа Document, и каждый такой фрагмент должен содержать метаданные, по которым будет производиться фильтрация позже, такие как tenantId, source, docType и effectiveDate. Без фильтров семантический поиск может показать контракт одного клиента в ответе другого клиента.
Запросы формируются так же быстро. Класс QuestionAnswerAdvisor в Spring AI представляет собой упрощённую версию этого цикла: получение данных, добавление контекста, вызов модели. Если вам понадобятся фильтры, переранжирование или цитаты, используйте similaritySearch самостоятельно и рассматривайте filterExpression как условие WHERE, ведь именно для этого оно и предназначено.
Выбор хранилища векторов без принуждений
Существует четыре варианта:
- Postgres с расширением pgvector. Это разумный стандарт, хорошо понятый в практическом применении. Благодаря индексации HNSW, мониторингу точности воспроизведения и компактным блокам данных он справляется с десятками миллионов векторов. Однако он не подходит, если требуется продвинутый гибридный поиск или команда, специализирующаяся на обслуживании инфраструктуры приблизительного поиска ближайших соседей.
Метод принятия решений прост, и в этом его сила. Начинайте использовать pgvector тогда, когда Postgres уже работает в производстве. Измените подход, если показатели воспроизведения данных, задержки или гибридного поиска не соответствуют установленным стандартам, а не потому, что где-то сказано, будто серьезные AI-приложения используют тот или иной продукт. Также храните ссылку на оригинальную запись рядом с каждым вектором, чтобы можно было заново его включить при изменении правил.
Именно этот последний момент обычно упускается в учебниках. Модели для включения данных меняются, методы разбиения на части становятся более эффективными, а юридические документы корректируются. Идемпотентная задача обработки данных с идентификатором версии документа поможет вам избежать лишних усилий для выяснения причин того, почему бот использует старую таблицу тарифов.
Spring AI против LangChain4j
Оба решения готовы к использованию в производстве. Выбор зависит от текущего уровня развития вашей команды.
Spring AI берет знакомую концепцию Spring — портабельные абстракции — и применяет её к моделям. Если представить его как Spring Data для LLM, это покажется логичным: автоконфигурация, ChatClient, советники, Actuator и Micrometer все вписываются в эту структуру. Используйте версию 2.0 с Boot 4. С Boot 3 следует оставаться на версии 1.1.x, поскольку 2.0 не будет совместима без дополнительных настроек.
LangChain4j изначально написан для Java и также предоставляет стартер Spring. Он поддерживает больше поставщиков сервисов, его типизированные AiServices похожи на клиенты Feign, направленные на модели, и он подходит командам, которые также используют Quarkus или обычный Java. Люди, желающие полного контроля над циклом работы агента, обычно выбирают именно его.
Ничто не мешает использовать оба решения одновременно. Один из работоспособных вариантов разделения — использование Spring AI для чатов и RAG в сервисах, ориентированных на клиентов, при этом LangChain4j покрывает недостатки для конкретных поставщиков или шаблонов агентов. Держите их компоненты раздельно и никогда не позволяйте двум разным моделям вкладки записывать несовместимые векторы в одну таблицу.
Система, полностью построенная на Spring Boot и способная к обновлению до версии 4, должна использовать Spring AI. В среде с смешанными JVM или в той, что уже год использует Boot 3, вероятно, окажется более удобным использование LangChain4j, менее зависящего от версионного цикла фреймворка.
Именно в производстве JVM демонстрирует преимущества
Любой может показать демонстрацию ответа. Однако продукт должен выдержать аудит. Необходимо учесть следующие аспекты:
- Ограничение работы модели и отказы. Ограничьте действия модели полученным контекстом и указывайте источники информации. Когда показатели сходства опускаются ниже установленного порога, ответом должно быть «этого нет в базе знаний», а не догадка. В сферах финансов, операционного управления и здравоохранения ошибка, сделанная уверенно, стоит дороже простого отказа.
- Аренда ресурсов и удаление конфиденциальной информации. Фильтруйте векторы по каждому арендатору и удаляйте секретную информацию из запросов. Из логов исходных запросов не включайте номера карт, номера счетов и медицинские данные. Если для отладки необходимо записать эти данные, сначала преобразуйте их в токены и храните согласно правилам хранения данных исходной системы.
- Бюджетирование затрат и времени обработки. Каждый токен стоит денег, поэтому фиксируйте количество входных и выходных токенов, время поиска информации и время работы модели. Установите лимит на количество токенов для каждого запроса, кэшируйте эмбеддинги документов, которые повторяются, и отправляйте задачи классификации или маршрутизации на более простую модель, используя более сложную только при необходимости.
Всё это — типичные задачи в Spring: обертка для удаленного вызова, меткирование метрик, отклонение неавторизованных запросов. LLM представляет собой новую зависимость с худшими условиями обслуживания, поэтому к ней следует относиться соответственно.
Когда утверждение «Java — король» верно
Java является лучшим выбором, когда система хранения данных уже работает на JVM, когда функция ИИ должна делить идентификаторы, тенантность и данные аудита с существующими API, когда необходимо использовать внутренние Java-сервисы в качестве инструментов, когда требования к соответствию нормам не позволяют использовать Python, и когда сотрудники, работающие в ночную смену, уже знакомы с Spring Boot.
Python по-прежнему остается лидером при обучении или доработке моделей, когда нужна исследовательская библиотека сразу после её выпуска, или когда сама модель является продуктом, а не просто одной из функций в более крупном приложении.
Это разные задачи, но в течение двух лет индустрия вела себя так, будто они едины. В результате появилось множество архитектур с использованием Python в качестве дополнительного компонента, при этом ожидалось, что их спецификация не изменится. Модель, которая может показаться интересной к 2026 году, является смешанной: Python или хостинговая лаборатория для моделей отвечают за обучение и оценку, Java обеспечивает обслуживание, векторный поиск работает параллельно с операционными данными, модель предоставляется поставщиком, а логика бизнес-процессов остается в ваших руках.
Разумный первый проект
Не начинайте с бесконтрольного корпоративного чат-бота. Выберите узкую, ценную нишу контента и вопрос, по которому можно оценить результат. Некоторые успешные примеры:
- Руководство с вопросами и ответами для инженеров, находящихся в режиме дежурства, с переходом на исходную страницу
- Помощник по правилам, который цитирует конкретные положения
- Вопросы и ответы по счету или отчету, только что загруженным пользователем
Разместите это решение за защищенным API, который у вас уже есть: ведите журнал всех запросов, отображайте цитаты в интерфейсе, добавьте функцию отключения через настройки и выясните стоимость одного запроса перед расширением объема данных. Первый проект обучает разбиению на части, работе с метаданными, оценке и контролю изменений в запросах, и эти навыки остаются с вами, в отличие от бренда фреймворка.
Среда выполнения, которой вы уже доверяете
Фраза «Java — новый король ИИ» подходит в качестве заголовка, но не может считаться утверждением. Java не победила в области машинного обучения; она просто интегрировала прикладной ИИ в платформу, уже используемую для мировых транзакционных систем.
Инженеру Spring Boot не нужно разрешения кого-либо, чтобы работать здесь, и не обязательно иметь диплом по науке о данных. Необходимы только поставщик моделей, эмбеддинговая модель, векторный индекс, а также тот же уровень операционного ухода, что и при обработке платежей и сообщений. Python продолжает формировать основу лабораторных разработок. Java становится лидером на пути от лаборатории к реальным записям, где ответы должны иметь основания, вызовы инструментов требуют авторизации, а каждый счет нуждается в объяснении. Для большинства команд это единственная ценная награда.
Если ваш сервис Spring Boot уже контролирует идентификацию, финансы и хронологию операций, нет причин ждать дополнительных инструментов. Выберите на этой неделе один узкий набор данных, разместите ChatClient перед pgvector и потребуйте указания источников информации от модели.