Галоўная / Артыкулы / Java як мова для стварэння AI-сервісаў: Spring Boot, RAG і pgvector

Java як мова для стварэння AI-сервісаў: Spring Boot, RAG і pgvector

Практычныя інструкцыі па стварэнню служб RAG на JVM з викорыстанням Spring AI або LangChain4j, выбору сховішча вектарных дадзеных, а таксама керуванню арендаванням, виткамі, оцэнкай і альтернатыўными рашэннямі.

2624 слоў

Python адаптуюе модэлі, а Java паступова стае языкам, які выкарыстоўваецца для ўпаковкі і розпаведзення гэтых модэляў. Прыбліжна трохі больш чаму трэх гадоў сцена AI адчувалася як канферэнція 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 мелі сваю постаўную цену:

  • два языкі ў аднам продукце
  • разныя процесы развяртання
  • разныя системы манітарынгу
  • Контракт інтэрфейсу, які час ад часу зменшваліся ў кожным спринті
  • Перагляды безпекі, які раптам пачалі включаць службу на Python, яка зберагала свае секрэты
  • Людзі прымалі гэта, таму што у Java не было серйозных інструментаў для LLM. До 2025 года гэта перестало быць правдай. Spring AI 1.0 стаў загальна доступным у мае 2025 года, а версія 2.0 з’явілася у чэрвені 2026 года разам з Spring Boot 4. LangChain4j таксама досяг версіі 1.0 у тым жа перыяде. Стак JVM больш не адстае. Для команд, якія вже выкарыстоўваюць Spring, гэта ўзгодны стандарт.

    Што значыць «дадаць AI» у прыкладнай програме на Spring

    Не трэба перапісваць код, достатня толькі троха функцыяй.

    1. Слой чату. Клас ChatClient у Spring AI або клас AiService у LangChain4j ператварае запит і історыю паведамленняў у адпаведную адказ модэлю. Праця з дадзеннямі у ручым режыме є стандартной, а структураваны выходны дадзенні можа быць зберажаны ў Java record, што захоўвае вас ад неабходнасці выкарыстоўвання рэгулярных выразаў для параскладывання JSON з тексту.
    2. Даступ да вашых сабеўных дадзенняў. Вы вырахоўваеце эмбеддынгі і зберагаеце іх у сховішчы вектароў, тады адказы выходзяць з вашых правілаў, рахункоў-фактур, інструкцый і документацыі да продукту, а не з таго, што модэль напявам памятае. Гэта і є метод генеравання з адзысквам дадзенняў (Retrieval-Augmented Generation, RAG).
    3. Выклікі інструментаў. Модэль можа выклікаць методы Java па вашых правілах автарызацыі, напрыклад, для пошуку замовлення, ачынення кейса або чытання залишку. Тут працюе система типаў і адзінстваясныя службы, якія вам вже є. Модэль не ёсць вашым аднаковым джерэлам правды; ён робіць выводы на адной з існуючых баз дадзенняў.

    За наявнасці Spring Security, Spring Data, Actuator і PostgreSQL гэты ўзьяўшыся ўжо аднаго з типаў кліента, падобна да таго, калі з’явіліся Redis чыста Kafka.

    RAG, апісаны для разработчика на Java

    Якщо пазбавіцца всіх таўтологій, RAG — это канвейр пошуку, які завершаецца на мовнай модэлі. Этапы:

    1. Разбіць дакументы на часткі.
    2. Ператворыць кожную частку на эмбеддінг — вектар з числаў, які кодуе ўсё значэнне дакумента.
    3. Зберагчы вектары разам з метаданаямі, такімі як ідэнтыфікатор аб’екта, ідэнтыфікатор дакумента, шлях да выхаднага кантэнту і дата.
    4. Калі прыходзіць запит, ўключыць яго ў формат эмбеддінга і знайсці найбліжэйшыя часткі.
    5. Уключыць гэтыя часткі ў запрошэнне да модэлі.
    6. Прыказаць модэлі адпавядаць толькі на аднойчыну з гэтых частак і паўтарыць, калі ў яных няма адпаведзення.

    База дадзенаў на вектарах не ёсць заменай вашай транзакцыйнай базы. Це семантычны індэкс, падобны да 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, монітарынгу результаатаў і компактных частак ён можа обрабоцваць дзесяткі мільйонаў вектараў. Однак ён не падходзіць, калі трэба заавангардны гібрыдны пошук чы команда, якая будзе кераваць інфраструктурой для апрыксиматыўнае пашуку найбліжэйшых суседзяў.
  • Redis. Шырока падтрымка, частаючы ў стэкі Spring, падходзіць для зберагчыка сэсый і малых баз знанняў. Галоўная проблема — цэна RAM.
  • Спецыяльныя двайнеры (Qdrant, Weaviate, Milvus, Pinecone). Яны ўпрыемныя, калі самым вынікам яе ўжо є адзысканне інфармацыі: вялікія корпусы дадзеных, гібрыдныя запиты на аснове лексыкі і вектараў, калькуляцыя з колькома індэксамі, або калі команда хочаць прыемнае для ANN програмнага забезпечэння. Spring AI адразу падтрымляе популярныя з іх.
  • Існуючы двайнер для пошуку. Elasticsearch і OpenSearch падтрымляюць алгорытм kNN, і якщо вашы дакументы вучацца там, ўжо наяўны ўплотнены вектарны поле можа заменіць дадатковую систему зберагчыка дадзеных.
  • Метод прыямлення ўлогічны, і гэта яго сіла. Пачніце з 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 starter. Ён падтрымлівае больш прадаўцоў, яго типаваныя AiServices падобныя да кліентаў Feign, накіраваных на модэляў, і ён падходзіць для команд, якія таксама выкарыстоўваюць Quarkus аб звычны Java. Людзі, якія хочуць строгі контроль над цыклам агента, часта выбіраюць яго.

    Ніщо не заважає вам використовувати обидва рішення одночасно. Одним з можливих підходів є використання Spring AI для чату та RAG у сервісі, орієнтованому на клієнтів, причому LangChain4j буде виконувати функції, пов’язані з певним форматом постачальника чи агента. Необхідно зберігати їхні компоненти окремо та ніколи не дозволяти двом різним моделям вбудовування записувати несумісні вектори в одну таблицю.

    Система, створена повністю на Spring Boot, яка може оновлюватися до версії 4, має використовувати Spring AI. У змішаному середовищі JVM чи у системі, яка вже рік працює на версії Boot 3, LangChain4j, ймовірно, буде менш залежним від оновлень цього фреймворку.

    У продакшені JVM має перевагу

    Будь-хто може продемонструвати просту роботу рішення. Продукт ж мусить витримати аудит. Ось ті аспекти, які потрібно врахувати:

    • Адаптаванне і адказы. Обмежыце модель толькі запрошаным контэкстам і прадасте цитаты. Калі рэшты схожасці падаюць нижыней за заданы порог, адказ павінен быць «гэтага няма ў базе знаёмых дадзенняў», а не проста здагадка. У фінансах, управленні і охороне здароў’я адказ пра памылку з высокай верыгоднасцю коштуе дорожэ, чым проста адказ пра адмову.
    • Аренда і маскаванне. Фільтруйце вектары па кожнаму корыстніку і адмахвайце секрэты з запитоў. Не включаюце номеры картак, номеры рахункоў і медычныя даны ў неапранутыя логі запитоў. Якщо падчас дыбаггінгу трэба іх зафіксаваць, спачатку токенізуйце іх і зберагаюце ў складзе па правілах системы.
    • Бюджэты на вартасць і час адпаведзення. Кожны токэн коштае грошы, таму фіксуйце колькість токэнаў увайшлых, выйшлых, час запрашання дадзенняў і час работы модэлю. Настаўце ліміт на колькасць токэнаў за кожны вызов, кешавайце эмбедынгі дакументаў, якія павтараюцца, і для класыфікацыі чы рутавання вядзіце працю маленькага модэлю, вярнучыся да большога толькі калі ён неабходны.
  • Часы выканання і ізоляцыя. Выклік модэлі — это даляжны I/O-запыт. Обмежаныя пулі нитак, прыборы для захиста ад кантролю і альтернатывныя шляхі (пошук за ключавымі словамі або чат-чэрга) запобегаюць таму, што збоі модэлі захопяць усе ніты Tomcat або Netty і спрычыніць проблемы з процесам выкаанання.
  • Ацэнкаванне. Прыказ не можа быць працаваны як елемент адзінковага тэставання, як расчыткі податкаў, але заморожаны набор з трыдцяці запытанняў з вядомымі адпаведзямі можа выклікнуць проблемы пад час будовы, калі спостыгаецца некалькавая точнасць. Таксама неабходна пераглядка рэзультатаў для RAG, прабаваючы пераканацца, чы роўна той фрагмент тексту патрапіў у прыказ. Большасць так званых проблем з якосцю модэлі ў рэальнасці ёсць багі ў процесе выкаанання.
  • Перагляд чалавекам. У корпаратыўным програмнаму забезпечэнні найценнейшай функцыяй ШІ часта ёсць проект, а не чат-бот: прыказка да справы, узгаданыя прычыны абыякавасці або стислы пераказ дужа дзяўгаг 40-сторонніцкага атласу. Неабходна, каб чалавек участваваў у пракцэсе затверджэння, пакуль бягавыя проблемы не стануць незначнымі.
  • Усё гэта — знакомая робота з Spring: абгортаванне даляніна далёкага вызову, атрыбутаванне метрыкі, адхоўленне неаутентыфікованых запитоў. LLM — гэта новая залежнасць з горшымі умовамі абслужвання, таму яе трэба кармаваць як такую.

    Дзе правдыя словы «Java — каралева»

    Java ўтварае лепшую падставу, калі система зберагання дадзэнняў вялікай меры ўжо працуе на JVM, калі функцыя ІІШ трэба дзеліць ідэнтыфікатор, умовы выкарыстоўвання і аудыт з існуючымі API, калі яй трэба вызываць внутршныя Java-сервісы як інструменты, калі вимаганняя даследжэнняў не дазволяюць викорыстоўвання Python, і калі адпаведальныя працовнікі у 2 гадзі ночы вже ведаюць Spring Boot.

    Python застаецца лідэрам, калі вы трэнуеце або дакладна налаштовваеце модэлі, калі вам трэбна науковая бібліятэка ў тыя ж недзелі пасля выпуску, або калі сам модэль ёсць продуктам, а не толькі функцыяй у большай працоўнай аплікацыі.

    Это адзінныя задачы, але працоўнікі галузі два гады велі ся так, як будто ўсё інакш. Рэзультатам стала маса архітектур з викорыстаннем Python sidecar і надзея, што ўмовы їхней роботы застануцца незменнымі. Модель, якая можа здавацца прыемной для 2026 года, ўскладнена: Python або хоставаныя модельныя лабораторыі займаюцца навчаннем і ацэнкай, Java выступае серверам, векторны пошук знаходзіцца праза оператыўнымі дадзеннямі, модель прыналежыць постаўчыку, а логіка домэна застаецца у вашых руках.

    Разумны першы проект

    Не пачынайце з безмежнага чат-бота для всей кампаніі. Выберыце вузкі, ценны кантэнт і пытанне, якое можна оценіць. Калекцыя праектаў, якія работаюць:

    • Кніга інструкцый з пытаннямі і адпаведзямі для інжынераў, якія працуюць у режыме 24/7, павязаная з асалютным разделам
    • Паслявучальнік правіл, який цитуе точны пункт
    • Пытання і адпаведзі ў зв’язку з рахункам-фактурой або выкладзеным корыстнікам звітом
  • Сапраўднікі квітакоў запісваюцца ў дакументацыю спрабы, а не ў окольны чат.
  • Застосавыце гэта за атрыбутаваным API, які ўжо у вас є: ліставайце кожны запыт, адображайце цитаты ў інтерфейсе, дадзіце можласць выключэння за дапамою налаштаванняў, і выявіце вартасць за адзін запыт прыяўшы больш дадзеных. Першы проект навучае тэхнікам разбівання на часткі, працы з метаданнымі, атрыбутамі оцэнкі і кантролю змян у запытах, і гэтыя навыкі застаюцца кориснымі, тады як марка фрэймворку — няўсёлі.

    Система выканання, якой вы ўжо даверяеце

    Фраза «Java — новы каралю AI» падходзіць як заглавле, але не ўсё так проста, калі гаворыць пра тэзу. Java не выграў у сферы машыннага навчання; ён проста перанёс практычную AI у платформу, якая вже падтрымлеўчы системы транзакцый у всім свете.

    Інжынеру Spring Boot не трэба нічыяй дазвол на работу тут, ні спачатку атестата па дадзейнаўскай науцы. Неабходныя ўместкі — цэх падаўчыка модэляў, модэль умяшчання, вектарны індекс, а таксама тыя ж правілы керавання, якія прыменяюцца да платэжаў і перадачы звесцей. Python продаважвае трэніраванне «зорак» лабараторыі. Java стае лідэрам на шляху з лабараторыі да рэўістрацыйнага журналу, дзе адпаведзі трэба падкрепляць доказамі, вызовы інструментаў — автарызацыяй, а кожны рахунак — адказам. Для большасці команд гэта ўсё, што мае цену.

    Якщо ваш сервіс Spring Boot вялічыць валіднасць, грошы і ход аудыту, няма прычыны чакаць на дапаможны элемент. Выберыце адзін вузкі корпус яшчо гэтой недзелы, разместіце ChatClient пры pgvector і заставіце модэль наводзіць цытаты.