Spaces:
Runtime error
Runtime error
| import asyncio | |
| import streamlit as st | |
| from dotenv import load_dotenv | |
| import os | |
| import random | |
| from middle_earth_adventure.constants import ALL_NAMES, ALL_SKILLS, ALL_TYPES, TEXT_MODEL, AUDIO_MODEL | |
| from middle_earth_adventure.game_core import GameCore | |
| from middle_earth_adventure.prompts import IMAGE_PROMPT | |
| from middle_earth_adventure.utils import are_all_options_are_filled, check_valid_player, pick_rand_index, pick_rand_items | |
| from middle_earth_adventure.schemas import Player, TechSpecs | |
| ################ BACKEND CODE ################ | |
| load_dotenv() | |
| key = os.environ.get("OPENAI_PERSONAL_KEY") | |
| # state-variables initialization | |
| if "text_area_value" not in st.session_state: | |
| st.session_state.text_area_value = "Choose you character..." | |
| if "player" not in st.session_state: | |
| st.session_state.player = None | |
| if "tech_specs" not in st.session_state: | |
| st.session_state.tech_specs = TechSpecs(narrator_voice="nova", image_model="", game_lenght=0) | |
| if "image" not in st.session_state: | |
| st.session_state.image = "resources/intro.jpg" | |
| if "narrator_audio"not in st.session_state: | |
| st.session_state.narrator_audio = None | |
| if "game"not in st.session_state: | |
| st.session_state.game = GameCore(api_key=key, text_model=TEXT_MODEL, tts_model=AUDIO_MODEL) | |
| if "game_iteration" not in st.session_state: | |
| st.session_state.game_iteration = 0 | |
| if "rand" not in st.session_state: | |
| st.session_state.rand = random.random() | |
| game = st.session_state.game | |
| async def progress_game(text_to_write, selection=None, start=False): | |
| with st.spinner('Loading...'): | |
| # utils | |
| player = st.session_state.player | |
| tech_specs = st.session_state.tech_specs | |
| st.session_state.game_iteration += 1 # count game rounds | |
| check_valid_player(player=st.session_state.player) | |
| # write text | |
| st.write(text_to_write) | |
| # Chat completion | |
| if start: | |
| narration_txt = await game.start_adventure(player=player) | |
| elif st.session_state.game_iteration < tech_specs.game_lenght: | |
| narration_txt = await game.continue_adventure(player=player, selection=selection) | |
| elif st.session_state.game_iteration == tech_specs.game_lenght: | |
| narration_txt = await game.finish_adventure(player=player, selection=selection) | |
| else: | |
| narration_txt = "Game has ended. Thanks for playing!" | |
| # update | |
| st.session_state.text_area_value = narration_txt # update | |
| # Text to Speech | |
| mp3_audio_bytes = await game.narrate_adventure_out_loud(narration_txt, tech_specs.narrator_voice) | |
| st.session_state.narrator_audio = mp3_audio_bytes # update | |
| # Text to image generation | |
| prompt = IMAGE_PROMPT.format(narration=narration_txt, response_format='b64_json',name=name, sex=sex, type=character_type) | |
| image_url = await game.generate_picture_of_the_adventure(prompt, tech_specs.image_model) | |
| st.session_state.image = image_url | |
| # Re-run to update states | |
| st.rerun() | |
| default_name = ALL_NAMES[pick_rand_index(ALL_NAMES)] | |
| default_type = pick_rand_index(ALL_TYPES) | |
| default_skills = pick_rand_items(ALL_SKILLS, 2) | |
| ################ USER INTERFACE (Streamlit) ################ | |
| # Title | |
| st.title("Middle Earth Adventures") | |
| # Character and Game Selection | |
| with st.form("selection_form"): | |
| # Tech Specs | |
| with st.expander("Technical Specs", expanded=False): | |
| narrator_voice = st.radio("Narrator's Voice", ["nova", "echo"], index=0) | |
| image_model = st.radio("Image Model", ['dall-e-2', 'dall-e-3'], index=1) | |
| game_lenght = st.selectbox("Game Lenght (nr of conversation turns)", [5, 7, 10, 15, 20], index=2) | |
| # Character Selection | |
| with st.expander("Character Selection", expanded=True): | |
| name = st.text_input("Name", value=default_name) | |
| character_type = st.selectbox("Type", ALL_TYPES, index=default_type) | |
| sex = st.radio("Gender", ["she", "he"], index=0) | |
| skills = st.multiselect("Skills (pick 2)", ALL_SKILLS, max_selections=2, help="") | |
| submit_button = st.form_submit_button("Create Character", use_container_width=True) | |
| if submit_button: | |
| # write player | |
| player = Player(name=name, type=character_type, sex=sex, skills=skills) | |
| st.session_state.player = player | |
| # write tech-specs | |
| tech_specs = TechSpecs(narrator_voice=narrator_voice, image_model=image_model, | |
| game_lenght=game_lenght) | |
| st.session_state.tech_specs = tech_specs | |
| # start adventure | |
| message = f"You are {name}, {sex} is a {character_type}. Your are good at {' and '.join(skills)}" | |
| if are_all_options_are_filled(player, name, character_type, sex, skills): | |
| asyncio.run(progress_game(message, start=True)) | |
| else: | |
| st.toast("Invalid character definition!") | |
| # Story Image | |
| st.image(st.session_state.image, use_column_width=True) | |
| # Story text | |
| st.markdown(f'{st.session_state.text_area_value}') | |
| # Narrator's Audio | |
| st.audio(st.session_state.narrator_audio, format="audio/mp3", start_time=0, loop=False, autoplay=False) | |
| # Action Buttons | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| if st.button("A", use_container_width=True) and check_valid_player(st.session_state.player): | |
| asyncio.run(progress_game("You chose option A", selection="A")) | |
| with col2: | |
| if st.button("B", use_container_width=True) and check_valid_player(st.session_state.player): | |
| asyncio.run(progress_game("You chose option B", selection="B")) | |
| with col3: | |
| if st.button("C", use_container_width=True) and check_valid_player(st.session_state.player): | |
| asyncio.run(progress_game("You chose option C", selection="C")) | |