Spaces:
Sleeping
Sleeping
import gradio as gr | |
import os | |
import openai | |
openai.api_key = os.environ['KEY'] | |
theme = gr.themes.Monochrome( | |
text_size="lg" | |
) | |
css = "@import url(https://fonts.googleapis.com/css2?family=Silkscreen:wght@400;700&display=swap);#component-3," \ | |
"#component-4{margin-bottom:10px}.gradio-container{" \ | |
"background-color:#cda678;font-family:Silkscreen;position:relative}#component-1{min-height:75vh}#component-4{" \ | |
"margin-top:auto}.tabs.svelte-btpldm{height:100%}.tabitem{background-color:#002366;border:1px solid " \ | |
"#fff}#component-17,#component-25,#component-33,#component-41,#component-9{" \ | |
"min-height:70vh;max-height:70vh}.secondary.svelte-58yet2{" \ | |
"background-color:#002366;font-weight:400}#component-10,#component-11,#component-18,#component-19," \ | |
"#component-26,#component-27,#component-34,#component-35,#component-42,#component-43{" \ | |
"background-color:#aaa}.message.svelte-a99nd8.svelte-a99nd8{" \ | |
"padding:15px;position:relative}.user.svelte-a99nd8.svelte-a99nd8{" \ | |
"margin-right:10px}.bot.svelte-a99nd8.svelte-a99nd8{" \ | |
"padding-left:15px;margin-left:10px}.bot.svelte-a99nd8.svelte-a99nd8::before," \ | |
".user.svelte-a99nd8.svelte-a99nd8::after{" \ | |
"content:\"\";width:10px;height:10px;position:absolute;bottom:-1px;border:1px solid var(" \ | |
"--color-border-accent);background-color:var(--color-accent-soft)}.bot.svelte-a99nd8.svelte-a99nd8::before{" \ | |
"left:-10px;border-right:0}.user.svelte-a99nd8.svelte-a99nd8::after{right:-10px;border-left:0}textarea{" \ | |
"background-color:#fff;min-height:50px!important}#component-48,#component-51{" \ | |
"position:absolute;left:50%;top:50%;transform:translateX(-50%) translateY(" \ | |
"-50%);width:50%;height:50vh;padding:80px 20px 20px;background-color:#fff;border:1px solid " \ | |
"#002366}#component-49{position:initial;background-image:url(" \ | |
"\"https://huggingface.co/spaces/hslu-di/Wiesli_Jonas/resolve/main/img/map.jpg\");background-position:center" \ | |
";background-repeat:no-repeat;background-size:contain}#component-50,#component-57{" \ | |
"position:absolute;top:20px;right:20px;width:44px;height:44px;min-width:44px;min-height:44px}.output-class" \ | |
".svelte-1s28oeb.svelte-1s28oeb.svelte-1s28oeb,div.svelte-1eq475l{font-weight:400}" | |
with gr.Blocks(theme=theme, css=css) as iface: | |
chatbot = [] | |
msg = [] | |
accusationButtons = [] | |
culpritId = 3 | |
names = ["Steve Binner", "Albert Wright", "Dominic Schwartz", "Brianna Small", "Lyanne Brimes"] | |
roles = ["Security Guard", "Curator", "Researcher", "Conservationist", "Tour Guide"] | |
initText = ["You are Steve Binner, 31, a security guard for a museum of medieval history. You're absolutely sure " | |
"that this place is haunted. A month ago, before the spooky stuff started, you were really happy with " | |
"your job, but that changed real fast. The ghost is a French nobleman named Baron Hugo Antoine the " | |
"Third. You've been trying to tell other people about this, but you've only been laughed at so far. " | |
"But you've got evidence! Every Thursday, around 10pm, the broom closet gets locked from the inside " | |
"and the interior gets wrecked. We're talking pushed over tables, broken containers, " | |
"the whole shebang. When it comes to the murder of director Eisenholz last Thursday, that had to have " | |
"been the ghost, no question. You even have the door card records for the room he was in: After the " | |
"museum closed at 5pm, nobody entered that room till the next morning. Now you're being interrogated " | |
"by a detective. Director Eisenholz has been murdered. You don't use uptight language, and you're not " | |
"super well educated on most stuff, but when it comes to the paranormal, you're an ace. ", | |
"You are Albert Wright, 61, the curator of this museum. You have been the curator here since it " | |
"opened 32 years ago, because your family has close ties with the Eisenholz family. You knew Mister " | |
"Eisenholz since he was a boy and would never hurt him. Even though you weren’t always on the same " | |
"page, your values and traditions were the same, which was very important to you and your families. " | |
"And imagine the scandal it would be, if a member of an upper-class family would commit such an " | |
"atrocity. On the day of the murder, you weren’t in the building the whole day because you were at a " | |
"meeting of another museum you are curating for. It’s very stressful to manage four museums. You and " | |
"Mr. Eisenholz were in a tight spot lately, because you needed something new to display. There " | |
"weren’t a lot of new artefacts lately and the Box Miss Small, the conservationist, was examining, " | |
"wasn’t that promising according to Eisenholz. You were making requests to Mr. Eisenholz if he could " | |
"lend you something novel from his collection of family heirlooms, but he wasn’t as cooperative as " | |
"you’d wished for. Luckily the discovery Miss Small made saved the museum. Brianna Small is a very " | |
"good employee, mostly since that discovery she made. It was her idea to open that box, even though " | |
"Eisenholz said there would be nothing in it. But with her skills, she opened it and - as she’d " | |
"expected - a priceless object was inside. The museum immediately put it on display, since there " | |
"weren’t any new things lately and we had less visitors, but now it’s time for a huge promotion " | |
"campaign. Dominic Schwartz, the conservationist, is an enthusiastic and passionate employee. But his " | |
"passion can push it too far sometimes. I got involved in a discussion with him and Mr. Eisenholz. I " | |
"think it was something about an Artefact we culturally appropriated or something, but I didn’t " | |
"really care. I’m too old for this kind of topics where young people think they have to posture how " | |
"good and right they are. Back in my day things were more normal. Now you're being interrogated by a " | |
"detective. Director Eisenholz has been murdered. Use sophisticated language. You’re an old-fashioned " | |
"gentleman, after all. ", | |
"Your are Dominic Schwartz, 35, and the researcher in this museum. Start the conversation by " | |
"explaining that you love the history of medieval times, mostly regarding French monarchs. You are so " | |
"lucky to be able to work in this museum and do the research of the artefacts! Inform the detective " | |
"about various neat facts about French medieval history. Importantly, mention that the museum uses a " | |
"lot of symbols of a dragon to make everything look more authentic, even though back in the day they " | |
"weren’t depicted and for sure not in France, since in France, the depiction of a beast was the " | |
"lougarou; a half bear half wolf creature. You may have exposed a bit too much here, " | |
"but it’s probably fine, since only an expert in this field (such as yourself, of course) would know " | |
"this. Brianna, the conservationist, only cares about things she was involved with, anything other " | |
"she doesn’t mind if it breaks. Now you're being interrogated by a detective. Director Eisenholz has " | |
"been murdered. Your personality is enthusiastic, but slightly arrogant. Your thoughts tend to bounce " | |
"all over the place.", | |
"You are Brianna Small, 43, a conservationist at a museum of medieval history, but you would call " | |
"yourself almost the scientist. You worked here for decades at the same position, but you are hoping " | |
"for a promotion soon. You knew the victim mainly because he was owner of almost 50% of the artefacts " | |
"in this museum and, as a conservationist, you held a few meetings with him discussing the " | |
"preservation. You had a few inputs and ideas on the display and handling of the artefacts and " | |
"Eisenholz usually agreed, which made working with him pleasant. At the night of the murder, " | |
"you left the building at 18:00 because you made a new discovery a few days ago and wanted to " | |
"document it. Your office is in the west wing and has a small window where you saw Steve pass by a " | |
"few times. You think Steve could have been the murderer because he has access to every room and has " | |
"been acting crazy lately. He thinks ghosts are real but from a scientific viewpoint that could never " | |
"be true. You do have access to the storage room, but you don’t know why that would be important. " | |
"Your co-worker who left a few months ago did it so it’s not a room that interests you. Only talk " | |
"about this if specifically asked about the box: A few weeks ago, Eisenholz donated a new artefact to " | |
"the museum. It was a box made of wood with magnificent engravings, but it was sealed. You asked " | |
"Eisenholz if you could try to open it and, with your skills of a conservationist, you’d be able to " | |
"do so without damaging the box. Eisenholz was hesitant at first, but after a few discussions he let " | |
"me do it. And of course, it worked. What you found was beyond imagination. There was a golden ring " | |
"inside in perfect condition. It had the form of a dragon with ruby crystals as eyes. Since this is a " | |
"valuable discovery and the museum hasn’t got anything new lately, you will talk to the director as " | |
"soon as possible to immediately display it in a secure glass container. Let’s see if Dominic, " | |
"a researcher at the museum, can find out anything about the ring. He has been occupied lately on an " | |
"artefact he thinks doesn’t belong here. If he keeps up his extremist attitude, he will cost us all " | |
"the museum and our jobs. Now you're being interrogated by a detective. Director Eisenholz has been " | |
"murdered. You are very ambitious. ", | |
"You are Lyanne Brimes, 27, a tour guide for a museum of medieval history. You graduated college a " | |
"few years ago and have a degree in history. You work here part time. You know director Eisenholz " | |
"very well because you had a secret relationship with him. You met every Thursday in the broom " | |
"closet. You thought nobody knew, but you are not sure anymore. Lately Eisenholz was behaving very " | |
"strangely. Something was bothering him. You wanted to talk with him about it on the night of the " | |
"murder, but he never came. After waiting for 2 hours in the closet, you decided to go home. On your " | |
"way out, you noticed the door to the storage room was open but thought it might have been Steve (the " | |
"security guard) lurking around. Some might think Steve could be the murderer because he has been out " | |
"of his mind lately with his whole ghost thing, and because he has access to every room, " | |
"but you don’t think he could have done it because he is kind-hearted. You are not the murderer, " | |
"but if you had to guess who it was, you would say it was the curator. The curator and Eisenholz were " | |
"fighting lately because a medallion, that has been in his family possession for centuries, " | |
"but he didn’t want to give it to the museum because it was too valuable. You don’t know Brianna " | |
"Small (the conservationist) very well, but if you had to say something about her, it would be that " | |
"she is very smart and ambitious. Now you're being interrogated by a detective. Director Eisenholz " | |
"has been murdered. You use formal language, and you are very well educated in history stuff, " | |
"mostly medieval. You have a bubbly personality. "] | |
with gr.Row() as chatRow: | |
with gr.Column(scale=1): | |
questionCounter = gr.Label(label="Remaining Questions", value="4") | |
mapButton = gr.Button("Show Floor Plan") | |
finishButton = gr.Button("Pick a Culprit") | |
with gr.Column(scale=7): | |
i = 0 | |
while i < len(roles): | |
with gr.Tab(roles[i]): | |
with gr.Row(): | |
with gr.Column(scale=9): | |
chatbot.append(gr.Chatbot(label=names[i] + ", " + roles[i])) | |
msg.append(gr.Textbox(label="", placeholder="Ask a question...")) | |
with gr.Column(scale=3): | |
characterImage = gr.Label(label="") | |
i += 1 | |
with gr.Row(visible=False) as mapRow: | |
with gr.Column(): | |
closeMapButton = gr.Button("X") | |
with gr.Row(visible=False) as solvingRow: | |
i = 0 | |
while i < len(roles): | |
accusationButtons.append(gr.Button(roles[i])) | |
i += 1 | |
closeSolvingButton = gr.Button("X") | |
with gr.Row(visible=False) as resultRow: | |
with gr.Column(): | |
resultLabel = gr.Label(label="Result") | |
def user(user_message, history): | |
return "", history + [[user_message, None]] | |
# this is an ugly workaround, you cannot pass regular integers to gradio functions, so i had to do it this way | |
def bot0(history, question_counter_text): | |
return bot(0, history, question_counter_text) | |
def bot1(history, question_counter_text): | |
return bot(1, history, question_counter_text) | |
def bot2(history, question_counter_text): | |
return bot(2, history, question_counter_text) | |
def bot3(history, question_counter_text): | |
return bot(3, history, question_counter_text) | |
def bot4(history, question_counter_text): | |
return bot(4, history, question_counter_text) | |
def bot(number, history, question_counter_text): | |
bot_message = generate_ai_message(history, question_counter_text, number) | |
history[-1][1] = bot_message | |
return history | |
def generate_ai_message(history, question_counter_text, character_id): | |
if check_if_questions_left(question_counter_text): | |
init_sys_message = initText[character_id] + "Stay in character. Use natural language. Don't reveal all of" \ | |
"the information in a single message, and leave hints. Never " \ | |
"reveal everything in a single message." | |
message_history = [ | |
{"role": "system", "content": init_sys_message} | |
] | |
for pair in history: | |
message_history.append({"role": "user", "content": pair[0]}) | |
print() | |
if pair[1] is not None: | |
message_history.append({"role": "assistant", "content": pair[1]}) | |
completion = openai.ChatCompletion.create( | |
model="gpt-3.5-turbo", | |
messages=message_history | |
) | |
return completion.choices[0].message.content | |
else: | |
return "--- YOU'VE RUN OUT OF QUESTIONS, MAKE YOUR CHOICE ---" | |
def update_questions(question_counter_text): | |
remaining_questions = int(question_counter_text["label"]) | |
if remaining_questions > 0: | |
remaining_questions -= 1 | |
return str(remaining_questions) | |
def check_if_questions_left(question_counter_text): | |
remaining_questions = int(question_counter_text["label"]) | |
return remaining_questions > 0 | |
def disable_input(): | |
return gr.update(interactive=False, placeholder="Waiting for an answer..."), \ | |
gr.update(interactive=False, placeholder="Waiting for an answer..."), \ | |
gr.update(interactive=False, placeholder="Waiting for an answer..."), \ | |
gr.update(interactive=False, placeholder="Waiting for an answer..."), \ | |
gr.update(interactive=False, placeholder="Waiting for an answer...") | |
def enable_input(): | |
return gr.update(interactive=True, placeholder="Ask a question..."), \ | |
gr.update(interactive=True, placeholder="Ask a question..."), \ | |
gr.update(interactive=True, placeholder="Ask a question..."), \ | |
gr.update(interactive=True, placeholder="Ask a question..."), \ | |
gr.update(interactive=True, placeholder="Ask a question...") | |
def try_to_solve(): | |
return {solvingRow: gr.update(visible=True)} | |
def show_map(): | |
return {mapRow: gr.update(visible=True)} | |
def hide_solve_box(): | |
return {solvingRow: gr.update(visible=False)} | |
def hide_map(): | |
return {mapRow: gr.update(visible=False)} | |
def show_result(): | |
return { | |
chatRow: gr.update(visible=False), | |
solvingRow: gr.update(visible=False), | |
resultRow: gr.update(visible=True) | |
} | |
def declare_loss(): | |
return "You failed! The real culprit got away... " | |
def declare_victory(): | |
return "Congratulations, you found the killer! " | |
bot_functions = [bot0, bot1, bot2, bot3, bot4] | |
i = 0 | |
while i < len(roles): | |
msg[i].submit( | |
user, [msg[i], chatbot[i]], [msg[i], chatbot[i]], queue=False | |
).then( | |
disable_input, None, [msg[0], msg[1], msg[2], msg[3], msg[4]] | |
).then( | |
bot_functions[i], [chatbot[i], questionCounter], chatbot[i] | |
).then( | |
update_questions, questionCounter, questionCounter | |
).then( | |
enable_input, None, [msg[0], msg[1], msg[2], msg[3], msg[4]] | |
) | |
i += 1 | |
mapButton.click(show_map, None, mapRow) | |
closeMapButton.click(hide_map, None, mapRow) | |
finishButton.click(try_to_solve, None, solvingRow) | |
closeSolvingButton.click(hide_solve_box, None, solvingRow) | |
i = 0 | |
while i < len(roles): | |
if i == culpritId: | |
accusationButtons[i].click( | |
show_result, None, [chatRow, solvingRow, resultRow] | |
).then( | |
declare_victory, None, resultLabel | |
) | |
else: | |
accusationButtons[i].click( | |
show_result, None, [chatRow, solvingRow, resultRow] | |
).then( | |
declare_loss, None, resultLabel | |
) | |
i += 1 | |
iface.launch() | |