DrGabrielLopez's picture
resolved random issue
520c904
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"))