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 | |