import pytest import logging logger = logging.getLogger("tinytroupe") import sys sys.path.insert(0, '../../tinytroupe/') # ensures that the package is imported from the parent directory, not the Python installation sys.path.insert(0, '../../') # ensures that the package is imported from the parent directory, not the Python installation sys.path.insert(0, '..') # ensures that the package is imported from the parent directory, not the Python installation #sys.path.append('../../tinytroupe/') #sys.path.append('../../') #sys.path.append('..') from tinytroupe.examples import create_oscar_the_architect, create_oscar_the_architect_2, create_lisa_the_data_scientist, create_lisa_the_data_scientist_2 from testing_utils import * def test_act(setup): for agent in [create_oscar_the_architect(), create_lisa_the_data_scientist()]: actions = agent.listen_and_act("Tell me a bit about your life.", return_actions=True) logger.info(agent.pp_current_interactions()) assert len(actions) >= 1, f"{agent.name} should have at least one action to perform (even if it is just DONE)." assert contains_action_type(actions, "TALK"), f"{agent.name} should have at least one TALK action to perform, since we asked him to do so." assert terminates_with_action_type(actions, "DONE"), f"{agent.name} should always terminate with a DONE action." def test_listen(setup): # test that the agent listens to a speech stimulus and updates its current messages for agent in [create_oscar_the_architect(), create_lisa_the_data_scientist()]: agent.listen("Hello, how are you?") assert len(agent.current_messages) > 0, f"{agent.name} should have at least one message in its current messages." assert agent.episodic_memory.retrieve_all()[-1]['role'] == 'user', f"{agent.name} should have the last message as 'user'." assert agent.episodic_memory.retrieve_all()[-1]['content']['stimuli'][0]['type'] == 'CONVERSATION', f"{agent.name} should have the last message as a 'CONVERSATION' stimulus." assert agent.episodic_memory.retrieve_all()[-1]['content']['stimuli'][0]['content'] == 'Hello, how are you?', f"{agent.name} should have the last message with the correct content." def test_define(setup): # test that the agent defines a value to its configuration and resets its prompt for agent in [create_oscar_the_architect(), create_lisa_the_data_scientist()]: # save the original prompt original_prompt = agent.current_messages[0]['content'] # define a new value agent.define('age', 25) # check that the configuration has the new value assert agent._persona['age'] == 25, f"{agent.name} should have the age set to 25." # check that the prompt has changed assert agent.current_messages[0]['content'] != original_prompt, f"{agent.name} should have a different prompt after defining a new value." # check that the prompt contains the new value assert '25' in agent.current_messages[0]['content'], f"{agent.name} should have the age in the prompt." def test_define_several(setup): # Test that defining several values to a group works as expected for agent in [create_oscar_the_architect(), create_lisa_the_data_scientist()]: agent.define("skills", ["Python", "Machine learning", "GPT-3"]) assert "Python" in agent._persona["skills"], f"{agent.name} should have Python as a skill." assert "Machine learning" in agent._persona["skills"], f"{agent.name} should have Machine learning as a skill." assert "GPT-3" in agent._persona["skills"], f"{agent.name} should have GPT-3 as a skill." def test_socialize(setup): # Test that socializing with another agent works as expected an_oscar = create_oscar_the_architect() a_lisa = create_lisa_the_data_scientist() for agent in [an_oscar, a_lisa]: other = a_lisa if agent.name == "Oscar" else an_oscar agent.make_agent_accessible(other, relation_description="My friend") agent.listen(f"Hi {agent.name}, I am {other.name}.") actions = agent.act(return_actions=True) assert len(actions) >= 1, f"{agent.name} should have at least one action to perform." assert contains_action_type(actions, "TALK"), f"{agent.name} should have at least one TALK action to perform, since we started a conversation." assert contains_action_content(actions, agent_first_name(other)), f"{agent.name} should mention {other.name}'s first name in the TALK action, since they are friends." def test_see(setup): # Test that seeing a visual stimulus works as expected for agent in [create_oscar_the_architect(), create_lisa_the_data_scientist()]: agent.see("A beautiful sunset over the ocean.") actions = agent.act(return_actions=True) assert len(actions) >= 1, f"{agent.name} should have at least one action to perform." assert contains_action_type(actions, "THINK"), f"{agent.name} should have at least one THINK action to perform, since they saw something interesting." assert contains_action_content(actions, "sunset"), f"{agent.name} should mention the sunset in the THINK action, since they saw it." def test_think(setup): # Test that thinking about something works as expected for agent in [create_oscar_the_architect(), create_lisa_the_data_scientist()]: agent.think("I will tell everyone right now how awesome life is!") actions = agent.act(return_actions=True) assert len(actions) >= 1, f"{agent.name} should have at least one action to perform." assert contains_action_type(actions, "TALK"), f"{agent.name} should have at least one TALK action to perform, since they are eager to talk." assert contains_action_content(actions, "life"), f"{agent.name} should mention life in the TALK action, since they thought about it." def test_internalize_goal(setup): # Test that internalizing a goal works as expected for agent in [create_oscar_the_architect(), create_lisa_the_data_scientist()]: agent.internalize_goal("I want to compose in my head a wonderful poem about how cats are glorious creatures.") actions = agent.act(return_actions=True) assert len(actions) >= 1, f"{agent.name} should have at least one action to perform." assert contains_action_type(actions, "THINK"), f"{agent.name} should have at least one THINK action to perform, since they internalized a goal." assert contains_action_content(actions, "cats"), f"{agent.name} should mention cats in the THINK action, since they internalized a goal about them." def test_move_to(setup): # Test that moving to a new location works as expected for agent in [create_oscar_the_architect(), create_lisa_the_data_scientist()]: agent.move_to("New York", context=["city", "busy", "diverse"]) assert agent._mental_state["location"] == "New York", f"{agent.name} should have New York as the current location." assert "city" in agent._mental_state["context"], f"{agent.name} should have city as part of the current context." assert "busy" in agent._mental_state["context"], f"{agent.name} should have busy as part of the current context." assert "diverse" in agent._mental_state["context"], f"{agent.name} should have diverse as part of the current context." def test_change_context(setup): # Test that changing the context works as expected for agent in [create_oscar_the_architect(), create_lisa_the_data_scientist()]: agent.change_context(["home", "relaxed", "comfortable"]) assert "home" in agent._mental_state["context"], f"{agent.name} should have home as part of the current context." assert "relaxed" in agent._mental_state["context"], f"{agent.name} should have relaxed as part of the current context." assert "comfortable" in agent._mental_state["context"], f"{agent.name} should have comfortable as part of the current context." def test_save_specification(setup): for agent in [create_oscar_the_architect(), create_lisa_the_data_scientist()]: # save to a file agent.save_specification(get_relative_to_test_path(f"{EXPORT_BASE_FOLDER}/serialization/{agent.name}.tinyperson.json"), include_memory=True) # check that the file exists assert os.path.exists(get_relative_to_test_path(f"{EXPORT_BASE_FOLDER}/serialization/{agent.name}.tinyperson.json")), f"{agent.name} should have saved the file." # load the file to see if the agent is the same. The agent name should be different because it TinyTroupe does not allow two agents with the same name. loaded_name = f"{agent.name}_loaded" loaded_agent = TinyPerson.load_specification(get_relative_to_test_path(f"{EXPORT_BASE_FOLDER}/serialization/{agent.name}.tinyperson.json"), new_agent_name=loaded_name) # check that the loaded agent is the same as the original assert loaded_agent.name == loaded_name, f"{agent.name} should have the same name as the loaded agent." assert agents_personas_are_equal(agent, loaded_agent, ignore_name=True), f"{agent.name} should have the same configuration as the loaded agent, except for the name." def test_programmatic_definitions(setup): for agent in [create_oscar_the_architect_2(), create_lisa_the_data_scientist_2()]: agent.listen_and_act("Tell me a bit about your life.")