diff --git a/aitools/pom.xml b/aitools/pom.xml
index 9e2031b..2f461e4 100644
--- a/aitools/pom.xml
+++ b/aitools/pom.xml
@@ -5,7 +5,7 @@
org.springframework.boot
spring-boot-starter-parent
- 4.0.1
+ 3.5.9
ru.ldeloff
@@ -28,12 +28,39 @@
25
+ 1.1.2
+
+
+
+ org.springframework.ai
+ spring-ai-bom
+ ${spring-ai.version}
+ pom
+ import
+
+
+
+
+ org.springframework.ai
+ spring-ai-starter-model-openai
+
org.springframework.boot
spring-boot-starter-webflux
+
+ org.springdoc
+ springdoc-openapi-starter-webflux-ui
+ 2.8.15
+
+
+
+ org.telegram
+ telegrambots
+ 6.9.7.1
+
org.projectlombok
@@ -42,16 +69,10 @@
- org.springframework.boot
- spring-boot-starter-webflux-test
+ io.projectreactor
+ reactor-test
test
-
-
- org.springdoc
- springdoc-openapi-starter-webflux-ui
- 3.0.1
-
diff --git a/aitools/src/main/java/ru/ldeloff/aitools/AitoolsApplication.java b/aitools/src/main/java/ru/ldeloff/aitools/AitoolsApplication.java
index dae30b5..13b484c 100644
--- a/aitools/src/main/java/ru/ldeloff/aitools/AitoolsApplication.java
+++ b/aitools/src/main/java/ru/ldeloff/aitools/AitoolsApplication.java
@@ -2,7 +2,9 @@ package ru.ldeloff.aitools;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cache.annotation.EnableCaching;
+@EnableCaching
@SpringBootApplication
public class AitoolsApplication {
diff --git a/aitools/src/main/java/ru/ldeloff/aitools/datetime/controller/TimeController.java b/aitools/src/main/java/ru/ldeloff/aitools/externaltools/datetime/controller/TimeController.java
similarity index 94%
rename from aitools/src/main/java/ru/ldeloff/aitools/datetime/controller/TimeController.java
rename to aitools/src/main/java/ru/ldeloff/aitools/externaltools/datetime/controller/TimeController.java
index d106c21..a332070 100644
--- a/aitools/src/main/java/ru/ldeloff/aitools/datetime/controller/TimeController.java
+++ b/aitools/src/main/java/ru/ldeloff/aitools/externaltools/datetime/controller/TimeController.java
@@ -1,4 +1,4 @@
-package ru.ldeloff.aitools.datetime.controller;
+package ru.ldeloff.aitools.externaltools.datetime.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
-import ru.ldeloff.aitools.datetime.dto.TimeResponse;
+import ru.ldeloff.aitools.externaltools.datetime.dto.TimeResponse;
import java.time.ZoneId;
import java.time.LocalDateTime;
diff --git a/aitools/src/main/java/ru/ldeloff/aitools/datetime/dto/TimeResponse.java b/aitools/src/main/java/ru/ldeloff/aitools/externaltools/datetime/dto/TimeResponse.java
similarity index 67%
rename from aitools/src/main/java/ru/ldeloff/aitools/datetime/dto/TimeResponse.java
rename to aitools/src/main/java/ru/ldeloff/aitools/externaltools/datetime/dto/TimeResponse.java
index d2fd6c0..ec17683 100644
--- a/aitools/src/main/java/ru/ldeloff/aitools/datetime/dto/TimeResponse.java
+++ b/aitools/src/main/java/ru/ldeloff/aitools/externaltools/datetime/dto/TimeResponse.java
@@ -1,4 +1,4 @@
-package ru.ldeloff.aitools.datetime.dto;
+package ru.ldeloff.aitools.externaltools.datetime.dto;
import lombok.AllArgsConstructor;
diff --git a/aitools/src/main/java/ru/ldeloff/aitools/telegrambot/bot/TelegramBot.java b/aitools/src/main/java/ru/ldeloff/aitools/telegrambot/bot/TelegramBot.java
new file mode 100644
index 0000000..29d6eab
--- /dev/null
+++ b/aitools/src/main/java/ru/ldeloff/aitools/telegrambot/bot/TelegramBot.java
@@ -0,0 +1,78 @@
+package ru.ldeloff.aitools.telegrambot.bot;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.ai.chat.messages.AssistantMessage;
+import org.springframework.ai.chat.messages.Message;
+import org.springframework.ai.chat.messages.UserMessage;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.telegram.telegrambots.bots.TelegramLongPollingBot;
+import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
+import org.telegram.telegrambots.meta.api.objects.Update;
+import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
+import ru.ldeloff.aitools.telegrambot.cache.MessageCache;
+import ru.ldeloff.aitools.telegrambot.service.LlmService;
+
+import java.util.List;
+
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class TelegramBot extends TelegramLongPollingBot {
+
+ private final MessageCache messageCache;
+ private final LlmService llmService;
+
+ @Value("${telegram.bot.name}")
+ private String telegramBotName;
+ @Value("${telegram.bot.token}")
+ private String telegramBotToken;
+
+
+ @Override
+ public String getBotUsername() {
+ return telegramBotName;
+ }
+
+ @Override
+ public String getBotToken() {
+ return telegramBotToken;
+ }
+
+ @Override
+ public void onUpdateReceived(Update update) {
+ log.info(update.toString());
+
+ if (update.hasMessage()) {
+ Long chatId = update.getMessage().getChatId();
+ if (update.getMessage().hasText()) {
+ String messageText = update.getMessage().getText();
+ if ("/start".equals(messageText)) {
+ messageCache.clearMessages(chatId);
+ sendText(chatId, "Начинаем диалог!");
+ }
+ List messageList = new java.util.ArrayList<>(messageCache.getOrInitMessages(chatId).stream().toList());
+ messageList.add(new UserMessage(messageText));
+ List assistantMessageList = llmService.sendMessages(messageList);
+ messageList.add(new AssistantMessage(assistantMessageList.getFirst()));
+ messageCache.saveMessages(chatId, messageList);
+ sendText(chatId, assistantMessageList.getFirst());
+ } else {
+ sendText(chatId, "Я понимаю только текст!");
+ }
+
+ }
+ }
+
+ public void sendText(Long telegramId, String message){
+ SendMessage sm = SendMessage.builder()
+ .chatId(telegramId.toString()) //Who are we sending a message to
+ .text(message).build(); //Message content
+ try {
+ execute(sm); //Actually sending the message
+ } catch (TelegramApiException e) {
+ throw new RuntimeException(e); //Any error will be printed here
+ }
+ }
+}
\ No newline at end of file
diff --git a/aitools/src/main/java/ru/ldeloff/aitools/telegrambot/cache/MessageCache.java b/aitools/src/main/java/ru/ldeloff/aitools/telegrambot/cache/MessageCache.java
new file mode 100644
index 0000000..bd87c48
--- /dev/null
+++ b/aitools/src/main/java/ru/ldeloff/aitools/telegrambot/cache/MessageCache.java
@@ -0,0 +1,29 @@
+package ru.ldeloff.aitools.telegrambot.cache;
+
+import org.springframework.ai.chat.messages.Message;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.CachePut;
+import org.springframework.cache.annotation.Cacheable;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Component
+public class MessageCache {
+
+ @Cacheable(cacheNames = "messages", key = "#chatId")
+ public List getOrInitMessages(Long chatId) {
+ return List.of();
+ }
+
+ @CachePut(cacheNames = "messages", key = "#chatId")
+ public List saveMessages(Long chatId, List messages) {
+ return messages;
+ }
+
+ @CacheEvict(cacheNames = "messages", key = "#chatId")
+ public List clearMessages(Long chatId) {
+ return List.of();
+ }
+
+}
diff --git a/aitools/src/main/java/ru/ldeloff/aitools/telegrambot/config/TelegramBotConfiguration.java b/aitools/src/main/java/ru/ldeloff/aitools/telegrambot/config/TelegramBotConfiguration.java
new file mode 100644
index 0000000..22f5c00
--- /dev/null
+++ b/aitools/src/main/java/ru/ldeloff/aitools/telegrambot/config/TelegramBotConfiguration.java
@@ -0,0 +1,18 @@
+package ru.ldeloff.aitools.telegrambot.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.telegram.telegrambots.meta.TelegramBotsApi;
+import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
+import org.telegram.telegrambots.updatesreceivers.DefaultBotSession;
+import ru.ldeloff.aitools.telegrambot.bot.TelegramBot;
+
+@Configuration
+public class TelegramBotConfiguration {
+ @Bean
+ public TelegramBotsApi telegramBotsApi(TelegramBot telegramBot) throws TelegramApiException {
+ var api = new TelegramBotsApi(DefaultBotSession.class);
+ api.registerBot(telegramBot);
+ return api;
+ }
+}
diff --git a/aitools/src/main/java/ru/ldeloff/aitools/telegrambot/service/LlmService.java b/aitools/src/main/java/ru/ldeloff/aitools/telegrambot/service/LlmService.java
new file mode 100644
index 0000000..33abd9d
--- /dev/null
+++ b/aitools/src/main/java/ru/ldeloff/aitools/telegrambot/service/LlmService.java
@@ -0,0 +1,32 @@
+package ru.ldeloff.aitools.telegrambot.service;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.ai.chat.messages.Message;
+import org.springframework.ai.chat.prompt.Prompt;
+import org.springframework.ai.openai.OpenAiChatModel;
+import org.springframework.ai.openai.OpenAiChatOptions;
+import org.springframework.ai.openai.api.ResponseFormat;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class LlmService {
+ private final OpenAiChatModel model;
+
+ public List sendMessages(List messages) {
+ return model.call(
+ new Prompt(
+ messages,
+ OpenAiChatOptions.builder()
+ .temperature(0.1)
+ .responseFormat(ResponseFormat.builder().type(ResponseFormat.Type.TEXT).build())
+ .build()
+
+ )
+ ).getResults().stream().map(x -> x.getOutput().getText()).toList();
+ }
+}
diff --git a/aitools/src/main/resources/application.properties b/aitools/src/main/resources/application.properties
deleted file mode 100644
index fb3d424..0000000
--- a/aitools/src/main/resources/application.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-spring.application.name=aitools
-
-springdoc.api-docs.path=/api-docs
diff --git a/aitools/src/main/resources/application.yaml b/aitools/src/main/resources/application.yaml
new file mode 100644
index 0000000..27e9f82
--- /dev/null
+++ b/aitools/src/main/resources/application.yaml
@@ -0,0 +1,25 @@
+spring:
+ application:
+ name: aitools
+ ai:
+ openai:
+ api-key: "no-key-needed" # OpenWebUI не требует ключа, но поле обязательно
+ base-url: http://192.168.10.110:8080 # Путь к API OpenWebUI
+ chat:
+ options:
+# model: "large/Qwen3-Next-80B-A3B-Thinking-UD-Q8_K_XL"
+ model: "large/Qwen3-Next-80B-A3B-Instruct-UD-Q8_K_XL"
+ client:
+ connect-timeout: 300s
+ read-timeout: 300s
+ write-timeout: 300s
+
+
+springdoc:
+ api-docs:
+ path: /api-docs
+
+telegram:
+ bot:
+ name: ${TELEGRAM_BOT_NAME}
+ token: ${TELEGRAM_BOT_TOKEN}
\ No newline at end of file
diff --git a/aitools/src/test/java/ru/ldeloff/aitools/AitoolsApplicationTests.java b/aitools/src/test/java/ru/ldeloff/aitools/AitoolsApplicationTests.java
deleted file mode 100644
index 7ee1edf..0000000
--- a/aitools/src/test/java/ru/ldeloff/aitools/AitoolsApplicationTests.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package ru.ldeloff.aitools;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.boot.test.context.SpringBootTest;
-
-@SpringBootTest
-class AitoolsApplicationTests {
-
- @Test
- void contextLoads() {
- }
-
-}