From 2ba8efa48ebbe7469a172498b0f9c907530f9053 Mon Sep 17 00:00:00 2001 From: pwgit-create Date: Mon, 17 Jun 2024 20:05:58 +0200 Subject: [PATCH 01/18] 1st itteration in super app feature --- .../main/java/pn/cg/app_system/AppSystem.java | 38 ++++++++++ .../code_generation/model/SuperApp.java | 27 +++++++ .../java/pn/cg/app_wish/QuestionBuilder.java | 2 +- .../constant/QuestionConstants.java | 38 ++++++++-- .../ollama_ai_remote/OllamaRemoteSystem.java | 15 +++- .../request/RequestHandler.java | 7 ++ .../request/RequestHandlerImpl.java | 75 +++++++++++++++---- .../src/main/java/pn/cg/util/StringUtil.java | 36 +++++++-- .../test/java/pn/cg/util/StringUtilTest.java | 18 +++-- 9 files changed, 218 insertions(+), 38 deletions(-) create mode 100644 cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/model/SuperApp.java diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/AppSystem.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/AppSystem.java index 48a481b..77069bd 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/AppSystem.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/AppSystem.java @@ -3,6 +3,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import pn.cg.app_system.code_generation.model.SuperApp; import pn.cg.ollama_ai_remote.OllamaRemoteSystem; import java.util.List; @@ -84,6 +85,43 @@ public static void StartCodeGenerator(String continueWithImprovementText, String StartCodeGenerator(continueWithImprovementText, true, false, false, javaClassName, javaFileContentInLines); } + /** + * Starts an app generation with the strategy to ask for each class that is needed and then compile each class in a new request until it compiles + * @param superAppWish The App Wish from the user + * @param isFirstRun Flag that shows if this is the first request attempt to ollama + * @param appWishCompileResult The method will call itself recursively unless this is true + * @param superApp The data holder for the current super app generation + */ + public static void StartSuperAppGeneration(String superAppWish, boolean isFirstRun, boolean appWishCompileResult, SuperApp superApp){ + OllamaRemoteSystem ollamaRemoteSystem = new OllamaRemoteSystem(); + + + + if (isFirstRun) { + log.info("Started the AppSystem"); + retryCounter = 1; + + // appWishCompileResult = ollamaRemoteSystem.CreateApp(appWish, true, "", null); + } + + + if (appWishCompileResult) { + + log.info("App System has compiled your app successfully"); + } + + if (!appWishCompileResult) { + + retryCounter++; + log.debug("In CheckCompilationRetryCounter with counter -> {}", retryCounter); + + + //appWishCompileResult = ollamaRemoteSystem.CreateApp(appWish, false, "", null); + StartSuperAppGeneration(superAppWish,isFirstRun,appWishCompileResult,superApp); + } + + } + } diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/model/SuperApp.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/model/SuperApp.java new file mode 100644 index 0000000..6bfaa69 --- /dev/null +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/model/SuperApp.java @@ -0,0 +1,27 @@ +package pn.cg.app_system.code_generation.model; + +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.LinkedList; +import java.util.List; + +/** + * This class serves as a data holder for the classes needed for an application and their implementation status*/ +public class SuperApp +{ + // The first parameter is the class name in text and the second parameter is for its implementation status + private final Dictionary classesNeededForApplicationDict; + + + public SuperApp() { + this.classesNeededForApplicationDict = new Hashtable(); + + } + + + + public void AddSuccessfulImplementationToClass(String nameOfClass){ + this.classesNeededForApplicationDict.put(nameOfClass,true); + + } +} diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_wish/QuestionBuilder.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_wish/QuestionBuilder.java index edb936c..0901c08 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_wish/QuestionBuilder.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_wish/QuestionBuilder.java @@ -54,7 +54,7 @@ public String createCompileErrorQuestion(String compileErrorMessage) { */ public String createClassesNeededForAppWishQuestion() { - return QuestionConstants.WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX + appWish + QuestionConstants.WHICH_CLASS_ARE_NEEDED_FOR_APP_SUFFIX; + return QuestionConstants.WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX + appWish + QuestionConstants.WHICH_CLASS_ARE_NEEDED_FOR_APP_RESPONSE_FORMAT_1; } diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/QuestionConstants.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/QuestionConstants.java index f8cc747..1a71996 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/QuestionConstants.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/QuestionConstants.java @@ -35,20 +35,44 @@ public record QuestionConstants() { /** * Prefix that should be sent to fetch a list of classes from the ollama model * - * @use-info The app wish should be concatenated at the tail of this String + * @use-info The (super) appWish should be concatenated at the tail of this String + * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX + * @chain-order 1/5 + * @SuperApp-Question + */ + public final static String WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX = "Which classes do we need to implement ourself in java to make an application with the features that is provided in the next coming lines?"; + + /** + * @use-info This is the string that will tell the AI-Model that the line above is the last line of the (super) appWish * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX - * @chain-order 1/2 + * @chain-order 2/5 + * @SuperApp-Question */ - public final static String WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX = "Which classes are needed for java code on "; + public final static String LAST_LINE_OF_SUPER_APP="The line above was the last line that included features of the app I need"; /** - * Suffix for WHICH_CLASS_ARE_NEEDED_FOR_APP * - * @use-info This String should be concatenated at the tail of the appWish (Instance variable in QuestionBuilder) + * @use-info Text that specifies the format of the response from the AI-model + * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX + * @chain-order 3/5 + */ + public final static String WHICH_CLASS_ARE_NEEDED_FOR_APP_RESPONSE_FORMAT_1 = "Please provide the name of the first java class and then make a new line for the second java class and then continue until you have listed all the class names of the application I need"; + + + /** + * @use-info Additional guidelines regarding format in the response from the AI-model + * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX + * @chain-order 4/5 + */ + public final static String ONLY_CLASS_NAMES_IN_ANSWER="Your response should only contain the needed classes name for the application and there should be one class name per line, your reply must not contain anything else"; + + /** + * @use-info Clarify that no numbers or dots should be included in the response from the AI-model * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX - * @chain-order 2/2 + * @chain-order 5/5 */ - public final static String WHICH_CLASS_ARE_NEEDED_FOR_APP_SUFFIX = "=? please provide me the java classes in a numbered list "; + public final static String CLARIFY_THAT_NO_DOTS_OR_NUMBERS_SHOULD_BE_INCLUDED_IN_THE_RESPONSE="Your respone should not contain number and dots to state the order of the classes, there should only be one class name per line and nothing else"; + /** * Optional Suffix to APP_WISH diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/OllamaRemoteSystem.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/OllamaRemoteSystem.java index a4dd590..6600e4b 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/OllamaRemoteSystem.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/OllamaRemoteSystem.java @@ -4,6 +4,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import pn.cg.app_system.code_generation.ClassCompiler; +import pn.cg.app_system.code_generation.model.SuperApp; import pn.cg.app_wish.QuestionBuilder; import pn.cg.datastorage.DataStorage; import pn.cg.datastorage.constant.QuestionConstants; @@ -76,15 +77,14 @@ public synchronized boolean CreateApp(String appWish, boolean firstRun, String i if (firstRun) { if(isCreateNewApp) outputFromOLLMA = requestHandler.sendQuestionToOllamaInstance(questionBuilder.createFeatureQuestion()); - else - outputFromOLLMA = requestHandler.sendQuestionToOllamaInstance(appWish,ifJavaAppShouldBeModifiedPath, + else outputFromOLLMA = requestHandler.sendQuestionToOllamaInstance(appWish,ifJavaAppShouldBeModifiedPath, contentOfJavaFileIfModifyRequest); } // Extract class name String className = StringUtil.extractClassNameFromTextWithJavaClasses(outputFromOLLMA); - log.debug("className -> " + className); + log.debug("className -> {}", className); if (className.equalsIgnoreCase(ERROR)) { //log.debug("Empty class name"); } else { @@ -126,6 +126,15 @@ public synchronized boolean CreateApp(String appWish, boolean firstRun, String i return DataStorage.getInstance().getCompilationJob().isResult(); } + public synchronized boolean CreateSuperApp(String superAppWish, boolean firstRun, String ifJavaAppShouldBeModifiedPath, List contentOfJavaFileIfModifyRequest) { + + SuperApp superApp = new SuperApp(); + + + return true; + } + + private String checkAndFixUnclosedBraceBuckets(String input) { diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandler.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandler.java index 6505712..2db3869 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandler.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandler.java @@ -26,4 +26,11 @@ public interface RequestHandler { */ String sendQuestionToOllamaInstance(String question,String pathToJavaFileToModify,List contentOfExistingJavaFile); + /** + * + * @param question Question that contains text that describes requirements and functionality of a new super app + * @return String + */ + String sendSuperAppQuestionToOllamaInstance(String question); + } diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandlerImpl.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandlerImpl.java index 12059a8..a82f4e7 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandlerImpl.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandlerImpl.java @@ -13,8 +13,10 @@ import io.github.amithkoujalgi.ollama4j.core.utils.Options; import io.github.amithkoujalgi.ollama4j.core.utils.OptionsBuilder; import io.github.amithkoujalgi.ollama4j.core.utils.PromptBuilder; +import pn.cg.util.StringUtil; import java.io.IOException; +import java.util.LinkedList; import java.util.List; import static pn.cg.util.CodeGeneratorUtil.isThisACreateNewAppRequest; @@ -22,13 +24,27 @@ public class RequestHandlerImpl implements RequestHandler { + private static final Logger log = LoggerFactory.getLogger(RequestHandlerImpl.class); + private final String HOST = "http://localhost:11434/"; + private final OllamaAPI api; + private final Options options; + private final CodeGeneratorConfig codeGeneratorConfig; - private static final Logger log = LoggerFactory.getLogger(RequestHandlerImpl.class); - public RequestHandlerImpl() { + this.api = new OllamaAPI(HOST); + this.codeGeneratorConfig = new CodeGeneratorConfig(); + this.options = new OptionsBuilder() + .setNumCtx(codeGeneratorConfig.getNUM_CTX()) + .setTopK(codeGeneratorConfig.getTOP_K()) + .setNumPredict(codeGeneratorConfig.getNUM_PREDICT()) + .setTemperature(codeGeneratorConfig.getTEMPERATURE()) + .build(); + + api.setRequestTimeoutSeconds(100000); + log.info("Is OLLAMA server alive? -> {}", api.ping()); // This is your local OLLAMA server running on localhost and is used for the LLM model } @Override @@ -40,18 +56,10 @@ public String sendQuestionToOllamaInstance(String question) { @Override public String sendQuestionToOllamaInstance(String question, String pathToJavaFileToModify, List contentOfExistingJavaFile) { - OllamaAPI api = new OllamaAPI(HOST); + boolean isThisNewAppRequest = isThisACreateNewAppRequest(pathToJavaFileToModify, contentOfExistingJavaFile); - CodeGeneratorConfig codeGeneratorConfig = new CodeGeneratorConfig(); - Options options = - new OptionsBuilder() - .setNumCtx(codeGeneratorConfig.getNUM_CTX()) - .setTopK(codeGeneratorConfig.getTOP_K()) - .setNumPredict(codeGeneratorConfig.getNUM_PREDICT()) - .setTemperature(codeGeneratorConfig.getTEMPERATURE()) - .build(); PromptBuilder promptBuilder; @@ -100,8 +108,7 @@ public String sendQuestionToOllamaInstance(String question, String pathToJavaFil .addLine(QuestionConstants.ONLY_CODE); } - api.setRequestTimeoutSeconds(100000); - log.info("Is OLLAMA server alive? -> {}", api.ping()); // This is your local OLLAMA server running on localhost and is used for the LLM model + OllamaResult result = null; try { @@ -116,6 +123,48 @@ public String sendQuestionToOllamaInstance(String question, String pathToJavaFil return outputFromOllamaAPI; } + @Override + public String sendSuperAppQuestionToOllamaInstance(String question) { + + + List classNames = GetListOfClasses(question); + + if(classNames.isEmpty()) + sendSuperAppQuestionToOllamaInstance(question); + + + + + return ""; + } + + private List GetListOfClasses(String question){ + + List classNames = new LinkedList<>(); + + + PromptBuilder initialPrompt = new PromptBuilder().addLine(QuestionConstants.WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX) + .addLine(question) + .addLine(QuestionConstants.LAST_LINE_OF_SUPER_APP) + .addLine(QuestionConstants.WHICH_CLASS_ARE_NEEDED_FOR_APP_RESPONSE_FORMAT_1) + .addLine(QuestionConstants.ONLY_CLASS_NAMES_IN_ANSWER) + .addLine(QuestionConstants.CLARIFY_THAT_NO_DOTS_OR_NUMBERS_SHOULD_BE_INCLUDED_IN_THE_RESPONSE); + + + OllamaResult result = null; + try { + result = api.generate(codeGeneratorConfig.getOllamaModel(), initialPrompt.build(), options); + + classNames = StringUtil.GetListOfClassNamesInSuperAppGeneration(result.getResponse()); + + } catch (OllamaBaseException | IOException | InterruptedException e) { + log.error("Error when sending the request to the local ollama server"); + } + + return classNames; + + } + } diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/StringUtil.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/StringUtil.java index b926fb1..4e78fde 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/StringUtil.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/StringUtil.java @@ -5,6 +5,10 @@ import org.slf4j.LoggerFactory; import pn.cg.datastorage.constant.CommonStringConstants; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + public class StringUtil { @@ -76,6 +80,7 @@ public static String getFirstLine(String input) { /** * Removes chars that might cause ollama´s api to send 400 + * * @param input input String * @return String */ @@ -175,7 +180,7 @@ public static int GetUnbalancedBraceBracketsFromString(String input) { /** * Appends brace buckets at the end of the String * - * @param input String Input + * @param input String Input * @param numberOfBraceBuckets int * @return input string appended with the given amount of brace buckets */ @@ -205,19 +210,38 @@ public static String RemoveCommonAdditionStringsFromAiModels(String input) { try { returnValue = returnValue.replace("```java", "") .replace("```", "") - .replace("```Java","") - .replace("```JAVA",""); + .replace("```Java", "") + .replace("```JAVA", ""); } catch (Exception e) { - log.debug("Could not remove common addition string"); + log.error("Could not remove common addition string"); } return returnValue; } + /** + * Takes an input string formated with new lines and converts it into a list + * + * @param input A string with class names delimited with new lines + * @return List + */ + public static List GetListOfClassNamesInSuperAppGeneration(String input) { + try { + + String[] classNamesArr = input.split("\n"); + + return new LinkedList<>(Arrays.asList(classNamesArr)); + } catch (Exception e) { + + log.error("Could not extract class names from the response from the AI-model"); + } + return new LinkedList<>(); + } + /** * Replace all occurrences (with an empty String) except the first one of the delimiter word * - * @param input input String + * @param input input String * @param delimiter delimiter String */ private static String RemoveAllExceptTheFirstOccurrenceOfaAWord(String input, String delimiter) { @@ -232,7 +256,7 @@ private static String RemoveAllExceptTheFirstOccurrenceOfaAWord(String input, St /** * Replace all occurrences (with an empty String) except the last one of the delimiter word * - * @param input input String + * @param input input String * @param delimiter String */ private static String RemoveAllExceptTheLastOccurrenceOfWord(String input, String delimiter) { diff --git a/cg/CodeGenerator/CodeGenerator/src/test/java/pn/cg/util/StringUtilTest.java b/cg/CodeGenerator/CodeGenerator/src/test/java/pn/cg/util/StringUtilTest.java index 12cda5b..5b936a6 100644 --- a/cg/CodeGenerator/CodeGenerator/src/test/java/pn/cg/util/StringUtilTest.java +++ b/cg/CodeGenerator/CodeGenerator/src/test/java/pn/cg/util/StringUtilTest.java @@ -274,9 +274,7 @@ public void RemoveExtraStartDelimitersInResponseTest() { public void removeExtraEndDelimitersInResponseTest() { final String TEST_TEXT = "@START_HERE javacode1.. more java code2... @END_HERE more javacode3.... @END_HERE"; - final String expected = "@START_HERE javacode1.. more java code2... more javacode3.... @END_HERE"; - final String actual = StringUtil.RemoveExtraEndDelimitersInResponse(TEST_TEXT); Assertions.assertEquals(expected, actual); @@ -288,9 +286,7 @@ public void removeExtraEndDelimitersInResponseTest() { public void getUnbalancedBraceBracketsFromStringTest() { final int expected = 1; - final String text = "public class PN{ Public static void main(String[] args) {} for(int i=0;i++;i<10){ }"; - final int actual = StringUtil.GetUnbalancedBraceBracketsFromString(text); Assertions.assertEquals(expected, actual); @@ -301,9 +297,7 @@ public void RemoveCommonAdditionStringsFromAiModelsTest() { final String text = "```java\npublic class PN{ Public static void main(String[] args) {} for(int i=0;i++;i<10){ }}\n```"; - final String expected = "\npublic class PN{ Public static void main(String[] args) {} for(int i=0;i++;i<10){ }}\n"; - final String actual = StringUtil.RemoveCommonAdditionStringsFromAiModels(text); Assertions.assertEquals(expected, actual); @@ -314,12 +308,20 @@ public void AppendWithCorrectNumberOfBraceBucketsAtEndOfTheString() { final String text = "public class PN{ Public static void main(String[] args) {} for(int i=0;i++;i<10){ }"; - final String expected = "public class PN{ Public static void main(String[] args) {} for(int i=0;i++;i<10){ }}"; - final String actual = StringUtil.AppendBraceBucketsAtEndofTheString(text, StringUtil.GetUnbalancedBraceBracketsFromString(text)); Assertions.assertEquals(expected, actual); } + @Test + public void ConvertStringWithClassNamesIntoAListTest(){ + + final String text ="Jframe\nAccount\nMain"; + final int expected=3; + final int actual = StringUtil.GetListOfClassNamesInSuperAppGeneration(text).size(); + + Assertions.assertEquals(expected,actual); + } + } \ No newline at end of file From c5a41527369504fdd49017100782bebf1fe1776a Mon Sep 17 00:00:00 2001 From: pwgit-create Date: Wed, 19 Jun 2024 15:07:57 +0200 Subject: [PATCH 02/18] Itteration 2 - SuperApp Creation --- .../main/java/pn/cg/app_system/AppSystem.java | 61 ++++++++-- .../code_generation/model/SuperApp.java | 22 ++-- .../java/pn/cg/datastorage/DataStorage.java | 14 +++ .../constant/QuestionConstants.java | 107 +++++++++++------- .../ollama_ai_remote/OllamaRemoteSystem.java | 7 +- .../request/RequestHandler.java | 6 +- .../request/RequestHandlerImpl.java | 12 +- .../java/pn/cg/util/CodeGeneratorUtil.java | 45 +++++++- 8 files changed, 195 insertions(+), 79 deletions(-) diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/AppSystem.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/AppSystem.java index 77069bd..491960e 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/AppSystem.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/AppSystem.java @@ -4,9 +4,12 @@ import org.slf4j.LoggerFactory; import pn.cg.app_system.code_generation.model.SuperApp; +import pn.cg.datastorage.DataStorage; import pn.cg.ollama_ai_remote.OllamaRemoteSystem; +import pn.cg.util.CodeGeneratorUtil; import java.util.List; +import java.util.NoSuchElementException; import static pn.cg.util.CodeGeneratorUtil.isThisACreateNewAppRequest; @@ -90,34 +93,68 @@ public static void StartCodeGenerator(String continueWithImprovementText, String * @param superAppWish The App Wish from the user * @param isFirstRun Flag that shows if this is the first request attempt to ollama * @param appWishCompileResult The method will call itself recursively unless this is true - * @param superApp The data holder for the current super app generation + * @param classList The data holder for the current super app generation implementation status + * @param superAppCreationComplete A flag that shows if the entire super app creation is complete or not */ - public static void StartSuperAppGeneration(String superAppWish, boolean isFirstRun, boolean appWishCompileResult, SuperApp superApp){ + public static void StartSuperAppGeneration(String superAppWish, boolean isFirstRun, boolean appWishCompileResult, List classList, + boolean superAppCreationComplete){ OllamaRemoteSystem ollamaRemoteSystem = new OllamaRemoteSystem(); - - + // Get Class names for the super app generation if (isFirstRun) { - log.info("Started the AppSystem"); + log.info("Started the Super AppSystem (Long-time code base generation"); retryCounter = 1; + classList = ollamaRemoteSystem.GetClassListForSuperAppCreation(superAppWish); + superAppCreationComplete = false; + isFirstRun = false; - // appWishCompileResult = ollamaRemoteSystem.CreateApp(appWish, true, "", null); - } + // Generate the first class in the super app class list + SuperApp selectedClassToCreate = CodeGeneratorUtil.getARandomUnimplementedClass(classList); + DataStorage.getInstance().setCurrentSuperClass(selectedClassToCreate); + } - if (appWishCompileResult) { - log.info("App System has compiled your app successfully"); + + + // Generate each class in the super app class list + + // Invoke call to generate the selected class + + + // Continue with next class if any unimplemented classes remain, else end the super app creation successfully + if (appWishCompileResult && !superAppCreationComplete) { + + log.info("Class Generated\nContinue..."); + + try { + // Select the next class to create (from the SuperApp list) + SuperApp selectedClassToCreate = CodeGeneratorUtil.getARandomUnimplementedClass(classList); + + DataStorage.getInstance().setCurrentSuperClass(selectedClassToCreate); + + } + // Success + catch (NoSuchElementException noSuchElementException){ + + log.info("No more classes to implement in super app creation"); + + // Validate + if(CodeGeneratorUtil.areAllSuperClassesImplemented(classList)) + superAppCreationComplete = true; + } + StartSuperAppGeneration(superAppWish,false,false,classList,false); } - if (!appWishCompileResult) { + // Retry compilation for a selected class + if (!appWishCompileResult && !superAppCreationComplete) { retryCounter++; - log.debug("In CheckCompilationRetryCounter with counter -> {}", retryCounter); + // Make a call to //appWishCompileResult = ollamaRemoteSystem.CreateApp(appWish, false, "", null); - StartSuperAppGeneration(superAppWish,isFirstRun,appWishCompileResult,superApp); + //StartSuperAppGeneration(superAppWish,isFirstRun,appWishCompileResult,superApp); } } diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/model/SuperApp.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/model/SuperApp.java index 6bfaa69..d89f0d1 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/model/SuperApp.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/code_generation/model/SuperApp.java @@ -9,19 +9,23 @@ * This class serves as a data holder for the classes needed for an application and their implementation status*/ public class SuperApp { - // The first parameter is the class name in text and the second parameter is for its implementation status - private final Dictionary classesNeededForApplicationDict; - - - public SuperApp() { - this.classesNeededForApplicationDict = new Hashtable(); + private final String className; + private boolean isImplemented; + public SuperApp(String className, boolean isImplemented) { + this.className = className; + this.isImplemented = isImplemented; } + public String getClassName() { + return className; + } + public boolean isImplemented() { + return isImplemented; + } - public void AddSuccessfulImplementationToClass(String nameOfClass){ - this.classesNeededForApplicationDict.put(nameOfClass,true); - + public void setImplemented(boolean implemented) { + isImplemented = implemented; } } diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/DataStorage.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/DataStorage.java index 0face7c..c6c33a9 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/DataStorage.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/DataStorage.java @@ -1,6 +1,7 @@ package pn.cg.datastorage; import pn.cg.app_system.code_generation.model.CompilationJob; +import pn.cg.app_system.code_generation.model.SuperApp; public class DataStorage { @@ -13,6 +14,11 @@ public class DataStorage { private String javaExecutionPath; + /** + * The class that is selected for implementation tries in a super app creation proccess + */ + private volatile SuperApp currentSuperClass; + private static DataStorage instance; private DataStorage() { @@ -45,6 +51,14 @@ public String getJavaExecutionPath() { public void setJavaExecutionPath(String javaExecutionPath) { this.javaExecutionPath = javaExecutionPath; } + + public SuperApp getCurrentSuperClass() { + return currentSuperClass; + } + + public void setCurrentSuperClass(SuperApp currentSuperClass) { + this.currentSuperClass = currentSuperClass; + } } diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/QuestionConstants.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/QuestionConstants.java index 1a71996..0df1d7f 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/QuestionConstants.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/QuestionConstants.java @@ -32,47 +32,6 @@ public record QuestionConstants() { public final static String CLASS_DID_NOT_COMPILE_PREFIX_2 = "The java code you’ve sent me did not compile "; - /** - * Prefix that should be sent to fetch a list of classes from the ollama model - * - * @use-info The (super) appWish should be concatenated at the tail of this String - * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX - * @chain-order 1/5 - * @SuperApp-Question - */ - public final static String WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX = "Which classes do we need to implement ourself in java to make an application with the features that is provided in the next coming lines?"; - - /** - * @use-info This is the string that will tell the AI-Model that the line above is the last line of the (super) appWish - * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX - * @chain-order 2/5 - * @SuperApp-Question - */ - public final static String LAST_LINE_OF_SUPER_APP="The line above was the last line that included features of the app I need"; - - /** - * - * @use-info Text that specifies the format of the response from the AI-model - * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX - * @chain-order 3/5 - */ - public final static String WHICH_CLASS_ARE_NEEDED_FOR_APP_RESPONSE_FORMAT_1 = "Please provide the name of the first java class and then make a new line for the second java class and then continue until you have listed all the class names of the application I need"; - - - /** - * @use-info Additional guidelines regarding format in the response from the AI-model - * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX - * @chain-order 4/5 - */ - public final static String ONLY_CLASS_NAMES_IN_ANSWER="Your response should only contain the needed classes name for the application and there should be one class name per line, your reply must not contain anything else"; - - /** - * @use-info Clarify that no numbers or dots should be included in the response from the AI-model - * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX - * @chain-order 5/5 - */ - public final static String CLARIFY_THAT_NO_DOTS_OR_NUMBERS_SHOULD_BE_INCLUDED_IN_THE_RESPONSE="Your respone should not contain number and dots to state the order of the classes, there should only be one class name per line and nothing else"; - /** * Optional Suffix to APP_WISH @@ -161,4 +120,70 @@ public record QuestionConstants() { public final static String ONLY_CODE ="Your answer should only contain code, any further explanations should be kept as comments within the code"; /// ***** /// + + /* + * Super app - specific questions + */ + /// ***** /// + + /** + * Prefix that should be sent to fetch a list of classes from the ollama model + * + * @use-info The (super) appWish should be concatenated at the tail of this String + * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX + * @chain-order 1/5 + * @SuperApp-Question + */ + public final static String WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX = "Which classes do we need to implement ourself in java to make an application with the features that is provided in the next coming lines?"; + + /** + * @use-info This is the string that will tell the AI-Model that the line above is the last line of the (super) appWish + * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX + * @chain-order 2/5 + * @SuperApp-Question + */ + public final static String LAST_LINE_OF_SUPER_APP="The line above was the last line that included features of the app I need"; + + /** + * + * @use-info Text that specifies the format of the response from the AI-model + * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX + * @chain-order 3/5 + */ + public final static String WHICH_CLASS_ARE_NEEDED_FOR_APP_RESPONSE_FORMAT_1 = "Please provide the name of the first java class and then make a new line for the second java class and then continue until you have listed all the class names of the application I need"; + + + /** + * @use-info Additional guidelines regarding format in the response from the AI-model + * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX + * @chain-order 4/5 + */ + public final static String ONLY_CLASS_NAMES_IN_ANSWER="Your response should only contain the needed classes name for the application and there should be one class name per line, your reply must not contain anything else"; + + /** + * @use-info Clarify that no numbers or dots should be included in the response from the AI-model + * @part-of-question-chain WHICH_CLASS_ARE_NEEDED_FOR_APP_PREFIX + * @chain-order 5/5 + */ + public final static String CLARIFY_THAT_NO_DOTS_OR_NUMBERS_SHOULD_BE_INCLUDED_IN_THE_RESPONSE="Your response should not contain number and dots to state the order of the classes, there should only be one class name per line and nothing else"; + + /** + * This is the line that initiates the phase that happens after the classes for the super app has been stated + * @use-info Use this when the classes for the super app has been decided as the first line to the AI-model + */ + public final static String FIRST_LINE_AFTER_CLASSES_HAS_BEEN_STATED_BY_MODEL="You have previously stated several classes that is needed to make my application"; + + /** + * Provide java code for a class + * @use-info Append the appWish at the tail of this question + */ + public final static String PROVIDE_ME_JAVA_CODE_SUPER_APP_SPECIFIC=APP_WISH_PREFIX_FEATURE+"the class with name "; + + /*** + * Clarify the rules for the superapp java class generation to the AI-model + */ + public final static String CLARIFY_JAVA_CODE_IN_SUPER_APP_RULES="Make sure that the generated code for the java class is compatible with the other classes that you stated was needed for the application , that includes correct variable names and correct imports and class names"; + /// ***** /// + + } diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/OllamaRemoteSystem.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/OllamaRemoteSystem.java index 6600e4b..a187d26 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/OllamaRemoteSystem.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/OllamaRemoteSystem.java @@ -126,12 +126,9 @@ public synchronized boolean CreateApp(String appWish, boolean firstRun, String i return DataStorage.getInstance().getCompilationJob().isResult(); } - public synchronized boolean CreateSuperApp(String superAppWish, boolean firstRun, String ifJavaAppShouldBeModifiedPath, List contentOfJavaFileIfModifyRequest) { + public synchronized List GetClassListForSuperAppCreation(String superAppWish) { - SuperApp superApp = new SuperApp(); - - - return true; + return requestHandler.sendClassesNeededForSuperAppQuestionToOllamaInstance(superAppWish); } diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandler.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandler.java index 2db3869..227222b 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandler.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandler.java @@ -1,5 +1,7 @@ package pn.cg.ollama_ai_remote.request; +import pn.cg.app_system.code_generation.model.SuperApp; + import java.util.List; @@ -29,8 +31,8 @@ public interface RequestHandler { /** * * @param question Question that contains text that describes requirements and functionality of a new super app - * @return String + * @return List that contains the class names for the super app (decided by the AI-model) and their implementation status */ - String sendSuperAppQuestionToOllamaInstance(String question); + List sendClassesNeededForSuperAppQuestionToOllamaInstance(String question); } diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandlerImpl.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandlerImpl.java index a82f4e7..3e4f579 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandlerImpl.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandlerImpl.java @@ -1,6 +1,7 @@ package pn.cg.ollama_ai_remote.request; +import pn.cg.app_system.code_generation.model.SuperApp; import pn.cg.datastorage.CodeGeneratorConfig; import pn.cg.datastorage.constant.QuestionConstants; @@ -13,6 +14,7 @@ import io.github.amithkoujalgi.ollama4j.core.utils.Options; import io.github.amithkoujalgi.ollama4j.core.utils.OptionsBuilder; import io.github.amithkoujalgi.ollama4j.core.utils.PromptBuilder; +import pn.cg.util.CodeGeneratorUtil; import pn.cg.util.StringUtil; import java.io.IOException; @@ -124,18 +126,14 @@ public String sendQuestionToOllamaInstance(String question, String pathToJavaFil } @Override - public String sendSuperAppQuestionToOllamaInstance(String question) { - + public List sendClassesNeededForSuperAppQuestionToOllamaInstance(String question) { List classNames = GetListOfClasses(question); if(classNames.isEmpty()) - sendSuperAppQuestionToOllamaInstance(question); - - - + sendClassesNeededForSuperAppQuestionToOllamaInstance(question); - return ""; + return CodeGeneratorUtil.convertListOfStringClassNamesIntoAnListOfUnimplementedSuperAppClasses(classNames); } private List GetListOfClasses(String question){ diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/CodeGeneratorUtil.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/CodeGeneratorUtil.java index 8fa4596..12744bc 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/CodeGeneratorUtil.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/CodeGeneratorUtil.java @@ -1,15 +1,54 @@ package pn.cg.util; +import pn.cg.app_system.code_generation.model.SuperApp; + +import java.util.LinkedList; import java.util.List; +import java.util.NoSuchElementException; -public class CodeGeneratorUtil { +public record CodeGeneratorUtil() { /** * Boolean method that checks if it's a new request or a continues app generation * Return false means that the request is sent to query the LLM Model further about an existing app */ - public static boolean isThisACreateNewAppRequest(String pathToJavaFileToModify, List contentOfExistingJavaFile){ + public static boolean isThisACreateNewAppRequest(String pathToJavaFileToModify, List contentOfExistingJavaFile) { return (contentOfExistingJavaFile == null || contentOfExistingJavaFile.size() <= 1 || pathToJavaFileToModify == null); } -} + + /** + * Converts a list of class names into unimplemented classes in the current super app generation + * + * @param classNames A list of strings that contains class names needed for the current super app generation + * @return List + */ + public static List convertListOfStringClassNamesIntoAnListOfUnimplementedSuperAppClasses(List classNames) { + + List superAppList = new LinkedList<>(); + classNames.forEach(className -> superAppList.add(new SuperApp(className, false))); + + return superAppList; + } + + /** + * Check the implementation status of the entire super app creation + * + * @param classList List of classes for the super app creation and their implementation status + * @return true if all classes are implemented , else false + */ + public static boolean areAllSuperClassesImplemented(List classList) { + return classList.stream().filter(superAppClass -> !superAppClass.isImplemented()).toList().isEmpty(); + } + + /** + * Get a random unimplemented class from the input list + * + * @param classList List of classes for the super app creation and their implementation status + * @return A random SuperApp from the input list with a status of unimplemented (if any) + */ + public static SuperApp getARandomUnimplementedClass(List classList) throws NoSuchElementException { + + return classList.stream().filter(SuperApp::isImplemented).findAny().orElseThrow(); + } +} \ No newline at end of file From afa950780164ea0a7095c7028f7d63329ae34232 Mon Sep 17 00:00:00 2001 From: pwgit-create Date: Wed, 19 Jun 2024 19:15:41 +0200 Subject: [PATCH 03/18] Itteration 3 --- .../CodeGenerator/dependency-reduced-pom.xml | 12 ++- .../main/java/pn/cg/app_system/AppSystem.java | 20 ++--- .../constant/QuestionConstants.java | 18 ++++- .../ollama_ai_remote/OllamaRemoteSystem.java | 80 +++++++++++++++++++ .../request/RequestHandler.java | 9 ++- .../request/RequestHandlerImpl.java | 71 ++++++++++++++-- .../src/main/java/pn/cg/util/TaskUtil.java | 8 +- 7 files changed, 191 insertions(+), 27 deletions(-) diff --git a/cg/CodeGenerator/CodeGenerator/dependency-reduced-pom.xml b/cg/CodeGenerator/CodeGenerator/dependency-reduced-pom.xml index 7569340..40abefb 100644 --- a/cg/CodeGenerator/CodeGenerator/dependency-reduced-pom.xml +++ b/cg/CodeGenerator/CodeGenerator/dependency-reduced-pom.xml @@ -3,7 +3,7 @@ 4.0.0 pn.dev code-generator-ollama - 1.7.2 + 1.8.1 The Java Application-Generator (pn.dev.code-generator-ollama) creates applications by giving a string of your desired features for a Java application, like this: AppSystem.StartCodeGenerator(String appWish) 2024 @@ -86,9 +86,17 @@ org.apache.maven.plugins maven-surefire-plugin - 3.1.2 + 3.3.0 test + + surefire-api + org.apache.maven.surefire + + + surefire-extensions-api + org.apache.maven.surefire + maven-surefire-common org.apache.maven.surefire diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/AppSystem.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/AppSystem.java index 491960e..586fa3b 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/AppSystem.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/app_system/AppSystem.java @@ -115,14 +115,7 @@ public static void StartSuperAppGeneration(String superAppWish, boolean isFirstR } - - - // Generate each class in the super app class list - - // Invoke call to generate the selected class - - - // Continue with next class if any unimplemented classes remain, else end the super app creation successfully + // Continue with next class (on success) if any unimplemented classes remain, else end the super app creation successfully :) if (appWishCompileResult && !superAppCreationComplete) { log.info("Class Generated\nContinue..."); @@ -130,11 +123,10 @@ public static void StartSuperAppGeneration(String superAppWish, boolean isFirstR try { // Select the next class to create (from the SuperApp list) SuperApp selectedClassToCreate = CodeGeneratorUtil.getARandomUnimplementedClass(classList); - DataStorage.getInstance().setCurrentSuperClass(selectedClassToCreate); - + StartSuperAppGeneration(superAppWish,false,false,classList,false); } - // Success + // Success on the entire super generation! catch (NoSuchElementException noSuchElementException){ log.info("No more classes to implement in super app creation"); @@ -143,7 +135,7 @@ public static void StartSuperAppGeneration(String superAppWish, boolean isFirstR if(CodeGeneratorUtil.areAllSuperClassesImplemented(classList)) superAppCreationComplete = true; } - StartSuperAppGeneration(superAppWish,false,false,classList,false); + } // Retry compilation for a selected class @@ -153,8 +145,8 @@ public static void StartSuperAppGeneration(String superAppWish, boolean isFirstR // Make a call to - //appWishCompileResult = ollamaRemoteSystem.CreateApp(appWish, false, "", null); - //StartSuperAppGeneration(superAppWish,isFirstRun,appWishCompileResult,superApp); + appWishCompileResult = ollamaRemoteSystem.CreateSuperApp(DataStorage.getInstance().getCurrentSuperClass(), false); + StartSuperAppGeneration(superAppWish,isFirstRun,appWishCompileResult,classList,false); } } diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/QuestionConstants.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/QuestionConstants.java index 0df1d7f..a05ed5c 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/QuestionConstants.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/datastorage/constant/QuestionConstants.java @@ -180,10 +180,26 @@ public record QuestionConstants() { public final static String PROVIDE_ME_JAVA_CODE_SUPER_APP_SPECIFIC=APP_WISH_PREFIX_FEATURE+"the class with name "; /*** - * Clarify the rules for the superapp java class generation to the AI-model + * Clarify the rules for the super app java class generation to the AI-model */ public final static String CLARIFY_JAVA_CODE_IN_SUPER_APP_RULES="Make sure that the generated code for the java class is compatible with the other classes that you stated was needed for the application , that includes correct variable names and correct imports and class names"; + + /** + * Share information to the AI-Model that it always should include a Main class that contains the Main Method + */ + public final static String MAIN_CLASS_SHOULD_ALWAYS_BE_ADDED_TO_THE_CLASS_LIST="The last entry in the class list that you will provide , please add a class called Main"; + + /** + * Super App specific variant on the original "AND_CORRECT_IMPORTS" question + */ + public final static String CORRECT_IMPORTS_SUPER_APP_SPECIFIC=AND_CORRECT_IMPORTS + "so that it corresponds with the classes that you stated was needed for this application"; + + /** + * Share information to the AI-Model about the requirements for the implementation of the Main class ( In a super app generation process) + */ + public final static String IMPLEMENT_MAIN_CLASS_IN_SUPER_APP_CREATION=WITH_MAIN_METHOD +" and that the body of that main method invokes a method in a suiting entry point in on of the other classes that this super app creation includes"; /// ***** /// + } diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/OllamaRemoteSystem.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/OllamaRemoteSystem.java index a187d26..7cf260f 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/OllamaRemoteSystem.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/OllamaRemoteSystem.java @@ -126,13 +126,93 @@ public synchronized boolean CreateApp(String appWish, boolean firstRun, String i return DataStorage.getInstance().getCompilationJob().isResult(); } + /** + * Get a list of classes needed for the creation of the super app + * @param superAppWish The requirements for the super app in text format + * @return List + */ public synchronized List GetClassListForSuperAppCreation(String superAppWish) { return requestHandler.sendClassesNeededForSuperAppQuestionToOllamaInstance(superAppWish); } + public synchronized boolean CreateSuperApp(SuperApp classInSuperAppDesign,boolean firstRun){ + + QuestionBuilder questionBuilder = new QuestionBuilder(classInSuperAppDesign.getClassName()); + String outputFromOLLMA = ""; + boolean isRetryCompilation; + boolean tmpRetryCompilationValue; + + + + if (firstRun) { + isRetryCompilation = false; + } else { + tmpRetryCompilationValue = DataStorage.getInstance().getCompilationJob().isResult(); + isRetryCompilation = !tmpRetryCompilationValue; + } + // Fetch response from OllAMA remote api + + if (isRetryCompilation) { + if (DataStorage.getInstance().getCompilationJob() != null && DataStorage.getInstance().getCompilationJob().getErrorMessage() != null) { + log.error("Class did not compile\nSending new request... "); + } + if (DataStorage.getInstance().getCompilationJob() != null && !DataStorage.getInstance().getCompilationJob().isResult()) { + + outputFromOLLMA = requestHandler.sendSuperAppQuestionToOllamaInstance(classInSuperAppDesign); + } + } + + // Extract class name + String className = StringUtil.extractClassNameFromTextWithJavaClasses(outputFromOLLMA); + log.debug("className -> {}", className); + if (className.equalsIgnoreCase(ERROR)) { + //log.debug("Empty class name"); + } else { + + String javaSourceCode = outputFromOLLMA; + javaSourceCode = StringUtil.RemoveExtraStartDelimitersInResponse(javaSourceCode); + javaSourceCode = StringUtil.RemoveExtraEndDelimitersInResponse(javaSourceCode); + + javaSourceCode = StringUtil.IncludeEveryThingAfterStartChar(javaSourceCode); + + javaSourceCode = StringUtil.RemoveEveryThingAfterEndChar(javaSourceCode); + + javaSourceCode = checkAndFixUnclosedBraceBuckets(javaSourceCode); + javaSourceCode = StringUtil.RemoveCommonAdditionStringsFromAiModels(javaSourceCode); + + + log.info("Java source code after modification = {}", javaSourceCode); + // Create file instance with class name and file extension + File file = new File(TaskUtil.addFilePathToClassName(className + JAVA_FILE_EXTENSION)); + + + + // Write the Java code provided from OLLAMA to file + try { + FileUtil.writeDataToFile(file, javaSourceCode); + } catch (IOException e) { + log.error(e.toString()); + throw new RuntimeException(e); + } + + classCompiler.compileClass(className); + + while (DataStorage.getInstance().getCompilationJob().isResult() == null) { + } + } + return DataStorage.getInstance().getCompilationJob().isResult(); + + } + + + /** + * Checks if the current brace buckets pairs are even and if they are not , Append brace buckets until they are + * @param input java code + * @return String + */ private String checkAndFixUnclosedBraceBuckets(String input) { diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandler.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandler.java index 227222b..852f4aa 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandler.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandler.java @@ -29,10 +29,17 @@ public interface RequestHandler { String sendQuestionToOllamaInstance(String question,String pathToJavaFileToModify,List contentOfExistingJavaFile); /** - * + * Send a request to the AI-Model and ask which classes are needed for the super app creation * @param question Question that contains text that describes requirements and functionality of a new super app * @return List that contains the class names for the super app (decided by the AI-model) and their implementation status */ List sendClassesNeededForSuperAppQuestionToOllamaInstance(String question); + /** + * Send a request to the AI-Model where we ask it to implement the input super class with java code + * @param superAppClass A class in the super app project + * @return String with meta information on the current progress + */ + String sendSuperAppQuestionToOllamaInstance(SuperApp superAppClass); + } diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandlerImpl.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandlerImpl.java index 3e4f579..3ca37cf 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandlerImpl.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/ollama_ai_remote/request/RequestHandlerImpl.java @@ -21,6 +21,7 @@ import java.util.LinkedList; import java.util.List; +import static pn.cg.datastorage.constant.QuestionConstants.*; import static pn.cg.util.CodeGeneratorUtil.isThisACreateNewAppRequest; @@ -67,7 +68,7 @@ public String sendQuestionToOllamaInstance(String question, String pathToJavaFil PromptBuilder promptBuilder; if (isThisNewAppRequest) { promptBuilder = new PromptBuilder() - .addLine(QuestionConstants.GREETING_TO_MODEL) + .addLine(GREETING_TO_MODEL) .addLine(question) .addLine(QuestionConstants.WITH_MAIN_METHOD) .addLine(QuestionConstants.AND_CORRECT_IMPORTS) @@ -86,7 +87,7 @@ public String sendQuestionToOllamaInstance(String question, String pathToJavaFil } else { promptBuilder = new PromptBuilder() - .addLine(QuestionConstants.GREETING_TO_MODEL) + .addLine(GREETING_TO_MODEL) .addLine(QuestionConstants.THANKS_FOR_ALL_GENERATED_APPS) .addLine(QuestionConstants.FUNCTIONALITY_NEEDED); @@ -117,7 +118,7 @@ public String sendQuestionToOllamaInstance(String question, String pathToJavaFil result = api.generate(codeGeneratorConfig.getOllamaModel(), promptBuilder.build(), options); } catch (OllamaBaseException | IOException | InterruptedException e) { - e.printStackTrace(); + log.error("Error while sending a request to the local Ollama Server"); } if (result == null) throw new AssertionError(); String outputFromOllamaAPI = (result.getResponse()); @@ -136,6 +137,66 @@ public List sendClassesNeededForSuperAppQuestionToOllamaInstance(Strin return CodeGeneratorUtil.convertListOfStringClassNamesIntoAnListOfUnimplementedSuperAppClasses(classNames); } + @Override + public String sendSuperAppQuestionToOllamaInstance(SuperApp superAppClass) { + + PromptBuilder promptBuilder; + + if(!superAppClass.getClassName().equalsIgnoreCase("main")){ + + promptBuilder=new PromptBuilder() + .addLine(GREETING_TO_MODEL) + .addLine(IMPLEMENT_MAIN_CLASS_IN_SUPER_APP_CREATION) + .addLine(CORRECT_IMPORTS_SUPER_APP_SPECIFIC) + .addLine(QuestionConstants.INCLUDE_IN_ONE_FILE) + .addLine(QuestionConstants.AND_MAKE_SURE_CORRECT_NUMBER_OF_BRACE_BRACKETS_ARE_USED_AT_THE_END_OF_THE_JAVA_CODE) + .addLine(QuestionConstants.MARK_START_CHAR_DELIMITER) + .addLine(QuestionConstants.MARK_THE_END_CHAR_DELIMITER) + .addLine(QuestionConstants.MAKE_SURE_THAT_START_DELIMITER_CHAR_IS_USED_ONCE) + .addLine(QuestionConstants.MAKE_SURE_THAT_END_DELIMITER_CHAR_IS_USED_ONCE) + .addLine(QuestionConstants.NO_JAVA_FX) + .addLine(QuestionConstants.NO_SPECIAL_LIBRARIES) + .addLine(QuestionConstants.MAKE_SURE_IT_WORKS_ON_JAVA_19) + .addLine(QuestionConstants.IMPLEMENT_AS_MUCH_AS_POSSIBLE) + .addLine(QuestionConstants.THREAD_PACKAGE) + .addLine(QuestionConstants.ONLY_CODE); + + // Instruct in prompt that the main method should be included in this class + } + else { + + promptBuilder = new PromptBuilder() + .addLine(GREETING_TO_MODEL) + .addLine(PROVIDE_ME_JAVA_CODE_SUPER_APP_SPECIFIC + superAppClass.getClassName()) + .addLine(QuestionConstants.CORRECT_IMPORTS_SUPER_APP_SPECIFIC) + .addLine(QuestionConstants.INCLUDE_IN_ONE_FILE) + .addLine(QuestionConstants.AND_MAKE_SURE_CORRECT_NUMBER_OF_BRACE_BRACKETS_ARE_USED_AT_THE_END_OF_THE_JAVA_CODE) + .addLine(QuestionConstants.MARK_START_CHAR_DELIMITER) + .addLine(QuestionConstants.MARK_THE_END_CHAR_DELIMITER) + .addLine(QuestionConstants.MAKE_SURE_THAT_START_DELIMITER_CHAR_IS_USED_ONCE) + .addLine(QuestionConstants.MAKE_SURE_THAT_END_DELIMITER_CHAR_IS_USED_ONCE) + .addLine(QuestionConstants.NO_JAVA_FX) + .addLine(QuestionConstants.NO_SPECIAL_LIBRARIES) + .addLine(QuestionConstants.MAKE_SURE_IT_WORKS_ON_JAVA_19) + .addLine(QuestionConstants.IMPLEMENT_AS_MUCH_AS_POSSIBLE) + .addLine(QuestionConstants.THREAD_PACKAGE) + .addLine(QuestionConstants.ONLY_CODE); + } + + OllamaResult result = null; + try { + result = api.generate(codeGeneratorConfig.getOllamaModel(), promptBuilder.build(), options); + + } catch (OllamaBaseException | IOException | InterruptedException e) { + log.error("Error while sending a request to the local Ollama Server"); + } + if (result == null) throw new AssertionError(); + String outputFromOllamaAPI = (result.getResponse()); + log.debug(outputFromOllamaAPI); + return outputFromOllamaAPI; + + } + private List GetListOfClasses(String question){ List classNames = new LinkedList<>(); @@ -146,8 +207,8 @@ private List GetListOfClasses(String question){ .addLine(QuestionConstants.LAST_LINE_OF_SUPER_APP) .addLine(QuestionConstants.WHICH_CLASS_ARE_NEEDED_FOR_APP_RESPONSE_FORMAT_1) .addLine(QuestionConstants.ONLY_CLASS_NAMES_IN_ANSWER) - .addLine(QuestionConstants.CLARIFY_THAT_NO_DOTS_OR_NUMBERS_SHOULD_BE_INCLUDED_IN_THE_RESPONSE); - + .addLine(QuestionConstants.CLARIFY_THAT_NO_DOTS_OR_NUMBERS_SHOULD_BE_INCLUDED_IN_THE_RESPONSE) + .addLine(QuestionConstants.MAIN_CLASS_SHOULD_ALWAYS_BE_ADDED_TO_THE_CLASS_LIST); OllamaResult result = null; try { diff --git a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/TaskUtil.java b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/TaskUtil.java index 8915d39..ba10c4b 100644 --- a/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/TaskUtil.java +++ b/cg/CodeGenerator/CodeGenerator/src/main/java/pn/cg/util/TaskUtil.java @@ -8,11 +8,11 @@ public class TaskUtil { /** * Adds the file path to the Java source code folder - * @param classname - * @return + * @param className Name of the class + * @return String */ - public static String addFilePathToClassName(String classname){ + public static String addFilePathToClassName(String className){ - return ScriptConstants.COMPILE_CLASS_STORAGE+ File.separator+classname; + return ScriptConstants.COMPILE_CLASS_STORAGE+ File.separator+className; } } From 70ce10407fdbfa6f294de745e2c31e7e73ef0d94 Mon Sep 17 00:00:00 2001 From: pwgit-create Date: Fri, 21 Jun 2024 20:01:20 +0200 Subject: [PATCH 04/18] Yet another itteration --- .../src/main/java/pn/app_wish/AppWish.java | 24 +++++++ .../AppWish/src/main/resources/config.props | 2 +- .../src/main/resources/ollama_model.props | 2 +- AppWish/AppWish/src/main/resources/start.fxml | 70 +++++++------------ .../main/java/pn/cg/app_system/AppSystem.java | 66 ++++++++++++----- .../code_generation/ClassCompiler.java | 33 ++++++++- .../java/pn/cg/datastorage/DataStorage.java | 13 +++- .../constant/QuestionConstants.java | 8 ++- .../datastorage/constant/ScriptConstants.java | 5 +- .../ollama_ai_remote/OllamaRemoteSystem.java | 48 +++++++------ .../request/RequestHandlerImpl.java | 9 +-- .../java/pn/cg/task/CompileClassTask.java | 8 +-- .../main/java/pn/cg/task/base/ScriptTask.java | 27 ------- .../java/pn/cg/util/CodeGeneratorUtil.java | 2 +- .../src/main/java/pn/cg/util/TaskUtil.java | 18 ++++- 15 files changed, 206 insertions(+), 129 deletions(-) diff --git a/AppWish/AppWish/src/main/java/pn/app_wish/AppWish.java b/AppWish/AppWish/src/main/java/pn/app_wish/AppWish.java index 746dfe4..18325e4 100644 --- a/AppWish/AppWish/src/main/java/pn/app_wish/AppWish.java +++ b/AppWish/AppWish/src/main/java/pn/app_wish/AppWish.java @@ -29,6 +29,7 @@ import pn.app_wish.util.AppWishUtil; import pn.cg.app_system.AppSystem; import pn.cg.app_system.code_generation.model.CompilationJob; +import pn.cg.app_system.code_generation.model.SuperApp; import pn.cg.datastorage.DataStorage; import pn.cg.datastorage.ThreadPoolMaster; import pn.cg.datastorage.constant.PathConstants; @@ -38,6 +39,7 @@ import java.nio.file.Files; import java.nio.file.Paths; +import java.util.LinkedList; import java.util.List; @@ -67,6 +69,8 @@ public class AppWish extends Application { public Button btn_StopGeneratedApp; @FXML public ImageView logo; + @FXML + public Button tmpfortest; private String javaExecutablePath; private Process executingJavaAppProcess; @@ -290,6 +294,11 @@ private void waitForCompilationResult() { } } + private void waitUntilAllClassesOfTheSuperAppCreationHasBeenImplemented(){ + + while(!DataStorage.getInstance().isSuperAppCreated()){} + } + /** * If a compilation result exist , check if the singleton in code-generator-ollama contains a path for an executable Java file * If the above is true , activate the "run application" button and remove the "generating code..." text @@ -354,4 +363,19 @@ private List readTextByLinesFromFile(File file) { return null; } } + + @FXML + public void tmpTestButton(ActionEvent ae) { + + isCodeGenerationOnGoing = true; + + DataStorage.getInstance().setCompilationJob(new CompilationJob(GUIConstants.DEFAULT_STAGE_TITLE)); + ThreadPoolMaster.getInstance().getExecutor().execute(() -> { + AppSystem.StartSuperAppGeneration(tf_input.getText(), true, false, new LinkedList<>(), false, null); + + + }); + + } + } \ No newline at end of file diff --git a/AppWish/AppWish/src/main/resources/config.props b/AppWish/AppWish/src/main/resources/config.props index b856ca5..ed0889b 100644 --- a/AppWish/AppWish/src/main/resources/config.props +++ b/AppWish/AppWish/src/main/resources/config.props @@ -1,4 +1,4 @@ NUM_CTX=2048 TOP_K=40 -NUM_PREDICT=-1 +NUM_PREDICT=128 TEMPERATURE=0.8 diff --git a/AppWish/AppWish/src/main/resources/ollama_model.props b/AppWish/AppWish/src/main/resources/ollama_model.props index ab1a2a4..2e0fc08 100644 --- a/AppWish/AppWish/src/main/resources/ollama_model.props +++ b/AppWish/AppWish/src/main/resources/ollama_model.props @@ -1 +1 @@ -MODEL_NAME=llama3:latest +MODEL_NAME=llama3:latest \ No newline at end of file diff --git a/AppWish/AppWish/src/main/resources/start.fxml b/AppWish/AppWish/src/main/resources/start.fxml index 67a25dc..ed464ab 100644 --- a/AppWish/AppWish/src/main/resources/start.fxml +++ b/AppWish/AppWish/src/main/resources/start.fxml @@ -1,81 +1,59 @@ - - - - - - - - - - - + + + + + + - - - + - + + + + + + + + + +
+ + + + - - - - - - - - - - - - - -
- - + + +