pycityagent 2.0.0a65__cp310-cp310-macosx_11_0_arm64.whl → 2.0.0a67__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.
- pycityagent/agent/agent.py +157 -57
- pycityagent/agent/agent_base.py +316 -43
- pycityagent/cityagent/bankagent.py +49 -9
- pycityagent/cityagent/blocks/__init__.py +1 -2
- pycityagent/cityagent/blocks/cognition_block.py +54 -31
- pycityagent/cityagent/blocks/dispatcher.py +22 -17
- pycityagent/cityagent/blocks/economy_block.py +46 -32
- pycityagent/cityagent/blocks/mobility_block.py +209 -105
- pycityagent/cityagent/blocks/needs_block.py +101 -54
- pycityagent/cityagent/blocks/other_block.py +42 -33
- pycityagent/cityagent/blocks/plan_block.py +59 -42
- pycityagent/cityagent/blocks/social_block.py +167 -126
- pycityagent/cityagent/blocks/utils.py +13 -6
- pycityagent/cityagent/firmagent.py +17 -35
- pycityagent/cityagent/governmentagent.py +3 -3
- pycityagent/cityagent/initial.py +79 -49
- pycityagent/cityagent/memory_config.py +123 -94
- pycityagent/cityagent/message_intercept.py +0 -4
- pycityagent/cityagent/metrics.py +41 -0
- pycityagent/cityagent/nbsagent.py +24 -36
- pycityagent/cityagent/societyagent.py +9 -4
- pycityagent/cli/wrapper.py +2 -2
- pycityagent/economy/econ_client.py +407 -81
- pycityagent/environment/__init__.py +0 -3
- pycityagent/environment/sim/__init__.py +0 -3
- pycityagent/environment/sim/aoi_service.py +2 -2
- pycityagent/environment/sim/client.py +3 -31
- pycityagent/environment/sim/clock_service.py +2 -2
- pycityagent/environment/sim/lane_service.py +8 -8
- pycityagent/environment/sim/light_service.py +8 -8
- pycityagent/environment/sim/pause_service.py +9 -10
- pycityagent/environment/sim/person_service.py +20 -20
- pycityagent/environment/sim/road_service.py +2 -2
- pycityagent/environment/sim/sim_env.py +21 -5
- pycityagent/environment/sim/social_service.py +4 -4
- pycityagent/environment/simulator.py +249 -27
- pycityagent/environment/utils/__init__.py +2 -2
- pycityagent/environment/utils/geojson.py +2 -2
- pycityagent/environment/utils/grpc.py +4 -4
- pycityagent/environment/utils/map_utils.py +2 -2
- pycityagent/llm/embeddings.py +147 -28
- pycityagent/llm/llm.py +178 -111
- pycityagent/llm/llmconfig.py +5 -0
- pycityagent/llm/utils.py +4 -0
- pycityagent/memory/__init__.py +0 -4
- pycityagent/memory/const.py +2 -2
- pycityagent/memory/faiss_query.py +140 -61
- pycityagent/memory/memory.py +394 -91
- pycityagent/memory/memory_base.py +140 -34
- pycityagent/memory/profile.py +13 -13
- pycityagent/memory/self_define.py +13 -13
- pycityagent/memory/state.py +14 -14
- pycityagent/message/message_interceptor.py +253 -3
- pycityagent/message/messager.py +133 -6
- pycityagent/metrics/mlflow_client.py +47 -4
- pycityagent/pycityagent-sim +0 -0
- pycityagent/pycityagent-ui +0 -0
- pycityagent/simulation/__init__.py +3 -2
- pycityagent/simulation/agentgroup.py +150 -54
- pycityagent/simulation/simulation.py +276 -66
- pycityagent/survey/manager.py +45 -3
- pycityagent/survey/models.py +42 -2
- pycityagent/tools/__init__.py +1 -2
- pycityagent/tools/tool.py +93 -69
- pycityagent/utils/avro_schema.py +2 -2
- pycityagent/utils/parsers/code_block_parser.py +1 -1
- pycityagent/utils/parsers/json_parser.py +2 -2
- pycityagent/utils/parsers/parser_base.py +2 -2
- pycityagent/workflow/block.py +64 -13
- pycityagent/workflow/prompt.py +31 -23
- pycityagent/workflow/trigger.py +91 -24
- {pycityagent-2.0.0a65.dist-info → pycityagent-2.0.0a67.dist-info}/METADATA +2 -2
- pycityagent-2.0.0a67.dist-info/RECORD +97 -0
- pycityagent/environment/interact/__init__.py +0 -0
- pycityagent/environment/interact/interact.py +0 -198
- pycityagent/environment/message/__init__.py +0 -0
- pycityagent/environment/sence/__init__.py +0 -0
- pycityagent/environment/sence/static.py +0 -416
- pycityagent/environment/sidecar/__init__.py +0 -8
- pycityagent/environment/sidecar/sidecarv2.py +0 -109
- pycityagent/environment/sim/economy_services.py +0 -192
- pycityagent/metrics/utils/const.py +0 -0
- pycityagent-2.0.0a65.dist-info/RECORD +0 -105
- {pycityagent-2.0.0a65.dist-info → pycityagent-2.0.0a67.dist-info}/LICENSE +0 -0
- {pycityagent-2.0.0a65.dist-info → pycityagent-2.0.0a67.dist-info}/WHEEL +0 -0
- {pycityagent-2.0.0a65.dist-info → pycityagent-2.0.0a67.dist-info}/entry_points.txt +0 -0
- {pycityagent-2.0.0a65.dist-info → pycityagent-2.0.0a67.dist-info}/top_level.txt +0 -0
@@ -1,13 +1,19 @@
|
|
1
|
+
import math
|
1
2
|
from typing import List
|
2
|
-
|
3
|
+
|
3
4
|
from pycityagent.environment.simulator import Simulator
|
4
5
|
from pycityagent.llm import LLM
|
5
6
|
from pycityagent.memory import Memory
|
6
7
|
from pycityagent.workflow.block import Block
|
8
|
+
import numpy as np
|
9
|
+
from operator import itemgetter
|
7
10
|
import random
|
8
11
|
import logging
|
9
|
-
logger = logging.getLogger("pycityagent")
|
10
12
|
from pycityagent.workflow.prompt import FormatPrompt
|
13
|
+
from .dispatcher import BlockDispatcher
|
14
|
+
|
15
|
+
logger = logging.getLogger("pycityagent")
|
16
|
+
|
11
17
|
|
12
18
|
PLACE_TYPE_SELECTION_PROMPT = """
|
13
19
|
As an intelligent decision system, please determine the type of place the user needs to visit based on their input requirement.
|
@@ -38,36 +44,104 @@ Current temperature: {temperature}
|
|
38
44
|
Your current emotion: {emotion_types}
|
39
45
|
Your current thought: {thought}
|
40
46
|
|
41
|
-
Please analyze how these emotions would affect travel willingness and return only a single integer number between
|
47
|
+
Please analyze how these emotions would affect travel willingness and return only a single integer number between 3000-100000 representing the maximum travel radius in meters. A more positive emotional state generally leads to greater willingness to travel further.
|
42
48
|
|
43
49
|
Return only the integer number without any additional text or explanation."""
|
44
50
|
|
51
|
+
|
52
|
+
def gravity_model(pois):
|
53
|
+
N = len(pois)
|
54
|
+
pois_Dis = {
|
55
|
+
"1k": [],
|
56
|
+
"2k": [],
|
57
|
+
"3k": [],
|
58
|
+
"4k": [],
|
59
|
+
"5k": [],
|
60
|
+
"6k": [],
|
61
|
+
"7k": [],
|
62
|
+
"8k": [],
|
63
|
+
"9k": [],
|
64
|
+
"10k": [],
|
65
|
+
"more": [],
|
66
|
+
}
|
67
|
+
for poi in pois:
|
68
|
+
iflt10k = True
|
69
|
+
for d in range(1, 11):
|
70
|
+
if (d - 1) * 1000 <= poi[1] < d * 1000:
|
71
|
+
pois_Dis["{}k".format(d)].append(poi)
|
72
|
+
iflt10k = False
|
73
|
+
break
|
74
|
+
if iflt10k:
|
75
|
+
pois_Dis["more"].append(poi)
|
76
|
+
|
77
|
+
res = []
|
78
|
+
distanceProb = []
|
79
|
+
for poi in pois:
|
80
|
+
iflt10k = True
|
81
|
+
for d in range(1, 11):
|
82
|
+
if (d - 1) * 1000 <= poi[1] < d * 1000:
|
83
|
+
n = len(pois_Dis["{}k".format(d)])
|
84
|
+
S = math.pi * ((d * 1000) ** 2 - ((d - 1) * 1000) ** 2)
|
85
|
+
density = n / S
|
86
|
+
distance = poi[1]
|
87
|
+
distance = distance if distance > 1 else 1
|
88
|
+
|
89
|
+
# distance decay coefficient, use the square of distance to calculate, so that distant places are less likely to be selected
|
90
|
+
weight = density / (distance**2) # the original weight is reasonable
|
91
|
+
res.append((poi[0]["name"], poi[0]["id"], weight, distance))
|
92
|
+
distanceProb.append(1 / (math.sqrt(distance)))
|
93
|
+
iflt10k = False
|
94
|
+
break
|
95
|
+
|
96
|
+
distanceProb = np.array(distanceProb)
|
97
|
+
distanceProb = distanceProb / np.sum(distanceProb)
|
98
|
+
distanceProb = list(distanceProb)
|
99
|
+
|
100
|
+
options = list(range(len(res)))
|
101
|
+
sample = list(
|
102
|
+
np.random.choice(options, size=50, p=distanceProb)
|
103
|
+
) # sample based on the probability value
|
104
|
+
|
105
|
+
get_elements = itemgetter(*sample)
|
106
|
+
random_elements = get_elements(res)
|
107
|
+
|
108
|
+
# normalize the weight to become the true probability value
|
109
|
+
weightSum = sum(item[2] for item in random_elements)
|
110
|
+
final = [
|
111
|
+
(item[0], item[1], item[2] / weightSum, item[3]) for item in random_elements
|
112
|
+
]
|
113
|
+
return final
|
114
|
+
|
115
|
+
|
45
116
|
class PlaceSelectionBlock(Block):
|
46
117
|
"""
|
47
|
-
|
118
|
+
Select destination
|
48
119
|
PlaceSelectionBlock
|
49
120
|
"""
|
121
|
+
|
50
122
|
configurable_fields: List[str] = ["search_limit"]
|
51
|
-
default_values = {
|
52
|
-
"search_limit": 10
|
53
|
-
}
|
123
|
+
default_values = {"search_limit": 10000}
|
54
124
|
|
55
125
|
def __init__(self, llm: LLM, memory: Memory, simulator: Simulator):
|
56
|
-
super().__init__(
|
126
|
+
super().__init__(
|
127
|
+
"PlaceSelectionBlock", llm=llm, memory=memory, simulator=simulator
|
128
|
+
)
|
57
129
|
self.description = "Used to select and determine destinations for unknown locations (excluding home and workplace), such as choosing specific shopping malls, restaurants and other places"
|
58
130
|
self.typeSelectionPrompt = FormatPrompt(PLACE_TYPE_SELECTION_PROMPT)
|
59
|
-
self.secondTypeSelectionPrompt = FormatPrompt(
|
131
|
+
self.secondTypeSelectionPrompt = FormatPrompt(
|
132
|
+
PLACE_SECOND_TYPE_SELECTION_PROMPT
|
133
|
+
)
|
60
134
|
self.radiusPrompt = FormatPrompt(RADIUS_PROMPT)
|
61
135
|
# configurable fields
|
62
|
-
self.search_limit =
|
136
|
+
self.search_limit = 10000
|
63
137
|
|
64
138
|
async def forward(self, step, context):
|
65
139
|
self.typeSelectionPrompt.format(
|
66
|
-
plan
|
67
|
-
intention
|
68
|
-
poi_category
|
140
|
+
plan=context["plan"],
|
141
|
+
intention=step["intention"],
|
142
|
+
poi_category=list(self.simulator.poi_cate.keys()),
|
69
143
|
)
|
70
|
-
levelOneType = await self.llm.atext_request(self.typeSelectionPrompt.to_dialog())
|
144
|
+
levelOneType = await self.llm.atext_request(self.typeSelectionPrompt.to_dialog()) # type: ignore
|
71
145
|
try:
|
72
146
|
sub_category = self.simulator.poi_cate[levelOneType]
|
73
147
|
except Exception as e:
|
@@ -75,67 +149,77 @@ class PlaceSelectionBlock(Block):
|
|
75
149
|
levelOneType = random.choice(list(self.simulator.poi_cate.keys()))
|
76
150
|
sub_category = self.simulator.poi_cate[levelOneType]
|
77
151
|
self.secondTypeSelectionPrompt.format(
|
78
|
-
plan
|
79
|
-
intention = step['intention'],
|
80
|
-
poi_category = sub_category
|
152
|
+
plan=context["plan"], intention=step["intention"], poi_category=sub_category
|
81
153
|
)
|
82
|
-
levelTwoType = await self.llm.atext_request(self.secondTypeSelectionPrompt.to_dialog())
|
83
|
-
center = await self.memory.status.get(
|
84
|
-
center = (center[
|
154
|
+
levelTwoType = await self.llm.atext_request(self.secondTypeSelectionPrompt.to_dialog()) # type: ignore
|
155
|
+
center = await self.memory.status.get("position")
|
156
|
+
center = (center["xy_position"]["x"], center["xy_position"]["y"])
|
85
157
|
self.radiusPrompt.format(
|
86
158
|
emotion_types=await self.memory.status.get("emotion_types"),
|
87
159
|
thought=await self.memory.status.get("thought"),
|
88
160
|
weather=self.simulator.sence("weather"),
|
89
|
-
temperature=self.simulator.sence("temperature")
|
161
|
+
temperature=self.simulator.sence("temperature"),
|
90
162
|
)
|
91
|
-
radius = int(await self.llm.atext_request(self.radiusPrompt.to_dialog()))
|
163
|
+
radius = int(await self.llm.atext_request(self.radiusPrompt.to_dialog())) # type: ignore
|
92
164
|
try:
|
93
165
|
pois = self.simulator.map.query_pois(
|
94
|
-
center
|
95
|
-
category_prefix
|
166
|
+
center=center,
|
167
|
+
category_prefix=levelTwoType,
|
96
168
|
radius=radius,
|
97
|
-
limit=self.search_limit
|
169
|
+
limit=self.search_limit,
|
98
170
|
)
|
99
171
|
except Exception as e:
|
100
172
|
logger.warning(f"Error querying pois: {e}")
|
101
173
|
levelTwoType = random.choice(sub_category)
|
102
174
|
pois = self.simulator.map.query_pois(
|
103
|
-
center
|
104
|
-
category_prefix
|
175
|
+
center=center,
|
176
|
+
category_prefix=levelTwoType,
|
105
177
|
radius=radius,
|
106
|
-
limit=self.search_limit
|
178
|
+
limit=self.search_limit,
|
107
179
|
)
|
108
180
|
if len(pois) > 0:
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
181
|
+
pois = gravity_model(pois)
|
182
|
+
probabilities = [item[2] for item in pois]
|
183
|
+
options = list(range(len(pois)))
|
184
|
+
sample = np.random.choice(
|
185
|
+
options, size=1, p=probabilities
|
186
|
+
) # sample based on the probability value
|
187
|
+
nextPlace = pois[sample[0]]
|
188
|
+
nextPlace = (nextPlace[0], nextPlace[1])
|
189
|
+
# save the destination to context
|
190
|
+
context["next_place"] = nextPlace
|
191
|
+
node_id = await self.memory.stream.add_mobility(
|
192
|
+
description=f"For {step['intention']}, I selected the destination: {nextPlace}"
|
193
|
+
)
|
114
194
|
return {
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
195
|
+
"success": True,
|
196
|
+
"evaluation": f"Successfully selected the destination: {nextPlace}",
|
197
|
+
"consumed_time": 5,
|
198
|
+
"node_id": node_id,
|
119
199
|
}
|
120
200
|
else:
|
121
201
|
simmap = self.simulator.map
|
122
202
|
poi = random.choice(list(simmap.pois.values()))
|
123
|
-
nextPlace = (poi[
|
124
|
-
#
|
125
|
-
context[
|
126
|
-
node_id = await self.memory.stream.add_mobility(
|
203
|
+
nextPlace = (poi["name"], poi["aoi_id"])
|
204
|
+
# save the destination to context
|
205
|
+
context["next_place"] = nextPlace
|
206
|
+
node_id = await self.memory.stream.add_mobility(
|
207
|
+
description=f"For {step['intention']}, I selected the destination: {nextPlace}"
|
208
|
+
)
|
127
209
|
return {
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
210
|
+
"success": True,
|
211
|
+
"evaluation": f"Successfully selected the destination: {nextPlace}",
|
212
|
+
"consumed_time": 5,
|
213
|
+
"node_id": node_id,
|
132
214
|
}
|
133
215
|
|
216
|
+
|
134
217
|
class MoveBlock(Block):
|
135
218
|
"""
|
136
|
-
|
219
|
+
Execute mobility operations
|
137
220
|
MoveBlock
|
138
221
|
"""
|
222
|
+
|
139
223
|
def __init__(self, llm: LLM, memory: Memory, simulator: Simulator):
|
140
224
|
super().__init__("MoveBlock", llm=llm, memory=memory, simulator=simulator)
|
141
225
|
self.description = "Used to execute specific mobility operations, such as returning home, going to work, or visiting a specific location"
|
@@ -145,68 +229,79 @@ class MoveBlock(Block):
|
|
145
229
|
# 这里应该添加移动的具体逻辑
|
146
230
|
agent_id = await self.memory.status.get("id")
|
147
231
|
self.placeAnalysisPrompt.format(
|
148
|
-
plan
|
149
|
-
intention = step["intention"]
|
232
|
+
plan=context["plan"], intention=step["intention"]
|
150
233
|
)
|
151
234
|
number_poi_visited = await self.memory.status.get("number_poi_visited")
|
152
235
|
number_poi_visited += 1
|
153
236
|
await self.memory.status.update("number_poi_visited", number_poi_visited)
|
154
|
-
response = await self.llm.atext_request(self.placeAnalysisPrompt.to_dialog())
|
155
|
-
if response ==
|
237
|
+
response = await self.llm.atext_request(self.placeAnalysisPrompt.to_dialog()) # type: ignore
|
238
|
+
if response == "home":
|
156
239
|
# 返回到家
|
157
|
-
home = await self.memory.status.get(
|
158
|
-
home = home[
|
159
|
-
nowPlace = await self.memory.status.get(
|
160
|
-
node_id = await self.memory.stream.add_mobility(
|
161
|
-
|
240
|
+
home = await self.memory.status.get("home")
|
241
|
+
home = home["aoi_position"]["aoi_id"]
|
242
|
+
nowPlace = await self.memory.status.get("position")
|
243
|
+
node_id = await self.memory.stream.add_mobility(
|
244
|
+
description=f"I returned home"
|
245
|
+
)
|
246
|
+
if (
|
247
|
+
"aoi_position" in nowPlace
|
248
|
+
and nowPlace["aoi_position"]["aoi_id"] == home
|
249
|
+
):
|
162
250
|
return {
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
251
|
+
"success": True,
|
252
|
+
"evaluation": f"Successfully returned home (already at home)",
|
253
|
+
"to_place": home,
|
254
|
+
"consumed_time": 0,
|
255
|
+
"node_id": node_id,
|
168
256
|
}
|
169
257
|
await self.simulator.set_aoi_schedules(
|
170
258
|
person_id=agent_id,
|
171
259
|
target_positions=home,
|
172
260
|
)
|
173
261
|
return {
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
262
|
+
"success": True,
|
263
|
+
"evaluation": f"Successfully returned home",
|
264
|
+
"to_place": home,
|
265
|
+
"consumed_time": 45,
|
266
|
+
"node_id": node_id,
|
179
267
|
}
|
180
|
-
elif response ==
|
268
|
+
elif response == "workplace":
|
181
269
|
# 返回到工作地点
|
182
|
-
work = await self.memory.status.get(
|
183
|
-
work = work[
|
184
|
-
nowPlace = await self.memory.status.get(
|
185
|
-
node_id = await self.memory.stream.add_mobility(
|
186
|
-
|
270
|
+
work = await self.memory.status.get("work")
|
271
|
+
work = work["aoi_position"]["aoi_id"]
|
272
|
+
nowPlace = await self.memory.status.get("position")
|
273
|
+
node_id = await self.memory.stream.add_mobility(
|
274
|
+
description=f"I went to my workplace"
|
275
|
+
)
|
276
|
+
if (
|
277
|
+
"aoi_position" in nowPlace
|
278
|
+
and nowPlace["aoi_position"]["aoi_id"] == work
|
279
|
+
):
|
187
280
|
return {
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
281
|
+
"success": True,
|
282
|
+
"evaluation": f"Successfully reached the workplace (already at the workplace)",
|
283
|
+
"to_place": work,
|
284
|
+
"consumed_time": 0,
|
285
|
+
"node_id": node_id,
|
193
286
|
}
|
194
287
|
await self.simulator.set_aoi_schedules(
|
195
288
|
person_id=agent_id,
|
196
289
|
target_positions=work,
|
197
290
|
)
|
198
291
|
return {
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
292
|
+
"success": True,
|
293
|
+
"evaluation": f"Successfully reached the workplace",
|
294
|
+
"to_place": work,
|
295
|
+
"consumed_time": 45,
|
296
|
+
"node_id": node_id,
|
204
297
|
}
|
205
298
|
else:
|
206
299
|
# 移动到其他地点
|
207
|
-
next_place = context.get(
|
208
|
-
nowPlace = await self.memory.status.get(
|
209
|
-
node_id = await self.memory.stream.add_mobility(
|
300
|
+
next_place = context.get("next_place", None)
|
301
|
+
nowPlace = await self.memory.status.get("position")
|
302
|
+
node_id = await self.memory.stream.add_mobility(
|
303
|
+
description=f"I went to {next_place}"
|
304
|
+
)
|
210
305
|
if next_place != None:
|
211
306
|
await self.simulator.set_aoi_schedules(
|
212
307
|
person_id=agent_id,
|
@@ -215,41 +310,46 @@ class MoveBlock(Block):
|
|
215
310
|
else:
|
216
311
|
while True:
|
217
312
|
r_aoi = random.choice(list(self.simulator.map.aois.values()))
|
218
|
-
if len(r_aoi[
|
219
|
-
r_poi = random.choice(r_aoi[
|
313
|
+
if len(r_aoi["poi_ids"]) > 0:
|
314
|
+
r_poi = random.choice(r_aoi["poi_ids"])
|
220
315
|
break
|
221
316
|
poi = self.simulator.map.pois[r_poi]
|
222
|
-
next_place = (poi[
|
317
|
+
next_place = (poi["name"], poi["aoi_id"])
|
223
318
|
await self.simulator.set_aoi_schedules(
|
224
319
|
person_id=agent_id,
|
225
320
|
target_positions=next_place[1],
|
226
321
|
)
|
227
322
|
return {
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
323
|
+
"success": True,
|
324
|
+
"evaluation": f"Successfully reached the destination: {next_place}",
|
325
|
+
"to_place": next_place[1],
|
326
|
+
"consumed_time": 45,
|
327
|
+
"node_id": node_id,
|
233
328
|
}
|
234
|
-
|
329
|
+
|
330
|
+
|
235
331
|
class MobilityNoneBlock(Block):
|
236
332
|
"""
|
237
333
|
空操作
|
238
334
|
MobilityNoneBlock
|
239
335
|
"""
|
336
|
+
|
240
337
|
def __init__(self, llm: LLM, memory: Memory):
|
241
338
|
super().__init__("MobilityNoneBlock", llm=llm, memory=memory)
|
242
339
|
self.description = "Used to handle other cases"
|
243
340
|
|
244
341
|
async def forward(self, step, context):
|
245
|
-
node_id = await self.memory.stream.add_mobility(
|
342
|
+
node_id = await self.memory.stream.add_mobility(
|
343
|
+
description=f"I finished {step['intention']}"
|
344
|
+
)
|
246
345
|
return {
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
346
|
+
"success": True,
|
347
|
+
"evaluation": f'Finished executing {step["intention"]}',
|
348
|
+
"consumed_time": 0,
|
349
|
+
"node_id": node_id,
|
251
350
|
}
|
252
351
|
|
352
|
+
|
253
353
|
class MobilityBlock(Block):
|
254
354
|
place_selection_block: PlaceSelectionBlock
|
255
355
|
move_block: MoveBlock
|
@@ -266,19 +366,23 @@ class MobilityBlock(Block):
|
|
266
366
|
# 初始化调度器
|
267
367
|
self.dispatcher = BlockDispatcher(llm)
|
268
368
|
# 注册所有块
|
269
|
-
self.dispatcher.register_blocks(
|
369
|
+
self.dispatcher.register_blocks(
|
370
|
+
[self.place_selection_block, self.move_block, self.mobility_none_block]
|
371
|
+
)
|
270
372
|
|
271
|
-
async def forward(self, step, context):
|
373
|
+
async def forward(self, step, context):
|
272
374
|
self.trigger_time += 1
|
273
|
-
consumption_start =
|
375
|
+
consumption_start = (
|
376
|
+
self.llm.prompt_tokens_used + self.llm.completion_tokens_used
|
377
|
+
)
|
274
378
|
|
275
379
|
# Select the appropriate sub-block using dispatcher
|
276
380
|
selected_block = await self.dispatcher.dispatch(step)
|
277
|
-
|
381
|
+
|
278
382
|
# Execute the selected sub-block and get the result
|
279
|
-
result = await selected_block.forward(step, context)
|
383
|
+
result = await selected_block.forward(step, context) # type: ignore
|
280
384
|
|
281
385
|
consumption_end = self.llm.prompt_tokens_used + self.llm.completion_tokens_used
|
282
386
|
self.token_consumption += consumption_end - consumption_start
|
283
|
-
|
284
|
-
return result
|
387
|
+
|
388
|
+
return result
|