pycityagent 2.0.0a47__cp39-cp39-macosx_11_0_arm64.whl → 2.0.0a49__cp39-cp39-macosx_11_0_arm64.whl
Sign up to get free protection for your applications and to get access to all the features.
- pycityagent/__init__.py +3 -2
- pycityagent/agent.py +109 -4
- pycityagent/cityagent/__init__.py +20 -0
- pycityagent/cityagent/bankagent.py +54 -0
- pycityagent/cityagent/blocks/__init__.py +20 -0
- pycityagent/cityagent/blocks/cognition_block.py +304 -0
- pycityagent/cityagent/blocks/dispatcher.py +78 -0
- pycityagent/cityagent/blocks/economy_block.py +356 -0
- pycityagent/cityagent/blocks/mobility_block.py +258 -0
- pycityagent/cityagent/blocks/needs_block.py +305 -0
- pycityagent/cityagent/blocks/other_block.py +103 -0
- pycityagent/cityagent/blocks/plan_block.py +309 -0
- pycityagent/cityagent/blocks/social_block.py +345 -0
- pycityagent/cityagent/blocks/time_block.py +116 -0
- pycityagent/cityagent/blocks/utils.py +66 -0
- pycityagent/cityagent/firmagent.py +75 -0
- pycityagent/cityagent/governmentagent.py +60 -0
- pycityagent/cityagent/initial.py +98 -0
- pycityagent/cityagent/memory_config.py +202 -0
- pycityagent/cityagent/nbsagent.py +92 -0
- pycityagent/cityagent/societyagent.py +291 -0
- pycityagent/memory/memory.py +0 -18
- pycityagent/message/messager.py +6 -3
- pycityagent/simulation/agentgroup.py +123 -37
- pycityagent/simulation/simulation.py +311 -316
- pycityagent/workflow/block.py +66 -1
- pycityagent/workflow/tool.py +9 -4
- {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a49.dist-info}/METADATA +2 -2
- {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a49.dist-info}/RECORD +33 -14
- {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a49.dist-info}/LICENSE +0 -0
- {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a49.dist-info}/WHEEL +0 -0
- {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a49.dist-info}/entry_points.txt +0 -0
- {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a49.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,116 @@
|
|
1
|
+
import asyncio
|
2
|
+
from datetime import datetime
|
3
|
+
import json
|
4
|
+
from pycityagent.workflow import Block
|
5
|
+
from pycityagent.llm.llm import LLM
|
6
|
+
from pycityagent.memory import Memory
|
7
|
+
from pycityagent.environment import Simulator
|
8
|
+
from pycityagent.workflow.prompt import FormatPrompt
|
9
|
+
from .utils import clean_json_response
|
10
|
+
|
11
|
+
class WorkReflectionBlock(Block):
|
12
|
+
"""
|
13
|
+
反馈工作感受
|
14
|
+
WorkReflectionBlock
|
15
|
+
"""
|
16
|
+
def __init__(self, llm: LLM, memory: Memory, simulator: Simulator):
|
17
|
+
super().__init__("WorkReflectionBlock", llm, memory, simulator)
|
18
|
+
self.description = "Feedback on work experience"
|
19
|
+
|
20
|
+
async def forward(self):
|
21
|
+
prompt = """
|
22
|
+
You are a {gender}, your consumption level is {consumption} and your education level is {education}.
|
23
|
+
Today's working experience:
|
24
|
+
{working_experience}
|
25
|
+
|
26
|
+
How is your feeling of work today?
|
27
|
+
|
28
|
+
Your answer should be one of the following:
|
29
|
+
- excellent
|
30
|
+
- good
|
31
|
+
- soso
|
32
|
+
- bad
|
33
|
+
- very bad
|
34
|
+
Answer in JSON format:
|
35
|
+
{{
|
36
|
+
"evaluation": "good",
|
37
|
+
}}
|
38
|
+
"""
|
39
|
+
prompt = FormatPrompt(prompt)
|
40
|
+
prompt.format(
|
41
|
+
**{key: await self.memory.get(key) for key in prompt.variables}
|
42
|
+
)
|
43
|
+
evaluation = await self.llm.atext_request(prompt.to_dialog(), timeout=300)
|
44
|
+
evaluation = clean_json_response(evaluation)
|
45
|
+
try:
|
46
|
+
evaluation = json.loads(evaluation)
|
47
|
+
except Exception as e:
|
48
|
+
evaluation = {'evaluation': 'soso'}
|
49
|
+
if evaluation['evaluation'] == 'excellent':
|
50
|
+
safe_improve = 0.2
|
51
|
+
elif evaluation['evaluation'] == 'good':
|
52
|
+
safe_improve = 0.1
|
53
|
+
elif evaluation['evaluation'] == 'soso':
|
54
|
+
safe_improve = 0.0
|
55
|
+
elif evaluation['evaluation'] == 'bad':
|
56
|
+
safe_improve = -0.1
|
57
|
+
elif evaluation['evaluation'] == 'very bad':
|
58
|
+
safe_improve = -0.2
|
59
|
+
else:
|
60
|
+
safe_improve = 0.0
|
61
|
+
|
62
|
+
needs = await self.memory.get("needs")
|
63
|
+
needs['safe'] += safe_improve
|
64
|
+
await self.memory.update("needs", needs)
|
65
|
+
await self.memory.update("working_experience", [])
|
66
|
+
return
|
67
|
+
|
68
|
+
|
69
|
+
class TimeBlock(Block):
|
70
|
+
"""固定时间trigger的工作流"""
|
71
|
+
def __init__(self, llm: LLM, memory: Memory, simulator: Simulator):
|
72
|
+
super().__init__(name="time_block", llm=llm, memory=memory, simulator=simulator)
|
73
|
+
self.blocks = []
|
74
|
+
self.work_reflection_block = WorkReflectionBlock(llm, memory, simulator)
|
75
|
+
self.blocks.append((self.work_reflection_block, self.str_to_time('23:59:59'))) # end of day
|
76
|
+
self.last_check_time = None
|
77
|
+
self.trigger_time = 0
|
78
|
+
self.token_consumption = 0
|
79
|
+
|
80
|
+
def str_to_time(self, time_str: str):
|
81
|
+
time_obj = datetime.strptime(time_str, '%H:%M:%S')
|
82
|
+
return time_obj.hour * 3600 + time_obj.minute * 60 + time_obj.second
|
83
|
+
|
84
|
+
async def blocks_to_trigger(self):
|
85
|
+
trigger_blocks = []
|
86
|
+
now_time = await self.simulator.get_time(format_time=True)
|
87
|
+
now_time = self.str_to_time(now_time)
|
88
|
+
if self.last_check_time is None:
|
89
|
+
self.last_check_time = now_time
|
90
|
+
else:
|
91
|
+
whether_cross_day = True if now_time < self.last_check_time else False
|
92
|
+
for block, trigger_time in self.blocks:
|
93
|
+
if whether_cross_day and trigger_time > self.last_check_time:
|
94
|
+
trigger_blocks.append(block)
|
95
|
+
elif not whether_cross_day and trigger_time > self.last_check_time and trigger_time <= now_time:
|
96
|
+
trigger_blocks.append(block)
|
97
|
+
self.last_check_time = now_time
|
98
|
+
return trigger_blocks
|
99
|
+
|
100
|
+
async def forward(self):
|
101
|
+
while True:
|
102
|
+
if len(self.blocks) == 0:
|
103
|
+
await asyncio.sleep(30)
|
104
|
+
continue
|
105
|
+
trigger_blocks = await self.blocks_to_trigger()
|
106
|
+
if len(trigger_blocks) == 0:
|
107
|
+
await asyncio.sleep(30)
|
108
|
+
continue
|
109
|
+
self.trigger_time += 1
|
110
|
+
consumption_start = self.llm.prompt_tokens_used + self.llm.completion_tokens_used
|
111
|
+
tasks = []
|
112
|
+
for block in trigger_blocks:
|
113
|
+
tasks.append(block.forward())
|
114
|
+
await asyncio.gather(*tasks)
|
115
|
+
consumption_end = self.llm.prompt_tokens_used + self.llm.completion_tokens_used
|
116
|
+
self.token_consumption += consumption_end - consumption_start
|
@@ -0,0 +1,66 @@
|
|
1
|
+
import re
|
2
|
+
import ast
|
3
|
+
|
4
|
+
TIME_ESTIMATE_PROMPT = """As an intelligent agent's time estimation system, please estimate the time needed to complete the current action based on the overall plan and current intention.
|
5
|
+
|
6
|
+
Overall plan:
|
7
|
+
{plan}
|
8
|
+
|
9
|
+
Current action: {intention}
|
10
|
+
|
11
|
+
Examples:
|
12
|
+
- "Learn programming": {{"time": 120}}
|
13
|
+
- "Watch a movie": {{"time": 150}}
|
14
|
+
- "Play mobile games": {{"time": 60}}
|
15
|
+
- "Read a book": {{"time": 90}}
|
16
|
+
- "Exercise": {{"time": 45}}
|
17
|
+
|
18
|
+
Please return the result in JSON format (Do not return any other text):
|
19
|
+
{{
|
20
|
+
"time": estimated completion time (integer, in minutes)
|
21
|
+
}}
|
22
|
+
"""
|
23
|
+
|
24
|
+
num_labor_hours = 168
|
25
|
+
month_days = 0.03
|
26
|
+
productivity_per_labor = 1
|
27
|
+
max_price_inflation = 0.1
|
28
|
+
max_wage_inflation = 0.05
|
29
|
+
natural_interest_rate = 0.01
|
30
|
+
target_inflation = 0.02
|
31
|
+
natural_unemployment_rate = 0.04
|
32
|
+
inflation_coeff, unemployment_coeff = 0.5, 0.5
|
33
|
+
tao = 1
|
34
|
+
period = 3
|
35
|
+
UBI = 0
|
36
|
+
|
37
|
+
def prettify_document(document: str) -> str:
|
38
|
+
# Remove sequences of whitespace characters (including newlines)
|
39
|
+
cleaned = re.sub(r'\s+', ' ', document).strip()
|
40
|
+
return cleaned
|
41
|
+
|
42
|
+
def extract_dict_from_string(input_string):
|
43
|
+
"""
|
44
|
+
提取输入字符串中的字典。支持跨行字典和嵌套字典。
|
45
|
+
"""
|
46
|
+
# 正则表达式查找所有可能的字典部分,允许多行
|
47
|
+
dict_pattern = r'\{(?:[^{}]|\{(?:[^{}]|\{[^{}]*\})*\})*\}' # 匹配字典的正则表达式,支持嵌套
|
48
|
+
matches = re.findall(dict_pattern, input_string, re.DOTALL) # re.DOTALL允许匹配换行符
|
49
|
+
|
50
|
+
dicts = []
|
51
|
+
|
52
|
+
for match in matches:
|
53
|
+
try:
|
54
|
+
# 使用 ast.literal_eval 将字符串转换为字典
|
55
|
+
parsed_dict = ast.literal_eval(match)
|
56
|
+
if isinstance(parsed_dict, dict):
|
57
|
+
dicts.append(parsed_dict)
|
58
|
+
except (ValueError, SyntaxError) as e:
|
59
|
+
print(f"解析字典失败: {e}")
|
60
|
+
|
61
|
+
return dicts
|
62
|
+
|
63
|
+
def clean_json_response(response: str) -> str:
|
64
|
+
"""清理LLM响应中的特殊字符"""
|
65
|
+
response = response.replace('```json', '').replace('```', '')
|
66
|
+
return response.strip()
|
@@ -0,0 +1,75 @@
|
|
1
|
+
import asyncio
|
2
|
+
from typing import Optional
|
3
|
+
|
4
|
+
import numpy as np
|
5
|
+
from pycityagent import Simulator, InstitutionAgent
|
6
|
+
from pycityagent.llm.llm import LLM
|
7
|
+
from pycityagent.economy import EconomyClient
|
8
|
+
from pycityagent.message import Messager
|
9
|
+
from pycityagent.memory import Memory
|
10
|
+
import logging
|
11
|
+
|
12
|
+
logger = logging.getLogger("pycityagent")
|
13
|
+
|
14
|
+
class FirmAgent(InstitutionAgent):
|
15
|
+
configurable_fields = ["time_diff", "max_price_inflation", "max_wage_inflation"]
|
16
|
+
default_values = {
|
17
|
+
"time_diff": 30 * 24 * 60 * 60,
|
18
|
+
"max_price_inflation": 0.05,
|
19
|
+
"max_wage_inflation": 0.05,
|
20
|
+
}
|
21
|
+
|
22
|
+
def __init__(self,
|
23
|
+
name: str,
|
24
|
+
llm_client: Optional[LLM] = None,
|
25
|
+
simulator: Optional[Simulator] = None,
|
26
|
+
memory: Optional[Memory] = None,
|
27
|
+
economy_client: Optional[EconomyClient] = None,
|
28
|
+
messager: Optional[Messager] = None,
|
29
|
+
avro_file: Optional[dict] = None,
|
30
|
+
) -> None:
|
31
|
+
super().__init__(name=name, llm_client=llm_client, simulator=simulator, memory=memory, economy_client=economy_client, messager=messager, avro_file=avro_file)
|
32
|
+
self.initailzed = False
|
33
|
+
self.last_time_trigger = None
|
34
|
+
self.forward_times = 0
|
35
|
+
self.time_diff = 30 * 24 * 60 * 60
|
36
|
+
self.max_price_inflation = 0.05
|
37
|
+
self.max_wage_inflation = 0.05
|
38
|
+
|
39
|
+
async def month_trigger(self):
|
40
|
+
now_time = await self.simulator.get_time()
|
41
|
+
if self.last_time_trigger is None:
|
42
|
+
self.last_time_trigger = now_time
|
43
|
+
return False
|
44
|
+
if now_time - self.last_time_trigger >= self.time_diff:
|
45
|
+
self.last_time_trigger = now_time
|
46
|
+
return True
|
47
|
+
return False
|
48
|
+
|
49
|
+
async def gather_messages(self, agent_ids, content):
|
50
|
+
infos = await super().gather_messages(agent_ids, content)
|
51
|
+
return [info['content'] for info in infos]
|
52
|
+
|
53
|
+
async def forward(self):
|
54
|
+
if await self.month_trigger():
|
55
|
+
employees = await self.memory.get("employees")
|
56
|
+
while True:
|
57
|
+
agents_forward = await self.gather_messages(employees, 'forward')
|
58
|
+
if np.all(np.array(agents_forward) > self.forward_times):
|
59
|
+
break
|
60
|
+
await asyncio.sleep(1)
|
61
|
+
goods_demand = await self.gather_messages(employees, 'goods_demand')
|
62
|
+
goods_consumption = await self.gather_messages(employees, 'goods_consumption')
|
63
|
+
print(f'goods_demand: {goods_demand}, goods_consumption: {goods_consumption}')
|
64
|
+
total_demand = sum(goods_demand)
|
65
|
+
last_inventory = sum(goods_consumption) + await self.economy_client.get(self._agent_id, "inventory")
|
66
|
+
print(f'total_demand: {total_demand}, last_inventory: {last_inventory}, goods_contumption: {sum(goods_consumption)}')
|
67
|
+
max_change_rate = (total_demand - last_inventory)/(max(total_demand, last_inventory)+1e-8)
|
68
|
+
skills = await self.gather_messages(employees, 'work_skill')
|
69
|
+
for skill, uuid in zip(skills, employees):
|
70
|
+
await self.send_message_to_agent(uuid, f"work_skill@{max(skill*(1 + np.random.uniform(0, max_change_rate*self.max_wage_inflation)), 1)}")
|
71
|
+
price = await self.economy_client.get(self._agent_id, 'price')
|
72
|
+
await self.economy_client.update(self._agent_id, 'price', max(price*(1 + np.random.uniform(0, max_change_rate*self.max_price_inflation)), 1))
|
73
|
+
self.forward_times += 1
|
74
|
+
for uuid in employees:
|
75
|
+
await self.send_message_to_agent(uuid, f"firm_forward@{self.forward_times}")
|
@@ -0,0 +1,60 @@
|
|
1
|
+
import asyncio
|
2
|
+
from typing import Optional
|
3
|
+
|
4
|
+
import numpy as np
|
5
|
+
from pycityagent import Simulator, InstitutionAgent
|
6
|
+
from pycityagent.llm.llm import LLM
|
7
|
+
from pycityagent.economy import EconomyClient
|
8
|
+
from pycityagent.message import Messager
|
9
|
+
from pycityagent.memory import Memory
|
10
|
+
import logging
|
11
|
+
|
12
|
+
logger = logging.getLogger("pycityagent")
|
13
|
+
|
14
|
+
class GovernmentAgent(InstitutionAgent):
|
15
|
+
def __init__(self,
|
16
|
+
name: str,
|
17
|
+
llm_client: Optional[LLM] = None,
|
18
|
+
simulator: Optional[Simulator] = None,
|
19
|
+
memory: Optional[Memory] = None,
|
20
|
+
economy_client: Optional[EconomyClient] = None,
|
21
|
+
messager: Optional[Messager] = None,
|
22
|
+
avro_file: Optional[dict] = None,
|
23
|
+
) -> None:
|
24
|
+
super().__init__(name=name, llm_client=llm_client, simulator=simulator, memory=memory, economy_client=economy_client, messager=messager, avro_file=avro_file)
|
25
|
+
self.initailzed = False
|
26
|
+
self.last_time_trigger = None
|
27
|
+
self.time_diff = 30 * 24 * 60 * 60
|
28
|
+
self.forward_times = 0
|
29
|
+
|
30
|
+
async def month_trigger(self):
|
31
|
+
now_time = await self.simulator.get_time()
|
32
|
+
if self.last_time_trigger is None:
|
33
|
+
self.last_time_trigger = now_time
|
34
|
+
return False
|
35
|
+
if now_time - self.last_time_trigger >= self.time_diff:
|
36
|
+
self.last_time_trigger = now_time
|
37
|
+
return True
|
38
|
+
return False
|
39
|
+
|
40
|
+
async def gather_messages(self, agent_ids, content):
|
41
|
+
infos = await super().gather_messages(agent_ids, content)
|
42
|
+
return [info['content'] for info in infos]
|
43
|
+
|
44
|
+
async def forward(self):
|
45
|
+
if await self.month_trigger():
|
46
|
+
citizens = await self.memory.get("citizens")
|
47
|
+
while True:
|
48
|
+
agents_forward = await self.gather_messages(citizens, 'forward')
|
49
|
+
if np.all(np.array(agents_forward) > self.forward_times):
|
50
|
+
break
|
51
|
+
await asyncio.sleep(1)
|
52
|
+
citizens_agent_id = await self.memory.get("citizens_agent_id")
|
53
|
+
incomes = await self.gather_messages(citizens, 'income_currency') # uuid
|
54
|
+
_, post_tax_incomes = await self.economy_client.calculate_taxes_due(self._agent_id, citizens_agent_id, incomes, enable_redistribution=False)
|
55
|
+
for uuid, income, post_tax_income in zip(citizens, incomes, post_tax_incomes):
|
56
|
+
tax_paid = income - post_tax_income
|
57
|
+
await self.send_message_to_agent(uuid, f"tax_paid@{tax_paid}")
|
58
|
+
self.forward_times += 1
|
59
|
+
for uuid in citizens:
|
60
|
+
await self.send_message_to_agent(uuid, f"government_forward@{self.forward_times}")
|
@@ -0,0 +1,98 @@
|
|
1
|
+
import random
|
2
|
+
from pycityagent.cityagent import SocietyAgent, FirmAgent, GovernmentAgent, BankAgent, NBSAgent
|
3
|
+
|
4
|
+
async def initialize_social_network(simulation):
|
5
|
+
"""
|
6
|
+
初始化智能体之间的社交网络,包括好友关系类型、好友关系和社交关系强度
|
7
|
+
"""
|
8
|
+
try:
|
9
|
+
print("Initializing social network...")
|
10
|
+
|
11
|
+
# 定义可能的关系类型
|
12
|
+
relation_types = ["family", "colleague", "friend"]
|
13
|
+
|
14
|
+
# 获取所有智能体ID
|
15
|
+
agent_ids = simulation.agent_uuids
|
16
|
+
for agent_id in agent_ids:
|
17
|
+
# 为每个智能体随机选择2-5个好友
|
18
|
+
num_friends = random.randint(2, 5)
|
19
|
+
possible_friends = [aid for aid in agent_ids if aid != agent_id]
|
20
|
+
friends = random.sample(possible_friends, min(num_friends, len(possible_friends)))
|
21
|
+
|
22
|
+
# 初始化好友关系
|
23
|
+
await simulation.update(agent_id, "friends", friends)
|
24
|
+
|
25
|
+
# 初始化与每个好友的关系类型和关系强度
|
26
|
+
relationships = {}
|
27
|
+
relation_type_map = {}
|
28
|
+
|
29
|
+
for friend_id in friends:
|
30
|
+
# 随机选择关系类型
|
31
|
+
relation_type = random.choice(relation_types)
|
32
|
+
# 根据关系类型设置初始关系强度范围
|
33
|
+
if relation_type == "family":
|
34
|
+
strength = random.randint(60, 90) # 家人关系强度较高
|
35
|
+
elif relation_type == "colleague":
|
36
|
+
strength = random.randint(40, 70) # 同事关系强度中等
|
37
|
+
else: # friend
|
38
|
+
strength = random.randint(30, 80) # 朋友关系强度范围较广
|
39
|
+
|
40
|
+
relationships[friend_id] = strength
|
41
|
+
relation_type_map[friend_id] = relation_type
|
42
|
+
|
43
|
+
# 更新关系强度和类型
|
44
|
+
await simulation.update(agent_id, "relationships", relationships)
|
45
|
+
await simulation.update(agent_id, "relation_types", relation_type_map)
|
46
|
+
|
47
|
+
# 初始化空的聊天历史和互动记录
|
48
|
+
await simulation.update(agent_id, "chat_histories", {friend_id: [] for friend_id in friends})
|
49
|
+
await simulation.update(agent_id, "interactions", {friend_id: [] for friend_id in friends})
|
50
|
+
|
51
|
+
print("Social network initialization completed!")
|
52
|
+
return True
|
53
|
+
|
54
|
+
except Exception as e:
|
55
|
+
print(f"Error initializing social network: {str(e)}")
|
56
|
+
return False
|
57
|
+
|
58
|
+
async def bind_agent_info(simulation):
|
59
|
+
"""
|
60
|
+
绑定智能体的信息,包括公民、公司、政府、银行和NBS的ID
|
61
|
+
"""
|
62
|
+
print("Binding agent info...")
|
63
|
+
infos = await simulation.gather('id')
|
64
|
+
citizen_uuids = await simulation.filter(types=[SocietyAgent])
|
65
|
+
firm_uuids = await simulation.filter(types=[FirmAgent])
|
66
|
+
government_uuids = await simulation.filter(types=[GovernmentAgent])
|
67
|
+
bank_uuids = await simulation.filter(types=[BankAgent])
|
68
|
+
nbs_uuids = await simulation.filter(types=[NBSAgent])
|
69
|
+
citizen_agent_ids = []
|
70
|
+
for info in infos:
|
71
|
+
for k, v in info.items():
|
72
|
+
if k in citizen_uuids:
|
73
|
+
citizen_agent_ids.append(v)
|
74
|
+
elif k in firm_uuids:
|
75
|
+
firm_id = v
|
76
|
+
elif k in government_uuids:
|
77
|
+
government_id = v
|
78
|
+
elif k in bank_uuids:
|
79
|
+
bank_id = v
|
80
|
+
elif k in nbs_uuids:
|
81
|
+
nbs_id = v
|
82
|
+
for citizen_uuid in citizen_uuids:
|
83
|
+
await simulation.update(citizen_uuid, 'firm_id', firm_id)
|
84
|
+
await simulation.update(citizen_uuid, 'government_id', government_id)
|
85
|
+
await simulation.update(citizen_uuid, 'bank_id', bank_id)
|
86
|
+
await simulation.update(citizen_uuid, 'nbs_id', nbs_id)
|
87
|
+
for firm_uuid in firm_uuids:
|
88
|
+
await simulation.update(firm_uuid, 'employees', citizen_uuids)
|
89
|
+
await simulation.update(firm_uuid, 'employees_agent_id', citizen_agent_ids)
|
90
|
+
for government_uuid in government_uuids:
|
91
|
+
await simulation.update(government_uuid, 'citizens', citizen_uuids)
|
92
|
+
await simulation.update(government_uuid, 'citizens_agent_id', citizen_agent_ids)
|
93
|
+
for bank_uuid in bank_uuids:
|
94
|
+
await simulation.update(bank_uuid, 'citizens', citizen_uuids)
|
95
|
+
await simulation.update(bank_uuid, 'citizens_agent_id', citizen_agent_ids)
|
96
|
+
for nbs_uuid in nbs_uuids:
|
97
|
+
await simulation.update(nbs_uuid, 'firm_id', firm_id)
|
98
|
+
print("Agent info binding completed!")
|
@@ -0,0 +1,202 @@
|
|
1
|
+
import random
|
2
|
+
from mosstool.map._map_util.const import AOI_START_ID
|
3
|
+
import numpy as np
|
4
|
+
import pycityproto.city.economy.v2.economy_pb2 as economyv2
|
5
|
+
from collections import deque
|
6
|
+
|
7
|
+
pareto_param = 8
|
8
|
+
payment_max_skill_multiplier = 950
|
9
|
+
payment_max_skill_multiplier = float(payment_max_skill_multiplier)
|
10
|
+
pmsm = payment_max_skill_multiplier
|
11
|
+
pareto_samples = np.random.pareto(pareto_param, size=(1000, 10))
|
12
|
+
clipped_skills = np.minimum(pmsm, (pmsm - 1) * pareto_samples + 1)
|
13
|
+
sorted_clipped_skills = np.sort(clipped_skills, axis=1)
|
14
|
+
agent_skills = list(sorted_clipped_skills.mean(axis=0))
|
15
|
+
|
16
|
+
def memory_config_societyagent():
|
17
|
+
EXTRA_ATTRIBUTES = {
|
18
|
+
"city": 'New York',
|
19
|
+
|
20
|
+
# 需求信息
|
21
|
+
"type": (str, 'citizen'),
|
22
|
+
"needs": (dict, {
|
23
|
+
'hungry': random.random(), # 饥饿感
|
24
|
+
'tired': random.random(), # 疲劳感
|
25
|
+
'safe': random.random(), # 安全需
|
26
|
+
'social': random.random(), # 社会需求
|
27
|
+
}, True),
|
28
|
+
"current_need": (str, "none", True),
|
29
|
+
"current_plan": (list, [], True),
|
30
|
+
"current_step": (dict, {"intention": "", "type": ""}, True),
|
31
|
+
"execution_context" : (dict, {}, True),
|
32
|
+
"plan_history": (list, [], True),
|
33
|
+
|
34
|
+
# cognition
|
35
|
+
"emotion": (dict, {"sadness": 5, "joy": 5, "fear": 5, "disgust": 5, "anger": 5, "surprise": 5}, True),
|
36
|
+
"attitude": (dict, {}, True),
|
37
|
+
"thought": (str, "Currently nothing good or bad is happening", True),
|
38
|
+
"emotion_types": (str, "Relief", True),
|
39
|
+
"incident": (list, [], True),
|
40
|
+
|
41
|
+
"city": (str, 'Texas', True),
|
42
|
+
"work_skill": (float, random.choice(agent_skills), True), # 工作技能, 即每小时的工资
|
43
|
+
"tax_paid": (float, 0.0, True), # 纳税
|
44
|
+
"consumption_currency": (float, 0.0, True), # 月消费
|
45
|
+
"goods_demand": (int, 0, True),
|
46
|
+
"goods_consumption": (int, 0, True),
|
47
|
+
"work_propensity": (float, 0.0, True),
|
48
|
+
"consumption_propensity": (float, 0.0, True),
|
49
|
+
"income_currency": (float, 0.0, True), # 月收入
|
50
|
+
"to_income": (float, 0.0, True),
|
51
|
+
"to_consumption_currency": (float, 0.0, True),
|
52
|
+
"firm_id": (int, 0, True),
|
53
|
+
"government_id": (int, 0, True),
|
54
|
+
"bank_id": (int, 0, True),
|
55
|
+
'nbs_id': (int, 0, True),
|
56
|
+
"dialog_queue": (deque(maxlen=3), [], True),
|
57
|
+
"firm_forward": (int, 0, True),
|
58
|
+
"bank_forward": (int, 0, True),
|
59
|
+
"nbs_forward": (int, 0, True),
|
60
|
+
"government_forward": (int, 0, True),
|
61
|
+
"forward": (int, 0, True),
|
62
|
+
"depression": (float, 0.0, True),
|
63
|
+
"ubi_opinion": (list, [], True),
|
64
|
+
|
65
|
+
#social
|
66
|
+
"friends": (list, [], True), # 好友列表
|
67
|
+
"relationships": (dict, {}, True), # 与每个好友的关系强度
|
68
|
+
"relation_types": (dict, {}, True),
|
69
|
+
"chat_histories": (dict, {}, True), # 所有聊天历史记录
|
70
|
+
"interactions": (dict, {}, True), # 所有互动记录
|
71
|
+
"to_discuss":(dict, {}, True),
|
72
|
+
|
73
|
+
# economy
|
74
|
+
"working_experience": (list, [], True),
|
75
|
+
"work_hour_month": (float, 160, True),
|
76
|
+
"work_hour_finish": (float, 0, True),
|
77
|
+
|
78
|
+
# mobility
|
79
|
+
"environment": (str, "The environment outside is good", True),
|
80
|
+
}
|
81
|
+
|
82
|
+
PROFILE = {
|
83
|
+
"name": random.choice(["Alice", "Bob", "Charlie", "David", "Eve", "Frank", "Grace", "Helen", "Ivy", "Jack", "Kelly", "Lily", "Mike", "Nancy", "Oscar", "Peter", "Queen", "Rose", "Sam", "Tom", "Ulysses", "Vicky", "Will", "Xavier", "Yvonne", "Zack"]),
|
84
|
+
"gender": random.choice(["male", "female"]),
|
85
|
+
"age": random.randint(18, 65),
|
86
|
+
"education": random.choice(["Doctor", "Master", "Bachelor", "College", "High School"]),
|
87
|
+
"skill": random.choice(["Good at problem-solving", "Good at communication", "Good at creativity", "Good at teamwork", "Other"]),
|
88
|
+
"occupation": random.choice(["Student", "Teacher", "Doctor", "Engineer", "Manager", "Businessman", "Artist", "Athlete", "Other"]),
|
89
|
+
"family_consumption": random.choice(["low", "medium", "high"]),
|
90
|
+
"consumption": random.choice(["sightly low", "low", "medium", "high"]),
|
91
|
+
"personality": random.choice(["outgoint", "introvert", "ambivert", "extrovert"]),
|
92
|
+
"income": '0',
|
93
|
+
"currency": random.randint(1000, 100000),
|
94
|
+
"residence": random.choice(["city", "suburb", "rural"]),
|
95
|
+
"race": random.choice(["Chinese", "American", "British", "French", "German", "Japanese", "Korean", "Russian", "Other"]),
|
96
|
+
"religion": random.choice(["none", "Christian", "Muslim", "Buddhist", "Hindu", "Other"]),
|
97
|
+
"marital_status": random.choice(["not married", "married", "divorced", "widowed"]),
|
98
|
+
}
|
99
|
+
|
100
|
+
BASE = {
|
101
|
+
"home": {"aoi_position": {"aoi_id": AOI_START_ID + random.randint(1000, 10000)}},
|
102
|
+
"work": {"aoi_position": {"aoi_id": AOI_START_ID + random.randint(1000, 10000)}},
|
103
|
+
}
|
104
|
+
|
105
|
+
return EXTRA_ATTRIBUTES, PROFILE, BASE
|
106
|
+
|
107
|
+
def memory_config_firm():
|
108
|
+
EXTRA_ATTRIBUTES = {'type': (int, economyv2.ORG_TYPE_FIRM),
|
109
|
+
'price': (float, float(np.mean(agent_skills))),
|
110
|
+
'inventory': (int, 0),
|
111
|
+
'employees': (list, []),
|
112
|
+
'employees_agent_id': (list, []),
|
113
|
+
'nominal_gdp': (list, []), # useless
|
114
|
+
'real_gdp': (list, []),
|
115
|
+
'unemployment': (list, []),
|
116
|
+
'wages': (list, []),
|
117
|
+
'prices': (list, [float(np.mean(agent_skills))]),
|
118
|
+
"working_hours": (list, []),
|
119
|
+
"depression": (list, []),
|
120
|
+
"consumption_currency": (list, []),
|
121
|
+
"income_currency": (list, []),
|
122
|
+
"locus_control": (list, []),
|
123
|
+
'bracket_cutoffs': (list, list(np.array([0, 9875, 40125, 85525, 163300, 207350, 518400])/12)),
|
124
|
+
"bracket_rates": (list, [0.1, 0.12, 0.22, 0.24, 0.32, 0.35, 0.37]),
|
125
|
+
'interest_rate': (float, 0.03),
|
126
|
+
'citizens': (list, []),
|
127
|
+
'citizens_agent_id': (list, []),
|
128
|
+
'firm_id': (int, 0),}
|
129
|
+
return EXTRA_ATTRIBUTES, {'currency': 1e12}, {}
|
130
|
+
|
131
|
+
def memory_config_government():
|
132
|
+
EXTRA_ATTRIBUTES = {'type': (int, economyv2.ORG_TYPE_GOVERNMENT),
|
133
|
+
# 'bracket_cutoffs': (list, list(np.array([0, 97, 394.75, 842, 1607.25, 2041, 5103])*100/12)),
|
134
|
+
'bracket_cutoffs': (list, list(np.array([0, 9875, 40125, 85525, 163300, 207350, 518400])/12)),
|
135
|
+
"bracket_rates": (list, [0.1, 0.12, 0.22, 0.24, 0.32, 0.35, 0.37]),
|
136
|
+
'citizens': (list, []),
|
137
|
+
'citizens_agent_id': (list, []),
|
138
|
+
'nominal_gdp': (list, []), # useless
|
139
|
+
'real_gdp': (list, []),
|
140
|
+
'unemployment': (list, []),
|
141
|
+
'wages': (list, []),
|
142
|
+
'prices': (list, [float(np.mean(agent_skills))]),
|
143
|
+
"working_hours": (list, []),
|
144
|
+
"depression": (list, []),
|
145
|
+
"consumption_currency": (list, []),
|
146
|
+
"income_currency": (list, []),
|
147
|
+
"locus_control": (list, []),
|
148
|
+
'inventory': (int, 0),
|
149
|
+
'interest_rate': (float, 0.03),
|
150
|
+
'price': (float, float(np.mean(agent_skills))),
|
151
|
+
'employees': (list, []),
|
152
|
+
'employees_agent_id': (list, []),
|
153
|
+
'firm_id': (int, 0),}
|
154
|
+
return EXTRA_ATTRIBUTES, {'currency': 1e12}, {}
|
155
|
+
|
156
|
+
def memory_config_bank():
|
157
|
+
EXTRA_ATTRIBUTES = {'type': (int, economyv2.ORG_TYPE_BANK),
|
158
|
+
'interest_rate': (float, 0.03),
|
159
|
+
'citizens': (list, []),
|
160
|
+
'citizens_agent_id': (list, []),
|
161
|
+
'bracket_cutoffs': (list, list(np.array([0, 9875, 40125, 85525, 163300, 207350, 518400])/12)), #useless
|
162
|
+
"bracket_rates": (list, [0.1, 0.12, 0.22, 0.24, 0.32, 0.35, 0.37]),
|
163
|
+
'inventory': (int, 0),
|
164
|
+
'nominal_gdp': (list, []), # useless
|
165
|
+
'real_gdp': (list, []),
|
166
|
+
'unemployment': (list, []),
|
167
|
+
'wages': (list, []),
|
168
|
+
'prices': (list, [float(np.mean(agent_skills))]),
|
169
|
+
"working_hours": (list, []),
|
170
|
+
"depression": (list, []),
|
171
|
+
"consumption_currency": (list, []),
|
172
|
+
"income_currency": (list, []),
|
173
|
+
"locus_control": (list, []),
|
174
|
+
'price': (float, float(np.mean(agent_skills))),
|
175
|
+
'employees': (list, []),
|
176
|
+
'employees_agent_id': (list, []),
|
177
|
+
'firm_id': (int, 0),}
|
178
|
+
return EXTRA_ATTRIBUTES, {'currency': 1e12}, {}
|
179
|
+
|
180
|
+
def memory_config_nbs():
|
181
|
+
EXTRA_ATTRIBUTES = {'type': (int, economyv2.ORG_TYPE_NBS),
|
182
|
+
'nominal_gdp': (list, []),
|
183
|
+
'real_gdp': (list, []),
|
184
|
+
'unemployment': (list, []),
|
185
|
+
'wages': (list, []),
|
186
|
+
'prices': (list, [float(np.mean(agent_skills))]),
|
187
|
+
"working_hours": (list, []),
|
188
|
+
"depression": (list, []),
|
189
|
+
"consumption_currency": (list, []),
|
190
|
+
"income_currency": (list, []),
|
191
|
+
"locus_control": (list, []),
|
192
|
+
'citizens': (list, []),
|
193
|
+
'citizens_agent_id': (list, []),
|
194
|
+
'firm_id': (int, 0),
|
195
|
+
'bracket_cutoffs': (list, list(np.array([0, 9875, 40125, 85525, 163300, 207350, 518400])/12)), #useless
|
196
|
+
"bracket_rates": (list, [0.1, 0.12, 0.22, 0.24, 0.32, 0.35, 0.37]),
|
197
|
+
'inventory': (int, 0),
|
198
|
+
'interest_rate': (float, 0.03),
|
199
|
+
'price': (float, float(np.mean(agent_skills))),
|
200
|
+
'employees': (list, []),
|
201
|
+
'employees_agent_id': (list, []),}
|
202
|
+
return EXTRA_ATTRIBUTES, {}, {}
|