pycityagent 2.0.0a52__cp311-cp311-macosx_11_0_arm64.whl → 2.0.0a53__cp311-cp311-macosx_11_0_arm64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. pycityagent/agent/agent.py +48 -62
  2. pycityagent/agent/agent_base.py +66 -53
  3. pycityagent/cityagent/bankagent.py +5 -7
  4. pycityagent/cityagent/blocks/__init__.py +0 -2
  5. pycityagent/cityagent/blocks/cognition_block.py +149 -172
  6. pycityagent/cityagent/blocks/economy_block.py +90 -129
  7. pycityagent/cityagent/blocks/mobility_block.py +56 -29
  8. pycityagent/cityagent/blocks/needs_block.py +163 -145
  9. pycityagent/cityagent/blocks/other_block.py +17 -9
  10. pycityagent/cityagent/blocks/plan_block.py +44 -56
  11. pycityagent/cityagent/blocks/social_block.py +70 -51
  12. pycityagent/cityagent/blocks/utils.py +2 -0
  13. pycityagent/cityagent/firmagent.py +6 -7
  14. pycityagent/cityagent/governmentagent.py +7 -9
  15. pycityagent/cityagent/memory_config.py +48 -48
  16. pycityagent/cityagent/nbsagent.py +6 -29
  17. pycityagent/cityagent/societyagent.py +204 -119
  18. pycityagent/environment/sim/client.py +10 -1
  19. pycityagent/environment/sim/clock_service.py +2 -2
  20. pycityagent/environment/sim/pause_service.py +61 -0
  21. pycityagent/environment/simulator.py +17 -12
  22. pycityagent/llm/embeddings.py +0 -24
  23. pycityagent/memory/faiss_query.py +29 -26
  24. pycityagent/memory/memory.py +720 -272
  25. pycityagent/pycityagent-sim +0 -0
  26. pycityagent/simulation/agentgroup.py +92 -99
  27. pycityagent/simulation/simulation.py +115 -40
  28. pycityagent/tools/tool.py +7 -9
  29. pycityagent/workflow/block.py +11 -4
  30. {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a53.dist-info}/METADATA +1 -1
  31. {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a53.dist-info}/RECORD +35 -35
  32. pycityagent/cityagent/blocks/time_block.py +0 -116
  33. {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a53.dist-info}/LICENSE +0 -0
  34. {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a53.dist-info}/WHEEL +0 -0
  35. {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a53.dist-info}/entry_points.txt +0 -0
  36. {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 choices",
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] = ["guidance_options", "max_plan_steps"]
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
- options = self.guidance_options.get(current_need, [])
183
- if not options:
184
- return None # type: ignore–
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
- current_need = await self.memory.get("current_need")
255
- if current_need == "none":
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
- "guidance": guidance_result # 保存方案选择的评估结果
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
- Overall Target: {plan['target']}
296
- Execution Steps: \n{formated_steps}
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
- """清理LLM响应中的特殊字符"""
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(intention=step['intention'])
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'完成执行{step["intention"]}',
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'完成执行{step["intention"]}',
75
- 'consumed_time': random.randint(1, 100)
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. My Profile:
95
+ 1. Your Profile:
88
96
  - Gender: {gender}
89
97
  - Education: {education}
90
98
  - Personality: {personality}
91
99
  - Occupation: {occupation}
92
100
 
93
- 2. My Current Intention: {intention}
101
+ 2. Your Current Intention: {intention}
94
102
 
95
- 3. My Friends List (shown as index-to-relationship pairs):
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
- profile = {
117
- "gender": await self.memory.get("gender"),
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
- # 获取LLM响应
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
- # 将索引转换为UUID
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
- # 使用prompt管理器获取格式化后的提示
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
@@ -8,6 +8,8 @@ Overall plan:
8
8
 
9
9
  Current action: {intention}
10
10
 
11
+ Current emotion: {emotion_types}
12
+
11
13
  Examples:
12
14
  - "Learn programming": {{"time": 120}}
13
15
  - "Watch a movie": {{"time": 150}}
@@ -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
- while True:
67
- agents_forward = await self.gather_messages(employees, "forward")
68
- if np.all(np.array(agents_forward) > self.forward_times):
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
- while True:
58
- agents_forward = await self.gather_messages(citizens, "forward")
59
- if np.all(np.array(agents_forward) > self.forward_times):
60
- break
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
  )