Beispiel #1
0
def getGenerator():
    colPrint(
        "\nInitializing AI Engine! (This might take a few minutes)\n",
        colors["loading-message"],
    )
    models = [x for x in Path('models').iterdir() if x.is_dir()]
    if not models:
        raise FileNotFoundError(
            'There are no models in the models directory! You must download a pytorch compatible model!'
        )
    elif len(models) > 1:
        colPrint(
            "You have multiple models in your models folder. Please select one to load:",
            colors['message'])
        for n, model_path in enumerate(models):
            colPrint("{}: {}".format(n, model_path.name), colors['menu'])

        model = models[getNumberInput(len(models) - 1)]
    else:
        model = models[0]
        logger.info("Using model: " + str(model))
    return GPT2Generator(
        model_path=model,
        generate_num=settings.getint("generate-num"),
        temperature=settings.getfloat("temp"),
        top_k=settings.getint("top-keks"),
        top_p=settings.getfloat("top-p"),
        repetition_penalty=settings.getfloat("rep-pen"),
    )
def instructions():
    if settings.getboolean("console-bell"):
        bell = "on"
    else:
        bell = "off"
    if settings.getboolean("action-d20"):
        d20 = "on"
    else:
        d20 = "off"
    print(
        '\033[' + colors["instructions"] + 'm' +
        'AID2: Clover Edition Instructions: \n Enter actions starting with a verb ex. "go to the tavern" or "attack the orc."\n To speak enter say "(thing you want to say)" or just "(thing you want to say)"'
    )
    print('The following commands can be entered for any action:')
    print(
        '  "/revert"            Reverts the last action allowing you to pick a different action.'
    )
    print('  "/quit"              Quits the game and saves')
    print(
        '  "/menu"              Starts a new game and saves your current one')
    print('  "/retry"             Retries the last action')
    print('  "/restart"           Restarts the current story')
    print(
        '  "/print"             Prints a transcript of your adventure (without extra newline formatting)'
    )
    print('  "/help"              Prints these instructions again')
    print(
        '  "/set SETTING VALUE" Sets the specified setting to the specified value.:'
    )
    print(
        '      temp            Higher values make the AI more random. Default: 0.4 | Current:',
        settings.getfloat("temp"))
    print(
        '      rep-pen         Controls how repetitive the AI is allowed to be. Default: 1.2 | Current:',
        settings.getfloat("rep-pen"))
    print(
        '      text-wrap-width Maximum width of lines printed by computer. Default: 80 | Current:',
        settings.getint("text-wrap-width"))
    print(
        '      console-bell    Beep after AI generates text? Default: on | Current:',
        bell)
    print(
        '      top-keks        Number of words the AI can randomly choose. Default: 20 | Current:',
        settings.getint("top-keks"))
    print('      generate-num    Default: 60 | Current:',
          settings.getint("generate-num"))
    print('      top-p           Default: 0.9 | Current:',
          settings.getfloat("top-p"))
    print('      log-level       Default: 3 | Current:',
          settings.getint("log-level"))
    print(
        '      action-sugg     How many actions to generate, 0 is off. Default: 4 | Current:',
        settings.getint("action-sugg"))
    print(
        '      action-d20      Make actions difficult. Default: on | Current:',
        d20)
    print(
        '      action-temp     How random the suggested actions are. Default: 1 | Current:',
        settings.getfloat("action-temp"), '\033[39m')
Beispiel #3
0
 def act(self, action):
     assert (self.context.strip() + action.strip())
     assert (settings.getint('top-keks') is not None)
     self.actions.append(format_result(action))
     result = self.generator.generate(
         self.get_story() + action,
         self.context + ' '.join(self.memory),
         temperature=settings.getfloat('temp'),
         top_p=settings.getfloat('top-p'),
         top_k=settings.getint('top-keks'),
         repetition_penalty=settings.getfloat('rep-pen'))
     self.results.append(format_result(result))
     return self.results[-1]
Beispiel #4
0
def colPrint(text, col="0", wrap=True, end=None):
    if wrap:
        width = settings.getint("text-wrap-width")
        width = 999999999 if width < 2 else width
        width = min(width, termWidth)
        text = textwrap.fill(text, width, replace_whitespace=False)
    print("\x1B[{}m{}\x1B[{}m".format(col, text, colors["default"]), end=end)
    return text.count('\n') + 1
    def act(self, action):
        assert (self.prompt + action)
        results = []
        for i in range(self.numResults):
            assert (settings.getint('top-keks') is not None)
            results.append(
                self.generator.generate(
                    self.getStory() + action,
                    self.prompt,
                    temperature=settings.getfloat('temp'),
                    top_p=settings.getfloat('top-p'),
                    top_k=settings.getint('top-keks'),
                    repetition_penalty=settings.getfloat('rep-pen')))
            #self.longTermMemory.join('\n\n'), self.prompt))

        self.story.append([action, results])
        return results
