
Title: Generative Agent-Based Modeling: Unveiling Social System Dynamics through Coupling Mechanistic Models with Generative Artificial Intelligence
Agent-Based Modeling은 산업공학에서 주로 사용하는 Simulation 방법이지만, 인간의 복잡한 의사결정에 대한 규칙을 정하고, 이를 정량화 하는 것에 어려움이 존재한다. 해당 논문은 LLM의 추론 및 사고 능력을 활용하여 인간의 의사결정을 표현하는 Generative Agent-Based Modeling, 즉 GABM을 제안한다.
LLM을 활용해 인간의 의사결정을 simulation할 때, 현실적인 인간 성향과 인구통계적 요소를 포함하는 persona를 설정하는 것이 중요!
해당 논문에서는 다양한 persona를 설정하여 실험을 진행
전통적인 Agent-Based Models vs GABM

알고리즘 순서
참고: 저자가 제공하는 Diffusion Model Code Link
try:
!pip -q install openai cohere tiktoken
import pandas as pd
import numpy as np
import openai
import time
import random
from matplotlib import pyplot as plt
print("Python modules installed successfully!")
except:
print("Error! One or more libraries could not be installed! Contact us.")
class world():
def __init__(self, no_workers, no_days):
self.no_workers = no_workers
self.no_days = no_days
self.blue_shirts = 0
self.worker_list = []
self.blue_over_time = []
for i in range(no_workers):
office_worker = worker(i, self, name = list_of_names[i], traits= list_of_traits[i])
if random.random() <0.5: # 0과 1 사이의 난수 반환 >> 0으로 변경하면 초록색 옷만 초기 assignment 가능!
office_worker.clothes = "blue"
office_worker.mem = np.append(office_worker.mem, 1)
else:
office_worker.clothes = "green"
office_worker.mem = np.append(office_worker.mem, 0)
self.worker_list.append(office_worker)
def set_clothes_info(self):
for worker in self.worker_list:
if worker.clothes == "blue":
self.blue_shirts +=1
self.blue_over_time.append(self.blue_shirts)
info = self.blue_shirts
self.blue_shirts = 0
for worker in self.worker_list:
worker.cumulative_shirts_info = info
def run(self):
for i in range (self.no_days+1):
self.set_clothes_info()
print(f"Yesterday on day {i}, {self.blue_over_time[-1]} of {self.no_workers} wore blue shirts.")
if i == self.no_days:
break
for worker in self.worker_list:
worker.decide_clothes()
client = openai.OpenAI(api_key="Yours")
class worker():
def __init__(self, unique_id, model, name, traits, clothes = None):
self.unique_id = unique_id
self.clothes = clothes
self.traits = traits # 성격 정보를 담고 있는 객체 속성 (5.2.2. Effect of Personas)
self.model = model
self.cumulative_shirts_info = None
self.name = name
self.mem = np.array([],dtype=int)
def get_output_from_chatgpt(self, messages, model ="gpt-4o-mini",temperature =0): # 저자들은 3-turbo 사용
success = False
retry = 0
max_retries = 30
while retry < max_retries and not success:
try:
response = client.chat.completions.create(
model=model,
messages=messages,
temperature=temperature,
# this is the degree of randomness of the model's output
# 5.2.4. Effect of stochasticity
)
success = True
except Exception as e :
print(f"Error: { e }\ nRetrying ...")
retry +=1
time.sleep(0.5)
return response.choices[0].message.content
def decide_clothes(self) :
question_prompt = f"""
You are {self.name}. You are a {self.traits} person.
You work in an office with {self.model.no_workers-1} other people. You want to be successful, and earn more money.
You need to decide between wearing blue shirt or green shirt to work. The weather is appropriate for either color.
You like to be comfortable at work.
You chose to wear {self.clothes} shirt yesterday.
Out of {self.model.no_workers} employees, yesterday, {self.cumulative_shirts_info} wore blue shirts,
and {self.model.no_workers-self.cumulative_shirts_info} wore green shirts at the office.
Based on the above context, you need to choose whether to wear blue or green shirt.
You must provide your reasoning for your choice and then your response in one word.
For example, if your answer is "blue”, your response will be:
Reasoning: [Your reason to choose to wear blue shirt]
Response: blue
If your answer is "green”, then your response will be :
Reasoning: [Your reason to choose to wear green shirt]
Response: green
Please make sure your response is in one word.
"""
messages = [{'role':'system', 'content':question_prompt}]
try:
output = self.get_output_from_chatgpt(messages)
except Exception as e:
print(f"{e}\nProgram paused. Retrying after 60s...")
time.sleep(60)
output = self.get_output_from_chatgpt(messages)
reasoning = ""
response = ""
try:
intermediate = output.split("Reasoning:",1)[1]
reasoning , response = intermediate.split ("Response:")
response = response.strip().split("." ,1)[0]
reasoning = reasoning.strip()
except:
print("Reasoning or response were not parsed correctly.")
print(f"Output: {output}")
response = "blue"
reasoning = "N/A"
reasoning = reasoning.strip()
response = response.strip()
print(f"{self.name}’s reasoning: {reasoning}")
print(f"{self.name}’s response: {response}")
if response.lower() == "blue":
self.clothes = "blue"
self.mem = np.append(self.mem,1)
elif response.lower() == "green":
self.clothes = "green"
self.mem = np.append(self.mem, 0)
else:
print("Warning! Response was neither blue nor green. Defaulting with blue.")
print(f"Response was: {response}")
self.clothes = "blue"
self.mem = np.append(self.mem, 1)
list_of_names = ["Adrian" ,"Mark" ,"Greg" ,"John" ,"Peter" ,"Liz" ,"Rosa" ,"Patricia" ,"Julia" ,"Kathy",
"William","Benjamin","Mike", "David", "George","Emma", "Olivia","Elizabeth","Isabella","Mia"]
list_of_traits = ["extremely conformist","highly conformist", "conformist", "low conformist", "non-conformist",
"extremely conformist","highly conformist", "conformist", "low conformist", "non-conformist",
"highly conformist","conformist", "conformist", "conformist", "low conformist",
"highly conformist","conformist", "conformist", "conformist", "low conformist"]
model = world(no_workers = 20, no_days = 7)
model.run()

