pycityagent 2.0.0a47__cp312-cp312-macosx_11_0_arm64.whl → 2.0.0a48__cp312-cp312-macosx_11_0_arm64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. pycityagent/__init__.py +3 -2
  2. pycityagent/agent.py +109 -4
  3. pycityagent/cityagent/__init__.py +20 -0
  4. pycityagent/cityagent/bankagent.py +54 -0
  5. pycityagent/cityagent/blocks/__init__.py +20 -0
  6. pycityagent/cityagent/blocks/cognition_block.py +304 -0
  7. pycityagent/cityagent/blocks/dispatcher.py +78 -0
  8. pycityagent/cityagent/blocks/economy_block.py +356 -0
  9. pycityagent/cityagent/blocks/mobility_block.py +258 -0
  10. pycityagent/cityagent/blocks/needs_block.py +305 -0
  11. pycityagent/cityagent/blocks/other_block.py +103 -0
  12. pycityagent/cityagent/blocks/plan_block.py +309 -0
  13. pycityagent/cityagent/blocks/social_block.py +345 -0
  14. pycityagent/cityagent/blocks/time_block.py +116 -0
  15. pycityagent/cityagent/blocks/utils.py +66 -0
  16. pycityagent/cityagent/firmagent.py +75 -0
  17. pycityagent/cityagent/governmentagent.py +60 -0
  18. pycityagent/cityagent/initial.py +98 -0
  19. pycityagent/cityagent/memory_config.py +202 -0
  20. pycityagent/cityagent/nbsagent.py +92 -0
  21. pycityagent/cityagent/societyagent.py +291 -0
  22. pycityagent/memory/memory.py +0 -18
  23. pycityagent/message/messager.py +6 -3
  24. pycityagent/simulation/agentgroup.py +118 -37
  25. pycityagent/simulation/simulation.py +311 -316
  26. pycityagent/workflow/block.py +66 -1
  27. pycityagent/workflow/tool.py +15 -11
  28. {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a48.dist-info}/METADATA +2 -2
  29. {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a48.dist-info}/RECORD +33 -14
  30. {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a48.dist-info}/LICENSE +0 -0
  31. {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a48.dist-info}/WHEEL +0 -0
  32. {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a48.dist-info}/entry_points.txt +0 -0
  33. {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a48.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, {}, {}