pre release 0.0.1
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Struchkov Mark 2023-03-15 20:29:59 +03:00
parent 7aa3baa31d
commit cc655a1bce
Signed by: upagge
GPG Key ID: D3018BE7BA428CA6
9 changed files with 528 additions and 54 deletions

View File

@ -0,0 +1,209 @@
---
kind: pipeline
type: docker
name: develop build
trigger:
branch:
- develop
services:
- name: docker
image: docker:20.10.22-dind-alpine3.17
privileged: true
volumes:
- name: dockersock
path: /var/run
volumes:
- name: m2
host:
path: /drone/volume/m2
- name: dockersock
temp: {}
steps:
- name: create jar
image: maven:3.8.6-eclipse-temurin-17
volumes:
- name: m2
path: /root/.m2/repository
commands:
- mvn -U clean package
- name: docker publish develop
image: upagge/docker-buildx:latest
environment:
STRUCHKOV_DOCKER_REGISTRY_TOKEN:
from_secret: STRUCHKOV_DOCKER_REGISTRY_TOKEN
STRUCHKOV_DOCKER_IMAGE_NAME:
from_secret: STRUCHKOV_DOCKER_IMAGE_NAME
DOCKER_REGISTRY_TOKEN:
from_secret: DOCKER_REGISTRY_TOKEN
DOCKER_IMAGE_NAME:
from_secret: DOCKER_IMAGE_NAME
DOCKER_REGISTRY_USER:
from_secret: DOCKER_REGISTRY_USER
volumes:
- name: dockersock
path: /var/run
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
- 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" .
#---
#
#kind: pipeline
#type: docker
#name: release build
#
#trigger:
# ref:
# - refs/tags/v.*.*.*
#
#services:
# - name: docker
# image: docker:20.10.22-dind-alpine3.17
# privileged: true
# volumes:
# - name: dockersock
# path: /var/run
#
#volumes:
# - name: m2
# host:
# path: /drone/volume/m2
# - name: dockersock
# temp: {}
#
#steps:
# - name: create jar
# image: maven:3.8.6-eclipse-temurin-17
# volumes:
# - name: m2
# path: /root/.m2/repository
# commands:
# - mvn -U clean package
#
# - name: docker publish release
# image: upagge/docker-buildx:latest
# environment:
# STRUCHKOV_DOCKER_REGISTRY_TOKEN:
# from_secret: STRUCHKOV_DOCKER_REGISTRY_TOKEN
# STRUCHKOV_DOCKER_IMAGE_NAME:
# from_secret: STRUCHKOV_DOCKER_IMAGE_NAME
# DOCKER_REGISTRY_TOKEN:
# from_secret: DOCKER_REGISTRY_TOKEN
# DOCKER_IMAGE_NAME:
# from_secret: DOCKER_IMAGE_NAME
# DOCKER_REGISTRY_USER:
# from_secret: DOCKER_REGISTRY_USER
# volumes:
# - name: dockersock
# path: /var/run
# 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
# - docker buildx create --use
# - docker buildx build --push --platform linux/amd64,linux/arm64/v8 -t "$DOCKER_IMAGE_NAME:latest" -t "$DOCKER_IMAGE_NAME:$DRONE_TAG" -t "git.struchkov.dev/$STRUCHKOV_DOCKER_IMAGE_NAME:latest" -t "git.struchkov.dev/$STRUCHKOV_DOCKER_IMAGE_NAME:$DRONE_TAG" .
#
#---
#kind: pipeline
#type: docker
#name: create-develop-docs-site
#
#trigger:
# branch:
# - develop
# - docs
#
#clone:
# disable: true
#
#steps:
#
# - name: build docs
# image: git.struchkov.dev/upagge/mkdocs-material-insiders:latest
# volumes:
# - name: mkdocs_cache
# path: ${DRONE_WORKSPACE}/documentation/ru/.cache
# environment:
# GIT_SSH:
# from_secret: GIT_SSH
# GIT_SSH_COMMAND: "ssh -i ~/.ssh/id_rsa -p 222"
# commands:
# - eval $(ssh-agent -s)
# - mkdir -p ~/.ssh
# - chmod 700 ~/.ssh
# - echo "$GIT_SSH" >> ~/.ssh/id_rsa
# - chmod 600 ~/.ssh/id_rsa
# - ssh-keyscan -p 222 git.struchkov.dev >> ~/.ssh/known_hosts
# - chmod 644 ~/.ssh/known_hosts
# - git config --global user.name "${DRONE_COMMIT_AUTHOR_NAME}"
# - git config --global user.email "${DRONE_COMMIT_AUTHOR_EMAIL}"
# - git clone ssh://git@git.struchkov.dev:222/Telegram-Bots/gitlab-notification.git .
# - git checkout $DRONE_COMMIT
# - cd documentation/ru
# - mike deploy --prefix gitlab-notification/ru --branch docs-deploy --push --update-aliases develop
#
#image_pull_secrets:
# - DOCKER_AUTH
#
#volumes:
# - name: mkdocs_cache
# host:
# path: /drone/volume/mkdocs_cache/gitlab_notification/ru
#
#---
#kind: pipeline
#type: docker
#name: create-release-docs-site
#
#trigger:
# ref:
# - refs/tags/v.*.*.*
#
#clone:
# disable: true
#
#steps:
#
# - name: build docs
# image: git.struchkov.dev/upagge/mkdocs-material-insiders:latest
# volumes:
# - name: mkdocs_cache
# path: ${DRONE_WORKSPACE}/documentation/ru/.cache
# environment:
# GIT_SSH:
# from_secret: GIT_SSH
# GIT_SSH_COMMAND: "ssh -i ~/.ssh/id_rsa -p 222"
# commands:
# - eval $(ssh-agent -s)
# - mkdir -p ~/.ssh
# - chmod 700 ~/.ssh
# - echo "$GIT_SSH" >> ~/.ssh/id_rsa
# - chmod 600 ~/.ssh/id_rsa
# - ssh-keyscan -p 222 git.struchkov.dev >> ~/.ssh/known_hosts
# - chmod 644 ~/.ssh/known_hosts
# - git config --global user.name "${DRONE_COMMIT_AUTHOR_NAME}"
# - git config --global user.email "${DRONE_COMMIT_AUTHOR_EMAIL}"
# - git clone ssh://git@git.struchkov.dev:222/Telegram-Bots/gitlab-notification.git .
# - git checkout $DRONE_COMMIT
# - cd documentation/ru
# - mike deploy --prefix gitlab-notification/ru --branch docs-deploy --push --update-aliases ${DRONE_TAG}
# - mike deploy --prefix gitlab-notification/ru --branch docs-deploy --push --update-aliases latest
#
#image_pull_secrets:
# - DOCKER_AUTH
#
#volumes:
# - name: mkdocs_cache
# host:
# path: /drone/volume/mkdocs_cache/gitlab_notification
---
kind: signature
hmac: cf1bd0800e8f6bb49dae0a6c5f607676b87d5ee713f4203f4f1ed08a17f71f68
...

