Spaces:
No application file
No application file
| import random | |
| from utils.text_generation import generate, get_rating | |
| import networkx as nx | |
| class Agent: | |
| """ | |
| A class to represent an individual agent in a simulation similar to The Sims. | |
| Attributes: | |
| ----------- | |
| name : str | |
| The name of the agent. | |
| description : str | |
| A brief description of the agent. | |
| location : str | |
| The current location of the agent in the simulated environment. | |
| memories : list | |
| A list of memories the agent has about their interactions. | |
| compressed_memories : list | |
| A list of compressed memories that summarize the agent's experiences. | |
| plans : str | |
| The agent's daily plans, generated at the beginning of each day. | |
| Methods: | |
| -------- | |
| plan(global_time, town_people, prompt_meta): | |
| Generates the agent's daily plan. | |
| execute_action(other_agents, location, global_time, town_areas, prompt_meta): | |
| Executes the agent's action based on their current situation and interactions with other agents. | |
| update_memories(other_agents, global_time, action_results): | |
| Updates the agent's memories based on their interactions with other agents. | |
| compress_memories(memory_ratings, global_time, MEMORY_LIMIT=10): | |
| Compresses the agent's memories to a more manageable and relevant set. | |
| rate_locations(locations, town_areas, global_time, prompt_meta): | |
| Rates different locations in the simulated environment based on the agent's preferences and experiences. | |
| """ | |
| def __init__(self, name, description, starting_location, world_graph, use_openai): | |
| self.name = name | |
| self.description = description | |
| self.location = starting_location | |
| self.memory_ratings = [] | |
| self.memories = [] | |
| self.compressed_memories = [] | |
| self.plans = "" | |
| self.world_graph = world_graph | |
| self.use_openai = use_openai | |
| def __repr__(self): | |
| return f"Agent({self.name}, {self.description}, {self.location})" | |
| def plan(self, global_time, prompt_meta): | |
| """ | |
| Generates the agent's daily plan. | |
| Parameters: | |
| ----------- | |
| global_time : int | |
| The current time in the simulation. | |
| prompt_meta : str | |
| The prompt used to generate the plan. | |
| """ | |
| prompt = "You are {}. The following is your description: {} You just woke up. What is your goal for today? Write it down in an hourly basis, starting at {}:00. Write only one or two very short sentences. Be very brief. Use at most 50 words.".format(self.name, self.description, str(global_time)) | |
| self.plans = generate(prompt_meta.format(prompt), self.use_openai) | |
| def execute_action(self, other_agents, location, global_time, town_areas, prompt_meta): | |
| """Executes the agent's action based on their current situation and interactions with other agents. | |
| Parameters: | |
| ----------- | |
| other_agents : list | |
| A list of other Agent objects in the simulation. | |
| location : Location | |
| The current Location object where the agent is located. | |
| global_time : int | |
| The current time in the simulation. | |
| town_areas : dict | |
| A dictionary of Location objects representing different areas in the simulated environment. | |
| prompt_meta : str | |
| The prompt used to generate the action. | |
| Returns: | |
| -------- | |
| action : str | |
| The action executed by the agent. | |
| """ | |
| people = [agent.name for agent in other_agents if agent.location == location] | |
| prompt = "You are {}. Your plans are: {}. You are currently in {} with the following description: {}. It is currently {}:00. The following people are in this area: {}. You can interact with them.".format(self.name, self.plans, location.name, town_areas[location.name], str(global_time), ', '.join(people)) | |
| people_description = [f"{agent.name}: {agent.description}" for agent in other_agents if agent.location == location.name] | |
| prompt += ' You know the following about people: ' + '. '.join(people_description) | |
| prompt += "What do you do in the next hour? Use at most 10 words to explain." | |
| action = generate(prompt_meta.format(prompt), self.use_openai) | |
| return action | |
| def update_memories(self, other_agents, global_time, action_results): | |
| """ | |
| Updates the agent's memories based on their interactions with other agents. | |
| Parameters: | |
| ----------- | |
| other_agents : list | |
| A list of other Agent objects in the simulation. | |
| global_time : int | |
| The current time in the simulation. | |
| action_results : dict | |
| A dictionary of the results of each agent's action. | |
| """ | |
| for agent in other_agents: | |
| if agent.location == self.location: | |
| self.memories.append('[Time: {}. Person: {}. Memory: {}]\n'.format(str(global_time), agent.name, action_results[agent.name])) | |
| def compress_memories(self, global_time, MEMORY_LIMIT=10): | |
| """ | |
| Compresses the agent's memories to a more manageable and relevant set. | |
| Parameters: | |
| ----------- | |
| global_time : int | |
| The current time in the simulation. | |
| MEMORY_LIMIT : int, optional | |
| The maximum number of memories to compress. Default is 10. | |
| Returns: | |
| -------- | |
| memory_string : str | |
| The compressed memory string. | |
| """ | |
| memories_sorted = sorted(self.memory_ratings, key=lambda x: x[1], reverse=True) | |
| relevant_memories = memories_sorted[:MEMORY_LIMIT] | |
| memory_string_to_compress = '.'.join([a[0] for a in relevant_memories]) | |
| return '[Recollection at Time {}:00: {}]'.format(str(global_time), memory_string_to_compress) | |
| def rate_memories(self, locations, global_time, prompt_meta): | |
| """ | |
| Rates the agent's memories based on their relevance and importance. | |
| Parameters: | |
| ----------- | |
| locations : Locations | |
| The Locations object representing different areas in the simulated environment. | |
| global_time : int | |
| The current time in the simulation. | |
| prompt_meta : str | |
| The prompt used to rate the memories. | |
| Returns: | |
| -------- | |
| memory_ratings : list | |
| A list of tuples representing the memory, its rating, and the generated response. | |
| """ | |
| memory_ratings = [] | |
| for memory in self.memories: | |
| prompt = "You are {}. Your plans are: {}. You are currently in {}. It is currently {}:00. You observe the following: {}. Give a rating, between 1 and 5, to how much you care about this.".format(self.name, self.plans, locations.get_location(self.location), str(global_time), memory) | |
| res = generate(prompt_meta.format(prompt), self.use_openai) | |
| rating = get_rating(res) | |
| max_attempts = 2 | |
| current_attempt = 0 | |
| while rating is None and current_attempt < max_attempts: | |
| rating = get_rating(res) | |
| current_attempt += 1 | |
| if rating is None: | |
| rating = 0 | |
| memory_ratings.append((memory, rating, res)) | |
| self.memory_ratings = memory_ratings | |
| return memory_ratings | |
| def rate_locations(self, locations, global_time, prompt_meta): | |
| """ | |
| Rates different locations in the simulated environment based on the agent's preferences and experiences. | |
| Parameters: | |
| ----------- | |
| locations : Locations | |
| The Locations object representing different areas in the simulated environment. | |
| global_time : int | |
| The current time in the simulation. | |
| prompt_meta : str | |
| The prompt used to rate the locations. | |
| Returns: | |
| -------- | |
| place_ratings : list | |
| A list of tuples representing the location, its rating, and the generated response. | |
| """ | |
| place_ratings = [] | |
| for location in locations.locations.values(): | |
| prompt = "You are {}. Your plans are: {}. It is currently {}:00. You are currently at {}. How likely are you to go to {} next?".format(self.name, self.plans, str(global_time), locations.get_location(self.location), location.name) | |
| res = generate(prompt_meta.format(prompt), self.use_openai) | |
| rating = get_rating(res) | |
| max_attempts = 2 | |
| current_attempt = 0 | |
| while rating is None and current_attempt < max_attempts: | |
| rating = get_rating(res) | |
| current_attempt += 1 | |
| if rating is None: | |
| rating = 0 | |
| place_ratings.append((location.name, rating, res)) | |
| self.place_ratings = place_ratings | |
| return sorted(place_ratings, key=lambda x: x[1], reverse=True) | |
| def move(self, new_location_name): | |
| if new_location_name == self.location: | |
| return self.location | |
| try: | |
| path = nx.shortest_path(self.world_graph, source=self.location, target=new_location_name) | |
| self.location = new_location_name | |
| except nx.NetworkXNoPath: | |
| print(f"No path found between {self.location} and {new_location_name}") | |
| return self.location | |
| return self.location | |