File size: 9,172 Bytes
ff5f2a0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import os
import re
import gradio as gr
import utils
from utils import ChatCompletion  #my customly built helpers to hold commonly used data models
from random import choice
from time import sleep
from uuid import uuid4
chat = ChatCompletion()
error_code = 0

images = {"Narrator": "Narrator.jpg"}
dubs = {"Narrator": "Josh"}
males = ["Adam", "Antoni", "Arnold", "Sam"]
females = ["Bella", "Domi", "Elli", "Rachel"]

im_gen_msg = f"""Stable Diffusion is an AI art generation model similar to DALLE-2.
Below is a list of prompts that can be used to generate images with Stable Diffusion:

- pirate, concept art, deep focus, fantasy, intricate, highly detailed, digital painting, artstation, matte, sharp focus, illustration, art by magali villeneuve, chippy, ryan yee, rk post, clint cearley, daniel ljunggren, zoltan boros, gabor szikszai, howard lyon, steve argyle, winona nelson
- a fantasy style portrait painting of rachel lane / alison brie hybrid in the style of francois boucher oil painting unreal 5 daz. rpg portrait, extremely detailed artgerm greg rutkowski alphonse mucha greg hildebrandt tim hildebrandt
- athena, greek goddess, claudia black, art by artgerm and greg rutkowski and magali villeneuve, bronze greek armor, owl crown, d & d, fantasy, intricate, portrait, highly detailed, headshot, digital painting, trending on artstation, concept art, sharp focus, illustration
- closeup portrait shot of a large strong female biomechanic woman in a scenic scifi environment, intricate, elegant, highly detailed, centered, digital painting, artstation, concept art, smooth, sharp focus, warframe, illustration, thomas kinkade, tomasz alen kopera, peter mohrbacher, donato giancola, leyendecker, boris vallejo

Follow the structure of the example prompts."""


start_msg = """Greetings, traveler from far-off worlds. I am Korkut, your humble guide through the boundless expanse of the universe. In this game, we shall embark on a journey like no other, delving deep into the mysteries of a sci-fi realm filled with endless wonders and unfathomable dangers.
As the Game Master, it is my honor to lead you on this epic quest, where we shall explore uncharted territories, encounter strange creatures and civilizations, and uncover hidden treasures beyond imagination.
But be warned, for the challenges that lie ahead are not for the faint of heart. Only the bravest and most cunning among us will survive. We shall be tested at every turn, and our fates will be decided by the choices we make.
So, dear friend, I ask you to take up your sword, your laser gun, or whatever weapon you prefer, and prepare to face the unknown. But first, let us know each other. What is your name, brave adventurer?"""


def chat_handler(hist):
    global error_code
    reply = chat.single_response(hist)

    if reply == "" or reply == -1:
        raise gr.Error("Chatbot response is empty. Please reload the page. If the issue repeats please contact me.")
    sleep(20) #TODO REMOVE/REDUCE    

    hist.append({"role": "assistant", "content": reply})
    speaker = re.findall(r"\[([A-Za-z0-9\s]+)\]:", reply)
    dialog = re.findall(r"\[[A-Za-z\s0-9]+\]:([^\[]*)", reply)
    results = list(zip(speaker, dialog))
    speaker_set = set(speaker).difference(set(images))
    if(len(speaker_set)>=1):
        hists = []
        for speaker in speaker_set:
            gender = chat.decide_gender(speaker)
            if gender == "male":
                dub = choice(males)
                dubs[speaker] = dub
            else:
                dub = choice(females)
                dubs[speaker] = dub

            tmp = []
            tmp.append({"role": "assistant", "content": reply})
            tmp.append({"role": "user", "content": im_gen_msg + f" Generate a prompt for {speaker}'s appearance. If you don't have enough information then generate an arbitrary prompt. Keep the prompt shorter than 70 words."})
            hists.append(tmp)
            tmp = []

        replies = chat.multi_response(hists)
        if -1 in replies:
            raise gr.Error("Image generation failed. Please reload the page. If the issue repeats please contact me.")
        images.update(dict(zip(speaker_set, replies)))

    for speaker in speaker_set:
        reply = images[speaker]
        img_path = chat.generate_image(reply, speaker)
        images[speaker] = img_path

    out_clip = []
    text = ""
    for result in results:
        if result[1].strip()=="": continue
        text += "**" + result[0] + ":** " + result[1].strip() + "\n"
        dub = dubs[result[0]]
        audio_name = utils.generate_audio(dub, result[1].strip())
        if audio_name == -1:
            error_code = -1
            raise gr.Error("Audio generation failed.Please contact me.")
        out_clip.append([result[0], audio_name, images[result[0]]])
    out_path = "video" + str(uuid4()) + ".mp4"
    try:
        utils.generate_video(out_clip, out_path)
    except Exception as e:
        error_code = -1
        print("Error:" + str(e))
        raise gr.Error("Video generation failed. Please contact me.")
    return out_path, text, hist


