woot upgraded guarded to support odds-or-evens game.

modified:   ../app.py
	new file:   activity22-odds-or-evens.yaml
	modified:   guarded_ai.py
This commit is contained in:
Russell Ballestrini 2024-08-11 08:43:47 -04:00
parent 3902ff48da
commit 14dd105d03
3 changed files with 174 additions and 14 deletions

20
app.py
View file

@ -2045,6 +2045,17 @@ def display_activity_metadata(room_name, username):
)
def execute_processing_script(metadata, script):
# Prepare the local environment for the script
local_env = {"metadata": metadata, "script_result": None}
# Execute the script
exec(script, {}, local_env)
# Return the result from the script
return local_env["script_result"]
def handle_activity_response(room_name, user_response, username):
with app.app_context():
room = get_room(room_name)
@ -2230,6 +2241,15 @@ def handle_activity_response(room_name, user_response, username):
metadata_tmp_keys.append(random_key)
activity_state.add_metadata(random_key, random_value)
# Execute the processing script if it exists
if "processing_script" in step:
result = execute_processing_script(
activity_state.dict_metadata, step["processing_script"]
)
# Add the result to the temporary metadata for use in AI feedback
metadata_tmp_keys.append("processing_script_result")
activity_state.add_metadata("processing_script_result", result)
print(activity_state.dict_metadata)
# Commit the changes after the loop

View file

@ -0,0 +1,101 @@
default_max_attempts_per_step: 30
sections:
- section_id: "section_1"
title: "Odds and Evens with History"
steps:
- step_id: "step_0"
title: "Challenge a Historical Figure"
content_blocks:
- "Welcome to the Odds and Evens challenge! 🎮"
- "You will be playing against a random historical figure."
- step_id: "step_1"
title: "Throw Your Fingers"
tokens_for_ai: |
Careful to check if user is trying to 'set_language' and do that first. Otherwise, figure out if they are picking a number between 0 and 5.
feedback_tokens_for_ai: |
Important, you do not have to calculate the winner, we have
under processing_script_result for you that determines the winner.
Important, you do not pick a random move, it was selected for you:
* 'ai_choice_finger': it's your number of fingers up that you will announce to the user.
* 'ai_choice': it's your guess of odd or even that you will announce to the user.
Speaking in first person as a historical figure, first always announce the move
selected for you and then move to a new line.
The rules are simple, the processing_script_result to determines winner or tie.
* Sum the numbers.
* If the sum of the fingers is even, the player who chose "even" wins.
* If the sum is odd, the player who chose "odd" wins.
* If both players are wrong or right about "odd" or "even" it's a tie.
* A user cannot win unless they have a match with the game name "odd" or "even"
Careful it's easy to add wrong or say a number is odd when it's even and vice versa.
Finally, continue to provide a witty fact as the figure. Don't ever mention AI.
The figure should also comment on the 'attempts' number and how many times played!
If you feel like it, jeer at the player about an early 'exit' & suggest they quit.
processing_script: |
user_input = metadata["user_choice"].split()
user_fingers = None
user_choice = None
for item in user_input:
if item.isdigit():
user_fingers = int(item)
elif item in ["odd", "even"]:
user_choice = item
ai_fingers = int(metadata["ai_choice_finger"]) # Ensure ai_fingers is an integer
ai_choice = metadata["ai_choice"]
total_fingers = user_fingers + ai_fingers
result = "even" if total_fingers % 2 == 0 else "odd"
user_wins = (result == user_choice)
ai_wins = (result == ai_choice)
if user_wins and not ai_wins:
winner = "User wins!"
elif ai_wins and not user_wins:
winner = "AI wins!"
else:
winner = "It's a tie!"
script_result = {"sum": total_fingers, "result": result, "winner": winner}
question: "How many fingers do you throw? (Choose a number between 0 and 5 & either even or odd.) 🤔"
buckets:
- throw_fingers
- set_language
- exit
transitions:
throw_fingers:
ai_feedback:
tokens_for_ai: "Declare your move and then determine who wins the game and provide a witty fact from the historical figure's perspective."
metadata_add:
attempts: "n+1"
metadata_tmp_add:
user_choice: "the-users-response"
ai_choice_finger: "n+random(0,5)"
metadata_tmp_random:
ai_choice: odd
ai_choice: even
next_section_and_step: "section_1:step_1"
set_language:
content_blocks:
- "Language preference updated. Please continue in your preferred language."
ai_feedback:
tokens_for_ai: "Acknowledge the language change and confirm the update."
metadata_add:
language: "the-users-response"
counts_as_attempt: false
exit:
next_section_and_step: "section_2:step_1"
- section_id: "section_2"
title: "Goodbye"
steps:
- step_id: "step_1"
title: "Exit"
content_blocks:
- "Thank you for playing! We hope you enjoyed the game. Have a great day! 🌟"

