Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ public static Collection<Feature> createFeatures(JDA jda, Database database, Con
ModAuditLogWriter modAuditLogWriter = new ModAuditLogWriter(config);
ScamHistoryStore scamHistoryStore = new ScamHistoryStore(database);
GitHubReference githubReference = new GitHubReference(config);
CodeMessageHandler codeMessageHandler =
new CodeMessageHandler(blacklistConfig.special(), jshellEval);
ChatGptService chatGptService = new ChatGptService(config);
CodeMessageHandler codeMessageHandler =
new CodeMessageHandler(blacklistConfig.special(), jshellEval, chatGptService);
HelpSystemHelper helpSystemHelper = new HelpSystemHelper(config, database, chatGptService);

// NOTE The system can add special system relevant commands also by itself,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public class ChatGptService {
* a separate iteration based on the input.
*/
private static final int MAX_NUMBER_OF_RESPONSES = 1;
private static final int MAX_CODE_LENGTH = 2000;
private static final String AI_MODEL = "gpt-3.5-turbo";

private boolean isDisabled = false;
Expand Down Expand Up @@ -96,12 +97,51 @@ public Optional<String> ask(String question, String context) {
return Optional.empty();
}

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

return getMessageResponse(questionWithContext);
}

/**
* Provide ChatGPT with code to format.
*
* @param code the code to be formatted by ChatGPT. If code exceeds {@value MAX_CODE_LENGTH}
* characters then this method returns an empty {@link Optional}
* @return an optional response from ChatGPT as a String
*/
public Optional<String> formatCode(CharSequence code) {
if (isDisabled || code.length() > MAX_CODE_LENGTH) {
return Optional.empty();
}

String payload = String.format(
"""
If you happen to find any code in the container below, FORMAT \
IT regardless of the programming language you find. MAKE IT HUMANLY READABLE. \
Output with no introduction, no explanation, no ``` stuff, only code. Double \
check that your response is correct. The code provided might not be readable.

--- BEGIN CODE ---
%s
--- END CODE ---
""",
code);

return getMessageResponse(payload);
}

/**
* Prompt ChatGPT with a message and get its response.
*
* @param message the message to send to ChatGPT
* @return an optional response from ChatGPT as a String
*/
private Optional<String> getMessageResponse(String message) {
try {
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(),
Objects.requireNonNull(questionWithContext));
ChatMessage chatMessage =
new ChatMessage(ChatMessageRole.USER.value(), Objects.requireNonNull(message));
ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
.model(AI_MODEL)
.messages(List.of(chatMessage))
Expand Down Expand Up @@ -131,6 +171,7 @@ public Optional<String> ask(String question, String context) {
logger.warn("There was an error using the OpenAI API: {}",
runtimeException.getMessage());
}

return Optional.empty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.togetherjava.tjbot.features.code;

import org.togetherjava.tjbot.features.chatgpt.ChatGptService;

import java.util.Optional;

/**
* A utility class for formatting code using ChatGPT.
*/
public final class ChatGPTFormatter {
private final ChatGptService chatGptService;

/**
* Constructs a new {@link ChatGPTFormatter} with the provided {@link ChatGptService}.
*
* @param chatGptService the {@link ChatGptService} used for formatting code
*/
public ChatGPTFormatter(ChatGptService chatGptService) {
this.chatGptService = chatGptService;
}

/**
* Formats the provided code using ChatGPT.
*
* @param code the code to be formatted
* @return an Optional containing the formatted code if successful, empty otherwise
*/
public Optional<String> format(CharSequence code) {
return chatGptService.formatCode(code);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.togetherjava.tjbot.features.MessageReceiverAdapter;
import org.togetherjava.tjbot.features.UserInteractionType;
import org.togetherjava.tjbot.features.UserInteractor;
import org.togetherjava.tjbot.features.chatgpt.ChatGptService;
import org.togetherjava.tjbot.features.componentids.ComponentIdGenerator;
import org.togetherjava.tjbot.features.componentids.ComponentIdInteractor;
import org.togetherjava.tjbot.features.jshell.JShellEval;
Expand Down Expand Up @@ -68,11 +69,14 @@ public final class CodeMessageHandler extends MessageReceiverAdapter implements
* disabled
* @param jshellEval used to execute java code and build visual result
*/
public CodeMessageHandler(FeatureBlacklist<String> blacklist, JShellEval jshellEval) {
public CodeMessageHandler(FeatureBlacklist<String> blacklist, JShellEval jshellEval,
ChatGptService chatGptService) {
componentIdInteractor = new ComponentIdInteractor(getInteractionType(), getName());

List<CodeAction> codeActions = blacklist
.filterStream(Stream.of(new FormatCodeCommand(), new EvalCodeCommand(jshellEval)),
.filterStream(
Stream.of(new FormatCodeCommand(chatGptService),
new EvalCodeCommand(jshellEval)),
codeAction -> codeAction.getClass().getName())
.toList();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.MessageEmbed;

import org.togetherjava.tjbot.features.chatgpt.ChatGptService;
import org.togetherjava.tjbot.features.utils.CodeFence;
import org.togetherjava.tjbot.formatter.Formatter;

Expand All @@ -13,6 +14,16 @@
*/
final class FormatCodeCommand implements CodeAction {
private final Formatter formatter = new Formatter();
private final ChatGPTFormatter chatGPTFormatter;

/**
* Initializes a {@link FormatCodeCommand} which formats code.
*
* @param service the {@link ChatGptService} instance to be used for code formatting
*/
public FormatCodeCommand(ChatGptService service) {
this.chatGPTFormatter = new ChatGPTFormatter(service);
}

@Override
public String getLabel() {
Expand All @@ -33,7 +44,13 @@ public MessageEmbed apply(CodeFence codeFence) {
.build();
}

/**
* Formats the provided code using either the ChatGPT formatter or the generic formatter.
*
* @param code the code to be formatted
* @return the formatted code
*/
private String formatCode(CharSequence code) {
return formatter.format(code);
return chatGPTFormatter.format(code).orElse(formatter.format(code));
}
}