Beispiel #6
0
 def get_suggestion(self):
     return re.sub('\n.*', '',
                   self.generator.generate_raw(
                       self.get_story() + "\n\n> You",
                       self.context,
                       temperature=settings.getfloat('action-temp'),
                       top_p=settings.getfloat('top-p'),
                       top_k=settings.getint('top-keks'),
                       repetition_penalty=1))
 def getSuggestion(self):
     #temporary fix (TODO)
     return re.sub(
         '\n.*', '',
         self.generator.generate_raw(
             self.getStory() + "\n\n> You",
             self.prompt,
             temperature=settings.getfloat('action-temp'),
             top_p=settings.getfloat('top-p'),
             top_k=settings.getint('top-keks'),
             repetition_penalty=1))
Beispiel #8
0
 def to_dict(self):
     res = {}
     res["temp"] = settings.getfloat('temp')
     res["top-p"] = settings.getfloat("top-p")
     res["top-keks"] = settings.getint("top-keks")
     res["rep-pen"] = settings.getfloat("rep-pen")
     res["context"] = self.context
     res["memory"] = self.memory
     res["actions"] = self.actions
     res["results"] = self.results
     return res
Beispiel #9
0
    def get_action(self):
        # While we want the story to be on track, but not to on track that it loops
        # the actions can be quite random, and this helps inject some user curated randomness
        # and prevent loops. So lets make the actions quite random, and prevent duplicates while we are at it

        # what to feed to model?
        mem_ind = random.randint(1, 6)  # How many steps to include
        sample = random.randint(0, 1)  # Random steps from history?
        include_prompt = random.randint(0, 1)  # Include the initial promts
        predicates = ['You try to ', 'You say "', 'You start to ',
                      '"']  # The model has to continue from here

        predicate = random.sample(predicates, 1)[0]
        action_prompt = self.story_manager.story_context(
            mem_ind, sample, include_prompt)
        action_prompt[-1] = action_prompt[-1].strip() + "\n> " + predicate

        result_raw = self.story_manager.generator.generate_raw(
            action_prompt,
            generate_num=settings.getint("action-generate-num"),
            temperature=settings.getfloat("action-temp"),
            stop_tokens=self.story_manager.generator.tokenizer.encode(
                ["<|endoftext|>", "\n", ">"])
            # stop_tokens=self.generator.tokenizer.encode(['>', '<|endoftext|>'])
        )
        logger.info(
            "get_action (mem_ind=%s, sample=%s, include_prompt=%s, predicate=`%r`) -> %r",
            mem_ind, sample, include_prompt, predicate, result_raw)
        result = predicate + result_raw.lstrip()
        result = clean_suggested_action(
            result, min_length=settings.getint("action-min-length"))
        # Sometimes the suggestion start with "You" we will add that on later anyway so remove it here
        result = re.sub("^ ?[Yy]ou try to ?", "You ", result)
        result = re.sub("^ ?[Yy]ou start to ?", "You ", result)
        result = re.sub("^ ?[Yy]ou say \"", "\"", result)
        result = re.sub("^ ?[Yy]ou ?", "", result)
        return result