def btn_1(text,history, hist):
    if error_code == -1:
        return {button1: gr.update(interactive=False), button2: gr.update(visible=False),textbox: gr.update(value="System error! Please contant me."), chatbot: gr.update(value=history), state: hist}
    
    user_name = utils.get_user_name(chat, text)
    
    if user_name == -1:
        return {button1: gr.update(interactive=False), button2: gr.update(visible=False),textbox: gr.update(value="This name is not appropriate! Please restart the game and choose an appropriate name."), chatbot: gr.update(value=history), state: hist}
    if user_name == -2:
        return {button1: gr.update(interactive=False), button2: gr.update(visible=False),textbox: gr.update(value="This name is invalid! Please restart the game and choose a valid name."), chatbot: gr.update(value=history), state: hist}
    
    history += [(None,text)]
    system_message = f"""You are a game master. You are going to create a DND game takes place in sci-fi setting. You use a mysterious, exciting and interesting language. The story you are telling must be compelling. Since I am the only one playing with you, you need to refer me as "you" when you are talking about my character's actions. You should use a lot dialogs in your story. Other characters can refer me as {user_name}. Dialogs should be formatted like 
    "[Person1 Name]: Speech
    [Person2 Name]: Speech"
    Also when there is no dialog and you are narrating story the you should output like "[Narrator]: Story".
    Overall an example output should look like the following 
    "[Narrator]: You wake up in a deserted planet.
    [Stranger]: Wake up! Who are you?
    [Narrator]: What are you going to do?"
    You mustn't generate my dialogs. Instead at the end of your message you should ask what I will do or say and your next message you should shape the story according to my response."""
    hist = [{"role": "system", "content": system_message}, {"role": "user", "content": "Start"}]
    try:
        out_path, text, hist = chat_handler(hist)
    except gr.Error as e:
        return {button1: gr.update(interactive=False), button2: gr.update(visible=False),textbox: gr.update(value=str(e)), chatbot: gr.update(value=history), state: hist}
    
    history += [((out_path,None),None),(text,None)]
    return {button1: gr.update(visible=False), button2: gr.update(visible=True), textbox: gr.update(label="What will you do?",value=""), chatbot: gr.update(value=history), state: hist}

def btn_2(text, history, hist):
    if error_code == -1:
        return {button2: gr.update(interactive=False), textbox: gr.update(value="System error! Please contant me."), chatbot: gr.update(value=history), state:hist}

    if not chat.safety_check(text):
        return {button2: gr.update(interactive=False), textbox: gr.update(value="This message is inappropriate! Please restart the game and use an appropriate language."), chatbot: gr.update(value=history), state:hist}

    hist.append({"role": "user", "content": text})

    try:
        out_path, text, hist = chat_handler(hist)
    except gr.Error as e:
        return {button2: gr.update(interactive=False), textbox: gr.update(value=str(e)), chatbot: gr.update(value=history), state: hist}
    
    history += [((out_path,None),None),(text,None)]
    return {textbox: gr.update(value=""), chatbot: gr.update(value=history), state: hist}

with gr.Blocks(theme=gr.themes.Soft()) as demo:
    state = gr.State([])
    gr.Markdown("# KORKUT: A Spacetime Odyssey")
    history = [(("./Opening.mp4",None),None),(start_msg, None)]
    chatbot = gr.Chatbot(history, elem_id="chatbot", starts_with="bot").style(height=600)
    textbox = gr.Textbox(lines=3, label="What is your name, brave adventurer?")
    button1 = gr.Button(value="Submit")
    button2 = gr.Button(value="Submit", visible=False)
    button2.click(btn_2, [textbox, chatbot, state],[textbox, chatbot, state, button2])
    button1.click(btn_1 ,[textbox, chatbot, state],[button1, button2, textbox, chatbot, state])
demo.queue().launch(share=True)