телеграм бот

This commit is contained in:
2026-01-18 17:26:39 +03:00
parent f600fa1523
commit 6668001a97
11 changed files with 217 additions and 28 deletions

View File

@@ -5,7 +5,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.1</version>
<version>3.5.9</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>ru.ldeloff</groupId>
@@ -28,12 +28,39 @@
</scm>
<properties>
<java.version>25</java.version>
<spring-ai.version>1.1.2</spring-ai.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
<version>2.8.15</version>
</dependency>
<dependency>
<groupId>org.telegram</groupId>
<artifactId>telegrambots</artifactId>
<version>6.9.7.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
@@ -42,16 +69,10 @@
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux-test</artifactId>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
<version>3.0.1</version>
</dependency>
</dependencies>
<build>

View File

@@ -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 {

View File

@@ -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;

View File

@@ -1,4 +1,4 @@
package ru.ldeloff.aitools.datetime.dto;
package ru.ldeloff.aitools.externaltools.datetime.dto;
import lombok.AllArgsConstructor;

View File

@@ -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<Message> messageList = new java.util.ArrayList<>(messageCache.getOrInitMessages(chatId).stream().toList());
messageList.add(new UserMessage(messageText));
List<String> 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
}
}
}

View File

@@ -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<Message> getOrInitMessages(Long chatId) {
return List.of();
}
@CachePut(cacheNames = "messages", key = "#chatId")
public List<Message> saveMessages(Long chatId, List<Message> messages) {
return messages;
}
@CacheEvict(cacheNames = "messages", key = "#chatId")
public List<Message> clearMessages(Long chatId) {
return List.of();
}
}

View File

@@ -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;
}
}

View File

@@ -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<String> sendMessages(List<Message> 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();
}
}

View File

@@ -1,3 +0,0 @@
spring.application.name=aitools
springdoc.api-docs.path=/api-docs

View File

@@ -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}

View File

@@ -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() {
}
}