Class AIGenerationTask

  • All Implemented Interfaces:
    Cloneable

    public class AIGenerationTask
    extends Object
    implements Cloneable
    We support the generation of files using an AI, specifically ChatGPT. A generation task can have several input files. Some of them can be prompt files with task descriptions, and some of them source files to be processed. The output of each task is one text file. A complex task can have several steps leading to several intermediate files.

    Since ChatGPT is not particularily fast not free and the generation results have to be manually checked, this is heavily cached. Into each output file we write the versions of all the input files from which it was generated into a comment. When the tasks are run, we compare the versions of all the input files with the versions recorded in the comment, and only regenerate the output file if the versions have changed. An input file can have a version comment that explicitly states the version, or we take the an abbreviated SHA256 hash of the input file as version. It is possible to explicitly state the versions in version comments in the input files to avoid regenerating all files if minor details e.g. in a prompt file are changed - only when the prompt file version comment is changed everything is regenerated.

    A version comment can e.g. look like this:

    // AIGenVersion(ourversion, inputfile1@version1, inputfile2@version2, ...)

    where ourversion and version1 and version2 are hashes. ourversion is the hash of the original output of the AI. The comment syntax (in this case //) is ignored - we just look for the AIGenVersion via regex.

    Normally the intermediate and final results should be checked in with Git. That ensures manual checks when they are regenerated, and minimizes regeneration.

    • Field Detail

      • LOG

        protected static final Logger LOG
      • FIXME

        public static final String FIXME
        A marker that can be inserted by the AI when something is wrong / unclear. We will make sure the user sees that by aborting.
        See Also:
        Constant Field Values
      • PATTERN_LICENCE

        protected static final Pattern PATTERN_LICENCE
        A pattern that matches the license header, which we want to remove to avoid clutter.
      • PATTERN_INFILEPROMPT

        protected static final Pattern PATTERN_INFILEPROMPT
        A pattern matching infile prompts like this:
         <%-- AIGenPromptStart(tablefromdatacopied)
         Make a markdown table from the data, with columns "Name" and "Profession".
         AIGenCommand(tablefromdatacopied)
         -f -m copy tablefromdata.md
         AIGenPromptEnd(tablefromdatacopied) --%>
         
        This matches a line containing AIGenPromptStart with an id until the corresponding AIGenPromptEnd.
      • updateRequested

        protected boolean updateRequested
      • prompt

        protected String prompt
        The actual prompt created from prompt files and parameters.
      • placeholdersAndValues

        protected Map<String,​String> placeholdersAndValues
      • systemMessage

        protected String systemMessage
      • systemMessageInput

        protected AIInOut systemMessageInput
      • maxTokens

        protected Integer maxTokens
    • Constructor Detail

      • AIGenerationTask

        public AIGenerationTask()
    • Method Detail

      • setUpdateRequested

        public AIGenerationTask setUpdateRequested​(boolean updateRequested)
        If true, adds the output file as a special input with a hint that this is the current state of the output that has to be updated with minimal changes.
      • hasToBeRun

        public boolean hasToBeRun()
      • getAdditionalMarkers

        protected List<String> getAdditionalMarkers()
      • getAllInputs

        protected List<AIInOut> getAllInputs()
      • addPrompt

        public AIGenerationTask addPrompt​(@Nonnull
                                          AIInOut promptInput,
                                          String... placeholdersAndValues)
        The actual prompt to be executed. The prompt file content can contain placeholders that are replaced by the values given: placeholdersAndValues contain alternatingly placeholder names and values for them.
        Returns:
        this
      • addPrompt

        public AIGenerationTask addPrompt​(@Nonnull
                                          File promptInput,
                                          String... placeholdersAndValues)
        The actual prompt to be executed. The prompt file content can contain placeholders that are replaced by the values given: placeholdersAndValues contain alternatingly placeholder names and values for them.
        Returns:
        this
      • addPrompt

        public AIGenerationTask addPrompt​(@Nonnull
                                          AIInOut promptFile,
                                          Map<String,​String> placeholdersAndValues)
        The actual prompt to be executed. The prompt file content can contain placeholders that are replaced by the values given.
        Returns:
        this
      • addPrompt

        public AIGenerationTask addPrompt​(@Nonnull
                                          File promptFile,
                                          Map<String,​String> placeholdersAndValues)
        The actual prompt to be executed. The prompt file content can contain placeholders that are replaced by the values given.
        Returns:
        this
      • getFileContent

        @Nullable
        protected String getFileContent​(@Nonnull
                                        File file)
      • unclutter

        public static String unclutter​(String content)
      • relativePath

        protected String relativePath​(@Nullable
                                      File file,
                                      @Nonnull
                                      File rootDirectory)
      • execute

        public AIGenerationTask execute​(@Nonnull
                                        Supplier<AIChatBuilder> chatBuilderFactory,
                                        @Nonnull
                                        File rootDirectory)
        Execute the task if necessary. If the output file is already there and up to date, nothing is done.
      • toJson

        public String toJson​(@Nonnull
                             Supplier<AIChatBuilder> chatBuilderFactory,
                             @Nonnull
                             File rootDirectory)
        For debugging purposes: returns the JSON that would be sent to the AI.
      • explain

        public String explain​(@Nonnull
                              Supplier<AIChatBuilder> chatBuilderFactory,
                              @Nonnull
                              File rootDirectory,
                              @Nonnull
                              String question)
        Ask a question about the previous task execution. We assume it was previously run (hasToBeRun() == false), add the result of the previous execution to the chat, and ask the AI the given question about it. This can be used e.g. to see why the AI did something, or in the process of improving the prompt, etc.
        Returns:
        the answer of the AI - not written to a file!