pycityagent 2.0.0a51__cp39-cp39-macosx_11_0_arm64.whl → 2.0.0a53__cp39-cp39-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 -10
  29. pycityagent/workflow/block.py +11 -4
  30. {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/METADATA +2 -2
  31. {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/RECORD +35 -35
  32. {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/WHEEL +1 -1
  33. pycityagent/cityagent/blocks/time_block.py +0 -116
  34. {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/LICENSE +0 -0
  35. {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/entry_points.txt +0 -0
  36. {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/top_level.txt +0 -0
@@ -1,54 +1,54 @@
1
1
  import json
2
2
  from pycityagent import Simulator
3
- from pycityagent.memory.memory import Memory
4
- from pycityagent.llm.llm import LLM
3
+ from pycityagent.memory import Memory
4
+ from pycityagent.llm import LLM
5
5
  from pycityagent.workflow.block import Block
6
6
  from pycityagent.workflow.prompt import FormatPrompt
7
7
  import logging
8
8
  logger = logging.getLogger("pycityagent")
9
9
 
10
- INITIAL_NEEDS_PROMPT = """You are an intelligent agent needs initialization system. Based on the profile information below, please help initialize the agent's needs and related parameters.
10
+ INITIAL_NEEDS_PROMPT = """You are an intelligent agent satisfaction initialization system. Based on the profile information below, please help initialize the agent's satisfaction levels and related parameters.
11
11
 
12
12
  Profile Information:
13
13
  - Gender: {gender}
14
- - Education: {education}
14
+ - Education Level: {education}
15
15
  - Consumption Level: {consumption}
16
16
  - Occupation: {occupation}
17
17
  - Age: {age}
18
18
  - Monthly Income: {income}
19
- - Race: {race}
20
- - Religion: {religion}
21
- - Skills: {skill}
19
+
20
+ Current Emotion: {emotion_types}
21
+ Current Thought: {thought}
22
22
 
23
23
  Current Time: {now_time}
24
24
 
25
- Please initialize the agent's needs and parameters based on the profile above. Return the values in JSON format with the following structure:
25
+ Please initialize the agent's satisfaction levels and parameters based on the profile above. Return the values in JSON format with the following structure:
26
26
 
27
- 1. Current needs satisfaction levels (0-1 float values, lower means less satisfied):
28
- - hungry: Hunger satisfaction level (Normally, the agent will be more hungry at eating time)
29
- - tired: Fatigue level (Normally, at night, the agent will be more tired)
30
- - safe: Safety satisfaction level (Normally, the agent will be more safe when they have high income and currency)
31
- - social: Social satisfaction level
27
+ 1. Current satisfaction levels (0-1 float values, lower means less satisfied):
28
+ - hunger_satisfaction: Hunger satisfaction level (Normally, the agent will be less satisfied with hunger at eating time)
29
+ - energy_satisfaction: Energy satisfaction level (Normally, at night, the agent will be less satisfied with energy)
30
+ - safety_satisfaction: Safety satisfaction level (Normally, the agent will be more satisfied with safety when they have high income and currency)
31
+ - social_satisfaction: Social satisfaction level
32
32
 
33
33
  2. Natural decay rates per hour (0-1 float values):
34
34
  - alpha_H: Hunger satisfaction decay rate
35
- - alpha_D: Fatigue decay rate
35
+ - alpha_D: Energy satisfaction decay rate
36
36
  - alpha_P: Safety satisfaction decay rate
37
37
  - alpha_C: Social satisfaction decay rate
38
38
 
39
39
  3. Threshold values (0-1 float values, below which the agent will try to improve):
40
40
  - T_H: Hunger satisfaction threshold
41
- - T_D: Fatigue threshold
42
- - T_S: Safety threshold
43
- - T_C: Social threshold
41
+ - T_D: Energy satisfaction threshold
42
+ - T_S: Safety satisfaction threshold
43
+ - T_C: Social satisfaction threshold
44
44
 
45
45
  Example response format (Do not return any other text):
46
46
  {{
47
- "current_needs": {{
48
- "hungry": 0.8,
49
- "tired": 0.7,
50
- "safe": 0.9,
51
- "social": 0.6
47
+ "current_satisfaction": {{
48
+ "hunger_satisfaction": 0.8,
49
+ "energy_satisfaction": 0.7,
50
+ "safety_satisfaction": 0.9,
51
+ "social_satisfaction": 0.6
52
52
  }},
53
53
  "decay_rates": {{
54
54
  "alpha_H": 0.2,
@@ -68,15 +68,22 @@ Example response format (Do not return any other text):
68
68
  EVALUATION_PROMPT = """You are an evaluation system for an intelligent agent. The agent has performed the following actions to satisfy the {current_need} need:
69
69
 
70
70
  Goal: {plan_target}
71
- Execution steps:
71
+ Execution situation:
72
72
  {evaluation_results}
73
73
 
74
- Current needs status: {current_needs}
74
+ Current satisfaction:
75
+ - hunger_satisfaction: {hunger_satisfaction}
76
+ - energy_satisfaction: {energy_satisfaction}
77
+ - safety_satisfaction: {safety_satisfaction}
78
+ - social_satisfaction: {social_satisfaction}
79
+
80
+ Current Emotion: {emotion_types}
81
+ Current Thought: {thought}
75
82
 
76
- Please evaluate and adjust the value of {current_need} need based on the execution results above.
83
+ Please evaluate and adjust the value of {current_need} satisfaction based on the execution results above.
77
84
 
78
85
  Notes:
79
- 1. Need values range from 0-1, where:
86
+ 1. Satisfaction values range from 0-1, where:
80
87
  - 1 means the need is fully satisfied
81
88
  - 0 means the need is completely unsatisfied
82
89
  - Higher values indicate greater need satisfaction
@@ -85,13 +92,13 @@ Notes:
85
92
 
86
93
  Example response format for specific need (hungry here) adjustment (Do not return any other text):
87
94
  {{
88
- "hungry": new_need_value
95
+ "hunger_satisfaction": new_need_value
89
96
  }}
90
97
 
91
98
  Example response format for whatever need adjustment (Do not return any other text):
92
99
  {{
93
- "safe": new_safe_value,
94
- "social": new_social_value
100
+ "safety_satisfaction": new_safe_value,
101
+ "social_satisfaction": new_social_value
95
102
  }}
96
103
  """
97
104
 
@@ -100,50 +107,63 @@ class NeedsBlock(Block):
100
107
  Generate needs
101
108
  """
102
109
  def __init__(self, llm: LLM, memory: Memory, simulator: Simulator):
103
- super().__init__("NeedsBlock", llm, memory, simulator)
110
+ super().__init__("NeedsBlock", llm=llm, memory=memory, simulator=simulator)
104
111
  self.evaluation_prompt = FormatPrompt(EVALUATION_PROMPT)
105
112
  self.initial_prompt = FormatPrompt(INITIAL_NEEDS_PROMPT)
113
+ self.need_work = True
114
+ self.now_day = -1
106
115
  self.last_evaluation_time = None
107
116
  self.trigger_time = 0
108
117
  self.token_consumption = 0
109
118
  self.initialized = False
110
- self.alpha_H, self.alpha_D, self.alpha_P, self.alpha_C = 0.2, 0.08, 0.05, 0.03 # 饥饿感与疲劳感自然衰减速率
111
- self.T_H, self.T_D, self.T_P, self.T_C = 0.4, 0.2, 0.2, 0.2 # 饥饿感与疲劳感临界值
119
+ self.alpha_H, self.alpha_D, self.alpha_P, self.alpha_C = 0.2, 0.08, 0.05, 0.03 # Hunger decay rate, Energy decay rate, Safety decay rate, Social decay rate
120
+ self.T_H, self.T_D, self.T_P, self.T_C = 0.4, 0.2, 0.2, 0.2 # Hunger threshold, Energy threshold, Safety threshold, Social threshold
112
121
 
113
122
  async def initialize(self):
114
- self.initial_prompt.format(
115
- gender=await self.memory.get("gender"),
116
- education=await self.memory.get("education"),
117
- consumption=await self.memory.get("consumption"),
118
- occupation=await self.memory.get("occupation"),
119
- age=await self.memory.get("age"),
120
- income=await self.memory.get("income"),
121
- race=await self.memory.get("race"),
122
- religion=await self.memory.get("religion"),
123
- skill=await self.memory.get("skill"),
124
- now_time=await self.simulator.get_time(format_time=True)
125
- )
126
- response = await self.llm.atext_request(
127
- self.initial_prompt.to_dialog()
128
- )
129
- response = self.clean_json_response(response)
130
- logger.info(f"Needs Initialization: {response}")
131
- try:
132
- needs = json.loads(response)
133
- await self.memory.update("needs", needs["current_needs"])
134
- self.alpha_H, self.alpha_D, self.alpha_P, self.alpha_C = needs["decay_rates"].values()
135
- self.T_H, self.T_D, self.T_P, self.T_C = needs["thresholds"].values()
136
- except json.JSONDecodeError:
137
- logger.warning(f"初始化响应不是有效的JSON格式: {response}")
138
- self.initialized = True
139
-
140
- async def forward(self):
141
- self.trigger_time += 1
142
- consumption_start = self.llm.prompt_tokens_used + self.llm.completion_tokens_used
123
+ day = await self.simulator.get_simulator_day()
124
+ if day != self.now_day:
125
+ self.now_day = day
126
+ self.need_work = True
127
+ self.initialized = False
143
128
 
144
129
  if not self.initialized:
145
- await self.initialize()
130
+ self.initial_prompt.format(
131
+ gender=await self.memory.status.get("gender"),
132
+ education=await self.memory.status.get("education"),
133
+ consumption=await self.memory.status.get("consumption"),
134
+ occupation=await self.memory.status.get("occupation"),
135
+ age=await self.memory.status.get("age"),
136
+ income=await self.memory.status.get("income"),
137
+ emotion_types=await self.memory.status.get("emotion_types"),
138
+ thought=await self.memory.status.get("thought"),
139
+ now_time=await self.simulator.get_time(format_time=True)
140
+ )
141
+ response = await self.llm.atext_request(
142
+ self.initial_prompt.to_dialog()
143
+ )
144
+ response = self.clean_json_response(response)
145
+ try:
146
+ satisfaction = json.loads(response)
147
+ satisfactions = satisfaction["current_satisfaction"]
148
+ await self.memory.status.update("hunger_satisfaction", satisfactions["hunger_satisfaction"])
149
+ await self.memory.status.update("energy_satisfaction", satisfactions["energy_satisfaction"])
150
+ await self.memory.status.update("safety_satisfaction", satisfactions["safety_satisfaction"])
151
+ await self.memory.status.update("social_satisfaction", satisfactions["social_satisfaction"])
152
+ self.alpha_H, self.alpha_D, self.alpha_P, self.alpha_C = satisfaction["decay_rates"].values()
153
+ self.T_H, self.T_D, self.T_P, self.T_C = satisfaction["thresholds"].values()
154
+ except json.JSONDecodeError:
155
+ logger.warning(f"初始化响应不是有效的JSON格式: {response}")
156
+
157
+ current_plan = await self.memory.status.get("current_plan")
158
+ history = await self.memory.status.get("plan_history")
159
+ history.append(current_plan)
160
+ await self.memory.status.update("plan_history", history)
161
+ await self.memory.status.update("current_plan", None)
162
+ await self.memory.status.update("current_step", {"intention": "", "type": ""})
163
+ await self.memory.status.update("execution_context", {})
164
+ self.initialized = True
146
165
 
166
+ async def time_decay(self):
147
167
  # 计算时间差
148
168
  time_now = await self.simulator.get_time()
149
169
  if self.last_evaluation_time is None:
@@ -153,103 +173,96 @@ class NeedsBlock(Block):
153
173
  time_diff = (time_now - self.last_evaluation_time)/3600
154
174
  self.last_evaluation_time = time_now
155
175
 
156
- # 获取当前需求
157
- needs = await self.memory.get("needs")
176
+ # 获取当前需求的满意度
177
+ hunger_satisfaction = await self.memory.status.get("hunger_satisfaction")
178
+ energy_satisfaction = await self.memory.status.get("energy_satisfaction")
179
+ safety_satisfaction = await self.memory.status.get("safety_satisfaction")
180
+ social_satisfaction = await self.memory.status.get("social_satisfaction")
158
181
 
159
182
  # 根据经过的时间计算饥饿与疲劳的衰减
160
183
  hungry_decay = self.alpha_H * time_diff
161
- tired_decay = self.alpha_D * time_diff
162
- safe_decay = self.alpha_P * time_diff
184
+ energy_decay = self.alpha_D * time_diff
185
+ safety_decay = self.alpha_P * time_diff
163
186
  social_decay = self.alpha_C * time_diff
164
- hungry = max(0, needs["hungry"] - hungry_decay)
165
- tired = max(0, needs["tired"] - tired_decay)
166
- safe = max(0, needs["safe"] - safe_decay)
167
- social = max(0, needs["social"] - social_decay)
168
- needs["hungry"] = hungry
169
- needs["tired"] = tired
170
- needs["safe"] = safe
171
- needs["social"] = social
172
-
173
- await self.memory.update("needs", needs)
187
+ hunger_satisfaction = max(0, hunger_satisfaction - hungry_decay)
188
+ energy_satisfaction = max(0, energy_satisfaction - energy_decay)
189
+ safety_satisfaction = max(0, safety_satisfaction - safety_decay)
190
+ social_satisfaction = max(0, social_satisfaction - social_decay)
191
+
192
+ # 更新满意度
193
+ await self.memory.status.update("hunger_satisfaction", hunger_satisfaction)
194
+ await self.memory.status.update("energy_satisfaction", energy_satisfaction)
195
+ await self.memory.status.update("safety_satisfaction", safety_satisfaction)
196
+ await self.memory.status.update("social_satisfaction", social_satisfaction)
174
197
 
198
+ async def update_when_plan_completed(self):
175
199
  # 判断当前是否有正在执行的plan
176
- current_plan = await self.memory.get("current_plan")
177
- if current_plan and current_plan.get("completed"):
200
+ current_plan = await self.memory.status.get("current_plan")
201
+ if current_plan and (current_plan.get("completed") or current_plan.get("failed")):
178
202
  # 评估计划执行过程并调整需求
179
203
  await self.evaluate_and_adjust_needs(current_plan)
180
204
  # 将完成的计划添加到历史记录
181
- history = await self.memory.get("plan_history")
205
+ history = await self.memory.status.get("plan_history")
182
206
  history.append(current_plan)
183
- await self.memory.update("plan_history", history)
184
- await self.memory.update("current_plan", None)
185
- await self.memory.update("current_step", {"intention": "", "type": ""})
186
- await self.memory.update("execution_context", {})
187
-
188
- needs = await self.memory.get("needs")
189
- hungry = needs["hungry"]
190
- tired = needs["tired"]
191
- safe = needs["safe"]
192
- social = needs["social"]
193
- logger.info(f"Time elapsed: {time_diff:.2f} hours")
194
- logger.info(f"Current state - Hungry: {hungry:.2f}, Tired: {tired:.2f}, Safe: {safe:.2f}, Social: {social:.2f}")
207
+ await self.memory.status.update("plan_history", history)
208
+ await self.memory.status.update("current_plan", None)
209
+ await self.memory.status.update("current_step", {"intention": "", "type": ""})
210
+ await self.memory.status.update("execution_context", {})
211
+
212
+ async def determine_current_need(self):
213
+ hunger_satisfaction = await self.memory.status.get("hunger_satisfaction")
214
+ energy_satisfaction = await self.memory.status.get("energy_satisfaction")
215
+ safety_satisfaction = await self.memory.status.get("safety_satisfaction")
216
+ social_satisfaction = await self.memory.status.get("social_satisfaction")
195
217
 
196
218
  # 如果需要调整需求,更新当前需求
197
219
  # 调整方案为,如果当前的需求为空,或有更高级的需求出现,则调整需求
198
- current_need = await self.memory.get("current_need")
220
+ current_plan = await self.memory.status.get("current_plan")
221
+ current_need = await self.memory.status.get("current_need")
199
222
 
200
223
  # 当前没有计划或计划已执行完毕,获取所有需求值,按优先级检查各需求是否达到阈值
201
224
  if not current_plan or current_plan.get("completed"):
202
225
  # 按优先级顺序检查需求
203
- if hungry <= self.T_H:
204
- await self.memory.update("current_need", "hungry")
205
- logger.info("Needs adjusted: Hungry")
206
- elif tired <= self.T_D:
207
- await self.memory.update("current_need", "tired")
208
- logger.info("Needs adjusted: Tired")
209
- elif safe <= self.T_P:
210
- await self.memory.update("current_need", "safe")
211
- logger.info("Needs adjusted: Safe")
212
- elif social <= self.T_C:
213
- await self.memory.update("current_need", "social")
214
- logger.info("Needs adjusted: Social")
226
+ if hunger_satisfaction <= self.T_H:
227
+ await self.memory.status.update("current_need", "hungry")
228
+ elif energy_satisfaction <= self.T_D:
229
+ await self.memory.status.update("current_need", "tired")
230
+ elif safety_satisfaction <= self.T_P:
231
+ await self.memory.status.update("current_need", "safe")
232
+ elif social_satisfaction <= self.T_C:
233
+ await self.memory.status.update("current_need", "social")
234
+ elif self.need_work:
235
+ await self.memory.status.update("current_need", "safe")
236
+ self.need_work = False
215
237
  else:
216
- await self.memory.update("current_need", "whatever")
217
- logger.info("Needs adjusted: Whatever")
238
+ await self.memory.status.update("current_need", "whatever")
218
239
  else:
219
240
  # 有正在执行的计划时,只在出现更高优先级需求时调整
220
241
  needs_changed = False
221
242
  new_need = None
222
- if hungry <= self.T_H and current_need not in ["hungry", "tired"]:
243
+ if hunger_satisfaction <= self.T_H and current_need not in ["hungry", "tired"]:
223
244
  new_need = "hungry"
224
- logger.info("Higher priority need detected, adjusted to: Hungry")
225
245
  needs_changed = True
226
- elif tired <= self.T_D and current_need not in ["hungry", "tired"]:
246
+ elif energy_satisfaction <= self.T_D and current_need not in ["hungry", "tired"]:
227
247
  new_need = "tired"
228
- logger.info("Higher priority need detected, adjusted to: Tired")
229
248
  needs_changed = True
230
- elif safe <= self.T_P and current_need not in ["hungry", "tired", "safe"]:
249
+ elif safety_satisfaction <= self.T_P and current_need not in ["hungry", "tired", "safe"]:
231
250
  new_need = "safe"
232
- logger.info("Higher priority need detected, adjusted to: Safe")
233
251
  needs_changed = True
234
- elif social <= self.T_C and current_need not in ["hungry", "tired", "safe", "social"]:
252
+ elif social_satisfaction <= self.T_C and current_need not in ["hungry", "tired", "safe", "social"]:
235
253
  new_need = "social"
236
- logger.info("Higher priority need detected, adjusted to: Social")
237
254
  needs_changed = True
238
255
 
239
256
  # 如果需求发生变化,中断当前计划
240
257
  if needs_changed:
241
258
  await self.evaluate_and_adjust_needs(current_plan)
242
- history = await self.memory.get("plan_history")
259
+ history = await self.memory.status.get("plan_history")
243
260
  history.append(current_plan)
244
- await self.memory.update("current_need", new_need)
245
- await self.memory.update("plan_history", history)
246
- await self.memory.update("current_plan", None)
247
- await self.memory.update("current_step", {"intention": "", "type": ""})
248
- await self.memory.update("execution_context", {})
249
- logger.info("----Agent's plan has been interrupted due to need change----")
250
-
251
- consumption_end = self.llm.prompt_tokens_used + self.llm.completion_tokens_used
252
- self.token_consumption += consumption_end - consumption_start
261
+ await self.memory.status.update("current_need", new_need)
262
+ await self.memory.status.update("plan_history", history)
263
+ await self.memory.status.update("current_plan", None)
264
+ await self.memory.status.update("current_step", {"intention": "", "type": ""})
265
+ await self.memory.status.update("execution_context", {})
253
266
 
254
267
  async def evaluate_and_adjust_needs(self, completed_plan):
255
268
  # 获取执行的计划和评估结果
@@ -258,41 +271,34 @@ class NeedsBlock(Block):
258
271
  if 'evaluation' in step['evaluation']:
259
272
  eva_ = step['evaluation']['evaluation']
260
273
  else:
261
- eva_ = 'Plan interrupted, not completed'
274
+ eva_ = 'Plan failed, not completed'
262
275
  evaluation_results.append(f"- {step['intention']} ({step['type']}): {eva_}")
263
276
  evaluation_results = "\n".join(evaluation_results)
264
277
 
265
278
  # 使用 LLM 进行评估
266
- current_need = await self.memory.get("current_need")
279
+ current_need = await self.memory.status.get("current_need")
267
280
  self.evaluation_prompt.format(
268
281
  current_need=current_need,
269
282
  plan_target=completed_plan["target"],
270
283
  evaluation_results=evaluation_results,
271
- current_needs=await self.memory.get("needs")
284
+ hunger_satisfaction=await self.memory.status.get("hunger_satisfaction"),
285
+ energy_satisfaction=await self.memory.status.get("energy_satisfaction"),
286
+ safety_satisfaction=await self.memory.status.get("safety_satisfaction"),
287
+ social_satisfaction=await self.memory.status.get("social_satisfaction"),
288
+ emotion_types=await self.memory.status.get("emotion_types"),
289
+ thought=await self.memory.status.get("thought")
272
290
  )
273
291
 
274
292
  response = await self.llm.atext_request(
275
293
  self.evaluation_prompt.to_dialog()
276
294
  )
277
295
 
278
- try:
279
- logger.info("\n=== Needs Evaluation ===")
280
- logger.info(f"Evaluating need: {current_need}")
281
- logger.info(f"Executing plan: {completed_plan['target']}")
282
- logger.info("Execution results:")
283
- logger.info(evaluation_results)
284
-
285
- new_needs = json.loads(self.clean_json_response(response)) # type: ignore
296
+ try:
297
+ new_satisfaction = json.loads(self.clean_json_response(response)) # type: ignore
286
298
  # 更新所有需求的数值
287
- needs = await self.memory.get("needs")
288
- logger.info(f"\nNeeds value adjustment:")
289
- for need_type, new_value in new_needs.items():
290
- if need_type in needs:
291
- old_value = needs[need_type]
292
- needs[need_type] = new_value
293
- logger.info(f"- {need_type}: {old_value} -> {new_value}")
294
- await self.memory.update("needs", needs)
295
- logger.info("===============\n")
299
+ for need_type, new_value in new_satisfaction.items():
300
+ if need_type in ['hunger_satisfaction', 'energy_satisfaction', 'safety_satisfaction', 'social_satisfaction']:
301
+ await self.memory.status.update(need_type, new_value)
296
302
  except json.JSONDecodeError:
297
303
  logger.warning(f"Evaluation response is not a valid JSON format: {response}")
298
304
  except Exception as e:
@@ -302,4 +308,16 @@ class NeedsBlock(Block):
302
308
  def clean_json_response(self, response: str) -> str:
303
309
  """清理LLM响应中的特殊字符"""
304
310
  response = response.replace('```json', '').replace('```', '')
305
- return response.strip()
311
+ return response.strip()
312
+
313
+ async def forward(self):
314
+ await self.initialize()
315
+
316
+ # satisfaction decay with time
317
+ await self.time_decay()
318
+
319
+ # update when plan completed
320
+ await self.update_when_plan_completed()
321
+
322
+ # determine current need
323
+ await self.determine_current_need()
@@ -12,30 +12,34 @@ logger = logging.getLogger("pycityagent")
12
12
 
13
13
  class SleepBlock(Block):
14
14
  def __init__(self, llm: LLM, memory: Memory):
15
- super().__init__("SleepBlock", llm, memory)
15
+ super().__init__("SleepBlock", llm=llm, memory=memory)
16
16
  self.description = "Sleep"
17
17
  self.guidance_prompt = FormatPrompt(template=TIME_ESTIMATE_PROMPT)
18
18
 
19
19
  async def forward(self, step, context):
20
20
  self.guidance_prompt.format(
21
21
  plan=context['plan'],
22
- intention=step['intention']
22
+ intention=step['intention'],
23
+ emotion_types=await self.memory.status.get("emotion_types"),
23
24
  )
24
25
  result = await self.llm.atext_request(self.guidance_prompt.to_dialog())
25
26
  result = clean_json_response(result)
27
+ node_id = await self.memory.stream.add_other(description=f"I slept")
26
28
  try:
27
29
  result = json.loads(result)
28
30
  return {
29
31
  'success': True,
30
32
  'evaluation': f'Sleep: {step["intention"]}',
31
- 'consumed_time': result['time']
33
+ 'consumed_time': result['time'],
34
+ 'node_id': node_id
32
35
  }
33
36
  except Exception as e:
34
37
  logger.warning(f"解析时间评估响应时发生错误: {str(e)}, 原始结果: {result}")
35
38
  return {
36
39
  'success': True,
37
40
  'evaluation': f'Sleep: {step["intention"]}',
38
- 'consumed_time': random.randint(1, 10)*60
41
+ 'consumed_time': random.randint(1, 10)*60,
42
+ 'node_id': node_id
39
43
  }
40
44
 
41
45
  class OtherNoneBlock(Block):
@@ -44,30 +48,34 @@ class OtherNoneBlock(Block):
44
48
  OtherNoneBlock
45
49
  """
46
50
  def __init__(self, llm: LLM, memory: Memory):
47
- super().__init__("OtherNoneBlock", llm, memory)
51
+ super().__init__("OtherNoneBlock", llm=llm, memory=memory)
48
52
  self.description = "Used to handle other cases"
49
53
  self.guidance_prompt = FormatPrompt(template=TIME_ESTIMATE_PROMPT)
50
54
 
51
55
  async def forward(self, step, context):
52
56
  self.guidance_prompt.format(
53
57
  plan=context['plan'],
54
- intention=step['intention']
58
+ intention=step['intention'],
59
+ emotion_types=await self.memory.status.get("emotion_types"),
55
60
  )
56
61
  result = await self.llm.atext_request(self.guidance_prompt.to_dialog())
57
62
  result = clean_json_response(result)
63
+ node_id = await self.memory.stream.add_other(description=f"I {step['intention']}")
58
64
  try:
59
65
  result = json.loads(result)
60
66
  return {
61
67
  'success': True,
62
68
  'evaluation': f'Finished executing {step["intention"]}',
63
- 'consumed_time': result['time']
69
+ 'consumed_time': result['time'],
70
+ 'node_id': node_id
64
71
  }
65
72
  except Exception as e:
66
73
  logger.warning(f"解析时间评估响应时发生错误: {str(e)}, 原始结果: {result}")
67
74
  return {
68
75
  'success': True,
69
76
  'evaluation': f'Finished executing {step["intention"]}',
70
- 'consumed_time': random.randint(1, 180)
77
+ 'consumed_time': random.randint(1, 180),
78
+ 'node_id': node_id
71
79
  }
72
80
 
73
81
 
@@ -76,7 +84,7 @@ class OtherBlock(Block):
76
84
  other_none_block: OtherNoneBlock
77
85
 
78
86
  def __init__(self, llm: LLM, memory: Memory):
79
- super().__init__("OtherBlock", llm, memory)
87
+ super().__init__("OtherBlock", llm=llm, memory=memory)
80
88
  # 初始化所有块
81
89
  self.sleep_block = SleepBlock(llm, memory)
82
90
  self.other_none_block = OtherNoneBlock(llm, memory)