diff --git a/app.py b/app.py index 370f68f..157494f 100644 --- a/app.py +++ b/app.py @@ -11,6 +11,8 @@ import json import yaml import os +import random + import boto3 import tiktoken import together @@ -2015,6 +2017,36 @@ def handle_activity_response(room_name, user_response, username): ) return + # this gives the llm context on what changed. + new_metadata = {} + + # Update metadata based on user actions + if "metadata_add" in step["transitions"][category]: + for key, value in step["transitions"][category][ + "metadata_add" + ].items(): + new_metadata[key] = value + activity_state.add_metadata(key, value) + + if "metadata_remove" in step["transitions"][category]: + for key in step["transitions"][category]["metadata_remove"]: + activity_state.remove_metadata(key) + + # Handle metadata_random + if "metadata_random" in step["transitions"][category]: + random_key = random.choice( + list(step["transitions"][category]["metadata_random"].keys()) + ) + random_value = step["transitions"][category]["metadata_random"][ + random_key + ] + new_metadata[random_key] = random_value + activity_state.add_metadata(random_key, random_value) + + # Commit the changes after the loop + db.session.add(activity_state) + db.session.commit() + # Provide feedback based on the category feedback, next_section_and_step = provide_feedback( activity_content, @@ -2025,6 +2057,7 @@ def handle_activity_response(room_name, user_response, username): user_response, username, activity_state.json_metadata, + json.dumps(new_metadata), ) # Store and emit the feedback @@ -2066,21 +2099,6 @@ def handle_activity_response(room_name, user_response, username): room=room_name, ) - # Update metadata based on user actions - if "metadata_add" in step["transitions"][category]: - for key, value in step["transitions"][category][ - "metadata_add" - ].items(): - activity_state.add_metadata(key, value) - - if "metadata_remove" in step["transitions"][category]: - for key in step["transitions"][category]["metadata_remove"]: - activity_state.remove_metadata(key) - - # Commit the changes after the loop - db.session.add(activity_state) - db.session.commit() - # if "correct" or max_attempts reached. if ( category @@ -2154,12 +2172,15 @@ def handle_activity_response(room_name, user_response, username): ) except Exception as e: + import traceback + + msg = traceback.format_exc() socketio.emit( "message", { "id": None, "username": "System", - "content": f"Error processing activity response: {e}", + "content": f"Error processing activity response: {e}\n\n{msg}", }, room=room_name, ) @@ -2314,7 +2335,7 @@ def categorize_response(question, response, buckets, tokens_for_ai): completion = openai_client.chat.completions.create( model=model_name, messages=messages, - max_tokens=5, + max_tokens=10, temperature=0, ) category = ( @@ -2326,7 +2347,15 @@ def categorize_response(question, response, buckets, tokens_for_ai): # Generate AI feedback -def generate_ai_feedback(category, question, user_response, tokens_for_ai, username, json_metadata): +def generate_ai_feedback( + category, + question, + user_response, + tokens_for_ai, + username, + json_metadata, + json_new_metadata, +): openai_client, model_name = get_openai_client_and_model() messages = [ { @@ -2335,7 +2364,7 @@ def generate_ai_feedback(category, question, user_response, tokens_for_ai, usern }, { "role": "user", - "content": f"Username: {username}\nQuestion: {question}\nResponse: {user_response}\nCategory: {category}\nMetadata: {json_metadata}", + "content": f"Username: {username}\nQuestion: {question}\nResponse: {user_response}\nCategory: {category}\nMetadata: {json_metadata}\n New Metadata: {json_new_metadata}", }, ] @@ -2350,7 +2379,15 @@ def generate_ai_feedback(category, question, user_response, tokens_for_ai, usern def provide_feedback( - yaml_content, section_id, step_id, category, question, user_response, username, json_metadata + yaml_content, + section_id, + step_id, + category, + question, + user_response, + username, + json_metadata, + json_new_metadata, ): section = next( (s for s in yaml_content["sections"] if s["section_id"] == section_id), None @@ -2372,7 +2409,7 @@ def provide_feedback( step["tokens_for_ai"] + " " + transition["ai_feedback"]["tokens_for_ai"] ) ai_feedback = generate_ai_feedback( - category, question, user_response, tokens_for_ai, username, json_metadata + category, question, user_response, tokens_for_ai, username, json_metadata, json_new_metadata, ) feedback += f"\n\nAI Feedback: {ai_feedback}" diff --git a/research/activity17-choose-adventure.yaml b/research/activity17-choose-adventure.yaml index 39e1e49..078b410 100644 --- a/research/activity17-choose-adventure.yaml +++ b/research/activity17-choose-adventure.yaml @@ -12,81 +12,39 @@ sections: content_blocks: - "You have entered the prize room! ๐ŸŽ" - "A prize is randomly selected for you from the room." - tokens_for_ai: "Randomly select one of the following items as the user's prize. DO NOT select go_back unless you are sure the user wants to go back to the temple pit." + - "You can also go to the temple pit from here." + tokens_for_ai: "DO NOT select go_back unless the users says 'go back' in their message." question: "You have received a prize! Guess what it could be? ๐Ÿค”" buckets: - - prize_1 - - prize_2 - - prize_3 - - prize_4 - - prize_5 - - prize_6 - - prize_7 - - prize_8 - - prize_9 - - prize_10 + - random_prize_guess + - go_to_temple_pit - go_back transitions: - prize_1: + random_prize_guess: + ai_feedback: + tokens_for_ai: "cheer for the player, they got a new item. list them all from metadata. now make a joke about their guess!" + content_blocks: - - "You received Prize 1: A golden keychain. ๐Ÿ—" - next_section_and_step: "section_2:step_1" - metadata_add: + - "You received a random prize! ๐ŸŽฒ" + next_section_and_step: "section_1:step_1" + metadata_random: golden_keychain: true - prize_2: - content_blocks: - - "You received Prize 2: A mysterious amulet. ๐Ÿงฟ" - next_section_and_step: "section_2:step_1" - metadata_add: mysterious_amulet: true - prize_3: - content_blocks: - - "You received Prize 3: A rare gemstone. ๐Ÿ’Ž" - next_section_and_step: "section_2:step_1" - metadata_add: rare_gemstone: true - prize_4: - content_blocks: - - "You received Prize 4: An ancient scroll. ๐Ÿ“œ" - next_section_and_step: "section_2:step_1" - metadata_add: ancient_scroll: true - prize_5: - content_blocks: - - "You received Prize 5: A magical wand. ๐Ÿช„" - next_section_and_step: "section_2:step_1" - metadata_add: magical_wand: true - prize_6: - content_blocks: - - "You received Prize 6: A treasure map. ๐Ÿ—บ" - next_section_and_step: "section_2:step_1" - metadata_add: treasure_map: true - prize_7: - content_blocks: - - "You received Prize 7: A silver coin. ๐Ÿช™" - next_section_and_step: "section_2:step_1" - metadata_add: silver_coin: true - prize_8: - content_blocks: - - "You received Prize 8: A mystical ring. ๐Ÿ’" - next_section_and_step: "section_2:step_1" - metadata_add: mystical_ring: true - prize_9: - content_blocks: - - "You received Prize 9: A rare book. ๐Ÿ“š" - next_section_and_step: "section_2:step_1" - metadata_add: rare_book: true - prize_10: - content_blocks: - - "You received Prize 10: A magical potion. ๐Ÿงช" - next_section_and_step: "section_2:step_1" - metadata_add: magical_potion: true + shadow_charm: true + flame_charm: true + + go_to_temple_pit: + content_blocks: + - "You chose to go to the temple pit room. ๐Ÿ›" + next_section_and_step: "section_2:step_1" go_back: content_blocks: - "You chose to go back to the temple pit room. ๐Ÿ›" @@ -113,6 +71,8 @@ sections: - offer_mystical_ring - offer_rare_book - offer_magical_potion + - offer_shadow_charm + - offer_flame_charm - go_back - off_topic transitions: @@ -226,6 +186,24 @@ sections: golden_keychain: true metadata_remove: magical_potion: true + offer_shadow_charm: + metadata_conditions: + shadow_charm: true + metadata_remove: + shadow_charm: true + content_blocks: + - "You offered the Shadow Charm to the god. ๐Ÿ–ค" + - "The god summons the Shadow Beast! Prepare for battle!" + next_section_and_step: "section_3:step_1" + offer_flame_charm: + metadata_conditions: + flame_charm: true + metadata_remove: + flame_charm: true + content_blocks: + - "You offered the Flame Charm to the god. ๐Ÿ”ฅ" + - "The god summons the Fire Drake! Prepare for battle!" + next_section_and_step: "section_4:step_1" go_back: content_blocks: - "You chose to go back to the prize room. ๐ŸŽ" @@ -234,3 +212,121 @@ sections: ai_feedback: tokens_for_ai: "Gently guide the user back to the story in a supportive manner. DO NOT ask any questions. Use emojis like ๐Ÿ”„ and ๐Ÿงญ." next_section_and_step: "section_2:step_1" + + - section_id: "section_3" + title: "The Dark Cavern" + steps: + - step_id: "step_1" + title: "Battle the Shadow Beast" + content_blocks: + - "You have entered the Dark Cavern. The air is thick with darkness, and a menacing growl echoes around you." + - "A Shadow Beast emerges from the shadows, ready to attack!" + tokens_for_ai: "Guide the user to choose their action based on their items." + question: "Do you fight the Shadow Beast? (You need the Magical Wand or Mystical Ring to win!)" + buckets: + - fight_with_wand + - fight_with_ring + - flee + transitions: + fight_with_wand: + metadata_conditions: + magical_wand: true + content_blocks: + - "You wield the Magical Wand and unleash a powerful spell!" + - "The Shadow Beast is defeated! You find a Shadow Crystal. ๐Ÿ’Ž" + next_section_and_step: "section_5:step_1" + metadata_add: + shadow_crystal: true + fight_with_ring: + metadata_conditions: + mystical_ring: true + content_blocks: + - "You use the Mystical Ring to channel your inner light!" + - "The Shadow Beast is defeated! You find a Shadow Crystal. ๐Ÿ’Ž" + next_section_and_step: "section_5:step_1" + metadata_add: + shadow_crystal: true + flee: + content_blocks: + - "You attempt to flee, but the Shadow Beast catches you. You have met your end. ๐Ÿ’€" + next_section_and_step: "death_ending:step_1" + + - section_id: "section_4" + title: "The Fiery Lair" + steps: + - step_id: "step_1" + title: "Battle the Fire Drake" + content_blocks: + - "You have entered the Fiery Lair. The heat is intense, and flames flicker around you." + - "A Fire Drake roars, ready to defend its territory!" + tokens_for_ai: "Guide the user to choose their action based on their items." + question: "Do you fight the Fire Drake? (You need the Treasure Map or Ancient Scroll to win!)" + buckets: + - fight_with_map + - fight_with_scroll + - flee + transitions: + fight_with_map: + metadata_conditions: + treasure_map: true + content_blocks: + - "You use the Treasure Map to find the Drake's weak spot!" + - "The Fire Drake is defeated! You find a Flame Pendant. ๐Ÿ”ฅ" + next_section_and_step: "section_5:step_1" + metadata_add: + flame_pendant: true + fight_with_scroll: + metadata_conditions: + ancient_scroll: true + content_blocks: + - "You read the Ancient Scroll and summon a powerful fire shield!" + - "The Fire Drake is defeated! You find a Flame Pendant. ๐Ÿ”ฅ" + next_section_and_step: "section_5:step_1" + metadata_add: + flame_pendant: true + flee: + content_blocks: + - "You attempt to flee, but the Fire Drake incinerates you. You have met your end. ๐Ÿ’€" + next_section_and_step: "death_ending_fire:step_1" + + - section_id: "section_5" + title: "The Final Path" + steps: + - step_id: "step_1" + title: "The Final Path" + content_blocks: + - "You have defeated the monster and continue on your journey." + - "You see a path leading to the final destination." + tokens_for_ai: "Guide the user to the final victory." + question: "Do you continue on the path to victory? ๐Ÿค”" + buckets: + - continue_to_victory + transitions: + continue_to_victory: + content_blocks: + - "You walk down the path and reach the final destination. You are victorious! ๐Ÿ†" + next_section_and_step: "victory:step_1" + + - section_id: "death_ending" + title: "The Abyss of Shadows" + steps: + - step_id: "step_1" + title: "Death Ending" + content_blocks: + - "Game Over." + + - section_id: "death_ending_fire" + title: "The Ashen Wastes" + steps: + - step_id: "step_1" + title: "Death Ending" + content_blocks: + - "Game Over." + + - section_id: "victory" + title: "Victory" + steps: + - step_id: "step_1" + title: "Victory" + content_blocks: + - "Thank you for playing!"