pycityagent 2.0.0a52__cp39-cp39-macosx_11_0_arm64.whl → 2.0.0a53__cp39-cp39-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 +48 -62
- pycityagent/agent/agent_base.py +66 -53
- 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 +44 -56
- 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/nbsagent.py +6 -29
- pycityagent/cityagent/societyagent.py +204 -119
- 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/simulator.py +17 -12
- pycityagent/llm/embeddings.py +0 -24
- pycityagent/memory/faiss_query.py +29 -26
- pycityagent/memory/memory.py +720 -272
- pycityagent/pycityagent-sim +0 -0
- pycityagent/simulation/agentgroup.py +92 -99
- pycityagent/simulation/simulation.py +115 -40
- pycityagent/tools/tool.py +7 -9
- pycityagent/workflow/block.py +11 -4
- {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a53.dist-info}/METADATA +1 -1
- {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a53.dist-info}/RECORD +35 -35
- pycityagent/cityagent/blocks/time_block.py +0 -116
- {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a53.dist-info}/LICENSE +0 -0
- {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a53.dist-info}/WHEEL +0 -0
- {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a53.dist-info}/entry_points.txt +0 -0
- {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a53.dist-info}/top_level.txt +0 -0
@@ -18,6 +18,8 @@ Available options: {options}
|
|
18
18
|
Current location: {current_location}
|
19
19
|
Current time: {current_time}
|
20
20
|
Current Environment: {environment}
|
21
|
+
Your emotion: {emotion_types}
|
22
|
+
Your thought: {thought}
|
21
23
|
|
22
24
|
Please evaluate and select the most appropriate option based on these three dimensions:
|
23
25
|
1. Attitude: Personal preference and evaluation of the option
|
@@ -26,7 +28,7 @@ Please evaluate and select the most appropriate option based on these three dime
|
|
26
28
|
|
27
29
|
Please return the evaluation results in JSON format (Do not return any other text):
|
28
30
|
{{
|
29
|
-
"selected_option": "Select the most suitable option from available
|
31
|
+
"selected_option": "Select the most suitable option from available options",
|
30
32
|
"evaluation": {{
|
31
33
|
"attitude": "Attitude score for the option (0-1)",
|
32
34
|
"subjective_norm": "Subjective norm score (0-1)",
|
@@ -42,6 +44,8 @@ Selected plan: {selected_option}
|
|
42
44
|
Current location: {current_location}
|
43
45
|
Current time: {current_time}
|
44
46
|
Current Environment: {environment}
|
47
|
+
Your emotion: {emotion_types}
|
48
|
+
Your thought: {thought}
|
45
49
|
|
46
50
|
Please generate specific execution steps and return in JSON format:
|
47
51
|
{{
|
@@ -148,26 +152,20 @@ Example outputs (Do not return any other text):
|
|
148
152
|
"""
|
149
153
|
|
150
154
|
class PlanBlock(Block):
|
151
|
-
configurable_fields: List[str] = ["
|
155
|
+
configurable_fields: List[str] = ["max_plan_steps"]
|
152
156
|
default_values = {
|
153
|
-
"guidance_options": {
|
154
|
-
"hungry": ['Eat at home', 'Eat outside'],
|
155
|
-
"tired": ['Sleep', 'Take a nap'],
|
156
|
-
"safe": ['Work'],
|
157
|
-
"social": ['Online social', 'Shopping'],
|
158
|
-
"whatever": ['Learning', 'Entertainment', 'Hang out', 'Exercise']
|
159
|
-
},
|
160
157
|
"max_plan_steps": 6
|
161
158
|
}
|
159
|
+
fields_description = {
|
160
|
+
"max_plan_steps": "The maximum number of steps in a plan"
|
161
|
+
}
|
162
162
|
|
163
163
|
def __init__(self, llm: LLM, memory: Memory, simulator: Simulator):
|
164
|
-
super().__init__("PlanBlock", llm, memory, simulator)
|
164
|
+
super().__init__("PlanBlock", llm=llm, memory=memory, simulator=simulator)
|
165
165
|
self.guidance_prompt = FormatPrompt(template=GUIDANCE_SELECTION_PROMPT)
|
166
166
|
self.detail_prompt = FormatPrompt(template=DETAILED_PLAN_PROMPT)
|
167
167
|
self.trigger_time = 0
|
168
168
|
self.token_consumption = 0
|
169
|
-
|
170
|
-
# configurable fields
|
171
169
|
self.guidance_options = {
|
172
170
|
"hungry": ['Eat at home', 'Eat outside'],
|
173
171
|
"tired": ['Sleep', 'Take a nap'],
|
@@ -175,30 +173,31 @@ class PlanBlock(Block):
|
|
175
173
|
"social": ['Online social', 'Shopping'],
|
176
174
|
"whatever": ['Learning', 'Entertainment', 'Hang out', 'Exercise']
|
177
175
|
}
|
176
|
+
|
177
|
+
# configurable fields
|
178
178
|
self.max_plan_steps = 6
|
179
179
|
|
180
180
|
async def select_guidance(self, current_need: str) -> Dict:
|
181
|
-
"""
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
position_now = await self.memory.get("position")
|
187
|
-
home_location = await self.memory.get("home")
|
188
|
-
work_location = await self.memory.get("work")
|
181
|
+
"""Select guidance plan"""
|
182
|
+
position_now = await self.memory.status.get("position")
|
183
|
+
home_location = await self.memory.status.get("home")
|
184
|
+
work_location = await self.memory.status.get("work")
|
189
185
|
current_location = "Out"
|
190
186
|
if 'aoi_position' in position_now and position_now['aoi_position'] == home_location['aoi_position']:
|
191
187
|
current_location = "At home"
|
192
188
|
elif 'aoi_position' in position_now and position_now['aoi_position'] == work_location['aoi_position']:
|
193
189
|
current_location = "At workplace"
|
194
190
|
current_time = await self.simulator.get_time(format_time=True)
|
195
|
-
environment = await self.memory.get("environment")
|
191
|
+
environment = await self.memory.status.get("environment")
|
192
|
+
options = self.guidance_options.get(current_need, [])
|
196
193
|
self.guidance_prompt.format(
|
197
194
|
current_need=current_need,
|
198
195
|
options=options,
|
199
196
|
current_location=current_location,
|
200
197
|
current_time=current_time,
|
201
|
-
environment=environment
|
198
|
+
environment=environment,
|
199
|
+
emotion_types=await self.memory.status.get("emotion_types"),
|
200
|
+
thought=await self.memory.status.get("thought")
|
202
201
|
)
|
203
202
|
|
204
203
|
response = await self.llm.atext_request(
|
@@ -207,32 +206,30 @@ class PlanBlock(Block):
|
|
207
206
|
|
208
207
|
try:
|
209
208
|
result = json.loads(self.clean_json_response(response)) # type: ignore
|
210
|
-
if result['selected_option'] not in options:
|
211
|
-
result['selected_option'] = random.choice(options)
|
212
|
-
logger.info(f"\n=== Plan Selection ===")
|
213
|
-
logger.info(f"Selected Plan: {result['selected_option']}")
|
214
209
|
return result
|
215
210
|
except Exception as e:
|
216
211
|
logger.warning(f"Error parsing guidance selection response: {str(e)}")
|
217
212
|
return None # type: ignore
|
218
213
|
|
219
214
|
async def generate_detailed_plan(self, current_need: str, selected_option: str) -> Dict:
|
220
|
-
"""
|
221
|
-
position_now = await self.memory.get("position")
|
222
|
-
home_location = await self.memory.get("home")
|
223
|
-
work_location = await self.memory.get("work")
|
215
|
+
"""Generate detailed execution plan"""
|
216
|
+
position_now = await self.memory.status.get("position")
|
217
|
+
home_location = await self.memory.status.get("home")
|
218
|
+
work_location = await self.memory.status.get("work")
|
224
219
|
current_location = "Out"
|
225
220
|
if 'aoi_position' in position_now and position_now['aoi_position'] == home_location['aoi_position']:
|
226
221
|
current_location = "At home"
|
227
222
|
elif 'aoi_position' in position_now and position_now['aoi_position'] == work_location['aoi_position']:
|
228
223
|
current_location = "At workplace"
|
229
224
|
current_time = await self.simulator.get_time(format_time=True)
|
230
|
-
environment = await self.memory.get("environment")
|
225
|
+
environment = await self.memory.status.get("environment")
|
231
226
|
self.detail_prompt.format(
|
232
227
|
selected_option=selected_option,
|
233
228
|
current_location=current_location,
|
234
229
|
current_time=current_time,
|
235
230
|
environment=environment,
|
231
|
+
emotion_types=await self.memory.status.get("emotion_types"),
|
232
|
+
thought=await self.memory.status.get("thought"),
|
236
233
|
max_plan_steps=self.max_plan_steps
|
237
234
|
)
|
238
235
|
|
@@ -250,36 +247,25 @@ class PlanBlock(Block):
|
|
250
247
|
async def forward(self):
|
251
248
|
self.trigger_time += 1
|
252
249
|
consumption_start = self.llm.prompt_tokens_used + self.llm.completion_tokens_used
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
await self.memory.update("current_plan", [])
|
257
|
-
await self.memory.update("current_step", {"intention": "", "type": ""})
|
258
|
-
return
|
259
|
-
|
260
|
-
# 第一步:选择指导方案
|
250
|
+
|
251
|
+
# Step 1: Select guidance plan
|
252
|
+
current_need = await self.memory.status.get("current_need")
|
261
253
|
guidance_result = await self.select_guidance(current_need)
|
262
254
|
if not guidance_result:
|
263
255
|
return
|
264
256
|
|
265
|
-
#
|
257
|
+
# Step 2: Generate detailed plan
|
266
258
|
detailed_plan = await self.generate_detailed_plan(
|
267
259
|
current_need,
|
268
260
|
guidance_result["selected_option"]
|
269
261
|
)
|
270
262
|
|
271
263
|
if not detailed_plan or "plan" not in detailed_plan:
|
272
|
-
await self.memory.update("current_plan", [])
|
273
|
-
await self.memory.update("current_step", {"intention": "", "type": ""})
|
264
|
+
await self.memory.status.update("current_plan", [])
|
265
|
+
await self.memory.status.update("current_step", {"intention": "", "type": ""})
|
274
266
|
return
|
275
|
-
logger.info("\n=== Plan Generation ===")
|
276
|
-
logger.info(f"Target: {detailed_plan['plan']['target']}")
|
277
|
-
logger.info("\nExecution Steps:")
|
278
|
-
for i, step in enumerate(detailed_plan['plan']['steps'], 1):
|
279
|
-
logger.info(f"{i}. {step['intention']} ({step['type']})")
|
280
|
-
logger.info("===============\n")
|
281
267
|
|
282
|
-
#
|
268
|
+
# Step 3: Update plan and current step
|
283
269
|
steps = detailed_plan["plan"]["steps"]
|
284
270
|
for step in steps:
|
285
271
|
step["evaluation"] = {"status": "pending", "details": ""}
|
@@ -288,22 +274,24 @@ class PlanBlock(Block):
|
|
288
274
|
"target": detailed_plan["plan"]["target"],
|
289
275
|
"steps": steps,
|
290
276
|
"completed": False,
|
291
|
-
"
|
277
|
+
"failed": False,
|
278
|
+
"stream_nodes": [],
|
279
|
+
"guidance": guidance_result # Save the evaluation result of the plan selection
|
292
280
|
}
|
293
281
|
formated_steps = "\n".join([f"{i}. {step['intention']}" for i, step in enumerate(plan['steps'], 1)])
|
294
282
|
formated_plan = f"""
|
295
|
-
|
296
|
-
|
283
|
+
Overall Target: {plan['target']}
|
284
|
+
Execution Steps: \n{formated_steps}
|
297
285
|
"""
|
298
286
|
plan['start_time'] = await self.simulator.get_time(format_time=True)
|
299
|
-
await self.memory.update("current_plan", plan)
|
300
|
-
await self.memory.update("current_step", steps[0] if steps else {"intention": "", "type": ""})
|
301
|
-
await self.memory.update("execution_context", {'plan': formated_plan})
|
287
|
+
await self.memory.status.update("current_plan", plan)
|
288
|
+
await self.memory.status.update("current_step", steps[0] if steps else {"intention": "", "type": ""})
|
289
|
+
await self.memory.status.update("execution_context", {'plan': formated_plan})
|
302
290
|
|
303
291
|
consumption_end = self.llm.prompt_tokens_used + self.llm.completion_tokens_used
|
304
292
|
self.token_consumption += consumption_end - consumption_start
|
305
293
|
|
306
294
|
def clean_json_response(self, response: str) -> str:
|
307
|
-
"""
|
295
|
+
"""Clean special characters in LLM response"""
|
308
296
|
response = response.replace('```json', '').replace('```', '')
|
309
297
|
return response.strip()
|
@@ -23,8 +23,8 @@ class MessagePromptManager:
|
|
23
23
|
async def get_prompt(self, memory, step: Dict[str, Any], target: str) -> str:
|
24
24
|
"""在这里改给模板输入的数据"""
|
25
25
|
# 获取数据
|
26
|
-
relationships = await memory.get("relationships") or {}
|
27
|
-
chat_histories = await memory.get("chat_histories") or {}
|
26
|
+
relationships = await memory.status.get("relationships") or {}
|
27
|
+
chat_histories = await memory.status.get("chat_histories") or {}
|
28
28
|
|
29
29
|
# 构建讨论话题约束
|
30
30
|
discussion_constraint = ""
|
@@ -34,12 +34,14 @@ class MessagePromptManager:
|
|
34
34
|
|
35
35
|
# 格式化提示
|
36
36
|
self.format_prompt.format(
|
37
|
-
gender=await memory.get("gender") or "",
|
38
|
-
education=await memory.get("education") or "",
|
39
|
-
personality=await memory.get("personality") or "",
|
40
|
-
occupation=await memory.get("occupation") or "",
|
37
|
+
gender=await memory.status.get("gender") or "",
|
38
|
+
education=await memory.status.get("education") or "",
|
39
|
+
personality=await memory.status.get("personality") or "",
|
40
|
+
occupation=await memory.status.get("occupation") or "",
|
41
41
|
relationship_score=relationships.get(target, 50),
|
42
42
|
intention=step.get("intention", ""),
|
43
|
+
emotion_types=await memory.status.get("emotion_types"),
|
44
|
+
thought=await memory.status.get("thought"),
|
43
45
|
chat_history=chat_histories.get(target, "") if isinstance(chat_histories, dict) else "",
|
44
46
|
discussion_constraint=discussion_constraint
|
45
47
|
)
|
@@ -52,47 +54,57 @@ class SocialNoneBlock(Block):
|
|
52
54
|
NoneBlock
|
53
55
|
"""
|
54
56
|
def __init__(self, llm: LLM, memory: Memory):
|
55
|
-
super().__init__("NoneBlock", llm, memory)
|
57
|
+
super().__init__("NoneBlock", llm=llm, memory=memory)
|
56
58
|
self.description = "Handle all other cases"
|
57
59
|
self.guidance_prompt = FormatPrompt(template=TIME_ESTIMATE_PROMPT)
|
58
60
|
|
59
61
|
async def forward(self, step, context):
|
60
|
-
self.guidance_prompt.format(
|
62
|
+
self.guidance_prompt.format(plan=context['plan'],
|
63
|
+
intention=step['intention'],
|
64
|
+
emotion_types=await self.memory.status.get("emotion_types"))
|
61
65
|
result = await self.llm.atext_request(self.guidance_prompt.to_dialog())
|
62
66
|
result = clean_json_response(result)
|
63
67
|
try:
|
64
68
|
result = json.loads(result)
|
69
|
+
node_id = await self.memory.stream.add_social(description=f"I {step['intention']}")
|
65
70
|
return {
|
66
71
|
'success': True,
|
67
|
-
'evaluation': f'
|
68
|
-
'consumed_time': result['time']
|
72
|
+
'evaluation': f'Finished {step["intention"]}',
|
73
|
+
'consumed_time': result['time'],
|
74
|
+
'node_id': node_id
|
69
75
|
}
|
70
76
|
except Exception as e:
|
71
77
|
logger.warning(f"解析时间评估响应时发生错误: {str(e)}, 原始结果: {result}")
|
78
|
+
node_id = await self.memory.stream.add_social(description=f"I failed to execute {step['intention']}")
|
72
79
|
return {
|
73
80
|
'success': False,
|
74
|
-
'evaluation': f'
|
75
|
-
'consumed_time':
|
81
|
+
'evaluation': f'Failed to execute {step["intention"]}',
|
82
|
+
'consumed_time': 5,
|
83
|
+
'node_id': node_id
|
76
84
|
}
|
77
85
|
|
78
86
|
class FindPersonBlock(Block):
|
79
87
|
"""寻找社交对象"""
|
80
88
|
def __init__(self, llm: LLM, memory: Memory, simulator: Simulator):
|
81
|
-
super().__init__("FindPersonBlock", llm, memory, simulator)
|
89
|
+
super().__init__("FindPersonBlock", llm=llm, memory=memory, simulator=simulator)
|
82
90
|
self.description = "Find a suitable person to socialize with"
|
83
91
|
|
84
92
|
self.prompt = """
|
85
93
|
Based on the following information, help me select the most suitable friend to interact with:
|
86
94
|
|
87
|
-
1.
|
95
|
+
1. Your Profile:
|
88
96
|
- Gender: {gender}
|
89
97
|
- Education: {education}
|
90
98
|
- Personality: {personality}
|
91
99
|
- Occupation: {occupation}
|
92
100
|
|
93
|
-
2.
|
101
|
+
2. Your Current Intention: {intention}
|
94
102
|
|
95
|
-
3.
|
103
|
+
3. Your Current Emotion: {emotion_types}
|
104
|
+
|
105
|
+
4. Your Current Thought: {thought}
|
106
|
+
|
107
|
+
5. Your Friends List (shown as index-to-relationship pairs):
|
96
108
|
{friend_info}
|
97
109
|
Note: For each friend, the relationship strength (0-100) indicates how close we are
|
98
110
|
|
@@ -112,26 +124,20 @@ class FindPersonBlock(Block):
|
|
112
124
|
|
113
125
|
async def forward(self, step: Dict[str, Any], context: Optional[Dict] = None) -> Dict[str, Any]:
|
114
126
|
try:
|
115
|
-
#
|
116
|
-
|
117
|
-
|
118
|
-
"education": await self.memory.get("education"),
|
119
|
-
"personality": await self.memory.get("personality"),
|
120
|
-
"occupation": await self.memory.get("occupation")
|
121
|
-
}
|
122
|
-
|
123
|
-
# 获取朋友列表和关系强度
|
124
|
-
friends = await self.memory.get("friends") or []
|
125
|
-
relationships = await self.memory.get("relationships") or {}
|
127
|
+
# Get friends list and relationship strength
|
128
|
+
friends = await self.memory.status.get("friends") or []
|
129
|
+
relationships = await self.memory.status.get("relationships") or {}
|
126
130
|
|
127
131
|
if not friends:
|
132
|
+
node_id = await self.memory.stream.add_social(description=f"I can't find any friends to socialize with.")
|
128
133
|
return {
|
129
134
|
'success': False,
|
130
135
|
'evaluation': 'No friends found in social network',
|
131
|
-
'consumed_time': 5
|
136
|
+
'consumed_time': 5,
|
137
|
+
'node_id': node_id
|
132
138
|
}
|
133
139
|
|
134
|
-
#
|
140
|
+
# Create a list of friends with all information
|
135
141
|
friend_info = []
|
136
142
|
index_to_uuid = {}
|
137
143
|
|
@@ -143,57 +149,63 @@ class FindPersonBlock(Block):
|
|
143
149
|
})
|
144
150
|
index_to_uuid[i] = friend_id
|
145
151
|
|
146
|
-
#
|
152
|
+
# Format friend information for easier reading
|
147
153
|
formatted_friend_info = {
|
148
154
|
i: {'relationship_strength': info['relationship_strength']}
|
149
155
|
for i, info in enumerate(friend_info)
|
150
156
|
}
|
151
157
|
|
152
|
-
#
|
158
|
+
# Format the prompt
|
153
159
|
formatted_prompt = FormatPrompt(self.prompt)
|
154
160
|
formatted_prompt.format(
|
155
|
-
gender=str(await self.memory.get("gender")),
|
156
|
-
education=str(await self.memory.get("education")),
|
157
|
-
personality=str(await self.memory.get("personality")),
|
158
|
-
occupation=str(await self.memory.get("occupation")),
|
161
|
+
gender=str(await self.memory.status.get("gender")),
|
162
|
+
education=str(await self.memory.status.get("education")),
|
163
|
+
personality=str(await self.memory.status.get("personality")),
|
164
|
+
occupation=str(await self.memory.status.get("occupation")),
|
159
165
|
intention=str(step.get("intention", "socialize")),
|
166
|
+
emotion_types=str(await self.memory.status.get("emotion_types")),
|
167
|
+
thought=str(await self.memory.status.get("thought")),
|
160
168
|
friend_info=str(formatted_friend_info)
|
161
169
|
)
|
162
170
|
|
163
|
-
#
|
171
|
+
# Get LLM response
|
164
172
|
response = await self.llm.atext_request(formatted_prompt.to_dialog(), timeout=300)
|
165
173
|
|
166
174
|
try:
|
167
|
-
#
|
175
|
+
# Parse the response
|
168
176
|
mode, friend_index = eval(response)
|
169
177
|
|
170
|
-
#
|
178
|
+
# Validate the response format
|
171
179
|
if not isinstance(mode, str) or mode not in ['online', 'offline']:
|
172
180
|
raise ValueError("Invalid mode")
|
173
181
|
if not isinstance(friend_index, int) or friend_index not in index_to_uuid:
|
174
182
|
raise ValueError("Invalid friend index")
|
175
183
|
|
176
|
-
#
|
184
|
+
# Convert index to UUID
|
177
185
|
target = index_to_uuid[friend_index]
|
178
186
|
context['target']=target
|
179
187
|
except Exception as e:
|
180
|
-
#
|
188
|
+
# If parsing fails, select the friend with the strongest relationship as the default option
|
181
189
|
target = max(relationships.items(), key=lambda x: x[1])[0] if relationships else friends[0]
|
182
190
|
mode = 'online'
|
183
|
-
|
191
|
+
|
192
|
+
node_id = await self.memory.stream.add_social(description=f"I selected the friend {target} for {mode} interaction")
|
184
193
|
return {
|
185
194
|
'success': True,
|
186
195
|
'evaluation': f'Selected friend {target} for {mode} interaction',
|
187
196
|
'consumed_time': 15,
|
188
197
|
'mode': mode,
|
189
|
-
'target': target
|
198
|
+
'target': target,
|
199
|
+
'node_id': node_id
|
190
200
|
}
|
191
201
|
|
192
202
|
except Exception as e:
|
203
|
+
node_id = await self.memory.stream.add_social(description=f"I can't find any friends to socialize with.")
|
193
204
|
return {
|
194
205
|
'success': False,
|
195
206
|
'evaluation': f'Error in finding person: {str(e)}',
|
196
|
-
'consumed_time': 5
|
207
|
+
'consumed_time': 5,
|
208
|
+
'node_id': node_id
|
197
209
|
}
|
198
210
|
|
199
211
|
class MessageBlock(Block):
|
@@ -209,7 +221,7 @@ class MessageBlock(Block):
|
|
209
221
|
}
|
210
222
|
|
211
223
|
def __init__(self, agent, llm: LLM, memory: Memory, simulator: Simulator):
|
212
|
-
super().__init__("MessageBlock", llm, memory, simulator)
|
224
|
+
super().__init__("MessageBlock", llm=llm, memory=memory, simulator=simulator)
|
213
225
|
self.agent = agent
|
214
226
|
self.description = "Generate and send a message to someone"
|
215
227
|
self.find_person_block = FindPersonBlock(llm, memory, simulator)
|
@@ -219,6 +231,9 @@ class MessageBlock(Block):
|
|
219
231
|
As a {gender} {occupation} with {education} education and {personality} personality,
|
220
232
|
generate a message for a friend (relationship strength: {relationship_score}/100)
|
221
233
|
about {intention}.
|
234
|
+
|
235
|
+
Your current emotion: {emotion_types}
|
236
|
+
Your current thought: {thought}
|
222
237
|
|
223
238
|
Previous chat history:
|
224
239
|
{chat_history}
|
@@ -256,7 +271,7 @@ class MessageBlock(Block):
|
|
256
271
|
}
|
257
272
|
target = result['target']
|
258
273
|
|
259
|
-
#
|
274
|
+
# Get formatted prompt using prompt manager
|
260
275
|
formatted_prompt = await self.prompt_manager.get_prompt(
|
261
276
|
self.memory,
|
262
277
|
step,
|
@@ -269,7 +284,7 @@ class MessageBlock(Block):
|
|
269
284
|
message = "Hello! How are you?"
|
270
285
|
|
271
286
|
# Update chat history with proper format
|
272
|
-
chat_histories = await self.memory.get("chat_histories") or {}
|
287
|
+
chat_histories = await self.memory.status.get("chat_histories") or {}
|
273
288
|
if not isinstance(chat_histories, dict):
|
274
289
|
chat_histories = {}
|
275
290
|
if target not in chat_histories:
|
@@ -278,23 +293,27 @@ class MessageBlock(Block):
|
|
278
293
|
chat_histories[target] += ","
|
279
294
|
chat_histories[target] += f"me: {message}"
|
280
295
|
|
281
|
-
await self.memory.update("chat_histories", chat_histories)
|
296
|
+
await self.memory.status.update("chat_histories", chat_histories)
|
282
297
|
|
283
298
|
# Send message
|
284
299
|
serialized_message = self._serialize_message(message, 1)
|
300
|
+
node_id = await self.memory.stream.add_social(description=f"I sent a message to {target}: {message}")
|
285
301
|
return {
|
286
302
|
'success': True,
|
287
303
|
'evaluation': f'Sent message to {target}: {message}',
|
288
304
|
'consumed_time': 10,
|
289
305
|
'message': message,
|
290
|
-
'target': target
|
306
|
+
'target': target,
|
307
|
+
'node_id': node_id
|
291
308
|
}
|
292
309
|
|
293
310
|
except Exception as e:
|
311
|
+
node_id = await self.memory.stream.add_social(description=f"I can't send a message to {target}")
|
294
312
|
return {
|
295
313
|
'success': False,
|
296
314
|
'evaluation': f'Error in sending message: {str(e)}',
|
297
|
-
'consumed_time': 5
|
315
|
+
'consumed_time': 5,
|
316
|
+
'node_id': node_id
|
298
317
|
}
|
299
318
|
|
300
319
|
class SocialBlock(Block):
|
@@ -304,10 +323,10 @@ class SocialBlock(Block):
|
|
304
323
|
noneblock: SocialNoneBlock
|
305
324
|
|
306
325
|
def __init__(self, agent, llm: LLM, memory: Memory, simulator: Simulator):
|
307
|
-
super().__init__("SocialBlock", llm, memory, simulator)
|
326
|
+
super().__init__("SocialBlock", llm=llm, memory=memory, simulator=simulator)
|
308
327
|
self.find_person_block = FindPersonBlock(llm, memory, simulator)
|
309
328
|
self.message_block = MessageBlock(agent, llm, memory, simulator)
|
310
|
-
self.noneblock=SocialNoneBlock(llm,memory)
|
329
|
+
self.noneblock=SocialNoneBlock(llm, memory)
|
311
330
|
self.dispatcher = BlockDispatcher(llm)
|
312
331
|
|
313
332
|
self.trigger_time = 0
|
@@ -62,12 +62,10 @@ class FirmAgent(InstitutionAgent):
|
|
62
62
|
|
63
63
|
async def forward(self):
|
64
64
|
if await self.month_trigger():
|
65
|
-
employees = await self.memory.get("employees")
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
break
|
70
|
-
await asyncio.sleep(1)
|
65
|
+
employees = await self.memory.status.get("employees")
|
66
|
+
agents_forward = []
|
67
|
+
if not np.all(np.array(agents_forward) > self.forward_times):
|
68
|
+
return
|
71
69
|
goods_demand = await self.gather_messages(employees, "goods_demand")
|
72
70
|
goods_consumption = await self.gather_messages(
|
73
71
|
employees, "goods_consumption"
|
@@ -90,6 +88,7 @@ class FirmAgent(InstitutionAgent):
|
|
90
88
|
await self.send_message_to_agent(
|
91
89
|
uuid,
|
92
90
|
f"work_skill@{max(skill*(1 + np.random.uniform(0, max_change_rate*self.max_wage_inflation)), 1)}",
|
91
|
+
"economy",
|
93
92
|
)
|
94
93
|
price = await self.economy_client.get(self._agent_id, "price")
|
95
94
|
await self.economy_client.update(
|
@@ -109,5 +108,5 @@ class FirmAgent(InstitutionAgent):
|
|
109
108
|
self.forward_times += 1
|
110
109
|
for uuid in employees:
|
111
110
|
await self.send_message_to_agent(
|
112
|
-
uuid, f"firm_forward@{self.forward_times}"
|
111
|
+
uuid, f"firm_forward@{self.forward_times}", "economy"
|
113
112
|
)
|
@@ -53,13 +53,11 @@ class GovernmentAgent(InstitutionAgent):
|
|
53
53
|
|
54
54
|
async def forward(self):
|
55
55
|
if await self.month_trigger():
|
56
|
-
citizens = await self.memory.get("citizens")
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
await asyncio.sleep(1)
|
62
|
-
citizens_agent_id = await self.memory.get("citizens_agent_id")
|
56
|
+
citizens = await self.memory.status.get("citizens")
|
57
|
+
agents_forward = await self.gather_messages(citizens, "forward")
|
58
|
+
if not np.all(np.array(agents_forward) > self.forward_times):
|
59
|
+
return
|
60
|
+
citizens_agent_id = await self.memory.status.get("citizens_agent_id")
|
63
61
|
incomes = await self.gather_messages(citizens, "income_currency") # uuid
|
64
62
|
_, post_tax_incomes = await self.economy_client.calculate_taxes_due(
|
65
63
|
self._agent_id, citizens_agent_id, incomes, enable_redistribution=False
|
@@ -68,9 +66,9 @@ class GovernmentAgent(InstitutionAgent):
|
|
68
66
|
citizens, incomes, post_tax_incomes
|
69
67
|
):
|
70
68
|
tax_paid = income - post_tax_income
|
71
|
-
await self.send_message_to_agent(uuid, f"tax_paid@{tax_paid}")
|
69
|
+
await self.send_message_to_agent(uuid, f"tax_paid@{tax_paid}", "economy")
|
72
70
|
self.forward_times += 1
|
73
71
|
for uuid in citizens:
|
74
72
|
await self.send_message_to_agent(
|
75
|
-
uuid, f"government_forward@{self.forward_times}"
|
73
|
+
uuid, f"government_forward@{self.forward_times}", "economy"
|
76
74
|
)
|