Spaces:
Runtime error
Runtime error
Commit ·
520c904
1
Parent(s): 0974473
resolved random issue
Browse files- app.py +20 -25
- middle_earth_adventure/constants.py +4 -7
- middle_earth_adventure/game_core.py +14 -10
- middle_earth_adventure/prompts.py +2 -1
- middle_earth_adventure/schemas.py +0 -1
- middle_earth_adventure/utils.py +10 -3
app.py
CHANGED
|
@@ -20,7 +20,7 @@ if "text_area_value" not in st.session_state:
|
|
| 20 |
if "player" not in st.session_state:
|
| 21 |
st.session_state.player = None
|
| 22 |
if "tech_specs" not in st.session_state:
|
| 23 |
-
st.session_state.tech_specs = TechSpecs(narrator_voice="nova", image_model="",
|
| 24 |
if "image" not in st.session_state:
|
| 25 |
st.session_state.image = "resources/intro.jpg"
|
| 26 |
if "narrator_audio"not in st.session_state:
|
|
@@ -61,7 +61,7 @@ async def progress_game(text_to_write, selection=None, start=False):
|
|
| 61 |
|
| 62 |
# Text to image generation
|
| 63 |
prompt = IMAGE_PROMPT.format(narration=narration_txt, response_format='b64_json',name=name, sex=sex, type=character_type)
|
| 64 |
-
image_url = await game.generate_picture_of_the_adventure(prompt, tech_specs.image_model
|
| 65 |
st.session_state.image = image_url
|
| 66 |
|
| 67 |
# Re-run to update states
|
|
@@ -76,34 +76,29 @@ default_skills = pick_rand_items(ALL_SKILLS, 2)
|
|
| 76 |
# Title
|
| 77 |
st.title("Middle Earth Adventures")
|
| 78 |
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
# Character Selection
|
| 89 |
-
with st.expander("Character Selection", expanded=True):
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
else:
|
| 97 |
-
final_selection = character_type
|
| 98 |
-
sex = st.radio("Gender", ["she", "he"], index=0)
|
| 99 |
-
skills = st.multiselect("Skills (pick 2)", ALL_SKILLS, max_selections=2, help="")
|
| 100 |
-
if st.button("Create Character", use_container_width=True):
|
| 101 |
# write player
|
| 102 |
player = Player(name=name, type=character_type, sex=sex, skills=skills)
|
| 103 |
st.session_state.player = player
|
| 104 |
# write tech-specs
|
| 105 |
tech_specs = TechSpecs(narrator_voice=narrator_voice, image_model=image_model,
|
| 106 |
-
|
| 107 |
st.session_state.tech_specs = tech_specs
|
| 108 |
# start adventure
|
| 109 |
message = f"You are {name}, {sex} is a {character_type}. Your are good at {' and '.join(skills)}"
|
|
|
|
| 20 |
if "player" not in st.session_state:
|
| 21 |
st.session_state.player = None
|
| 22 |
if "tech_specs" not in st.session_state:
|
| 23 |
+
st.session_state.tech_specs = TechSpecs(narrator_voice="nova", image_model="", game_lenght=0)
|
| 24 |
if "image" not in st.session_state:
|
| 25 |
st.session_state.image = "resources/intro.jpg"
|
| 26 |
if "narrator_audio"not in st.session_state:
|
|
|
|
| 61 |
|
| 62 |
# Text to image generation
|
| 63 |
prompt = IMAGE_PROMPT.format(narration=narration_txt, response_format='b64_json',name=name, sex=sex, type=character_type)
|
| 64 |
+
image_url = await game.generate_picture_of_the_adventure(prompt, tech_specs.image_model)
|
| 65 |
st.session_state.image = image_url
|
| 66 |
|
| 67 |
# Re-run to update states
|
|
|
|
| 76 |
# Title
|
| 77 |
st.title("Middle Earth Adventures")
|
| 78 |
|
| 79 |
+
|
| 80 |
+
# Character and Game Selection
|
| 81 |
+
with st.form("selection_form"):
|
| 82 |
+
# Tech Specs
|
| 83 |
+
with st.expander("Technical Specs", expanded=False):
|
| 84 |
+
narrator_voice = st.radio("Narrator's Voice", ["nova", "echo"], index=0)
|
| 85 |
+
image_model = st.radio("Image Model", ['dall-e-2', 'dall-e-3'], index=1)
|
| 86 |
+
game_lenght = st.selectbox("Game Lenght (nr of conversation turns)", [5, 7, 10, 15, 20], index=2)
|
| 87 |
+
|
| 88 |
+
# Character Selection
|
| 89 |
+
with st.expander("Character Selection", expanded=True):
|
| 90 |
+
name = st.text_input("Name", value=default_name)
|
| 91 |
+
character_type = st.selectbox("Type", ALL_TYPES, index=default_type)
|
| 92 |
+
sex = st.radio("Gender", ["she", "he"], index=0)
|
| 93 |
+
skills = st.multiselect("Skills (pick 2)", ALL_SKILLS, max_selections=2, help="")
|
| 94 |
+
submit_button = st.form_submit_button("Create Character", use_container_width=True)
|
| 95 |
+
if submit_button:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
# write player
|
| 97 |
player = Player(name=name, type=character_type, sex=sex, skills=skills)
|
| 98 |
st.session_state.player = player
|
| 99 |
# write tech-specs
|
| 100 |
tech_specs = TechSpecs(narrator_voice=narrator_voice, image_model=image_model,
|
| 101 |
+
game_lenght=game_lenght)
|
| 102 |
st.session_state.tech_specs = tech_specs
|
| 103 |
# start adventure
|
| 104 |
message = f"You are {name}, {sex} is a {character_type}. Your are good at {' and '.join(skills)}"
|
middle_earth_adventure/constants.py
CHANGED
|
@@ -14,15 +14,12 @@ OPENAI_KEY = os.environ.get("OPENAI_PERSONAL_KEY")
|
|
| 14 |
|
| 15 |
# Character
|
| 16 |
ALL_SKILLS = ["Speed", "Carisma", "Intelligence", "Force", "Deceit", "Perception", "Stealth", "Creativity", "Dexterity", "Vision"]
|
| 17 |
-
ALL_TYPES = ["Warrior", "Wizard's Apprentice", "Mystical Feline", "Beautiful Ghost", "Naive Wood Elf", "Oktoberfest Peasant"
|
| 18 |
ALL_NAMES = ["Kim", "Gearld", "Yoyo", "Jojee"]
|
| 19 |
|
| 20 |
# Game variability
|
| 21 |
PLAYER_FEELINGS = ["scared", "anxious", "hopeful", "intrigued", "naive"]
|
| 22 |
RIDDLE_OPTIONS = ["greek-inspired", "old-fashion", "funny", "fancy sounding", "human-centered", "animal-inspired"]
|
| 23 |
-
FIGHT_OPTIONS = ["funny", "epic", "magical", "gothic", "
|
| 24 |
-
ROMANCE_OPTIONS = ["
|
| 25 |
-
|
| 26 |
-
"(give me a {opt} riddle)".format(opt=" and ".join(pick_rand_items(RIDDLE_OPTIONS, nr=2))),
|
| 27 |
-
"(give me {opt} romance)".format(opt=" and ".join(pick_rand_items(ROMANCE_OPTIONS, nr=2))),
|
| 28 |
-
"(add an epic building)"]
|
|
|
|
| 14 |
|
| 15 |
# Character
|
| 16 |
ALL_SKILLS = ["Speed", "Carisma", "Intelligence", "Force", "Deceit", "Perception", "Stealth", "Creativity", "Dexterity", "Vision"]
|
| 17 |
+
ALL_TYPES = ["Warrior", "Wizard's Apprentice", "Mystical Feline", "Beautiful Ghost", "Naive Wood Elf", "Oktoberfest Peasant"]
|
| 18 |
ALL_NAMES = ["Kim", "Gearld", "Yoyo", "Jojee"]
|
| 19 |
|
| 20 |
# Game variability
|
| 21 |
PLAYER_FEELINGS = ["scared", "anxious", "hopeful", "intrigued", "naive"]
|
| 22 |
RIDDLE_OPTIONS = ["greek-inspired", "old-fashion", "funny", "fancy sounding", "human-centered", "animal-inspired"]
|
| 23 |
+
FIGHT_OPTIONS = ["funny", "epic", "magical", "gothic", "danger", "mystical", "scary"]
|
| 24 |
+
ROMANCE_OPTIONS = ["mystic", "dramatic", "adventurous", "loyal"]
|
| 25 |
+
|
|
|
|
|
|
|
|
|
middle_earth_adventure/game_core.py
CHANGED
|
@@ -3,14 +3,13 @@ import random
|
|
| 3 |
import time
|
| 4 |
from openai import OpenAI
|
| 5 |
from dotenv import load_dotenv
|
| 6 |
-
from middle_earth_adventure.constants import
|
| 7 |
from middle_earth_adventure.prompts import FINISH_PROMPT, SYSTEM_PROMPT, START_PROMPT, CONTINUE_PROMPT
|
| 8 |
-
from middle_earth_adventure.utils import
|
| 9 |
from middle_earth_adventure.schemas import Player
|
| 10 |
|
| 11 |
load_dotenv()
|
| 12 |
|
| 13 |
-
|
| 14 |
class GameCore:
|
| 15 |
|
| 16 |
def __init__(self, api_key:str, text_model:str, tts_model: str) -> None:
|
|
@@ -38,11 +37,8 @@ class GameCore:
|
|
| 38 |
# Continue Adventure
|
| 39 |
async def continue_adventure(self, selection: str, player: Player):
|
| 40 |
if player is None: return None
|
| 41 |
-
|
| 42 |
-
variants
|
| 43 |
-
feeling = random.choice(PLAYER_FEELINGS)
|
| 44 |
-
print('variants=', variants)
|
| 45 |
-
print('seed=', variants)
|
| 46 |
message= {"role": "user", "content": CONTINUE_PROMPT.format(selection=selection, feeling=feeling, variants=variants)}
|
| 47 |
|
| 48 |
ai_response = self.client.chat.completions.create(messages=[*self.message_history, message], model=self.text_model)
|
|
@@ -74,9 +70,17 @@ class GameCore:
|
|
| 74 |
# audio_base64 = base64.b64encode(mp3_narration).decode('utf-8')
|
| 75 |
return mp3_narration
|
| 76 |
|
| 77 |
-
async def generate_picture_of_the_adventure(self, prompt, model
|
| 78 |
if model == "dall-e-2": size = "512x512"
|
| 79 |
if model == "dall-e-3": size = "1024x1024"
|
| 80 |
image = self.client.images.generate(model=model, prompt=prompt, response_format='url',
|
| 81 |
-
size=size, quality=
|
| 82 |
return (image.data[0].url)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
import time
|
| 4 |
from openai import OpenAI
|
| 5 |
from dotenv import load_dotenv
|
| 6 |
+
from middle_earth_adventure.constants import FIGHT_OPTIONS, PLAYER_FEELINGS, RIDDLE_OPTIONS, ROMANCE_OPTIONS
|
| 7 |
from middle_earth_adventure.prompts import FINISH_PROMPT, SYSTEM_PROMPT, START_PROMPT, CONTINUE_PROMPT
|
| 8 |
+
from middle_earth_adventure.utils import pick_rand_items
|
| 9 |
from middle_earth_adventure.schemas import Player
|
| 10 |
|
| 11 |
load_dotenv()
|
| 12 |
|
|
|
|
| 13 |
class GameCore:
|
| 14 |
|
| 15 |
def __init__(self, api_key:str, text_model:str, tts_model: str) -> None:
|
|
|
|
| 37 |
# Continue Adventure
|
| 38 |
async def continue_adventure(self, selection: str, player: Player):
|
| 39 |
if player is None: return None
|
| 40 |
+
variants, feeling = self.get_game_variations()
|
| 41 |
+
print('variants=', str(variants))
|
|
|
|
|
|
|
|
|
|
| 42 |
message= {"role": "user", "content": CONTINUE_PROMPT.format(selection=selection, feeling=feeling, variants=variants)}
|
| 43 |
|
| 44 |
ai_response = self.client.chat.completions.create(messages=[*self.message_history, message], model=self.text_model)
|
|
|
|
| 70 |
# audio_base64 = base64.b64encode(mp3_narration).decode('utf-8')
|
| 71 |
return mp3_narration
|
| 72 |
|
| 73 |
+
async def generate_picture_of_the_adventure(self, prompt, model):
|
| 74 |
if model == "dall-e-2": size = "512x512"
|
| 75 |
if model == "dall-e-3": size = "1024x1024"
|
| 76 |
image = self.client.images.generate(model=model, prompt=prompt, response_format='url',
|
| 77 |
+
size=size, quality="standard", n=1)
|
| 78 |
return (image.data[0].url)
|
| 79 |
+
|
| 80 |
+
def get_game_variations(self):
|
| 81 |
+
story_variants = ["(give me a {opt} fight)".format(opt=" and ".join(random.sample(FIGHT_OPTIONS, 2))),
|
| 82 |
+
"(give me a {opt} riddle)".format(opt=" and ".join(random.sample(RIDDLE_OPTIONS, 2))),
|
| 83 |
+
"(give me an {opt} character encounter)".format(opt=" and ".join(random.sample(ROMANCE_OPTIONS, 2))),
|
| 84 |
+
"(add an epic building)"]
|
| 85 |
+
feeling = random.choice(PLAYER_FEELINGS)
|
| 86 |
+
return random.choice(story_variants), random.choice(feeling)
|
middle_earth_adventure/prompts.py
CHANGED
|
@@ -39,5 +39,6 @@ Scenic context:
|
|
| 39 |
{narration}
|
| 40 |
|
| 41 |
Hero ({sex} is a 25 year old dutch {type}) and the landscape/situation {sex} is involved are clearly depicted.
|
| 42 |
-
Background is the middle-earth. No text.
|
|
|
|
| 43 |
"""
|
|
|
|
| 39 |
{narration}
|
| 40 |
|
| 41 |
Hero ({sex} is a 25 year old dutch {type}) and the landscape/situation {sex} is involved are clearly depicted.
|
| 42 |
+
Background is the middle-earth. No text.
|
| 43 |
+
I NEED to test how the tool works with extremely simple prompts. DO NOT add any detail, just use it AS-IS.
|
| 44 |
"""
|
middle_earth_adventure/schemas.py
CHANGED
|
@@ -15,5 +15,4 @@ class Player(BaseModel):
|
|
| 15 |
class TechSpecs(BaseModel):
|
| 16 |
narrator_voice: str
|
| 17 |
image_model: str
|
| 18 |
-
image_quality: str
|
| 19 |
game_lenght: int
|
|
|
|
| 15 |
class TechSpecs(BaseModel):
|
| 16 |
narrator_voice: str
|
| 17 |
image_model: str
|
|
|
|
| 18 |
game_lenght: int
|
middle_earth_adventure/utils.py
CHANGED
|
@@ -2,7 +2,7 @@ import streamlit as st
|
|
| 2 |
import random
|
| 3 |
import numpy as np
|
| 4 |
import base64
|
| 5 |
-
|
| 6 |
from middle_earth_adventure.schemas import Player
|
| 7 |
|
| 8 |
def check_valid_player(player: Player):
|
|
@@ -11,12 +11,19 @@ def check_valid_player(player: Player):
|
|
| 11 |
return False
|
| 12 |
return True
|
| 13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
def pick_rand_index(list_to_pick: list):
|
| 15 |
-
|
|
|
|
| 16 |
return index
|
| 17 |
|
| 18 |
def pick_rand_items(list_to_pick: list, nr=2):
|
| 19 |
-
|
|
|
|
| 20 |
return random.sample(list_to_pick, nr)
|
| 21 |
|
| 22 |
def are_all_options_are_filled(player, name, character_type, sex, skills):
|
|
|
|
| 2 |
import random
|
| 3 |
import numpy as np
|
| 4 |
import base64
|
| 5 |
+
import time
|
| 6 |
from middle_earth_adventure.schemas import Player
|
| 7 |
|
| 8 |
def check_valid_player(player: Player):
|
|
|
|
| 11 |
return False
|
| 12 |
return True
|
| 13 |
|
| 14 |
+
def get_rand_number():
|
| 15 |
+
seed = time.time()
|
| 16 |
+
random.seed(seed)
|
| 17 |
+
return random.random(), seed
|
| 18 |
+
|
| 19 |
def pick_rand_index(list_to_pick: list):
|
| 20 |
+
rand_nr, _ = get_rand_number()
|
| 21 |
+
index = int(np.floor(rand_nr*len(list_to_pick)))
|
| 22 |
return index
|
| 23 |
|
| 24 |
def pick_rand_items(list_to_pick: list, nr=2):
|
| 25 |
+
_, seed = get_rand_number()
|
| 26 |
+
random.seed(seed)
|
| 27 |
return random.sample(list_to_pick, nr)
|
| 28 |
|
| 29 |
def are_all_options_are_filled(player, name, character_type, sex, skills):
|