pycityagent 2.0.0a52__cp311-cp311-macosx_11_0_arm64.whl → 2.0.0a54__cp311-cp311-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pycityagent/agent/agent.py +83 -62
- pycityagent/agent/agent_base.py +81 -54
- pycityagent/cityagent/bankagent.py +5 -7
- pycityagent/cityagent/blocks/__init__.py +0 -2
- pycityagent/cityagent/blocks/cognition_block.py +149 -172
- pycityagent/cityagent/blocks/economy_block.py +90 -129
- pycityagent/cityagent/blocks/mobility_block.py +56 -29
- pycityagent/cityagent/blocks/needs_block.py +163 -145
- pycityagent/cityagent/blocks/other_block.py +17 -9
- pycityagent/cityagent/blocks/plan_block.py +45 -57
- pycityagent/cityagent/blocks/social_block.py +70 -51
- pycityagent/cityagent/blocks/utils.py +2 -0
- pycityagent/cityagent/firmagent.py +6 -7
- pycityagent/cityagent/governmentagent.py +7 -9
- pycityagent/cityagent/memory_config.py +48 -48
- pycityagent/cityagent/message_intercept.py +99 -0
- pycityagent/cityagent/nbsagent.py +6 -29
- pycityagent/cityagent/societyagent.py +325 -127
- pycityagent/cli/wrapper.py +4 -0
- pycityagent/economy/econ_client.py +0 -2
- pycityagent/environment/__init__.py +7 -1
- pycityagent/environment/sim/client.py +10 -1
- pycityagent/environment/sim/clock_service.py +2 -2
- pycityagent/environment/sim/pause_service.py +61 -0
- pycityagent/environment/sim/sim_env.py +34 -46
- pycityagent/environment/simulator.py +18 -14
- pycityagent/llm/embeddings.py +0 -24
- pycityagent/llm/llm.py +18 -10
- pycityagent/memory/faiss_query.py +29 -26
- pycityagent/memory/memory.py +733 -247
- pycityagent/message/__init__.py +8 -1
- pycityagent/message/message_interceptor.py +322 -0
- pycityagent/message/messager.py +42 -11
- pycityagent/pycityagent-sim +0 -0
- pycityagent/simulation/agentgroup.py +137 -96
- pycityagent/simulation/simulation.py +184 -38
- pycityagent/simulation/storage/pg.py +2 -2
- pycityagent/tools/tool.py +7 -9
- pycityagent/utils/__init__.py +7 -2
- pycityagent/utils/pg_query.py +1 -0
- pycityagent/utils/survey_util.py +26 -23
- pycityagent/workflow/block.py +14 -7
- {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a54.dist-info}/METADATA +2 -2
- {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a54.dist-info}/RECORD +48 -46
- pycityagent/cityagent/blocks/time_block.py +0 -116
- {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a54.dist-info}/LICENSE +0 -0
- {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a54.dist-info}/WHEEL +0 -0
- {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a54.dist-info}/entry_points.txt +0 -0
- {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a54.dist-info}/top_level.txt +0 -0
@@ -17,24 +17,22 @@ agent_skills = list(sorted_clipped_skills.mean(axis=0))
|
|
17
17
|
|
18
18
|
def memory_config_societyagent():
|
19
19
|
EXTRA_ATTRIBUTES = {
|
20
|
-
"city": "New York",
|
21
|
-
# 需求信息
|
22
20
|
"type": (str, "citizen"),
|
23
|
-
"
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
},
|
31
|
-
True,
|
32
|
-
),
|
21
|
+
"city": (str, "New York", True),
|
22
|
+
|
23
|
+
# Needs Model
|
24
|
+
"hunger_satisfaction": (float, random.random(), True), # 饥饿满意度
|
25
|
+
"energy_satisfaction": (float, random.random(), True), # 精力满意度
|
26
|
+
"safety_satisfaction": (float, random.random(), True), # 安全满意度
|
27
|
+
"social_satisfaction": (float, random.random(), True), # 社交满意度
|
33
28
|
"current_need": (str, "none", True),
|
29
|
+
|
30
|
+
# Plan Behavior Model
|
34
31
|
"current_plan": (list, [], True),
|
35
32
|
"current_step": (dict, {"intention": "", "type": ""}, True),
|
36
33
|
"execution_context": (dict, {}, True),
|
37
34
|
"plan_history": (list, [], True),
|
35
|
+
|
38
36
|
# cognition
|
39
37
|
"emotion": (
|
40
38
|
dict,
|
@@ -46,25 +44,25 @@ def memory_config_societyagent():
|
|
46
44
|
"anger": 5,
|
47
45
|
"surprise": 5,
|
48
46
|
},
|
49
|
-
|
47
|
+
False,
|
50
48
|
),
|
51
49
|
"attitude": (dict, {}, True),
|
52
50
|
"thought": (str, "Currently nothing good or bad is happening", True),
|
53
51
|
"emotion_types": (str, "Relief", True),
|
54
|
-
|
55
|
-
|
52
|
+
|
53
|
+
# economy
|
56
54
|
"work_skill": (
|
57
55
|
float,
|
58
56
|
random.choice(agent_skills),
|
59
57
|
True,
|
60
|
-
), #
|
61
|
-
"tax_paid": (float, 0.0, True), #
|
62
|
-
"consumption_currency": (float, 0.0, True), #
|
58
|
+
), # work skill
|
59
|
+
"tax_paid": (float, 0.0, True), # tax paid
|
60
|
+
"consumption_currency": (float, 0.0, True), # consumption
|
63
61
|
"goods_demand": (int, 0, True),
|
64
62
|
"goods_consumption": (int, 0, True),
|
65
63
|
"work_propensity": (float, 0.0, True),
|
66
64
|
"consumption_propensity": (float, 0.0, True),
|
67
|
-
"income_currency": (float, 0.0, True), #
|
65
|
+
"income_currency": (float, 0.0, True), # monthly income
|
68
66
|
"to_income": (float, 0.0, True),
|
69
67
|
"to_consumption_currency": (float, 0.0, True),
|
70
68
|
"firm_id": (int, 0, True),
|
@@ -79,23 +77,25 @@ def memory_config_societyagent():
|
|
79
77
|
"forward": (int, 0, True),
|
80
78
|
"depression": (float, 0.0, True),
|
81
79
|
"ubi_opinion": (list, [], True),
|
82
|
-
# social
|
83
|
-
"friends": (list, [], True), # 好友列表
|
84
|
-
"relationships": (dict, {}, True), # 与每个好友的关系强度
|
85
|
-
"relation_types": (dict, {}, True),
|
86
|
-
"chat_histories": (dict, {}, True), # 所有聊天历史记录
|
87
|
-
"interactions": (dict, {}, True), # 所有互动记录
|
88
|
-
"to_discuss": (dict, {}, True),
|
89
|
-
# economy
|
90
80
|
"working_experience": (list, [], True),
|
91
81
|
"work_hour_month": (float, 160, True),
|
92
82
|
"work_hour_finish": (float, 0, True),
|
83
|
+
|
84
|
+
# social
|
85
|
+
"friends": (list, [], True), # friends list
|
86
|
+
"relationships": (dict, {}, True), # relationship strength with each friend
|
87
|
+
"relation_types": (dict, {}, True),
|
88
|
+
"chat_histories": (dict, {}, True), # all chat histories
|
89
|
+
"interactions": (dict, {}, True), # all interaction records
|
90
|
+
"to_discuss": (dict, {}, True),
|
91
|
+
|
93
92
|
# mobility
|
94
93
|
"environment": (str, "The environment outside is good", True),
|
94
|
+
"number_poi_visited": (int, 1, True),
|
95
95
|
}
|
96
96
|
|
97
97
|
PROFILE = {
|
98
|
-
"name": random.choice(
|
98
|
+
"name": (str,random.choice(
|
99
99
|
[
|
100
100
|
"Alice",
|
101
101
|
"Bob",
|
@@ -124,13 +124,13 @@ def memory_config_societyagent():
|
|
124
124
|
"Yvonne",
|
125
125
|
"Zack",
|
126
126
|
]
|
127
|
-
),
|
128
|
-
"gender": random.choice(["male", "female"]),
|
129
|
-
"age": random.randint(18, 65),
|
130
|
-
"education": random.choice(
|
127
|
+
), True),
|
128
|
+
"gender": (str, random.choice(["male", "female"]), True),
|
129
|
+
"age": (int, random.randint(18, 65), True),
|
130
|
+
"education": (str, random.choice(
|
131
131
|
["Doctor", "Master", "Bachelor", "College", "High School"]
|
132
|
-
),
|
133
|
-
"skill": random.choice(
|
132
|
+
), True),
|
133
|
+
"skill": (str, random.choice(
|
134
134
|
[
|
135
135
|
"Good at problem-solving",
|
136
136
|
"Good at communication",
|
@@ -138,8 +138,8 @@ def memory_config_societyagent():
|
|
138
138
|
"Good at teamwork",
|
139
139
|
"Other",
|
140
140
|
]
|
141
|
-
),
|
142
|
-
"occupation": random.choice(
|
141
|
+
), True),
|
142
|
+
"occupation": (str, random.choice(
|
143
143
|
[
|
144
144
|
"Student",
|
145
145
|
"Teacher",
|
@@ -151,16 +151,16 @@ def memory_config_societyagent():
|
|
151
151
|
"Athlete",
|
152
152
|
"Other",
|
153
153
|
]
|
154
|
-
),
|
155
|
-
"family_consumption": random.choice(["low", "medium", "high"]),
|
156
|
-
"consumption": random.choice(["sightly low", "low", "medium", "high"]),
|
157
|
-
"personality": random.choice(
|
154
|
+
), True),
|
155
|
+
"family_consumption": (str, random.choice(["low", "medium", "high"]), True),
|
156
|
+
"consumption": (str, random.choice(["sightly low", "low", "medium", "high"]), True),
|
157
|
+
"personality": (str, random.choice(
|
158
158
|
["outgoint", "introvert", "ambivert", "extrovert"]
|
159
|
-
),
|
159
|
+
), True),
|
160
160
|
"income": "0",
|
161
161
|
"currency": random.randint(1000, 100000),
|
162
|
-
"residence": random.choice(["city", "suburb", "rural"]),
|
163
|
-
"race": random.choice(
|
162
|
+
"residence": (str, random.choice(["city", "suburb", "rural"]), True),
|
163
|
+
"race": (str, random.choice(
|
164
164
|
[
|
165
165
|
"Chinese",
|
166
166
|
"American",
|
@@ -172,13 +172,13 @@ def memory_config_societyagent():
|
|
172
172
|
"Russian",
|
173
173
|
"Other",
|
174
174
|
]
|
175
|
-
),
|
176
|
-
"religion": random.choice(
|
175
|
+
), True),
|
176
|
+
"religion": (str, random.choice(
|
177
177
|
["none", "Christian", "Muslim", "Buddhist", "Hindu", "Other"]
|
178
|
-
),
|
179
|
-
"marital_status": random.choice(
|
178
|
+
), True),
|
179
|
+
"marital_status": (str, random.choice(
|
180
180
|
["not married", "married", "divorced", "widowed"]
|
181
|
-
),
|
181
|
+
), True),
|
182
182
|
}
|
183
183
|
|
184
184
|
BASE = {
|
@@ -0,0 +1,99 @@
|
|
1
|
+
import asyncio
|
2
|
+
|
3
|
+
from pycityagent.llm import LLM
|
4
|
+
from pycityagent.message import MessageBlockBase, MessageBlockListenerBase
|
5
|
+
|
6
|
+
|
7
|
+
async def check_message(
|
8
|
+
from_uuid: str, to_uuid: str, llm_client: LLM, content: str
|
9
|
+
) -> bool:
|
10
|
+
"""
|
11
|
+
使用LLM检查消息是否合规
|
12
|
+
返回: (是否合规, from_uuid, to_uuid)
|
13
|
+
"""
|
14
|
+
print(f"\n检查消息: {from_uuid} -> {to_uuid}: {content}")
|
15
|
+
|
16
|
+
prompt = f"""
|
17
|
+
请判断以下消息是否具有情绪煽动性:
|
18
|
+
发送者ID: {from_uuid}
|
19
|
+
接收者ID: {to_uuid}
|
20
|
+
消息内容: {content}
|
21
|
+
|
22
|
+
如果消息具有情绪煽动性,请返回 False;如果消息正常,请返回 True。
|
23
|
+
"""
|
24
|
+
|
25
|
+
if "test" in content.lower():
|
26
|
+
is_valid = False
|
27
|
+
else:
|
28
|
+
is_valid = True
|
29
|
+
print(f"消息检查结果: {'合规' if is_valid else '不合规'}")
|
30
|
+
return is_valid
|
31
|
+
|
32
|
+
|
33
|
+
class EdgeMessageBlock(MessageBlockBase):
|
34
|
+
async def forward( # type:ignore
|
35
|
+
self,
|
36
|
+
from_uuid: str,
|
37
|
+
to_uuid: str,
|
38
|
+
msg: str,
|
39
|
+
black_list: list[tuple[str, str]],
|
40
|
+
):
|
41
|
+
if (from_uuid, to_uuid) in set(black_list):
|
42
|
+
# 可选同时返回入队的信息(False,err) 如果只返回bool值则默认报错信息入队
|
43
|
+
return False
|
44
|
+
else:
|
45
|
+
is_valid = await check_message(
|
46
|
+
from_uuid=from_uuid,
|
47
|
+
to_uuid=to_uuid,
|
48
|
+
llm_client=self.llm,
|
49
|
+
content=msg,
|
50
|
+
)
|
51
|
+
if not is_valid:
|
52
|
+
# 直接添加即可 在框架内部的异步锁保证不会冲突
|
53
|
+
black_list.append((from_uuid, to_uuid))
|
54
|
+
return is_valid
|
55
|
+
|
56
|
+
|
57
|
+
class PointMessageBlock(MessageBlockBase):
|
58
|
+
async def forward( # type:ignore
|
59
|
+
self,
|
60
|
+
from_uuid: str,
|
61
|
+
to_uuid: str,
|
62
|
+
msg: str,
|
63
|
+
violation_counts: dict[str, int],
|
64
|
+
black_list: list[tuple[str, str]],
|
65
|
+
):
|
66
|
+
if (from_uuid, to_uuid) in set(black_list):
|
67
|
+
# 可选同时返回入队的信息(False,err) 如果只返回bool值则默认报错信息入队
|
68
|
+
return False
|
69
|
+
else:
|
70
|
+
# violation count在框架内自动维护 这里不用管
|
71
|
+
is_valid = await check_message(
|
72
|
+
from_uuid=from_uuid,
|
73
|
+
to_uuid=to_uuid,
|
74
|
+
llm_client=self.llm,
|
75
|
+
content=msg,
|
76
|
+
)
|
77
|
+
if not is_valid and violation_counts[from_uuid] >= 3 - 1:
|
78
|
+
# 直接添加即可 在框架内部的异步锁保证不会冲突
|
79
|
+
black_list.append((from_uuid, to_uuid))
|
80
|
+
return is_valid
|
81
|
+
|
82
|
+
|
83
|
+
class MessageBlockListener(MessageBlockListenerBase):
|
84
|
+
def __init__(
|
85
|
+
self, save_queue_values: bool = False, get_queue_period: float = 0.1
|
86
|
+
) -> None:
|
87
|
+
super().__init__(save_queue_values, get_queue_period)
|
88
|
+
|
89
|
+
async def forward(
|
90
|
+
self,
|
91
|
+
):
|
92
|
+
while True:
|
93
|
+
if self.has_queue:
|
94
|
+
value = await self.queue.get_async() # type: ignore
|
95
|
+
if self._save_queue_values:
|
96
|
+
self._values_from_queue.append(value)
|
97
|
+
print(f"get `{value}` from queue")
|
98
|
+
# do something with the value
|
99
|
+
await asyncio.sleep(self._get_queue_period)
|
@@ -9,14 +9,11 @@ from pycityagent.economy import EconomyClient
|
|
9
9
|
from pycityagent.llm.llm import LLM
|
10
10
|
from pycityagent.memory import Memory
|
11
11
|
from pycityagent.message import Messager
|
12
|
-
from pycityagent.tools import ExportMlflowMetrics
|
13
12
|
|
14
13
|
logger = logging.getLogger("pycityagent")
|
15
14
|
|
16
15
|
|
17
16
|
class NBSAgent(InstitutionAgent):
|
18
|
-
export_metrics = ExportMlflowMetrics(log_batch_size=3)
|
19
|
-
|
20
17
|
def __init__(
|
21
18
|
self,
|
22
19
|
name: str,
|
@@ -60,15 +57,13 @@ class NBSAgent(InstitutionAgent):
|
|
60
57
|
|
61
58
|
async def forward(self):
|
62
59
|
if await self.month_trigger():
|
63
|
-
citizens = await self.memory.get("citizens")
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
break
|
68
|
-
await asyncio.sleep(1)
|
60
|
+
citizens = await self.memory.status.get("citizens")
|
61
|
+
agents_forward = []
|
62
|
+
if not np.all(np.array(agents_forward) > self.forward_times):
|
63
|
+
return
|
69
64
|
work_propensity = await self.gather_messages(citizens, "work_propensity")
|
70
65
|
working_hours = np.mean(work_propensity) * self.num_labor_hours
|
71
|
-
firm_id = await self.memory.get("firm_id")
|
66
|
+
firm_id = await self.memory.status.get("firm_id")
|
72
67
|
price = await self.economy_client.get(firm_id, "price")
|
73
68
|
prices = await self.economy_client.get(self._agent_id, "prices")
|
74
69
|
initial_price = prices[0]
|
@@ -116,23 +111,5 @@ class NBSAgent(InstitutionAgent):
|
|
116
111
|
self.forward_times += 1
|
117
112
|
for uuid in citizens:
|
118
113
|
await self.send_message_to_agent(
|
119
|
-
uuid, f"nbs_forward@{self.forward_times}"
|
120
|
-
)
|
121
|
-
|
122
|
-
metrics = {
|
123
|
-
"nominal_gdp": nominal_gdp,
|
124
|
-
"working_hours": working_hours,
|
125
|
-
"price": price,
|
126
|
-
"depression": depression,
|
127
|
-
"consumption": consumption_currency,
|
128
|
-
"income": income_currency,
|
129
|
-
}
|
130
|
-
for k, v in metrics.items():
|
131
|
-
await self.export_metrics(
|
132
|
-
metric={
|
133
|
-
"key": k,
|
134
|
-
"value": v,
|
135
|
-
"step": self.forward_times,
|
136
|
-
},
|
137
|
-
clear_cache=True,
|
114
|
+
uuid, f"nbs_forward@{self.forward_times}", "economy"
|
138
115
|
)
|