##plot
plt.grid()
plt.plot(model.blue_over_time)
plt.ylim(0,model.no_workers)
plt.xlabel("Day")
plt.ylabel("Workers Wearing Blue")
plt.savefig("plot_of_blue_over_time.jpg")
plt.tight_layout()
plt.show()
##table
agent_choices = []
for w in model.worker_list:
agent_choices.append(w.mem)
column_names = [f"Day {i}" for i in range(model.no_days+1)]
index_names = list_of_names[:model.no_workers]
df = pd.DataFrame(agent_choices, index = index_names, columns = column_names)
print(df)

Simulation 예시
출력 결과
![]()
12가지 다른 시나리오에서, 각 시나리오마다 100번 실험 진행
각 시나리오에서 Norm Diffusion이 나타나는지 시각화한 결과
Dorminant Norm이 존재하는 경우: A,C,G,H,I,J,K,L
A: Base run
B,C,D: persona의 영향을 확인하기 위해 성격 특징 정보를 추가 및 제거
# 5.2.2 Table 4: More extensive trait information
list_of_traits = ["extremely conformist, curious, friendly, and sensitive",
"highly conformist, cautious, friendly, and confident",
"conformist, curious, critical, and confident",
"low conformist, cautious, critical, and sensitive",
"non-conformist, curious, friendly, and sensitive",
"extremely conformist, cautious, friendly, and confident",
"highly conformist, curious, critical, and confident",
"conformist, cautious, critical, and sensitive",
"low conformist, curious, friendly, and sensitive",
"non-conformist, cautious, critical, and confident",
"highly conformist, curious, friendly, and confident",
"conformist, cautious, critical, and sensitive",
"conformist, curious, critical, and sensitive",
"conformist, cautious, friendly, and confident",
"low conformist, curious, critical, and confident",
"highly conformist, cautious, friendly, and sensitive",
"conformist, curious, friendly, and sensitive",
"conformist, cautious, friendly, and confident",
"conformist, curious, critical, and confident",
"low conformist, cautious, critical, and sensitive"]
E,F: Effect of a strong adoption force
Michael, the new CEO, bikes to work everyday, likes coffee, and often wears blue shirts. #추가한 프롬프트 5.2.3.
You note that your neighbor who works in a difference compnay wears green. #추가한 프롬프트 5.2.3.
최근에 LLM에 대해서 공부하기 시작해서 이것저것 글 읽어보고 있었는데 LLM을 활용한 의사결정 시뮬레이션 방법은 처음 봐서 신기했습니다! 잘 읽고 갑니다~!