View file

@ -43,7 +43,7 @@ def categorize_response(question, response, buckets, tokens_for_ai):
# Generate AI feedback using gpt-4o-mini
def generate_ai_feedback(category, question, user_response, tokens_for_ai):
def generate_ai_feedback(category, question, user_response, tokens_for_ai, metadata):
messages = [
{
"role": "system",
@ -51,7 +51,7 @@ def generate_ai_feedback(category, question, user_response, tokens_for_ai):
},
{
"role": "user",
"content": f"Question: {question}\nResponse: {user_response}\nCategory: {category}",
"content": f"Question: {question}\nResponse: {user_response}\nCategory: {category},\nMetadata: {metadata}",
},
]
@ -67,19 +67,36 @@ def generate_ai_feedback(category, question, user_response, tokens_for_ai):
# Provide feedback based on the category
def provide_feedback(
transition, category, question, user_response, user_language, tokens_for_ai
transition,
category,
question,
user_response,
user_language,
tokens_for_ai,
metadata,
):
feedback = ""
if "ai_feedback" in transition:
tokens_for_ai += f" Provide the feedback in {user_language}. {transition['ai_feedback'].get('tokens_for_ai', '')}."
ai_feedback = generate_ai_feedback(
category, question, user_response, tokens_for_ai
category, question, user_response, tokens_for_ai, metadata
)
feedback += f"\n\nAI Feedback: {ai_feedback}"
return feedback
def execute_processing_script(metadata, script):
# Prepare the local environment for the script
local_env = {"metadata": metadata, "script_result": None}
# Execute the script
exec(script, {}, local_env)
# Return the result from the script
return local_env["script_result"]
def get_next_section_and_step(activity_content, current_section_id, current_step_id):
for section in activity_content["sections"]:
if section["section_id"] == current_section_id:
@ -208,16 +225,6 @@ def simulate_activity(yaml_file_path):
)
print(translated_transition_content)
feedback = provide_feedback(
transition,
category,
question,
user_response,
user_language,
step["tokens_for_ai"],
)
print(f"\nFeedback: {feedback}")
# Track temporary metadata keys
metadata_tmp_keys = []
@ -246,6 +253,20 @@ def simulate_activity(yaml_file_path):
for key, value in transition["metadata_tmp_add"].items():
if value == "the-users-response":
value = user_response
elif isinstance(value, str):
if value.startswith("n+random(") and value.endswith(")"):
# Extract the range and apply the random increment
range_values = value[9:-1].split(",")
if len(range_values) == 2:
x, y = map(int, range_values)
value = random.randint(x, y)
elif value.startswith("n+") or value.startswith("n-"):
# Extract the numeric part c and apply the operation +/-
c = int(value[1:])
if value.startswith("n+"):
value = metadata.get(key, 0) + c
elif value.startswith("n-"):
value = metadata.get(key, 0) - c
metadata[key] = value
metadata_tmp_keys.append(key) # Track temporary keys
@ -268,8 +289,26 @@ def simulate_activity(yaml_file_path):
metadata[random_key] = random_value
metadata_tmp_keys.append(random_key) # Track temporary keys
# Execute the processing script if it exists
if "processing_script" in step:
result = execute_processing_script(metadata, step["processing_script"])
metadata["processing_script_result"] = result
metadata_tmp_keys.append("processing_script_result")
print(f"\nMetadata: {json.dumps(metadata, indent=2)}")
# Provide feedback based on the category
feedback = provide_feedback(
transition,
category,
question,
user_response,
user_language,
step.get("feedback_tokens_for_ai", ""),
metadata,
)
print(f"\nFeedback: {feedback}")
if category not in [
"partial_understanding",
"limited_effort",