View File

@ -6,7 +6,6 @@ import dev.struchkov.openai.context.ChatGptService;
import dev.struchkov.openai.context.GPTClient; import dev.struchkov.openai.context.GPTClient;
import dev.struchkov.openai.data.local.ChatGptLocalStorage; import dev.struchkov.openai.data.local.ChatGptLocalStorage;
import dev.struchkov.openai.domain.conf.GPTConfig; import dev.struchkov.openai.domain.conf.GPTConfig;
import dev.struchkov.openai.domain.model.gpt.GPT3Model;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -17,9 +16,7 @@ public class AppConf {
@Bean @Bean
@ConfigurationProperties("openai") @ConfigurationProperties("openai")
public GPTConfig gptConfig() { public GPTConfig gptConfig() {
final GPTConfig gptConfig = new GPTConfig(); return new GPTConfig();
gptConfig.setAiModel(GPT3Model.GPT_3_5_TURBO);
return gptConfig;
} }
@Bean @Bean
@ -28,9 +25,7 @@ public class AppConf {
} }
@Bean @Bean
public ChatGptService chatGptService( public ChatGptService chatGptService(GPTClient gptClient) {
GPTClient gptClient
) {
return new ChatGptServiceImpl( return new ChatGptServiceImpl(
gptClient, gptClient,
new ChatGptLocalStorage() new ChatGptLocalStorage()

View File

@ -0,0 +1,16 @@
package dev.struchkov.example.bot.conf;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Getter
@Setter
@Component
@ConfigurationProperties("app")
public class AppProperty {
private String telegramId;
}

View File

@ -1,44 +0,0 @@
package dev.struchkov.example.bot.unit;
import dev.struchkov.godfather.main.domain.annotation.Unit;
import dev.struchkov.godfather.main.domain.content.Mail;
import dev.struchkov.godfather.simple.domain.unit.AnswerText;
import dev.struchkov.godfather.telegram.domain.ChatAction;
import dev.struchkov.godfather.telegram.simple.context.service.TelegramService;
import dev.struchkov.godfather.telegram.starter.UnitConfiguration;
import dev.struchkov.openai.context.ChatGptService;
import dev.struchkov.openai.context.GPTClient;
import dev.struchkov.openai.domain.chat.ChatInfo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import static dev.struchkov.example.bot.util.UnitName.GENERAL_MENU;
import static dev.struchkov.godfather.simple.domain.BoxAnswer.boxAnswer;
@Component
@RequiredArgsConstructor
public class ChatGPTUnit implements UnitConfiguration {
private ChatInfo test;
private final TelegramService telegramService;
private final GPTClient gptClient;
private final ChatGptService chatGptService;
@Unit(value = GENERAL_MENU, main = true)
public AnswerText<Mail> chatGpt() {
return AnswerText.<Mail>builder()
.answer(message -> {
if (test == null) {
test = chatGptService.createChat();
}
telegramService.executeAction(message.getPersonId(), ChatAction.TYPING);
final String answerText = chatGptService.sendNewMessage(test.getChatId(), message.getText());
return boxAnswer(answerText);
})
.build();
}
}

View File

@ -0,0 +1,72 @@
package dev.struchkov.example.bot.unit;
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.ChatMail;
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.ChatUnitConfiguration;
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 org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
import static dev.struchkov.godfather.simple.domain.BoxAnswer.boxAnswer;
@Component
public class GroupChatGPTUnit implements ChatUnitConfiguration {
private final GPTClient gptClient;
public GroupChatGPTUnit(
GPTClient gptClient
) {
this.gptClient = gptClient;
}
@Unit(value = UnitName.PROMPT, main = true)
public AnswerText<ChatMail> prompt() {
return AnswerText.<ChatMail>builder()
.triggerCheck(
mail -> {
final List<Attachment> attachments = mail.getAttachments();
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
if (optCommand.isPresent()) {
final CommandAttachment command = optCommand.get();
return Cmd.GPT.equals(command.getCommandType());
}
return false;
}
)
.answer(
mail -> {
final CommandAttachment promptCommand = Attachments.findFirstCommand(mail.getAttachments()).get();
final Optional<String> optPrompt = promptCommand.getArg();
if (optPrompt.isPresent()) {
final String prompt = optPrompt.get();
final GptResponse gptResponse = gptClient.execute(
GptRequest.builder()
.model(GPT3Model.GPT_3_5_TURBO)
.message(GptMessage.fromUser(prompt))
.build()
);
final List<Choice> choices = gptResponse.getChoices();
return boxAnswer(choices.get(choices.size() - 1).getMessage().getContent());
}
return BoxAnswer.builder().build();
}
)
.build();
}
}

View File

@ -0,0 +1,209 @@
package dev.struchkov.example.bot.unit;
import dev.struchkov.example.bot.conf.AppProperty;
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.ChatAction;
import dev.struchkov.godfather.telegram.domain.ClientBotCommand;
import dev.struchkov.godfather.telegram.domain.attachment.CommandAttachment;
import dev.struchkov.godfather.telegram.main.context.MailPayload;
import dev.struchkov.godfather.telegram.main.core.util.Attachments;
import dev.struchkov.godfather.telegram.simple.context.service.TelegramSending;
import dev.struchkov.godfather.telegram.simple.context.service.TelegramService;
import dev.struchkov.godfather.telegram.starter.PersonUnitConfiguration;
import dev.struchkov.haiti.utils.Strings;
import dev.struchkov.openai.context.ChatGptService;
import dev.struchkov.openai.context.GPTClient;
import dev.struchkov.openai.domain.chat.ChatInfo;
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 jakarta.annotation.PostConstruct;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
import static dev.struchkov.example.bot.util.UnitName.CLEAR_CONTEXT;
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.replaceBoxAnswer;
@Component
public class PersonalChatGPTUnit implements PersonUnitConfiguration {
private ChatInfo chatInfo;
private final TelegramSending telegramSending;
private final TelegramService telegramService;
private final AppProperty appProperty;
private final GPTClient gptClient;
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
public void createCommands() {
telegramService.addCommand(List.of(
ClientBotCommand.builder()
.key(Cmd.CLEAR_CONTEXT)
.description("Clears the discussion context. Start a conversation from the beginning")
.build(),
ClientBotCommand.builder()
.key(Cmd.HELP)
.description("help in use")
.build()
));
}
@Unit(value = UnitName.ACCESS_ERROR, main = true)
public AnswerText<Mail> accessError() {
return AnswerText.<Mail>builder()
.triggerCheck(mail -> !mail.getFromPersonId().equals(appProperty.getTelegramId()))
.answer(message -> {
final StringBuilder messageText = new StringBuilder("\uD83D\uDEA8 *Attempted unauthorized access to the bot*")
.append("\n-- -- -- -- --\n");
message.getPayLoad(MailPayload.USERNAME)
.ifPresent(username -> messageText.append("\uD83E\uDDB9\u200D♂: @").append(username));
messageText.append("\n")
.append("\uD83D\uDCAC: ").append(message.getText())
.toString();
return BoxAnswer.builder()
.recipientPersonId(appProperty.getTelegramId())
.message(messageText.toString())
.build();
})
.build();
}
@Unit(value = GPT_UNIT, main = true)
public AnswerText<Mail> chatGpt() {
return AnswerText.<Mail>builder()
.triggerCheck(mail -> mail.getFromPersonId().equals(appProperty.getTelegramId()))
.answer(message -> {
telegramService.executeAction(message.getFromPersonId(), ChatAction.TYPING);
final BoxAnswer answerWait = BoxAnswer.builder()
.recipientPersonId(message.getFromPersonId())
.message("Wait... Response is being generated...\nIt might take a long time ⏳")
.build();
telegramSending.send(answerWait);
final String answerText = chatGptService.sendNewMessage(chatInfo.getChatId(), message.getText());
return replaceBoxAnswer(answerText);
})
.priority(5)
.build();
}
@Unit(value = CLEAR_CONTEXT, main = true)
public AnswerText<Mail> clearContext() {
return AnswerText.<Mail>builder()
.triggerCheck(
mail -> {
if (mail.getFromPersonId().equals(appProperty.getTelegramId())) {
final List<Attachment> attachments = mail.getAttachments();
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
if (optCommand.isPresent()) {
final CommandAttachment command = optCommand.get();
return Cmd.CLEAR_CONTEXT.equals(command.getCommandType());
}
}
return false;
}
)
.answer(message -> {
chatGptService.closeChat(chatInfo.getChatId());
chatInfo = chatGptService.createChat();
return boxAnswer("\uD83E\uDDF9 Discussion context cleared successfully");
})
.build();
}
@Unit(value = UnitName.PROMPT, main = true)
public AnswerText<Mail> prompt() {
return AnswerText.<Mail>builder()
.triggerCheck(
mail -> {
if (mail.getFromPersonId().equals(appProperty.getTelegramId())) {
final List<Attachment> attachments = mail.getAttachments();
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
if (optCommand.isPresent()) {
final CommandAttachment command = optCommand.get();
return Cmd.PROMPT.equals(command.getCommandType());
}
}
return false;
}
)
.answer(
mail -> {
final CommandAttachment promptCommand = Attachments.findFirstCommand(mail.getAttachments()).get();
final Optional<String> optPrompt = promptCommand.getArg();
if (optPrompt.isPresent()) {
final String prompt = optPrompt.get();
final GptResponse gptResponse = gptClient.execute(
GptRequest.builder()
.model(GPT3Model.GPT_3_5_TURBO)
.message(GptMessage.fromUser(prompt))
.build()
);
final List<Choice> choices = gptResponse.getChoices();
return boxAnswer(choices.get(choices.size() - 1).getMessage().getContent());
}
return BoxAnswer.builder().build();
}
)
.build();
}
@Unit(value = UnitName.HELP, main = true)
public AnswerText<Mail> help() {
return AnswerText.<Mail>builder()
.triggerCheck(
mail -> {
if (mail.getFromPersonId().equals(appProperty.getTelegramId())) {
final List<Attachment> attachments = mail.getAttachments();
final Optional<CommandAttachment> optCommand = Attachments.findFirstCommand(attachments);
if (optCommand.isPresent()) {
final CommandAttachment command = optCommand.get();
return Cmd.HELP.equals(command.getCommandType());
}
}
return false;
}
)
.answer(boxAnswer(Strings.escapeMarkdown("""
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:
/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.
""")))
.build();
}
}

View File

@ -0,0 +1,13 @@
package dev.struchkov.example.bot.util;
import lombok.experimental.UtilityClass;
@UtilityClass
public class Cmd {
public static final String CLEAR_CONTEXT = "clear_context";
public static final String PROMPT = "prompt";
public static final String GPT = "gpt";
public static final String HELP = "help";
}

View File

@ -5,6 +5,10 @@ import lombok.experimental.UtilityClass;
@UtilityClass @UtilityClass
public class UnitName { public class UnitName {
public static final String GENERAL_MENU = "GENERAL_MENU"; public static final String GPT_UNIT = "GENERAL_MENU";
public static final String CLEAR_CONTEXT = "CLEAR_CONTEXT";
public static final String HELP = "HELP";
public static final String PROMPT = "PROMPT";
public static final String ACCESS_ERROR = "ACCESS_ERROR";
} }

View File

@ -1,9 +1,9 @@
app:
telegram-id: ${TELEGRAM_ID}
telegram: telegram:
bot: bot:
username: ${TELEGRAM_BOT_USERNAME} username: ${TELEGRAM_BOT_USERNAME}
token: ${TELEGRAM_BOT_TOKEN} token: ${TELEGRAM_BOT_TOKEN}
autoresponder:
threads: ${AUTORESPONDER_THREADS:8}
proxy: proxy:
enable: ${PROXY_ENABLE:false} enable: ${PROXY_ENABLE:false}
host: ${PROXY_HOST:} host: ${PROXY_HOST:}