Spring AI или LangChain4j: настройка, первый эндпоинт и стиль проектирования
Сравниваем Spring AI и LangChain4j по архитектуре, стартерам Spring Boot, конфигурации и первому REST-эндпоинту для чата и разбираемся, какой стиль подойдёт вашей команде.
Списки возможностей мало что говорят. На самом деле хочется понять, каково работать с фреймворком через несколько недель разработки, а документация на этот вопрос не отвечает. Поэтому представим команду, которая начинает новый проект на Spring Boot и пробует и Spring AI, и LangChain4j. Ниже сравним архитектуру, настройку проекта, конфигурацию, первый ИИ-эндпоинт и повседневные ощущения разработчика. Обе библиотеки решают одну и ту же задачу, но подходят к ней совсем по-разному.
Две архитектурные философии
Разница в дизайне определяет почти все дальнейшие решения, так что на неё стоит посмотреть до того, как писать код.
Архитектура Spring AI
Spring AI следует схеме, которую узнает любой, кто писал на Spring Boot.
Spring Boot Application
│
ChatClient API
│
Spring AI Abstractions
│
OpenAI | Gemini | Ollama | Claude | Azure
│
Large Language Model
Фреймворк стоит между вашим приложением и ИИ-провайдером. Код не обращается к OpenAI или Gemini напрямую, а работает с абстракциями Spring AI. Это окупается несколькими способами. Переход с Gemini на OpenAI обычно не затрагивает бизнес-код: меняется только конфигурация. Та же идея, что и в Spring Data, где можно сменить базу данных, не переписывая логику репозиториев.
Почему этот подход кажется знакомым
Тому, кто годами пишет приложения на Spring Boot, структура понятна с первого взгляда. В центре — внедрение зависимостей, бины настраиваются автоматически, а настройки лежат в application.yml. Ощущение такое, будто вы осваиваете не ИИ-фреймворк, а ещё один стартер Spring, и для корпоративных команд это большой плюс.
Архитектура LangChain4j
У LangChain4j другой склад мышления. Он не строит всё вокруг одной центральной абстракции, а даёт набор переиспользуемых строительных блоков.
Spring Boot Application
│
AI Service Interface
│
┌──────────┬─────────────┬──────────────┐
│ │ │ │
Chat Model Memory Tools Retriever
│
OpenAI / Gemini / Ollama
Кроме того, он не прячет ИИ-концепции, а выставляет их наружу. Работать придётся напрямую вот с такими компонентами:
- чат-модели и модели эмбеддингов
- память чата
- ИИ-сервисы
- ретриверы контента и провайдеры инструментов
У каждого из них одна понятная задача, а вы собираете из них собственный ИИ-конвейер. Поначалу это может выглядеть как лишняя работа. Но когда приложение разрастается, модульный дизайн начинает себя оправдывать.
Настройка Spring AI
Начать работу со Spring AI можно быстро. Всё как с Spring Data JPA или Spring Security: добавляете нужный стартер.
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-gemini</artifactId>
</dependency>
Затем указываете API-ключ в конфигурации.
spring:
ai:
vertex:
ai:
gemini:
project-id: your-project
location: us-central1
# OR
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
Дальше Spring Boot сам создаёт нужные бины. Никаких фабрик, ручного связывания и билдеров — всё готово к внедрению зависимостей. Для Spring-разработчика это выглядит совершенно естественно.
Настройка LangChain4j
У LangChain4j тоже есть стартеры для Spring Boot, и настройка отличается совсем немного.
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
</dependency>
Конфигурация выглядит почти так же.
langchain4j:
open-ai:
chat-model:
api-key: ${OPENAI_API_KEY}
model-name: gpt-4o-mini
И снова Spring Boot создаёт бины автоматически, так что в существующем проекте на Spring Boot опыт почти не отличается от Spring AI. Но LangChain4j даёт ещё один вариант: можно вообще обойтись без стартеров и собрать всё вручную.
ChatLanguageModel model = OpenAiChatModel.builder()
.apiKey(apiKey)
.modelName("gpt-4o-mini")
.build();
Такая гибкость — настоящий плюс. В обычном Java-приложении или в Quarkus ничего не меняется, потому что библиотека не привязана к Spring.
Первый ИИ-эндпоинт
Теперь самое интересное. Соберём на каждом фреймворке один и тот же REST-эндпоинт: он принимает вопрос и возвращает сгенерированный ответ.
Версия на Spring AI
@RestController
@RequestMapping("/chat")
public class ChatController {
private final ChatClient chatClient;
public ChatController(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
@GetMapping
public String chat(@RequestParam String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
Получилось на удивление аккуратно. Fluent API напоминает WebClient из Spring, и каждый шаг читается естественно.
prompt()
↓
user()
↓
call()
↓
content()
Кто работал с fluent API в Spring, скорее всего, поймёт идею с одного взгляда.
Версия на LangChain4j
@RestController
@RequestMapping("/chat")
public class ChatController {
private final ChatLanguageModel model;
public ChatController(ChatLanguageModel model) {
this.model = model;
}
@GetMapping
public String chat(@RequestParam String message) {
return model.generate(message);
}
}
Здесь ещё короче. Вместо того чтобы собирать промпт через билдер, вы обращаетесь к языковой модели напрямую. Церемоний меньше, и код выглядит почти как вызов обычного Java-сервиса.
Что проще?
Разработчики часто об этом спрашивают, и честный ответ такой: оба отличные. Для простого чат-приложения явного победителя нет. Каждому нужно всего несколько строк, оба встраиваются в Spring Boot, сами настраивают зависимости и дают чистый, читаемый код.
Разница не в объёме кода, а в том, как развивается приложение. Spring AI хочет, чтобы всё шло через ChatClient, и по мере роста проекта вокруг этого клиента появляются Advisors, память, вызов инструментов, RAG и наблюдаемость.
LangChain4j идёт другим путём. Он не наращивает один центральный клиент, а подталкивает к специализированным ИИ-сервисам, и приложение в итоге выглядит так:
CustomerSupportAgent
DocumentAssistant
CodeReviewAgent
EmailGenerator
MeetingSummarizer
Каждый из них — отдельный Java-интерфейс с чётко определённой задачей. Для крупных ИИ-приложений такой подход очень изящен. Но если проект уже построен на привычных сервисных паттернах Spring, Spring AI покажется роднее. Объективно лучшего нет: они рассчитаны на разный способ мышления.
Чему учит один и тот же чат-бот, собранный дважды
Первый чат-бот на Spring AI пишется как очередное приложение на Spring Boot. Сюрпризов мало: всё лежит там, где ожидаешь, внедрение зависимостей работает как обычно, конфигурация остаётся в application.yml, и рабочий ИИ-эндпоинт можно поднять за час.
Тот же чат-бот на LangChain4j оставляет другое первое впечатление. Вместо интеграции с API вы начинаете думать о проектировании умного ассистента. Разница тонкая, но она меняет то, как вы организуете код. LangChain4j с первого дня подталкивает выносить промпты, инструменты, память и поиск в переиспользуемые компоненты, а Spring AI позволяет добавлять эти возможности по одной по мере развития приложения. Ни одна из философий не ошибочна. Правильный выбор зависит от того, какой софт вы делаете и как ваша команда любит структурировать кодовую базу.
Где пути действительно расходятся
Пока различия ещё невелики. Настоящее расхождение начинается, когда вы делаете ИИ-функции уровня продакшена: структурированный вывод, вызов инструментов, генерацию с дополненным поиском (RAG) и агентов. Именно там каждый фреймворк показывает свои сильные стороны, и выбор между ними начинает значить намного больше.