Behavior set, multi-account, inline mod, and other little things
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
89c42edc25
commit
e85e2c03bd
@ -34,10 +34,6 @@ steps:
|
|||||||
- name: docker publish develop
|
- name: docker publish develop
|
||||||
image: upagge/docker-buildx:latest
|
image: upagge/docker-buildx:latest
|
||||||
environment:
|
environment:
|
||||||
STRUCHKOV_DOCKER_REGISTRY_TOKEN:
|
|
||||||
from_secret: STRUCHKOV_DOCKER_REGISTRY_TOKEN
|
|
||||||
STRUCHKOV_DOCKER_IMAGE_NAME:
|
|
||||||
from_secret: STRUCHKOV_DOCKER_IMAGE_NAME
|
|
||||||
DOCKER_REGISTRY_TOKEN:
|
DOCKER_REGISTRY_TOKEN:
|
||||||
from_secret: DOCKER_REGISTRY_TOKEN
|
from_secret: DOCKER_REGISTRY_TOKEN
|
||||||
DOCKER_IMAGE_NAME:
|
DOCKER_IMAGE_NAME:
|
||||||
@ -48,10 +44,9 @@ steps:
|
|||||||
- name: dockersock
|
- name: dockersock
|
||||||
path: /var/run
|
path: /var/run
|
||||||
commands:
|
commands:
|
||||||
- echo "$STRUCHKOV_DOCKER_REGISTRY_TOKEN" | docker login git.struchkov.dev --username $DOCKER_REGISTRY_USER --password-stdin
|
|
||||||
- echo "$DOCKER_REGISTRY_TOKEN" | docker login docker.io --username $DOCKER_REGISTRY_USER --password-stdin
|
- echo "$DOCKER_REGISTRY_TOKEN" | docker login docker.io --username $DOCKER_REGISTRY_USER --password-stdin
|
||||||
- docker buildx create --use
|
- docker buildx create --use
|
||||||
- docker buildx build -f Dockerfile-develop --push --platform linux/amd64,linux/arm64/v8 -t "$DOCKER_IMAGE_NAME:develop" -t "git.struchkov.dev/$STRUCHKOV_DOCKER_IMAGE_NAME:develop" .
|
- docker buildx build -f Dockerfile-develop --push --platform linux/amd64,linux/arm64/v8 -t "$DOCKER_IMAGE_NAME:develop" .
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
@ -203,6 +198,6 @@ volumes:
|
|||||||
path: /drone/volume/mkdocs_cache/chatgpt-telegram-bot/en
|
path: /drone/volume/mkdocs_cache/chatgpt-telegram-bot/en
|
||||||
---
|
---
|
||||||
kind: signature
|
kind: signature
|
||||||
hmac: 44ca201fe0ea4a7b739d9e170e0852171c5175c0128bfd3e77f7247f92db56a8
|
hmac: b615ac14d736c1ff2354f10d96117108866cd0bc8d387f827ea063fbe66b418c
|
||||||
|
|
||||||
...
|
...
|
||||||
|
10
pom.xml
10
pom.xml
@ -15,8 +15,8 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<java.version>17</java.version>
|
<java.version>17</java.version>
|
||||||
|
|
||||||
<openai.api.version>0.0.1</openai.api.version>
|
<openai.api.version>0.0.2-SNAPSHOT</openai.api.version>
|
||||||
<godfather.version>0.0.53</godfather.version>
|
<godfather.version>0.0.54-SNAPSHOT</godfather.version>
|
||||||
|
|
||||||
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-plugin -->
|
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-plugin -->
|
||||||
<plugin.maven.compiler.ver>3.10.1</plugin.maven.compiler.ver>
|
<plugin.maven.compiler.ver>3.10.1</plugin.maven.compiler.ver>
|
||||||
@ -61,6 +61,12 @@
|
|||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>31.1-jre</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<repositories>
|
<repositories>
|
||||||
|
@ -4,10 +4,10 @@ import org.springframework.boot.SpringApplication;
|
|||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class SpringBootTelegramBotExampleApplication {
|
public class ChatGptTelegramBot {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
SpringApplication.run(SpringBootTelegramBotExampleApplication.class, args);
|
SpringApplication.run(ChatGptTelegramBot.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -5,13 +5,15 @@ import lombok.Setter;
|
|||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@Component
|
@Component
|
||||||
@ConfigurationProperties("app")
|
@ConfigurationProperties("app")
|
||||||
public class AppProperty {
|
public class AppProperty {
|
||||||
|
|
||||||
private String telegramId;
|
private List<String> telegramIds;
|
||||||
private String version;
|
private String version;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,13 +19,21 @@ public class ErrorTelegramHandler implements ErrorHandler {
|
|||||||
private final TelegramSending sending;
|
private final TelegramSending sending;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(Message message, Exception e) {
|
public void handle(Message message, Throwable e) {
|
||||||
log.error(e.getMessage(), e);
|
log.error(e.getMessage(), e);
|
||||||
final String errorMessage = escapeMarkdown(e.getMessage());
|
final String errorMessage = escapeMarkdown(e.getMessage());
|
||||||
|
|
||||||
|
final String recipientTelegramId;
|
||||||
|
if (appProperty.getTelegramIds().contains(message.getFromPersonId())) {
|
||||||
|
recipientTelegramId = message.getFromPersonId();
|
||||||
|
} else {
|
||||||
|
recipientTelegramId = appProperty.getTelegramIds().get(0);
|
||||||
|
}
|
||||||
|
|
||||||
sending.send(
|
sending.send(
|
||||||
BoxAnswer.builder()
|
BoxAnswer.builder()
|
||||||
.message("Error message:\n\n" + errorMessage)
|
.message("Error message:\n\n" + errorMessage)
|
||||||
.recipientPersonId(appProperty.getTelegramId())
|
.recipientPersonId(recipientTelegramId)
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
package dev.struchkov.example.bot.handler;
|
||||||
|
|
||||||
|
import dev.struchkov.example.bot.conf.AppProperty;
|
||||||
|
import dev.struchkov.example.bot.service.InlineStorage;
|
||||||
|
import dev.struchkov.godfather.main.domain.EventContainer;
|
||||||
|
import dev.struchkov.godfather.simple.context.service.EventHandler;
|
||||||
|
import dev.struchkov.godfather.telegram.simple.context.service.TelegramSending;
|
||||||
|
import dev.struchkov.openai.context.GPTClient;
|
||||||
|
import dev.struchkov.openai.domain.common.GptMessage;
|
||||||
|
import dev.struchkov.openai.domain.model.gpt.GPT3Model;
|
||||||
|
import dev.struchkov.openai.domain.request.GptRequest;
|
||||||
|
import dev.struchkov.openai.domain.response.Choice;
|
||||||
|
import dev.struchkov.openai.domain.response.GptResponse;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.telegram.telegrambots.meta.api.objects.inlinequery.ChosenInlineQuery;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static dev.struchkov.godfather.simple.domain.BoxAnswer.boxAnswer;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class InlineChoseHandler implements EventHandler<ChosenInlineQuery> {
|
||||||
|
|
||||||
|
private final GPTClient gptClient;
|
||||||
|
private final InlineStorage inlineStorage;
|
||||||
|
private final AppProperty appProperty;
|
||||||
|
private final TelegramSending telegramSending;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(EventContainer<ChosenInlineQuery> event) {
|
||||||
|
final ChosenInlineQuery chosenInlineQuery = event.getObject();
|
||||||
|
final String personId = chosenInlineQuery.getFrom().getId().toString();
|
||||||
|
|
||||||
|
if (appProperty.getTelegramIds().contains(personId)) {
|
||||||
|
final Optional<String> optRequest = inlineStorage.getQuery(chosenInlineQuery.getResultId());
|
||||||
|
if (optRequest.isPresent()) {
|
||||||
|
final String request = optRequest.get();
|
||||||
|
final GptResponse gptResponse = gptClient.execute(
|
||||||
|
GptRequest.builder()
|
||||||
|
.model(GPT3Model.GPT_3_5_TURBO)
|
||||||
|
.message(
|
||||||
|
GptMessage.fromUser(request)
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
final List<Choice> choices = gptResponse.getChoices();
|
||||||
|
final String answer = choices.get(choices.size() - 1).getMessage().getContent();
|
||||||
|
telegramSending.replaceInlineMessage(chosenInlineQuery.getInlineMessageId(), boxAnswer(answer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<ChosenInlineQuery> getEventClass() {
|
||||||
|
return ChosenInlineQuery.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
package dev.struchkov.example.bot.handler;
|
||||||
|
|
||||||
|
import dev.struchkov.example.bot.conf.AppProperty;
|
||||||
|
import dev.struchkov.example.bot.service.InlineStorage;
|
||||||
|
import dev.struchkov.godfather.main.domain.EventContainer;
|
||||||
|
import dev.struchkov.godfather.simple.context.service.EventHandler;
|
||||||
|
import dev.struchkov.godfather.telegram.simple.context.service.TelegramConnect;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.telegram.telegrambots.meta.api.methods.AnswerInlineQuery;
|
||||||
|
import org.telegram.telegrambots.meta.api.objects.inlinequery.InlineQuery;
|
||||||
|
import org.telegram.telegrambots.meta.api.objects.inlinequery.inputmessagecontent.InputTextMessageContent;
|
||||||
|
import org.telegram.telegrambots.meta.api.objects.inlinequery.result.InlineQueryResultArticle;
|
||||||
|
import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
|
||||||
|
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton;
|
||||||
|
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
|
||||||
|
import org.telegram.telegrambots.meta.exceptions.TelegramApiValidationException;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class InlineQueryHandler implements EventHandler<InlineQuery> {
|
||||||
|
|
||||||
|
private final InlineStorage inlineStorage;
|
||||||
|
private final AppProperty appProperty;
|
||||||
|
private final TelegramConnect telegramConnect;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handle(EventContainer<InlineQuery> event) {
|
||||||
|
final InlineQuery inlineQuery = event.getObject();
|
||||||
|
if (appProperty.getTelegramIds().contains(inlineQuery.getFrom().getId().toString())) {
|
||||||
|
|
||||||
|
final InputTextMessageContent buildMessageContent = InputTextMessageContent.builder()
|
||||||
|
.messageText(inlineQuery.getQuery())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
try {
|
||||||
|
buildMessageContent.validate();
|
||||||
|
} catch (TelegramApiValidationException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String id = UUID.randomUUID().toString();
|
||||||
|
inlineStorage.save(id, inlineQuery.getQuery());
|
||||||
|
|
||||||
|
final InlineQueryResultArticle result = InlineQueryResultArticle.builder()
|
||||||
|
.id(id)
|
||||||
|
.title("Your request to ChatGPT:")
|
||||||
|
.description(inlineQuery.getQuery())
|
||||||
|
.hideUrl(true)
|
||||||
|
.thumbUrl("https://struchkov.dev/static/img/openai.jpeg")
|
||||||
|
.replyMarkup(
|
||||||
|
InlineKeyboardMarkup.builder()
|
||||||
|
.keyboard(List.of(List.of(
|
||||||
|
InlineKeyboardButton.builder()
|
||||||
|
.text("Wait... The answer is generated...")
|
||||||
|
.callbackData("inline_query")
|
||||||
|
.build()
|
||||||
|
)))
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
.inputMessageContent(buildMessageContent).build();
|
||||||
|
|
||||||
|
try {
|
||||||
|
result.validate();
|
||||||
|
} catch (TelegramApiValidationException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
final AnswerInlineQuery answerInlineQuery = AnswerInlineQuery.builder()
|
||||||
|
.inlineQueryId(inlineQuery.getId())
|
||||||
|
.result(result)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
try {
|
||||||
|
answerInlineQuery.validate();
|
||||||
|
} catch (TelegramApiValidationException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
telegramConnect.getAbsSender().execute(answerInlineQuery);
|
||||||
|
} catch (TelegramApiException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<InlineQuery> getEventClass() {
|
||||||
|
return InlineQuery.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package dev.struchkov.example.bot.service;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class InlineStorage {
|
||||||
|
|
||||||
|
private final ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor();
|
||||||
|
|
||||||
|
private final Cache<String, String> cache = CacheBuilder.newBuilder()
|
||||||
|
.expireAfterWrite(5, TimeUnit.MINUTES)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public InlineStorage() {
|
||||||
|
scheduledExecutor.scheduleAtFixedRate(cache::cleanUp, 1, 1, TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(String inlineId, String query) {
|
||||||
|
cache.put(inlineId, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<String> getQuery(String inlineId) {
|
||||||
|
return Optional.ofNullable(cache.getIfPresent(inlineId));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package dev.struchkov.example.bot.service;
|
||||||
|
|
||||||
|
import dev.struchkov.example.bot.conf.AppProperty;
|
||||||
|
import dev.struchkov.openai.context.ChatGptService;
|
||||||
|
import dev.struchkov.openai.domain.chat.ChatInfo;
|
||||||
|
import dev.struchkov.openai.domain.chat.CreateChat;
|
||||||
|
import dev.struchkov.openai.domain.chat.UpdateChat;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class PersonalChatService {
|
||||||
|
|
||||||
|
private final ChatGptService chatGptService;
|
||||||
|
private final Map<String, String> chatDefaultContext = new ConcurrentHashMap<>();
|
||||||
|
private final Map<String, ChatInfo> chatMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
public PersonalChatService(
|
||||||
|
AppProperty appProperty,
|
||||||
|
ChatGptService chatGptService
|
||||||
|
) {
|
||||||
|
this.chatGptService = chatGptService;
|
||||||
|
appProperty.getTelegramIds().forEach(
|
||||||
|
telegramId -> {
|
||||||
|
final ChatInfo newChat = this.chatGptService.createChat(
|
||||||
|
CreateChat.builder().build()
|
||||||
|
);
|
||||||
|
chatMap.put(telegramId, newChat);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChatInfo getChatByPersonId(String personId) {
|
||||||
|
return chatMap.get(personId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChatInfo recreateChat(String personId) {
|
||||||
|
final ChatInfo chatInfo = chatMap.get(personId);
|
||||||
|
chatGptService.closeChat(chatInfo.getChatId());
|
||||||
|
final ChatInfo newChat = chatGptService.createChat(
|
||||||
|
CreateChat.builder()
|
||||||
|
.systemBehavior(chatDefaultContext.get(personId))
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
chatMap.put(personId, newChat);
|
||||||
|
return newChat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBehavior(String fromPersonId, String behavior) {
|
||||||
|
chatDefaultContext.put(fromPersonId, behavior);
|
||||||
|
final ChatInfo chatInfo = chatMap.get(fromPersonId);
|
||||||
|
chatGptService.updateChat(
|
||||||
|
UpdateChat.builder()
|
||||||
|
.chatId(chatInfo.getChatId())
|
||||||
|
.systemBehavior(behavior)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
118
src/main/java/dev/struchkov/example/bot/unit/BehaviorUnit.java
Normal file
118
src/main/java/dev/struchkov/example/bot/unit/BehaviorUnit.java
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
package dev.struchkov.example.bot.unit;
|
||||||
|
|
||||||
|
import dev.struchkov.example.bot.conf.AppProperty;
|
||||||
|
import dev.struchkov.example.bot.service.PersonalChatService;
|
||||||
|
import dev.struchkov.example.bot.util.Cmd;
|
||||||
|
import dev.struchkov.example.bot.util.UnitName;
|
||||||
|
import dev.struchkov.godfather.main.domain.annotation.Unit;
|
||||||
|
import dev.struchkov.godfather.main.domain.content.Attachment;
|
||||||
|
import dev.struchkov.godfather.main.domain.content.Mail;
|
||||||
|
import dev.struchkov.godfather.simple.domain.BoxAnswer;
|
||||||
|
import dev.struchkov.godfather.simple.domain.unit.AnswerText;
|
||||||
|
import dev.struchkov.godfather.telegram.domain.attachment.CommandAttachment;
|
||||||
|
import dev.struchkov.godfather.telegram.main.core.util.Attachments;
|
||||||
|
import dev.struchkov.godfather.telegram.starter.PersonUnitConfiguration;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static dev.struchkov.godfather.simple.domain.BoxAnswer.boxAnswer;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class BehaviorUnit implements PersonUnitConfiguration {
|
||||||
|
|
||||||
|
private final PersonalChatService personalChatService;
|
||||||
|
private final AppProperty appProperty;
|
||||||
|
|
||||||
|
@Unit(value = UnitName.BEHAVIOR, global = true)
|
||||||
|
public AnswerText<Mail> behavior() {
|
||||||
|
return AnswerText.<Mail>builder()
|
||||||
|
.triggerCheck(
|
||||||
|
mail -> {
|
||||||
|
if (appProperty.getTelegramIds().contains(mail.getFromPersonId())) {
|
||||||
|
final List<Attachment> attachments = mail.getAttachments();
|
||||||
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
||||||
|
if (optCommand.isPresent()) {
|
||||||
|
final CommandAttachment command = optCommand.get();
|
||||||
|
return Cmd.BEHAVIOR.equals(command.getCommandType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.answer(mail -> {
|
||||||
|
final CommandAttachment command = Attachments.findFirstCommand(mail.getAttachments()).orElseThrow();
|
||||||
|
final Optional<String> optArg = command.getArg();
|
||||||
|
if (optArg.isEmpty()) {
|
||||||
|
return BoxAnswer.builder()
|
||||||
|
.message(
|
||||||
|
"""
|
||||||
|
Allows you to set the ChatGPT behavior for chat. Remains active when the context is cleared.
|
||||||
|
|
||||||
|
If you want to set your own behavior, then send the command:
|
||||||
|
|
||||||
|
/behavior description_behavior
|
||||||
|
|
||||||
|
Or choose one of the available options:
|
||||||
|
|
||||||
|
1. Гопник
|
||||||
|
Представь, что ты славянский гопник и общаешься со своими собутыльниками по подъезду. Используй побольше мата и блатного жаргона. Используй как можно больше «бля» и «ёпта». Отвечай в таком стиле всегда, какой бы вопрос не задали пользователи в этом чате.
|
||||||
|
👉 /behavior1
|
||||||
|
|
||||||
|
2. Copilot
|
||||||
|
Ты - помощник для программистов. На любой вопрос отвечай с примерами кода, если нужно и присылай советы по улучшению кода
|
||||||
|
👉 /behavior2
|
||||||
|
|
||||||
|
3. Linux
|
||||||
|
Я хочу, чтобы вы выступали в роли терминала Linux. Я буду вводить команды, а вы будете отвечать тем, что должен показать терминал. Я хочу, чтобы вы ответили выводом терминала только внутри одного уникального блока кода, и ничего больше. не пишите пояснений. не вводите команды, если я не поручу вам это сделать. Когда мне нужно будет сказать вам что-то на русском языке, я буду заключать текст в фигурные скобки {вот так}.
|
||||||
|
👉 /behavior3
|
||||||
|
|
||||||
|
4. Тренера по взаимоотношениям
|
||||||
|
Я хочу, чтобы вы выступили в роли тренера по взаимоотношениям. Я предоставлю некоторые подробности о двух людях, вовлеченных в конфликт, а ваша задача - предложить, как они могут решить проблемы, которые их разделяют. Это могут быть советы по технике общения или различные стратегии для улучшения понимания ими точек зрения друг друга. Первый запрос: "Мне нужна помощь в разрешении конфликтов между мной и моим парнем".
|
||||||
|
👉 /behavior4
|
||||||
|
|
||||||
|
5. Наставник
|
||||||
|
Вы наставник, который всегда отвечает в сократовском стиле. Вы *никогда* не даете ученику ответа, но всегда стараетесь задать правильный вопрос, чтобы помочь ему научиться думать самостоятельно. Вы всегда должны согласовывать свой вопрос с интересами и знаниями учащегося, разбивая проблему на более простые части, пока она не достигнет нужного для них уровня.
|
||||||
|
👉 /behavior5
|
||||||
|
|
||||||
|
6. В двух словах
|
||||||
|
Отвечай максимально коротко, даже если тебя просят ответить развернуто. Весь ответ должен уложиться в пару предложений.
|
||||||
|
👉 /behavior6
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
} else {
|
||||||
|
final String behavior = optArg.get();
|
||||||
|
personalChatService.setBehavior(mail.getFromPersonId(), behavior);
|
||||||
|
return boxAnswer("\uD83D\uDC4C");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Unit(value = UnitName.BEHAVIOUR, global = true)
|
||||||
|
// public AnswerText<Mail> behaviour1() {
|
||||||
|
// return AnswerText.<Mail>builder()
|
||||||
|
// .triggerCheck(
|
||||||
|
// mail -> {
|
||||||
|
// if (appProperty.getTelegramIds().contains(mail.getFromPersonId())) {
|
||||||
|
// final List<Attachment> attachments = mail.getAttachments();
|
||||||
|
// final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
||||||
|
// if (optCommand.isPresent()) {
|
||||||
|
// final CommandAttachment command = optCommand.get();
|
||||||
|
// return Cmd.BEHAVIOUR_1.equals(command.getCommandType());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
// .answer(() -> {
|
||||||
|
//
|
||||||
|
// })
|
||||||
|
// .build();
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package dev.struchkov.example.bot.unit;
|
package dev.struchkov.example.bot.unit;
|
||||||
|
|
||||||
import dev.struchkov.example.bot.conf.AppProperty;
|
import dev.struchkov.example.bot.conf.AppProperty;
|
||||||
|
import dev.struchkov.example.bot.service.PersonalChatService;
|
||||||
import dev.struchkov.example.bot.util.Cmd;
|
import dev.struchkov.example.bot.util.Cmd;
|
||||||
import dev.struchkov.example.bot.util.UnitName;
|
import dev.struchkov.example.bot.util.UnitName;
|
||||||
import dev.struchkov.godfather.main.domain.annotation.Unit;
|
import dev.struchkov.godfather.main.domain.annotation.Unit;
|
||||||
@ -8,6 +9,7 @@ import dev.struchkov.godfather.main.domain.content.Attachment;
|
|||||||
import dev.struchkov.godfather.main.domain.content.Mail;
|
import dev.struchkov.godfather.main.domain.content.Mail;
|
||||||
import dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton;
|
import dev.struchkov.godfather.main.domain.keyboard.button.SimpleButton;
|
||||||
import dev.struchkov.godfather.simple.domain.BoxAnswer;
|
import dev.struchkov.godfather.simple.domain.BoxAnswer;
|
||||||
|
import dev.struchkov.godfather.simple.domain.SentBox;
|
||||||
import dev.struchkov.godfather.simple.domain.unit.AnswerText;
|
import dev.struchkov.godfather.simple.domain.unit.AnswerText;
|
||||||
import dev.struchkov.godfather.telegram.domain.ChatAction;
|
import dev.struchkov.godfather.telegram.domain.ChatAction;
|
||||||
import dev.struchkov.godfather.telegram.domain.ClientBotCommand;
|
import dev.struchkov.godfather.telegram.domain.ClientBotCommand;
|
||||||
@ -24,65 +26,57 @@ import dev.struchkov.openai.context.ChatGptService;
|
|||||||
import dev.struchkov.openai.context.GPTClient;
|
import dev.struchkov.openai.context.GPTClient;
|
||||||
import dev.struchkov.openai.domain.chat.ChatInfo;
|
import dev.struchkov.openai.domain.chat.ChatInfo;
|
||||||
import dev.struchkov.openai.domain.common.GptMessage;
|
import dev.struchkov.openai.domain.common.GptMessage;
|
||||||
|
import dev.struchkov.openai.domain.message.AnswerChatMessage;
|
||||||
import dev.struchkov.openai.domain.model.gpt.GPT3Model;
|
import dev.struchkov.openai.domain.model.gpt.GPT3Model;
|
||||||
import dev.struchkov.openai.domain.request.GptRequest;
|
import dev.struchkov.openai.domain.request.GptRequest;
|
||||||
import dev.struchkov.openai.domain.response.Choice;
|
import dev.struchkov.openai.domain.response.Choice;
|
||||||
import dev.struchkov.openai.domain.response.GptResponse;
|
import dev.struchkov.openai.domain.response.GptResponse;
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static dev.struchkov.example.bot.util.UnitName.CLEAR_CONTEXT;
|
import static dev.struchkov.example.bot.util.UnitName.CLEAR_CONTEXT;
|
||||||
import static dev.struchkov.example.bot.util.UnitName.GPT_UNIT;
|
import static dev.struchkov.example.bot.util.UnitName.GPT_UNIT;
|
||||||
import static dev.struchkov.godfather.simple.domain.BoxAnswer.boxAnswer;
|
import static dev.struchkov.godfather.simple.domain.BoxAnswer.boxAnswer;
|
||||||
import static dev.struchkov.godfather.simple.domain.BoxAnswer.replaceBoxAnswer;
|
|
||||||
import static dev.struchkov.godfather.telegram.main.context.BoxAnswerPayload.DISABLE_WEB_PAGE_PREVIEW;
|
import static dev.struchkov.godfather.telegram.main.context.BoxAnswerPayload.DISABLE_WEB_PAGE_PREVIEW;
|
||||||
|
import static dev.struchkov.godfather.telegram.main.context.BoxAnswerPayload.ENABLE_MARKDOWN;
|
||||||
|
import static java.text.MessageFormat.format;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
||||||
|
|
||||||
private ChatInfo chatInfo;
|
private final PersonalChatService personalChatService;
|
||||||
|
|
||||||
private final TelegramSending telegramSending;
|
private final TelegramSending telegramSending;
|
||||||
private final TelegramService telegramService;
|
private final TelegramService telegramService;
|
||||||
private final AppProperty appProperty;
|
private final AppProperty appProperty;
|
||||||
private final GPTClient gptClient;
|
private final GPTClient gptClient;
|
||||||
private final ChatGptService chatGptService;
|
private final ChatGptService chatGptService;
|
||||||
|
|
||||||
public PersonalChatGPTUnit(
|
|
||||||
TelegramSending telegramSending,
|
|
||||||
TelegramService telegramService,
|
|
||||||
GPTClient gptClient,
|
|
||||||
AppProperty appProperty,
|
|
||||||
ChatGptService chatGptService
|
|
||||||
) {
|
|
||||||
this.telegramSending = telegramSending;
|
|
||||||
this.telegramService = telegramService;
|
|
||||||
this.appProperty = appProperty;
|
|
||||||
this.gptClient = gptClient;
|
|
||||||
this.chatGptService = chatGptService;
|
|
||||||
this.chatInfo = chatGptService.createChat();
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void createCommands() {
|
public void createCommands() {
|
||||||
telegramService.addCommand(List.of(
|
telegramService.addCommand(List.of(
|
||||||
ClientBotCommand.builder()
|
|
||||||
.key(Cmd.CLEAR_CONTEXT)
|
|
||||||
.description("Clears the discussion context. Start a conversation from the beginning")
|
|
||||||
.build(),
|
|
||||||
|
|
||||||
ClientBotCommand.builder()
|
ClientBotCommand.builder()
|
||||||
.key(Cmd.HELP)
|
.key(Cmd.HELP)
|
||||||
.description("help in use")
|
.description("help in use")
|
||||||
.build(),
|
.build(),
|
||||||
|
|
||||||
|
ClientBotCommand.builder()
|
||||||
|
.key(Cmd.CLEAR_CONTEXT)
|
||||||
|
.description("Clears the discussion context. Start a conversation from the beginning.")
|
||||||
|
.build(),
|
||||||
|
|
||||||
|
ClientBotCommand.builder()
|
||||||
|
.key(Cmd.BEHAVIOR)
|
||||||
|
.description("Allows you to set the initial behavior of ChatGPT.")
|
||||||
|
.build(),
|
||||||
|
|
||||||
ClientBotCommand.builder()
|
ClientBotCommand.builder()
|
||||||
.key(Cmd.SUPPORT_DEV)
|
.key(Cmd.SUPPORT_DEV)
|
||||||
.description("Support project development")
|
.description("Support project development.")
|
||||||
.build()
|
.build()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -90,7 +84,7 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
@Unit(value = UnitName.ACCESS_ERROR, main = true)
|
@Unit(value = UnitName.ACCESS_ERROR, main = true)
|
||||||
public AnswerText<Mail> accessError() {
|
public AnswerText<Mail> accessError() {
|
||||||
return AnswerText.<Mail>builder()
|
return AnswerText.<Mail>builder()
|
||||||
.triggerCheck(mail -> !mail.getFromPersonId().equals(appProperty.getTelegramId()))
|
.triggerCheck(mail -> !appProperty.getTelegramIds().contains(mail.getFromPersonId()))
|
||||||
.answer(message -> {
|
.answer(message -> {
|
||||||
final StringBuilder messageText = new StringBuilder("\uD83D\uDEA8 *Attempted unauthorized access to the bot*")
|
final StringBuilder messageText = new StringBuilder("\uD83D\uDEA8 *Attempted unauthorized access to the bot*")
|
||||||
.append("\n-- -- -- -- --\n");
|
.append("\n-- -- -- -- --\n");
|
||||||
@ -99,32 +93,32 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
.ifPresent(username -> messageText.append("\uD83E\uDDB9\u200D♂️: @").append(username));
|
.ifPresent(username -> messageText.append("\uD83E\uDDB9\u200D♂️: @").append(username));
|
||||||
|
|
||||||
messageText.append("\n")
|
messageText.append("\n")
|
||||||
.append("\uD83D\uDCAC: ").append(message.getText())
|
.append("\uD83D\uDCAC: ").append(message.getText());
|
||||||
.toString();
|
|
||||||
return BoxAnswer.builder()
|
return BoxAnswer.builder()
|
||||||
.recipientPersonId(appProperty.getTelegramId())
|
.recipientPersonId(appProperty.getTelegramIds().get(0))
|
||||||
.message(messageText.toString())
|
.message(messageText.toString())
|
||||||
.build();
|
.build();
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unit(value = GPT_UNIT, main = true)
|
@Unit(value = GPT_UNIT, global = true)
|
||||||
public AnswerText<Mail> chatGpt() {
|
public AnswerText<Mail> chatGpt() {
|
||||||
return AnswerText.<Mail>builder()
|
return AnswerText.<Mail>builder()
|
||||||
.triggerCheck(mail -> {
|
.triggerCheck(mail -> {
|
||||||
if (mail.getFromPersonId().equals(appProperty.getTelegramId())) {
|
if (appProperty.getTelegramIds().contains(mail.getFromPersonId())) {
|
||||||
final Optional<CommandAttachment> firstCommand = Attachments.findFirstCommand(mail.getAttachments());
|
final Optional<CommandAttachment> firstCommand = Attachments.findFirstCommand(mail.getAttachments());
|
||||||
return firstCommand.isEmpty();
|
return firstCommand.isEmpty();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
})
|
})
|
||||||
.answer(message -> {
|
.answer(message -> {
|
||||||
|
final ChatInfo chatInfo = personalChatService.getChatByPersonId(message.getFromPersonId());
|
||||||
final long countMessages = chatGptService.getCountMessages(chatInfo.getChatId());
|
final long countMessages = chatGptService.getCountMessages(chatInfo.getChatId());
|
||||||
|
|
||||||
final StringBuilder builder = new StringBuilder();
|
final StringBuilder builder = new StringBuilder();
|
||||||
builder.append("Wait... Response is being generated...\nIt might take a long time ⏳");
|
builder.append("Wait... Response is being generated...\nIt might take a long time ⏳");
|
||||||
telegramService.executeAction(message.getFromPersonId(), ChatAction.TYPING);
|
|
||||||
|
|
||||||
if (countMessages > 40) {
|
if (countMessages > 40) {
|
||||||
builder.append(Strings.escapeMarkdown("\n-- -- -- -- --\nWe recommend periodically clearing the conversation context (/clear_context). If this is not done, then the memory resources on your PC will run out."));
|
builder.append(Strings.escapeMarkdown("\n-- -- -- -- --\nWe recommend periodically clearing the conversation context (/clear_context). If this is not done, then the memory resources on your PC will run out."));
|
||||||
@ -134,20 +128,27 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
.recipientPersonId(message.getFromPersonId())
|
.recipientPersonId(message.getFromPersonId())
|
||||||
.message(builder.toString())
|
.message(builder.toString())
|
||||||
.build();
|
.build();
|
||||||
telegramSending.send(answerWait);
|
final Optional<SentBox> optSentBox = telegramSending.send(answerWait);
|
||||||
final String answerText = chatGptService.sendNewMessage(chatInfo.getChatId(), message.getText());
|
|
||||||
return replaceBoxAnswer(answerText);
|
telegramService.executeAction(message.getFromPersonId(), ChatAction.TYPING);
|
||||||
|
|
||||||
|
final AnswerChatMessage answer = chatGptService.sendNewMessage(chatInfo.getChatId(), message.getText());
|
||||||
|
if (optSentBox.isPresent()) {
|
||||||
|
final SentBox sentBox = optSentBox.get();
|
||||||
|
telegramSending.replaceMessage(sentBox.getPersonId(), sentBox.getMessageId(), boxAnswer(format("\uD83D\uDC47 Answer received. Request cost: {0} tokens", answer.getUsage().getTotalTokens())));
|
||||||
|
}
|
||||||
|
return boxAnswer(answer.getMessage());
|
||||||
})
|
})
|
||||||
.priority(5)
|
.priority(5)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unit(value = CLEAR_CONTEXT, main = true)
|
@Unit(value = CLEAR_CONTEXT, global = true)
|
||||||
public AnswerText<Mail> clearContext() {
|
public AnswerText<Mail> clearContext() {
|
||||||
return AnswerText.<Mail>builder()
|
return AnswerText.<Mail>builder()
|
||||||
.triggerCheck(
|
.triggerCheck(
|
||||||
mail -> {
|
mail -> {
|
||||||
if (mail.getFromPersonId().equals(appProperty.getTelegramId())) {
|
if (appProperty.getTelegramIds().contains(mail.getFromPersonId())) {
|
||||||
final List<Attachment> attachments = mail.getAttachments();
|
final List<Attachment> attachments = mail.getAttachments();
|
||||||
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
||||||
if (optCommand.isPresent()) {
|
if (optCommand.isPresent()) {
|
||||||
@ -159,19 +160,18 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.answer(message -> {
|
.answer(message -> {
|
||||||
chatGptService.closeChat(chatInfo.getChatId());
|
personalChatService.recreateChat(message.getFromPersonId());
|
||||||
chatInfo = chatGptService.createChat();
|
|
||||||
return boxAnswer("\uD83E\uDDF9 Discussion context cleared successfully");
|
return boxAnswer("\uD83E\uDDF9 Discussion context cleared successfully");
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unit(value = UnitName.START, main = true)
|
@Unit(value = UnitName.START, global = true)
|
||||||
public AnswerText<Mail> startMessage() {
|
public AnswerText<Mail> startMessage() {
|
||||||
return AnswerText.<Mail>builder()
|
return AnswerText.<Mail>builder()
|
||||||
.triggerCheck(
|
.triggerCheck(
|
||||||
mail -> {
|
mail -> {
|
||||||
if (mail.getFromPersonId().equals(appProperty.getTelegramId())) {
|
if (appProperty.getTelegramIds().contains(mail.getFromPersonId())) {
|
||||||
final List<Attachment> attachments = mail.getAttachments();
|
final List<Attachment> attachments = mail.getAttachments();
|
||||||
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
||||||
if (optCommand.isPresent()) {
|
if (optCommand.isPresent()) {
|
||||||
@ -184,7 +184,7 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
)
|
)
|
||||||
.answer(message -> {
|
.answer(message -> {
|
||||||
return BoxAnswer.builder()
|
return BoxAnswer.builder()
|
||||||
.message(MessageFormat.format(
|
.message(format(
|
||||||
"""
|
"""
|
||||||
Hello 👋
|
Hello 👋
|
||||||
Your personal ChatGPT bot has been successfully launched.
|
Your personal ChatGPT bot has been successfully launched.
|
||||||
@ -198,18 +198,19 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
appProperty.getVersion()
|
appProperty.getVersion()
|
||||||
))
|
))
|
||||||
.keyBoard(InlineKeyBoard.inlineKeyBoard(SimpleButton.simpleButton("❤️ Support Develop", "support")))
|
.keyBoard(InlineKeyBoard.inlineKeyBoard(SimpleButton.simpleButton("❤️ Support Develop", "support")))
|
||||||
.payload(DISABLE_WEB_PAGE_PREVIEW, true)
|
.payload(DISABLE_WEB_PAGE_PREVIEW)
|
||||||
|
.payload(ENABLE_MARKDOWN)
|
||||||
.build();
|
.build();
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unit(value = UnitName.PROMPT, main = true)
|
@Unit(value = UnitName.PROMPT, global = true)
|
||||||
public AnswerText<Mail> prompt() {
|
public AnswerText<Mail> prompt() {
|
||||||
return AnswerText.<Mail>builder()
|
return AnswerText.<Mail>builder()
|
||||||
.triggerCheck(
|
.triggerCheck(
|
||||||
mail -> {
|
mail -> {
|
||||||
if (mail.getFromPersonId().equals(appProperty.getTelegramId())) {
|
if (appProperty.getTelegramIds().contains(mail.getFromPersonId())) {
|
||||||
final List<Attachment> attachments = mail.getAttachments();
|
final List<Attachment> attachments = mail.getAttachments();
|
||||||
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
||||||
if (optCommand.isPresent()) {
|
if (optCommand.isPresent()) {
|
||||||
@ -221,19 +222,38 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.answer(
|
.answer(
|
||||||
mail -> {
|
message -> {
|
||||||
final CommandAttachment promptCommand = Attachments.findFirstCommand(mail.getAttachments()).get();
|
final CommandAttachment promptCommand = Attachments.findFirstCommand(message.getAttachments()).get();
|
||||||
final Optional<String> optPrompt = promptCommand.getArg();
|
final Optional<String> optPrompt = promptCommand.getArg();
|
||||||
if (optPrompt.isPresent()) {
|
if (optPrompt.isPresent()) {
|
||||||
final String prompt = optPrompt.get();
|
final String prompt = optPrompt.get();
|
||||||
|
|
||||||
|
final BoxAnswer answerWait = BoxAnswer.builder()
|
||||||
|
.recipientPersonId(message.getFromPersonId())
|
||||||
|
.message("Wait... Response is being generated...\nIt might take a long time ⏳")
|
||||||
|
.build();
|
||||||
|
final Optional<SentBox> optSentBox = telegramSending.send(answerWait);
|
||||||
|
|
||||||
|
telegramService.executeAction(message.getFromPersonId(), ChatAction.TYPING);
|
||||||
|
|
||||||
final GptResponse gptResponse = gptClient.execute(
|
final GptResponse gptResponse = gptClient.execute(
|
||||||
GptRequest.builder()
|
GptRequest.builder()
|
||||||
.model(GPT3Model.GPT_3_5_TURBO)
|
.model(GPT3Model.GPT_3_5_TURBO)
|
||||||
.message(GptMessage.fromUser(prompt))
|
.message(GptMessage.fromUser(prompt))
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (optSentBox.isPresent()) {
|
||||||
|
final SentBox sentBox = optSentBox.get();
|
||||||
|
telegramSending.replaceMessage(sentBox.getPersonId(), sentBox.getMessageId(), boxAnswer(format("\uD83D\uDC47 Answer received. Request cost: {0} tokens", gptResponse.getUsage().getTotalTokens())));
|
||||||
|
}
|
||||||
|
|
||||||
final List<Choice> choices = gptResponse.getChoices();
|
final List<Choice> choices = gptResponse.getChoices();
|
||||||
return boxAnswer(choices.get(choices.size() - 1).getMessage().getContent());
|
final String answer = choices.get(choices.size() - 1).getMessage().getContent();
|
||||||
|
return BoxAnswer.builder()
|
||||||
|
.message(answer)
|
||||||
|
.payload(ENABLE_MARKDOWN)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
return BoxAnswer.builder().build();
|
return BoxAnswer.builder().build();
|
||||||
}
|
}
|
||||||
@ -241,12 +261,12 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unit(value = UnitName.SUPPORT, main = true)
|
@Unit(value = UnitName.SUPPORT, global = true)
|
||||||
public AnswerText<Mail> support() {
|
public AnswerText<Mail> support() {
|
||||||
return AnswerText.<Mail>builder()
|
return AnswerText.<Mail>builder()
|
||||||
.triggerCheck(
|
.triggerCheck(
|
||||||
mail -> {
|
mail -> {
|
||||||
if (mail.getFromPersonId().equals(appProperty.getTelegramId())) {
|
if (appProperty.getTelegramIds().contains(mail.getFromPersonId())) {
|
||||||
final List<Attachment> attachments = mail.getAttachments();
|
final List<Attachment> attachments = mail.getAttachments();
|
||||||
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
||||||
if (optCommand.isPresent()) {
|
if (optCommand.isPresent()) {
|
||||||
@ -264,34 +284,37 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
.answer(
|
.answer(
|
||||||
boxAnswer("""
|
() -> BoxAnswer.builder()
|
||||||
❤️ *Support Develop*
|
.message("""
|
||||||
|
❤️ *Support Develop*
|
||||||
|
|
||||||
Sponsorship makes a project sustainable because it pays for the time of the maintainers of that project, a very scarce resource that is spent on developing new features, fixing bugs, improving stability, solving problems, and general support. *The biggest bottleneck in Open Source is time.*
|
Sponsorship makes a project sustainable because it pays for the time of the maintainers of that project, a very scarce resource that is spent on developing new features, fixing bugs, improving stability, solving problems, and general support. *The biggest bottleneck in Open Source is time.*
|
||||||
|
|
||||||
Bank card (Russia): [https://www.tinkoff.ru/cf/4iU6NB3uzqx](https://www.tinkoff.ru/cf/4iU6NB3uzqx)
|
Bank card (Russia): [https://www.tinkoff.ru/cf/4iU6NB3uzqx](https://www.tinkoff.ru/cf/4iU6NB3uzqx)
|
||||||
|
|
||||||
TON: `struchkov-mark.ton`
|
TON: `struchkov-mark.ton`
|
||||||
|
|
||||||
BTC:
|
BTC:
|
||||||
`bc1pt49vnp43c4mktk6309zlq3020dzd0p89gc8d90zzn4sgjvck56xs0t86vy`
|
`bc1pt49vnp43c4mktk6309zlq3020dzd0p89gc8d90zzn4sgjvck56xs0t86vy`
|
||||||
|
|
||||||
ETH (USDT, DAI, USDC):
|
ETH (USDT, DAI, USDC):
|
||||||
`0x7668C802Bd71Be965671D4Bbb1AD90C7f7f32921`
|
`0x7668C802Bd71Be965671D4Bbb1AD90C7f7f32921`
|
||||||
|
|
||||||
BNB (USDT, DAI, USDC):
|
BNB (USDT, DAI, USDC):
|
||||||
`0xDa41aC95f606850f2E01ba775e521Cd385AA7D03`
|
`0xDa41aC95f606850f2E01ba775e521Cd385AA7D03`
|
||||||
""")
|
""")
|
||||||
|
.payload(ENABLE_MARKDOWN)
|
||||||
|
.build()
|
||||||
)
|
)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Unit(value = UnitName.HELP, main = true)
|
@Unit(value = UnitName.HELP, global = true)
|
||||||
public AnswerText<Mail> help() {
|
public AnswerText<Mail> help() {
|
||||||
return AnswerText.<Mail>builder()
|
return AnswerText.<Mail>builder()
|
||||||
.triggerCheck(
|
.triggerCheck(
|
||||||
mail -> {
|
mail -> {
|
||||||
if (mail.getFromPersonId().equals(appProperty.getTelegramId())) {
|
if (appProperty.getTelegramIds().contains(mail.getFromPersonId())) {
|
||||||
final List<Attachment> attachments = mail.getAttachments();
|
final List<Attachment> attachments = mail.getAttachments();
|
||||||
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
|
||||||
if (optCommand.isPresent()) {
|
if (optCommand.isPresent()) {
|
||||||
@ -302,7 +325,7 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.answer(boxAnswer(Strings.escapeMarkdown("""
|
.answer(() -> boxAnswer("""
|
||||||
All correspondence is conducted within one chat. This allows ChatGPT to understand the context of the questions. The context is 100 messages (questions and answers).
|
All correspondence is conducted within one chat. This allows ChatGPT to understand the context of the questions. The context is 100 messages (questions and answers).
|
||||||
|
|
||||||
Available commands:
|
Available commands:
|
||||||
@ -310,7 +333,7 @@ public class PersonalChatGPTUnit implements PersonUnitConfiguration {
|
|||||||
/clear_context - Clears the conversation context. In fact, it deletes the chat and creates a new one.
|
/clear_context - Clears the conversation context. In fact, it deletes the chat and creates a new one.
|
||||||
|
|
||||||
/prompt your_question - Allows you to ask a question outside the context of the main conversation.
|
/prompt your_question - Allows you to ask a question outside the context of the main conversation.
|
||||||
""")))
|
"""))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ import java.text.MessageFormat;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import static dev.struchkov.godfather.telegram.main.context.BoxAnswerPayload.DISABLE_WEB_PAGE_PREVIEW;
|
import static dev.struchkov.godfather.telegram.main.context.BoxAnswerPayload.DISABLE_WEB_PAGE_PREVIEW;
|
||||||
|
import static dev.struchkov.godfather.telegram.main.context.BoxAnswerPayload.ENABLE_MARKDOWN;
|
||||||
import static dev.struchkov.haiti.utils.Checker.checkNotBlank;
|
import static dev.struchkov.haiti.utils.Checker.checkNotBlank;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -34,26 +35,29 @@ public class StartNotify {
|
|||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void sendStartNotify() {
|
public void sendStartNotify() {
|
||||||
final BoxAnswer boxAnswer = BoxAnswer.builder()
|
for (String telegramId : appProperty.getTelegramIds()) {
|
||||||
.message(MessageFormat.format(
|
final BoxAnswer boxAnswer = BoxAnswer.builder()
|
||||||
"""
|
.message(MessageFormat.format(
|
||||||
Hello 👋
|
"""
|
||||||
Your personal ChatGPT bot has been successfully launched.
|
Hello 👋
|
||||||
|
Your personal ChatGPT bot has been successfully launched.
|
||||||
|
|
||||||
Use the help command to find out about the possibilities 🚀
|
Use the help command to find out about the possibilities 🚀
|
||||||
-- -- -- -- --
|
-- -- -- -- --
|
||||||
🤘 Version: {0}
|
🤘 Version: {0}
|
||||||
👨💻 Developer: [Struchkov Mark](https://mark.struchkov.dev/)
|
👨💻 Developer: [Struchkov Mark](https://mark.struchkov.dev/)
|
||||||
💊 Docs: https://docs.struchkov.dev/chatgpt-telegram-bot
|
💊 Docs: https://docs.struchkov.dev/chatgpt-telegram-bot
|
||||||
""",
|
""",
|
||||||
appProperty.getVersion()
|
appProperty.getVersion()
|
||||||
))
|
))
|
||||||
.keyBoard(InlineKeyBoard.inlineKeyBoard(SimpleButton.simpleButton("❤️ Support Develop", "support")))
|
.keyBoard(InlineKeyBoard.inlineKeyBoard(SimpleButton.simpleButton("❤️ Support Develop", "support")))
|
||||||
.payload(DISABLE_WEB_PAGE_PREVIEW, true)
|
.payload(DISABLE_WEB_PAGE_PREVIEW, true)
|
||||||
.build();
|
.payload(ENABLE_MARKDOWN)
|
||||||
boxAnswer.setRecipientIfNull(appProperty.getTelegramId());
|
.build();
|
||||||
sending.send(boxAnswer);
|
boxAnswer.setRecipientIfNull(telegramId);
|
||||||
sendNotice();
|
sending.send(boxAnswer);
|
||||||
|
sendNotice();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,16 +71,19 @@ public class StartNotify {
|
|||||||
if (response.code() == 200) {
|
if (response.code() == 200) {
|
||||||
final String noticeMessage = response.body().string();
|
final String noticeMessage = response.body().string();
|
||||||
if (checkNotBlank(noticeMessage)) {
|
if (checkNotBlank(noticeMessage)) {
|
||||||
final BoxAnswer notice = BoxAnswer.builder()
|
for (String telegramId : appProperty.getTelegramIds()) {
|
||||||
.message(noticeMessage)
|
final BoxAnswer notice = BoxAnswer.builder()
|
||||||
.recipientPersonId(appProperty.getTelegramId())
|
.message(noticeMessage)
|
||||||
.payload(DISABLE_WEB_PAGE_PREVIEW, true)
|
.recipientPersonId(telegramId)
|
||||||
.build();
|
.payload(DISABLE_WEB_PAGE_PREVIEW)
|
||||||
final Optional<SentBox> optSentBox = sending.send(notice);
|
.payload(ENABLE_MARKDOWN)
|
||||||
if (optSentBox.isPresent()) {
|
.build();
|
||||||
final SentBox sentBox = optSentBox.get();
|
final Optional<SentBox> optSentBox = sending.send(notice);
|
||||||
final String messageId = sentBox.getMessageId();
|
if (optSentBox.isPresent()) {
|
||||||
telegramService.pinMessage(appProperty.getTelegramId(), messageId);
|
final SentBox sentBox = optSentBox.get();
|
||||||
|
final String messageId = sentBox.getMessageId();
|
||||||
|
telegramService.pinMessage(telegramId, messageId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,4 +12,12 @@ public class Cmd {
|
|||||||
public static final String SUPPORT_DEV = "support";
|
public static final String SUPPORT_DEV = "support";
|
||||||
public static final String START = "start";
|
public static final String START = "start";
|
||||||
|
|
||||||
|
public static final String BEHAVIOR = "behavior";
|
||||||
|
public static final String BEHAVIOR_1 = "behavior1";
|
||||||
|
public static final String BEHAVIOR_2 = "behavior2";
|
||||||
|
public static final String BEHAVIOR_3 = "behavior3";
|
||||||
|
public static final String BEHAVIOR_4 = "behavior4";
|
||||||
|
public static final String BEHAVIOR_5 = "behavior5";
|
||||||
|
public static final String BEHAVIOR_6 = "behavior6";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,6 @@ public class UnitName {
|
|||||||
public static final String ACCESS_ERROR = "ACCESS_ERROR";
|
public static final String ACCESS_ERROR = "ACCESS_ERROR";
|
||||||
public static final String SUPPORT = "SUPPORT";
|
public static final String SUPPORT = "SUPPORT";
|
||||||
public static final String START = "START";
|
public static final String START = "START";
|
||||||
|
public static final String BEHAVIOR = "BEHAVIOR";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
app:
|
app:
|
||||||
telegram-id: ${TELEGRAM_PERSON_ID}
|
telegram-ids: ${TELEGRAM_PERSON_ID}
|
||||||
version: 0.0.1
|
version: 0.0.1
|
||||||
telegram:
|
telegram:
|
||||||
bot:
|
bot:
|
||||||
|
Loading…
Reference in New Issue
Block a user