pycityagent 2.0.0a52__cp310-cp310-macosx_11_0_arm64.whl → 2.0.0a53__cp310-cp310-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.
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
@@ -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)