Beispiel #10
0
def play(generator):
    print("\n")

    with open(Path("interface", "mainTitle.txt"), "r",
              encoding="utf-8") as file:
        colPrint(file.read(), colors["title"], wrap=False)

    with open(Path("interface", "subTitle.txt"), "r",
              encoding="utf-8") as file:
        cols = termWidth
        for line in file:
            line = re.sub(r'\n', '', line)
            line = line[:cols]
            #fills in the graphic using reverse video mode substituted into the areas between |'s
            colPrint(
                re.sub(r'\|[ _]*(\||$)',
                       lambda x: '\x1B[7m' + x.group(0) + '\x1B[27m', line),
                colors['subtitle'], False)

    print()
    colPrint(
        "Go to https://github.com/cloveranon/Clover-Edition/ or email [email protected] for bug reports, help, and feature requests.",
        colors['subsubtitle'])

    while True:
        # May be needed to avoid out of mem
        gc.collect()
        torch.cuda.empty_cache()

        print("\n\n")

        colPrint(
            "0: Pick Prompt From File (Default if you type nothing)\n1: Write Custom Prompt",
            colors['menu'])

        if getNumberInput(1) == 1:
            with open(Path("interface", "prompt-instructions.txt"),
                      "r",
                      encoding="utf-8") as file:
                colPrint(file.read(), colors["instructions"], False)
            prompt = colInput("Prompt>", colors["main-prompt"],
                              colors["user-text"])
            context = colInput("Context>", colors["main-prompt"],
                               colors["user-text"])
            filename = colInput(
                "Name to save prompt as? (Leave blank for no save): ",
                colors["query"],
                colors["user-text"],
            )
            filename = re.sub(
                "-$", "",
                re.sub("^-", "", re.sub("[^a-zA-Z0-9_-]+", "-", filename)))
            if filename != "":
                with open(Path("prompts", filename + ".txt"),
                          "w",
                          encoding="utf-8") as f:
                    f.write(context + "\n" + prompt)
        else:
            prompt, context = selectFile()
        assert (prompt + context)

        instructions()

        print()
        colPrint("Generating story...", colors["loading-message"])

        story = newStory(generator, prompt, context)

        while True:
            # Generate suggested actions
            act_alts = settings.getint("action-sugg")
            if act_alts > 0:

                # TODO change this to two messages for different colors
                suggested_actions = []
                colPrint("\nSuggested actions:", colors["selection-value"])
                action_suggestion_lines = 2
                for i in range(act_alts):
                    suggested_action = story.getSuggestion()
                    if len(suggested_action.strip()) > 0:
                        j = len(suggested_actions)
                        suggested_actions.append(suggested_action)
                        suggestion = "{}> {}".format(j, suggested_action)
                        action_suggestion_lines += colPrint(
                            suggestion, colors["selection-value"])
                print()

            bell()
            action = colInput("> You ", colors["main-prompt"],
                              colors["user-text"])

            # Clear suggestions and user input
            if act_alts > 0:
                action_suggestion_lines += 2
                if not IN_COLAB:
                    clear_lines(action_suggestion_lines)

                    # Show user input again
                    # colPrint("\n> " + action.rstrip(), colors["user-text"], end="")

            setRegex = re.search("^/set ([^ ]+) ([^ ]+)$", action)
            if setRegex:
                if setRegex.group(1) in settings:
                    currentSettingValue = settings[setRegex.group(1)]
                    colPrint(
                        "Current Value of {}: {}     Changing to: {}".format(
                            setRegex.group(1), currentSettingValue,
                            setRegex.group(2)))
                    settings[setRegex.group(1)] = setRegex.group(2)
                    colPrint("Save config file?", colors["query"])
                    colPrint("Saving an invalid option will corrupt file!",
                             colors["error"])
                    if (colInput(
                            "y/n? >",
                            colors["selection-prompt"],
                            colors["selection-value"],
                    ) == "y"):
                        with open("config.ini", "w", encoding="utf-8") as file:
                            config.write(file)
                else:
                    colPrint("Invalid Setting", colors["error"])
                    instructions()
            elif action == "/menu":
                break
            elif action == "/restart":
                print()
                colPrint("Restarting story...", colors["loading-message"])

                story = newStory(generator, story.prompt, context)
                continue
            elif action == "/quit":
                exit()
            elif action == "/help":
                instructions()
            elif action == "/print":
                print("\nPRINTING\n")
                #TODO colorize printed story
                colPrint(str(story), colors["print-story"])
            elif action == '/retry':

                if len(story.story) == 1:
                    print()
                    colPrint("Restarting story...", colors["loading-message"])
                    story = newStory(generator, story.prompt, context)
                    continue
                else:
                    newaction = story.story[-1][0]

                colPrint(newaction, colors['user-text'], end='')
                story.story = story.story[:-1]
                result = "\n" + story.act(newaction)[0]

                if len(story.story) >= 2:
                    similarity = get_similarity(result, story.story[-2][1][0])
                    if similarity > 0.9:
                        story.story = story.story[:-1]
                        colPrint(
                            "Woops that action caused the model to start looping. Try a different action to prevent that.",
                            colors["error"],
                        )
                        continue
                colPrint(result, colors["ai-text"])

                continue

            elif action == '/revert':

                if len(story.story) == 1:
                    colPrint("You can't go back any farther. ",
                             colors["error"])
                    continue

                story.story = story.story[:-1]
                colPrint("Last action reverted. ", colors["message"])
                if len(story.story) < 2:
                    colPrint(story.prompt, colors["ai-text"])
                colPrint(story.story[-1][1][0], colors["ai-text"])

                continue

            elif action == "/alter":
                story.story[-1][1][0] = alterText(story.story[-1][1][0])
                if len(story.story) < 2:
                    colPrint(story.prompt, colors["ai-text"])
                else:
                    colPrint("\n" + story.story[-1][0] + "\n",
                             colors["transformed-user-text"])
                colPrint("\n" + story.story[-1][1][0] + "\n\n",
                         colors["ai-text"])

            elif action == "/prompt":
                story.prompt = alterText(story.prompt)
                if len(story.story) < 2:
                    colPrint(story.prompt, colors["ai-text"])
                else:
                    colPrint("\n" + story.story[-1][0] + "\n",
                             colors["transformed-user-text"])
                colPrint("\n" + story.story[-1][1][0] + "\n\n",
                         colors["ai-text"])

            else:
                if act_alts > 0:
                    # Options to select a suggestion action
                    if action in [
                            str(i) for i in range(len(suggested_actions))
                    ]:
                        action = suggested_actions[int(action)]

                original_action = action
                action = action.strip()
                #TODO debug stuff to delete
                if action != original_action:
                    logger.debug("STRIPPED WHITE SPACE OFF ACTION %r vs %r",
                                 original_action, action)

                # Crop actions to a max length
                #action = action[:4096]

                if action != "":

                    # Roll a 20 sided dice to make things interesting
                    d = random.randint(1, 20)
                    logger.debug("roll d20=%s", d)

                    # If it says 'You say "' then it's still dialouge. Normalise it by removing `You say `, we will add again soon
                    action = re.sub("^ ?[Yy]ou say [\"']", '"', action)
                    if any(action.lstrip().startswith(t) for t in ['"', "'"]):
                        if settings.getboolean("action-d20"):
                            action = d20ify_speech(action, d)
                        else:
                            action = "You say " + action
                        logger.info(
                            "%r. %r, %r", action,
                            any(action.lstrip().startswith(t)
                                for t in ['"', "'"]),
                            settings.getboolean("action-d20"))
                    else:
                        action = first_to_second_person(action)
                        if not action.lower().startswith(
                                "you ") and not action.lower().startswith(
                                    "i "):
                            action = action[0].lower() + action[1:]
                            # roll a d20
                            if settings.getboolean("action-d20"):
                                action = d20ify_action(action, d)
                            else:
                                action = "You " + action

                        if action[-1] not in [".", "?", "!"]:
                            action = action + "."

                action = "\n> " + action + "\n"

                colPrint(
                    "\n>" + action.lstrip().lstrip("> \n"),
                    colors["transformed-user-text"],
                )
                #TODO check if leading white space makes sense
                result = "\n" + story.act(action)[0]

                #TODO: Replace all this nonsense
                if len(story.story) >= 2:
                    similarity = get_similarity(result, story.story[-2][1][0])
                    if similarity > 0.9:
                        story.story = story.story[:-1]
                        colPrint(
                            "Woops that action caused the model to start looping. Try a different action to prevent that.",
                            colors["error"],
                        )
                        continue

                if player_won(result):
                    colPrint(result + "\n CONGRATS YOU WIN", colors["message"])
                    break
                elif player_died(result):
                    colPrint(result, colors["ai-text"])
                    colPrint("YOU DIED. GAME OVER", colors["error"])
                    colPrint(
                        "\nOptions:\n0)Start a new game\n1)\"I'm not dead yet!\" (If you didn't actually die)",
                        colors["menu"],
                    )
                    choice = getNumberInput(1)
                    if choice == 0:
                        break
                    else:
                        colPrint("Sorry about that...where were we?",
                                 colors["query"])
                colPrint(result, colors["ai-text"])
