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
@@ -1,54 +1,54 @@
|
|
1
1
|
import json
|
2
2
|
from pycityagent import Simulator
|
3
|
-
from pycityagent.memory
|
4
|
-
from pycityagent.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
|
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
|
-
|
20
|
-
|
21
|
-
|
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
|
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
|
28
|
-
-
|
29
|
-
-
|
30
|
-
-
|
31
|
-
-
|
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:
|
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:
|
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
|
-
"
|
48
|
-
"
|
49
|
-
"
|
50
|
-
"
|
51
|
-
"
|
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
|
71
|
+
Execution situation:
|
72
72
|
{evaluation_results}
|
73
73
|
|
74
|
-
Current
|
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}
|
83
|
+
Please evaluate and adjust the value of {current_need} satisfaction based on the execution results above.
|
77
84
|
|
78
85
|
Notes:
|
79
|
-
1.
|
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
|
-
"
|
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
|
-
"
|
94
|
-
"
|
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.
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
162
|
-
|
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
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
await self.memory.update("
|
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
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
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
|
-
|
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
|
204
|
-
await self.memory.update("current_need", "hungry")
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
elif
|
210
|
-
await self.memory.update("current_need", "
|
211
|
-
|
212
|
-
|
213
|
-
|
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
|
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
|
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
|
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
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
288
|
-
|
289
|
-
|
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)
|