-
-
Notifications
You must be signed in to change notification settings - Fork 87
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* * Refactor folder name * Add ChatGPT command/service code and utils. * * Fix Features.java import statements and add ChatGPTService being passed in to helper. * Add parsing of question to helper. * * Add AI Help message to when user asks question. (Either direction to the command if the service fails or an explanation that the next response is AI generated) * * Add test files and test suite for AIResponseParser.java * Add logger.debug() to catch responses before being parsed in case of failing to parse correctly to generate new tests [AIResponseParser.java]. * * Refactor how AIResponseParserTest parameterizes file names (ints instead of full file names). * Remove ChatGPTServiceTest.java as it was an older way to generate long responses from ChatGPT for testing. * Add another test file and include in parameters for AIResponseParserTest.java
- Loading branch information
1 parent
03b1112
commit ae006d2
Showing
12 changed files
with
566 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 82 additions & 0 deletions
82
application/src/main/java/org/togetherjava/tjbot/features/chatgpt/AIResponseParser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package org.togetherjava.tjbot.features.chatgpt; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
/** | ||
* Represents a class to partition long text blocks into smaller blocks which work with Discord's | ||
* API. Initially constructed to partition text from AI text generation APIs. | ||
*/ | ||
public class AIResponseParser { | ||
private AIResponseParser() { | ||
throw new UnsupportedOperationException("Utility class, construction not supported"); | ||
} | ||
|
||
private static final Logger logger = LoggerFactory.getLogger(AIResponseParser.class); | ||
private static final int RESPONSE_LENGTH_LIMIT = 2_000; | ||
|
||
/** | ||
* Parses the response generated by AI. If response is longer than | ||
* {@value RESPONSE_LENGTH_LIMIT}, then breaks apart the response into suitable lengths for | ||
* Discords API. | ||
* | ||
* @param response The response from the AI which we want to send over Discord. | ||
* @return An array potentially holding the original response split up into shorter than | ||
* {@value RESPONSE_LENGTH_LIMIT} length pieces. | ||
*/ | ||
public static String[] parse(String response) { | ||
String[] partedResponse = new String[] {response}; | ||
if (response.length() > RESPONSE_LENGTH_LIMIT) { | ||
logger.debug("Response to parse:\n{}", response); | ||
partedResponse = partitionAiResponse(response); | ||
} | ||
|
||
return partedResponse; | ||
} | ||
|
||
private static String[] partitionAiResponse(String response) { | ||
List<String> responseChunks = new ArrayList<>(); | ||
String[] splitResponseOnMarks = response.split("```"); | ||
|
||
for (int i = 0; i < splitResponseOnMarks.length; i++) { | ||
String split = splitResponseOnMarks[i]; | ||
List<String> chunks = new ArrayList<>(); | ||
chunks.add(split); | ||
|
||
// Check each chunk for correct length. If over the length, split in two and check | ||
// again. | ||
while (!chunks.stream().allMatch(s -> s.length() < RESPONSE_LENGTH_LIMIT)) { | ||
for (int j = 0; j < chunks.size(); j++) { | ||
String chunk = chunks.get(j); | ||
if (chunk.length() > RESPONSE_LENGTH_LIMIT) { | ||
int midpointNewline = chunk.lastIndexOf("\n", chunk.length() / 2); | ||
chunks.set(j, chunk.substring(0, midpointNewline)); | ||
chunks.add(j + 1, chunk.substring(midpointNewline)); | ||
} | ||
} | ||
} | ||
|
||
// Given the splitting on ```, the odd numbered entries need to have code marks | ||
// restored. | ||
if (i % 2 != 0) { | ||
// We assume that everything after the ``` on the same line is the language | ||
// declaration. Could be empty. | ||
String lang = split.substring(0, split.indexOf(System.lineSeparator())); | ||
chunks = chunks.stream() | ||
.map(s -> ("```" + lang).concat(s).concat("```")) | ||
// Handle case of doubling language declaration | ||
.map(s -> s.replaceFirst("```" + lang + lang, "```" + lang)) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
List<String> list = chunks.stream().filter(string -> !string.equals("")).toList(); | ||
responseChunks.addAll(list); | ||
} // end of for loop. | ||
|
||
return responseChunks.toArray(new String[0]); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.