Beispiel #11
0
def output(text1,
           col1=None,
           text2=None,
           col2=None,
           wrap=True,
           beg=None,
           end='\n',
           sep=' ',
           rem_beg_spaces=True):
    print('', end=beg)
    ptoolkit = use_ptoolkit() and ptcolors['displaymethod'] == "prompt-toolkit"

    if wrap:
        width = settings.getint("text-wrap-width")
        width = 999999999 if width < 2 else width
        width = min(width, termWidth)
        wtext = text1 + '\u200D' + sep + '\u200D' + text2 if text2 is not None else text1
        wtext = fill_text(wtext, width)
        wtext = re.sub(r"\n[ \t]+", "\n", wtext) if rem_beg_spaces else wtext
        wtext = wtext.split('\u200D')
        text1 = wtext[0]
        if text2 is not None:
            sep = wtext[1]
            text2 = ' '.join(wtext[2:])

    if ptoolkit:
        col1 = ptcolors[col1] if col1 and ptcolors[col1] else ""
        col2 = ptcolors[col2] if col2 and ptcolors[col2] else ""
        print_formatted_text(to_formatted_text(text1, col1), end='')
        if text2:
            print_formatted_text(to_formatted_text(sep), end='')
            print_formatted_text(to_formatted_text(text2, col2), end='')
        print('', end=end)

    else:
        col1 = colors[col1] if col1 and colors[col1] and colors[col1][
            0].isdigit() else None
        col2 = colors[col2] if col2 and colors[col2] and colors[col2][
            0].isdigit() else None

        clb1 = "\x1B[{}m".format(col1) if col1 else ""
        clb2 = "\x1B[{}m".format(col2) if col2 else ""
        cle1 = "\x1B[0m" if col1 else ""
        cle2 = "\x1B[0m" if col2 else ""
        text1 = clb1 + text1 + cle1
        if text2 is not None:
            text2 = clb2 + text2 + cle2
            print(text1, end='')
            print(sep, end='')
            print(text2, end=end)
        else:
            print(text1, end=end)

    linecount = 1
    if beg:
        linecount += beg.count('\n')
    if text1:
        linecount += text1.count('\n')
    if end:
        linecount += end.count('\n')
    if text2:
        linecount += text2.count('\n')
        if sep:
            linecount += sep.count('\n')
    return linecount
