From 5f3eef77ceef05362842b473ed19b572237e88fb Mon Sep 17 00:00:00 2001 From: alphaBEE <61616007+ankitsmt211@users.noreply.github.com> Date: Tue, 19 Dec 2023 15:45:13 +0530 Subject: [PATCH 1/8] refactor question builder for gpt feature * removing logic that prepends all applied tags to question builder * passing first tag as context to gptservice * setting context before sending the question --- .../tjbot/features/chatgpt/ChatGptCommand.java | 3 ++- .../tjbot/features/chatgpt/ChatGptService.java | 7 ++++--- .../tjbot/features/help/HelpSystemHelper.java | 17 ++--------------- 3 files changed, 8 insertions(+), 19 deletions(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptCommand.java b/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptCommand.java index 2f06384d90..30477ba74e 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptCommand.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptCommand.java @@ -74,8 +74,9 @@ public void onSlashCommand(SlashCommandInteractionEvent event) { public void onModalSubmitted(ModalInteractionEvent event, List args) { event.deferReply().queue(); + String context = ""; Optional optional = - chatGptService.ask(event.getValue(QUESTION_INPUT).getAsString()); + chatGptService.ask(event.getValue(QUESTION_INPUT).getAsString(), context); if (optional.isPresent()) { userIdToAskedAtCache.put(event.getMember().getId(), Instant.now()); } diff --git a/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java b/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java index 24cf088852..a4de7b4228 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java @@ -68,14 +68,15 @@ public ChatGptService(Config config) { * @see ChatGPT * Tokens. */ - public Optional ask(String question) { + public Optional ask(String question, String context) { if (isDisabled) { return Optional.empty(); } try { - ChatMessage chatMessage = - new ChatMessage(ChatMessageRole.USER.value(), Objects.requireNonNull(question)); + String questionWithContext = "context: %s %s".formatted(context, question); + ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), + Objects.requireNonNull(questionWithContext)); ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() .model(AI_MODEL) .messages(List.of(chatMessage)) diff --git a/application/src/main/java/org/togetherjava/tjbot/features/help/HelpSystemHelper.java b/application/src/main/java/org/togetherjava/tjbot/features/help/HelpSystemHelper.java index aa64f10dcc..0f154409bb 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/help/HelpSystemHelper.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/help/HelpSystemHelper.java @@ -125,7 +125,8 @@ RestAction constructChatGptAttempt(ThreadChannel threadChannel, String question = questionOptional.get(); logger.debug("The final question sent to chatGPT: {}", question); - chatGPTAnswer = chatGptService.ask(question); + String context = threadChannel.getAppliedTags().getFirst().getName(); + chatGPTAnswer = chatGptService.ask(question, context); if (chatGPTAnswer.isEmpty()) { return useChatGptFallbackMessage(threadChannel); } @@ -178,20 +179,6 @@ private Optional prepareChatGptQuestion(ThreadChannel threadChannel, .min(MAX_QUESTION_LENGTH - questionBuilder.length(), originalQuestion.length())); questionBuilder.append(originalQuestion); - - StringBuilder tagBuilder = new StringBuilder(); - int stringLength = questionBuilder.length(); - for (ForumTag tag : threadChannel.getAppliedTags()) { - String tagName = tag.getName(); - stringLength += tagName.length(); - if (stringLength > MAX_QUESTION_LENGTH) { - break; - } - tagBuilder.append(String.format("%s ", tagName)); - } - - questionBuilder.insert(0, tagBuilder); - return Optional.of(questionBuilder.toString()); } From 87154a15083625174bd9b18d32918dac5f6478a8 Mon Sep 17 00:00:00 2001 From: alphaBEE <61616007+ankitsmt211@users.noreply.github.com> Date: Tue, 19 Dec 2023 15:54:31 +0530 Subject: [PATCH 2/8] refactoring setup message --- .../togetherjava/tjbot/features/chatgpt/ChatGptService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java b/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java index a4de7b4228..1e161125c8 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java @@ -46,7 +46,8 @@ public ChatGptService(Config config) { """ Please answer questions in 1500 characters or less. Remember to count spaces in the character limit. For code supplied for review, refer to the old code supplied rather than - rewriting the code. Don't supply a corrected version of the code.\s"""); + rewriting the code. Don't supply a corrected version of the code. If response contains any code, + replace parts of it by pseudo code to strictly follow character limit.\s"""); ChatCompletionRequest systemSetupRequest = ChatCompletionRequest.builder() .model(AI_MODEL) .messages(List.of(setupMessage)) From 1cd7c95979ab385440e8551216a0405b2f481729 Mon Sep 17 00:00:00 2001 From: alphaBEE <61616007+ankitsmt211@users.noreply.github.com> Date: Tue, 19 Dec 2023 16:11:57 +0530 Subject: [PATCH 3/8] improving context --- .../togetherjava/tjbot/features/chatgpt/ChatGptService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java b/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java index 1e161125c8..c9c24c55ae 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java @@ -75,7 +75,8 @@ public Optional ask(String question, String context) { } try { - String questionWithContext = "context: %s %s".formatted(context, question); + String questionWithContext = + "context: Category %s on a java q/a server. %s".formatted(context, question); ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), Objects.requireNonNull(questionWithContext)); ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() From 24f9ce716939775cde110b9f7cad8c374a3cd593 Mon Sep 17 00:00:00 2001 From: alphaBEE <61616007+ankitsmt211@users.noreply.github.com> Date: Tue, 19 Dec 2023 16:28:18 +0530 Subject: [PATCH 4/8] refactoring context for more appropriate responses --- .../togetherjava/tjbot/features/chatgpt/ChatGptService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java b/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java index c9c24c55ae..cfb477939b 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java @@ -47,7 +47,7 @@ public ChatGptService(Config config) { Please answer questions in 1500 characters or less. Remember to count spaces in the character limit. For code supplied for review, refer to the old code supplied rather than rewriting the code. Don't supply a corrected version of the code. If response contains any code, - replace parts of it by pseudo code to strictly follow character limit.\s"""); + replace parts of it using pseudo code to strictly follow character limit.\s"""); ChatCompletionRequest systemSetupRequest = ChatCompletionRequest.builder() .model(AI_MODEL) .messages(List.of(setupMessage)) @@ -75,8 +75,8 @@ public Optional ask(String question, String context) { } try { - String questionWithContext = - "context: Category %s on a java q/a server. %s".formatted(context, question); + String questionWithContext = "context: Category %s on a Java Q&A discord server. %s" + .formatted(context, question); ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), Objects.requireNonNull(questionWithContext)); ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() From fc55bb9919185ba029cb2c2c7f19b0614a3c1418 Mon Sep 17 00:00:00 2001 From: alphaBEE <61616007+ankitsmt211@users.noreply.github.com> Date: Tue, 19 Dec 2023 16:49:50 +0530 Subject: [PATCH 5/8] get matching tag or default for context --- .../togetherjava/tjbot/features/help/HelpSystemHelper.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/features/help/HelpSystemHelper.java b/application/src/main/java/org/togetherjava/tjbot/features/help/HelpSystemHelper.java index 0f154409bb..6d91f6ce6c 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/help/HelpSystemHelper.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/help/HelpSystemHelper.java @@ -125,7 +125,10 @@ RestAction constructChatGptAttempt(ThreadChannel threadChannel, String question = questionOptional.get(); logger.debug("The final question sent to chatGPT: {}", question); - String context = threadChannel.getAppliedTags().getFirst().getName(); + ForumTag defaultTag = threadChannel.getAppliedTags().getFirst(); + ForumTag matchingTag = getCategoryTagOfChannel(threadChannel).orElse(defaultTag); + + String context = matchingTag.getName(); chatGPTAnswer = chatGptService.ask(question, context); if (chatGPTAnswer.isEmpty()) { return useChatGptFallbackMessage(threadChannel); From d3e8376995d6a3496a78da0862b47e31e90b8d45 Mon Sep 17 00:00:00 2001 From: alphaBEE <61616007+ankitsmt211@users.noreply.github.com> Date: Wed, 20 Dec 2023 01:57:40 +0530 Subject: [PATCH 6/8] sending instructions along with question, instead of setup --- .../tjbot/features/chatgpt/ChatGptService.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java b/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java index cfb477939b..95dff72b98 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java @@ -42,12 +42,9 @@ public ChatGptService(Config config) { openAiService = new OpenAiService(apiKey, TIMEOUT); - ChatMessage setupMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), - """ - Please answer questions in 1500 characters or less. Remember to count spaces in the - character limit. For code supplied for review, refer to the old code supplied rather than - rewriting the code. Don't supply a corrected version of the code. If response contains any code, - replace parts of it using pseudo code to strictly follow character limit.\s"""); + ChatMessage setupMessage = new ChatMessage(ChatMessageRole.SYSTEM.value(), """ + For code supplied for review, refer to the old code supplied rather than + rewriting the code. DON'T supply a corrected version of the code.\s"""); ChatCompletionRequest systemSetupRequest = ChatCompletionRequest.builder() .model(AI_MODEL) .messages(List.of(setupMessage)) @@ -75,8 +72,9 @@ public Optional ask(String question, String context) { } try { - String questionWithContext = "context: Category %s on a Java Q&A discord server. %s" - .formatted(context, question); + String instructions = "KEEP IT CONCISE, NOT MORE THAN 500 WORDS"; + String questionWithContext = "context: Category %s on a Java Q&A discord server. %s %s" + .formatted(context, instructions, question); ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), Objects.requireNonNull(questionWithContext)); ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() @@ -90,7 +88,7 @@ public Optional ask(String question, String context) { String response = openAiService.createChatCompletion(chatCompletionRequest) .getChoices() - .get(0) + .getFirst() .getMessage() .getContent(); From be500818ee3a9993c90ece3c18035db805b42127 Mon Sep 17 00:00:00 2001 From: alphaBEE <61616007+ankitsmt211@users.noreply.github.com> Date: Tue, 9 Jan 2024 09:50:03 +0530 Subject: [PATCH 7/8] prompt for shorter responses --- .../org/togetherjava/tjbot/features/chatgpt/ChatGptService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java b/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java index 95dff72b98..85213c2d14 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java @@ -72,7 +72,7 @@ public Optional ask(String question, String context) { } try { - String instructions = "KEEP IT CONCISE, NOT MORE THAN 500 WORDS"; + String instructions = "KEEP IT CONCISE, NOT MORE THAN 280 WORDS"; String questionWithContext = "context: Category %s on a Java Q&A discord server. %s %s" .formatted(context, instructions, question); ChatMessage chatMessage = new ChatMessage(ChatMessageRole.USER.value(), From 3f4901b48aad1661353a830794dfdbd37e55b8c5 Mon Sep 17 00:00:00 2001 From: alphaBEE <61616007+ankitsmt211@users.noreply.github.com> Date: Wed, 10 Jan 2024 05:23:03 +0530 Subject: [PATCH 8/8] values responsible for tweaking AI responses are not declared as constants, docs are also added for such values --- .../features/chatgpt/ChatGptService.java | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java b/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java index 85213c2d14..db91b64f64 100644 --- a/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java +++ b/application/src/main/java/org/togetherjava/tjbot/features/chatgpt/ChatGptService.java @@ -21,7 +21,30 @@ public class ChatGptService { private static final Logger logger = LoggerFactory.getLogger(ChatGptService.class); private static final Duration TIMEOUT = Duration.ofSeconds(90); + + /** The maximum number of tokens allowed for the generated answer. */ private static final int MAX_TOKENS = 3_000; + + /** + * This parameter reduces the likelihood of the AI repeating itself. A higher frequency penalty + * makes the model less likely to repeat the same lines verbatim. It helps in generating more + * diverse and varied responses. + */ + private static final double FREQUENCY_PENALTY = 0.5; + + /** + * This parameter controls the randomness of the AI's responses. A higher temperature results in + * more varied, unpredictable, and creative responses. Conversely, a lower temperature makes the + * model's responses more deterministic and conservative. + */ + private static final double TEMPERATURE = 0.8; + + /** + * n: This parameter specifies the number of responses to generate for each prompt. If n is more + * than 1, the AI will generate multiple different responses to the same prompt, each one being + * a separate iteration based on the input. + */ + private static final int MAX_NUMBER_OF_RESPONSES = 1; private static final String AI_MODEL = "gpt-3.5-turbo"; private boolean isDisabled = false; @@ -48,10 +71,10 @@ public ChatGptService(Config config) { ChatCompletionRequest systemSetupRequest = ChatCompletionRequest.builder() .model(AI_MODEL) .messages(List.of(setupMessage)) - .frequencyPenalty(0.5) - .temperature(0.3) + .frequencyPenalty(FREQUENCY_PENALTY) + .temperature(TEMPERATURE) .maxTokens(50) - .n(1) + .n(MAX_NUMBER_OF_RESPONSES) .build(); // Sending the system setup message to ChatGPT. @@ -80,10 +103,10 @@ public Optional ask(String question, String context) { ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder() .model(AI_MODEL) .messages(List.of(chatMessage)) - .frequencyPenalty(0.5) - .temperature(0.3) + .frequencyPenalty(FREQUENCY_PENALTY) + .temperature(TEMPERATURE) .maxTokens(MAX_TOKENS) - .n(1) + .n(MAX_NUMBER_OF_RESPONSES) .build(); String response = openAiService.createChatCompletion(chatCompletionRequest)