#a little script to test if 16 bit degrades accuracy of the model. Not a perfect experiment but I think it's good enough
#must be moved to the clover-edition directory or it will not run
#I can not figure out why. According to pythons documentation, only the current directory matters, not the placement of the file
from getconfig import settings
settings['log-level'] = str(min(settings.getint('log-level'), 10))
from gpt2generator import GPT2Generator
import torch
import numpy as np
import gc
from pathlib import Path
import random
import string
import time

#seed=0
seed = int(time.time()) % 10000
top_p = 0.5
top_k = 0
temp = 0.2


def randomString(stringLength=12):
    letters = string.ascii_lowercase + ' ' + string.digits
    return ''.join(random.choice(letters) for i in range(stringLength))


prompt = 'abcd1234'
#prompt=randomString(12)

print('\x1B[0m')  #I really am addicted to color output
with open(Path('interface/', 'clover', encoding='utf-8')) as file:
Beispiel #13
0
def output(text1,
           col1=None,
           text2=None,
           col2=None,
           wrap=True,
           beg=None,
           end='\n',
           sep=' '):
    print('', end=beg)
    ptoolkit = use_ptoolkit() and ptcolors['displaymethod'] == "prompt-toolkit"

    if not ptoolkit:
        col1 = colors[col1] if col1 and colors[col1] and colors[col1][
            0].isdigit() else None
        col2 = colors[col2] if col2 and colors[col2] and colors[col2][
            0].isdigit() else None

        clb1 = "\x1B[{}m".format(col1) if col1 else ""
        clb2 = "\x1B[{}m".format(col2) if col2 else ""
        cle1 = "\x1B[0m" if col1 else ""
        cle2 = "\x1B[0m" if col2 else ""
        text1 = clb1 + text1 + cle1
        if text2 is not None:
            text2 = clb2 + text2 + cle2
    if wrap:
        width = settings.getint("text-wrap-width")
        width = 999999999 if width < 2 else width
        width = min(width, termWidth)
        text1 = textwrap.fill(text1,
                              width,
                              replace_whitespace=False,
                              drop_whitespace=False)
        if text2:
            if len(text1) + 1 + len(text2) >= width:
                if not re.match("^\n+$", sep):
                    sep += '\n'
            text2 = textwrap.fill(text2,
                                  width,
                                  replace_whitespace=False,
                                  drop_whitespace=False)

    if ptoolkit:
        col1 = ptcolors[col1] if col1 and ptcolors[col1] else ""
        col2 = ptcolors[col2] if col2 and ptcolors[col2] else ""
        print_formatted_text(to_formatted_text(text1, col1), end='')
        if text2:
            print_formatted_text(to_formatted_text(sep), end='')
            print_formatted_text(to_formatted_text(text2, col2), end='')
        print('', end=end)
    else:
        if not text2:
            print(text1, end=end)
        else:
            print(text1, end='')
            print(sep, end='')
            print(text2, end=end)

    linecount = 1
    if text1:
        linecount += text1.count('\n')
    if end:
        linecount += end.count('\n')
    if sep:
        linecount += sep.count('\n')
    if text2:
        linecount += text2.count('\n')
    return linecount