pycityagent 2.0.0a48__cp39-cp39-macosx_11_0_arm64.whl → 2.0.0a49__cp39-cp39-macosx_11_0_arm64.whl
Sign up to get free protection for your applications and to get access to all the features.
- pycityagent/agent.py +7 -7
- pycityagent/simulation/agentgroup.py +22 -17
- pycityagent/workflow/tool.py +20 -19
- {pycityagent-2.0.0a48.dist-info → pycityagent-2.0.0a49.dist-info}/METADATA +1 -1
- {pycityagent-2.0.0a48.dist-info → pycityagent-2.0.0a49.dist-info}/RECORD +9 -9
- {pycityagent-2.0.0a48.dist-info → pycityagent-2.0.0a49.dist-info}/LICENSE +0 -0
- {pycityagent-2.0.0a48.dist-info → pycityagent-2.0.0a49.dist-info}/WHEEL +0 -0
- {pycityagent-2.0.0a48.dist-info → pycityagent-2.0.0a49.dist-info}/entry_points.txt +0 -0
- {pycityagent-2.0.0a48.dist-info → pycityagent-2.0.0a49.dist-info}/top_level.txt +0 -0
pycityagent/agent.py
CHANGED
@@ -9,7 +9,7 @@ from abc import ABC, abstractmethod
|
|
9
9
|
from copy import deepcopy
|
10
10
|
from datetime import datetime, timezone
|
11
11
|
from enum import Enum
|
12
|
-
from typing import Any,
|
12
|
+
from typing import Any, Optional, Type, get_type_hints
|
13
13
|
from uuid import UUID
|
14
14
|
|
15
15
|
import fastavro
|
@@ -49,7 +49,7 @@ class Agent(ABC):
|
|
49
49
|
"""
|
50
50
|
Agent base class
|
51
51
|
"""
|
52
|
-
configurable_fields:
|
52
|
+
configurable_fields: list[str] = []
|
53
53
|
default_values: dict[str, Any] = {}
|
54
54
|
|
55
55
|
def __init__(
|
@@ -107,7 +107,7 @@ class Agent(ABC):
|
|
107
107
|
return state
|
108
108
|
|
109
109
|
@classmethod
|
110
|
-
def export_class_config(cls) ->
|
110
|
+
def export_class_config(cls) -> dict[str, Dict]:
|
111
111
|
result = {
|
112
112
|
"agent_name": cls.__name__,
|
113
113
|
"config": {},
|
@@ -131,7 +131,7 @@ class Agent(ABC):
|
|
131
131
|
return result
|
132
132
|
|
133
133
|
@classmethod
|
134
|
-
def _export_subblocks(cls, block_cls: Type[Block]) ->
|
134
|
+
def _export_subblocks(cls, block_cls: Type[Block]) -> list[Dict]:
|
135
135
|
children = []
|
136
136
|
hints = get_type_hints(block_cls) # 获取类的注解
|
137
137
|
for attr_name, attr_type in hints.items():
|
@@ -151,7 +151,7 @@ class Agent(ABC):
|
|
151
151
|
json.dump(config, f, indent=4)
|
152
152
|
|
153
153
|
@classmethod
|
154
|
-
def import_block_config(cls, config:
|
154
|
+
def import_block_config(cls, config: dict[str, list[Dict]]) -> "Agent":
|
155
155
|
agent = cls(name=config["agent_name"])
|
156
156
|
|
157
157
|
def build_block(block_data: Dict) -> Block:
|
@@ -172,7 +172,7 @@ class Agent(ABC):
|
|
172
172
|
config = json.load(f)
|
173
173
|
return cls.import_block_config(config)
|
174
174
|
|
175
|
-
def load_from_config(self, config:
|
175
|
+
def load_from_config(self, config: dict[str, list[Dict]]) -> None:
|
176
176
|
"""
|
177
177
|
使用配置更新当前Agent实例的Block层次结构。
|
178
178
|
"""
|
@@ -185,7 +185,7 @@ class Agent(ABC):
|
|
185
185
|
# 递归更新或创建顶层Block
|
186
186
|
for block_data in config.get("blocks", []):
|
187
187
|
block_name = block_data["name"]
|
188
|
-
existing_block = getattr(self, block_name, None)
|
188
|
+
existing_block = getattr(self, block_name, None) # type:ignore
|
189
189
|
|
190
190
|
if existing_block:
|
191
191
|
# 如果Block已经存在,则递归更新
|
@@ -1,9 +1,9 @@
|
|
1
1
|
import asyncio
|
2
|
-
from collections.abc import Callable
|
3
2
|
import json
|
4
3
|
import logging
|
5
4
|
import time
|
6
5
|
import uuid
|
6
|
+
from collections.abc import Callable
|
7
7
|
from datetime import datetime, timezone
|
8
8
|
from pathlib import Path
|
9
9
|
from typing import Any, Optional, Type, Union
|
@@ -34,7 +34,10 @@ class AgentGroup:
|
|
34
34
|
self,
|
35
35
|
agent_class: Union[type[Agent], list[type[Agent]]],
|
36
36
|
number_of_agents: Union[int, list[int]],
|
37
|
-
memory_config_function_group: Union[
|
37
|
+
memory_config_function_group: Union[
|
38
|
+
Callable[[], tuple[dict, dict, dict]],
|
39
|
+
list[Callable[[], tuple[dict, dict, dict]]],
|
40
|
+
],
|
38
41
|
config: dict,
|
39
42
|
exp_id: str | UUID,
|
40
43
|
exp_name: str,
|
@@ -81,14 +84,14 @@ class AgentGroup:
|
|
81
84
|
# prepare Messager
|
82
85
|
if "mqtt" in config["simulator_request"]:
|
83
86
|
self.messager = Messager.remote(
|
84
|
-
hostname=config["simulator_request"]["mqtt"]["server"],
|
87
|
+
hostname=config["simulator_request"]["mqtt"]["server"], # type:ignore
|
85
88
|
port=config["simulator_request"]["mqtt"]["port"],
|
86
89
|
username=config["simulator_request"]["mqtt"].get("username", None),
|
87
90
|
password=config["simulator_request"]["mqtt"].get("password", None),
|
88
91
|
)
|
89
92
|
else:
|
90
93
|
self.messager = None
|
91
|
-
|
94
|
+
|
92
95
|
self.message_dispatch_task = None
|
93
96
|
self._pgsql_writer = pgsql_writer
|
94
97
|
self._last_asyncio_pg_task = None # 将SQL写入的IO隐藏到计算任务后
|
@@ -168,21 +171,21 @@ class AgentGroup:
|
|
168
171
|
@property
|
169
172
|
def agent_count(self):
|
170
173
|
return self.number_of_agents
|
171
|
-
|
174
|
+
|
172
175
|
@property
|
173
176
|
def agent_uuids(self):
|
174
177
|
return list(self.id2agent.keys())
|
175
|
-
|
178
|
+
|
176
179
|
@property
|
177
180
|
def agent_type(self):
|
178
181
|
return self.agent_class
|
179
|
-
|
182
|
+
|
180
183
|
def get_agent_count(self):
|
181
184
|
return self.agent_count
|
182
|
-
|
185
|
+
|
183
186
|
def get_agent_uuids(self):
|
184
187
|
return self.agent_uuids
|
185
|
-
|
188
|
+
|
186
189
|
def get_agent_type(self):
|
187
190
|
return self.agent_type
|
188
191
|
|
@@ -190,10 +193,6 @@ class AgentGroup:
|
|
190
193
|
self.message_dispatch_task.cancel() # type: ignore
|
191
194
|
await asyncio.gather(self.message_dispatch_task, return_exceptions=True) # type: ignore
|
192
195
|
|
193
|
-
async def __aexit__(self, exc_type, exc_value, traceback):
|
194
|
-
self.message_dispatch_task.cancel() # type: ignore
|
195
|
-
await asyncio.gather(self.message_dispatch_task, return_exceptions=True) # type: ignore
|
196
|
-
|
197
196
|
async def init_agents(self):
|
198
197
|
logger.debug(f"-----Initializing Agents in AgentGroup {self._uuid} ...")
|
199
198
|
logger.debug(f"-----Binding Agents to Simulator in AgentGroup {self._uuid} ...")
|
@@ -201,6 +200,7 @@ class AgentGroup:
|
|
201
200
|
await agent.bind_to_simulator() # type: ignore
|
202
201
|
self.id2agent = {agent._uuid: agent for agent in self.agents}
|
203
202
|
logger.debug(f"-----Binding Agents to Messager in AgentGroup {self._uuid} ...")
|
203
|
+
assert self.messager is not None
|
204
204
|
await self.messager.connect.remote()
|
205
205
|
if await self.messager.is_connected.remote():
|
206
206
|
await self.messager.start_listening.remote()
|
@@ -293,10 +293,12 @@ class AgentGroup:
|
|
293
293
|
self.initialized = True
|
294
294
|
logger.debug(f"-----AgentGroup {self._uuid} initialized")
|
295
295
|
|
296
|
-
async def filter(
|
297
|
-
|
298
|
-
|
299
|
-
|
296
|
+
async def filter(
|
297
|
+
self,
|
298
|
+
types: Optional[list[Type[Agent]]] = None,
|
299
|
+
keys: Optional[list[str]] = None,
|
300
|
+
values: Optional[list[Any]] = None,
|
301
|
+
) -> list[str]:
|
300
302
|
filtered_uuids = []
|
301
303
|
for agent in self.agents:
|
302
304
|
add = True
|
@@ -304,6 +306,7 @@ class AgentGroup:
|
|
304
306
|
if agent.__class__ in types:
|
305
307
|
if keys:
|
306
308
|
for key in keys:
|
309
|
+
assert values is not None
|
307
310
|
if not agent.memory.get(key) == values[keys.index(key)]:
|
308
311
|
add = False
|
309
312
|
break
|
@@ -311,6 +314,7 @@ class AgentGroup:
|
|
311
314
|
filtered_uuids.append(agent._uuid)
|
312
315
|
elif keys:
|
313
316
|
for key in keys:
|
317
|
+
assert values is not None
|
314
318
|
if not agent.memory.get(key) == values[keys.index(key)]:
|
315
319
|
add = False
|
316
320
|
break
|
@@ -335,6 +339,7 @@ class AgentGroup:
|
|
335
339
|
async def message_dispatch(self):
|
336
340
|
logger.debug(f"-----Starting message dispatch for group {self._uuid}")
|
337
341
|
while True:
|
342
|
+
assert self.messager is not None
|
338
343
|
if not await self.messager.is_connected.remote():
|
339
344
|
logger.warning(
|
340
345
|
"Messager is not connected. Skipping message processing."
|
pycityagent/workflow/tool.py
CHANGED
@@ -1,10 +1,16 @@
|
|
1
|
-
|
1
|
+
import asyncio
|
2
|
+
import time
|
2
3
|
from collections import defaultdict
|
3
4
|
from collections.abc import Callable, Sequence
|
5
|
+
from typing import Any, Optional, Union
|
6
|
+
|
4
7
|
from mlflow.entities import Metric
|
5
|
-
import time
|
6
8
|
|
7
|
-
from ..
|
9
|
+
from ..agent import Agent
|
10
|
+
from ..utils.decorators import lock_decorator
|
11
|
+
from ..environment import (LEVEL_ONE_PRE, POI_TYPE_DICT, AoiService,
|
12
|
+
PersonService)
|
13
|
+
from ..workflow import Block
|
8
14
|
|
9
15
|
|
10
16
|
class Tool:
|
@@ -34,31 +40,23 @@ class Tool:
|
|
34
40
|
raise NotImplementedError
|
35
41
|
|
36
42
|
@property
|
37
|
-
def agent(self):
|
43
|
+
def agent(self) -> Agent:
|
38
44
|
instance = self._instance # type:ignore
|
39
|
-
if not isinstance(instance,
|
45
|
+
if not isinstance(instance, Agent):
|
40
46
|
raise RuntimeError(
|
41
47
|
f"Tool bind to object `{type(instance).__name__}`, not an `Agent` object!"
|
42
48
|
)
|
43
49
|
return instance
|
44
50
|
|
45
51
|
@property
|
46
|
-
def block(self):
|
52
|
+
def block(self) -> Block:
|
47
53
|
instance = self._instance # type:ignore
|
48
|
-
if not isinstance(instance,
|
54
|
+
if not isinstance(instance, Block):
|
49
55
|
raise RuntimeError(
|
50
56
|
f"Tool bind to object `{type(instance).__name__}`, not an `Block` object!"
|
51
57
|
)
|
52
58
|
return instance
|
53
59
|
|
54
|
-
def _get_agent_class(self):
|
55
|
-
from ..agent import Agent
|
56
|
-
return Agent
|
57
|
-
|
58
|
-
def _get_block_class(self):
|
59
|
-
from ..workflow import Block
|
60
|
-
return Block
|
61
|
-
|
62
60
|
|
63
61
|
class GetMap(Tool):
|
64
62
|
"""Retrieve the map from the simulator. Can be bound only to an `Agent` instance."""
|
@@ -140,7 +138,7 @@ class SencePOI(Tool):
|
|
140
138
|
|
141
139
|
class UpdateWithSimulator(Tool):
|
142
140
|
def __init__(self) -> None:
|
143
|
-
|
141
|
+
self._lock = asyncio.Lock()
|
144
142
|
|
145
143
|
async def _update_motion_with_sim(
|
146
144
|
self,
|
@@ -164,6 +162,7 @@ class UpdateWithSimulator(Tool):
|
|
164
162
|
except KeyError as e:
|
165
163
|
continue
|
166
164
|
|
165
|
+
@lock_decorator
|
167
166
|
async def __call__(
|
168
167
|
self,
|
169
168
|
):
|
@@ -173,8 +172,9 @@ class UpdateWithSimulator(Tool):
|
|
173
172
|
|
174
173
|
class ResetAgentPosition(Tool):
|
175
174
|
def __init__(self) -> None:
|
176
|
-
|
175
|
+
self._lock = asyncio.Lock()
|
177
176
|
|
177
|
+
@lock_decorator
|
178
178
|
async def __call__(
|
179
179
|
self,
|
180
180
|
aoi_id: Optional[int] = None,
|
@@ -198,7 +198,8 @@ class ExportMlflowMetrics(Tool):
|
|
198
198
|
self._log_batch_size = log_batch_size
|
199
199
|
# TODO: support other log types
|
200
200
|
self.metric_log_cache: dict[str, list[Metric]] = defaultdict(list)
|
201
|
-
|
201
|
+
self._lock = asyncio.Lock()
|
202
|
+
@lock_decorator
|
202
203
|
async def __call__(
|
203
204
|
self,
|
204
205
|
metric: Union[Sequence[Union[Metric, dict]], Union[Metric, dict]],
|
@@ -230,7 +231,7 @@ class ExportMlflowMetrics(Tool):
|
|
230
231
|
_cache = _cache[batch_size:]
|
231
232
|
if clear_cache:
|
232
233
|
await self._clear_cache()
|
233
|
-
|
234
|
+
@lock_decorator
|
234
235
|
async def _clear_cache(
|
235
236
|
self,
|
236
237
|
):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: pycityagent
|
3
|
-
Version: 2.0.
|
3
|
+
Version: 2.0.0a49
|
4
4
|
Summary: LLM-based city environment agent building library
|
5
5
|
Author-email: Yuwei Yan <pinkgranite86@gmail.com>, Junbo Yan <yanjb20thu@gmali.com>, Jun Zhang <zhangjun990222@gmali.com>
|
6
6
|
License: MIT License
|
@@ -1,7 +1,7 @@
|
|
1
1
|
pycityagent/pycityagent-sim,sha256=n96jlVZRINlBec5SPOGAdUmeLWMoEKGgoH29iOVJ0wE,34081890
|
2
2
|
pycityagent/__init__.py,sha256=9sHyzo8monlBPDe7LTlxCIHeNPYj8HJJDCeuJrYJLsQ,750
|
3
3
|
pycityagent/pycityagent-ui,sha256=cHZjqtrQ4Fh4qtRahFNCNbT2DNHLmUexiDAa-72Z3RQ,40333378
|
4
|
-
pycityagent/agent.py,sha256=
|
4
|
+
pycityagent/agent.py,sha256=iaF83y344V29-jghx5bJD3yY8kMuSzInBPNi7cVxYiA,34026
|
5
5
|
pycityagent/metrics/mlflow_client.py,sha256=g_tHxWkWTDijtbGL74-HmiYzWVKb1y8-w12QrY9jL30,4449
|
6
6
|
pycityagent/metrics/__init__.py,sha256=X08PaBbGVAd7_PRGLREXWxaqm7nS82WBQpD1zvQzcqc,128
|
7
7
|
pycityagent/metrics/utils/const.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -23,7 +23,7 @@ pycityagent/memory/faiss_query.py,sha256=Z0JS4udyPYCIzHMq464QtHscnswu35gh9fQptik
|
|
23
23
|
pycityagent/memory/state.py,sha256=TYItiyDtehMEQaSBN7PpNrnNxdDM5jGppr9R9Ufv3kA,5134
|
24
24
|
pycityagent/simulation/simulation.py,sha256=7Y1r5DAFaB1vuDd3l_85NWpHQUy2GLkFEb800xsJr0E,25565
|
25
25
|
pycityagent/simulation/__init__.py,sha256=P5czbcg2d8S0nbbnsQXFIhwzO4CennAhZM8OmKvAeYw,194
|
26
|
-
pycityagent/simulation/agentgroup.py,sha256=
|
26
|
+
pycityagent/simulation/agentgroup.py,sha256=DGN6q9S65K9gSv_ihBeT6iJ__LJhl27yXBFyLEk55t0,29302
|
27
27
|
pycityagent/simulation/storage/pg.py,sha256=5itxKOkNPlOzN7z2_3oKU1ZK0uLTDugfld8ZkRbD69I,8407
|
28
28
|
pycityagent/message/__init__.py,sha256=TCjazxqb5DVwbTu1fF0sNvaH_EPXVuj2XQ0p6W-QCLU,55
|
29
29
|
pycityagent/message/messager.py,sha256=78K31EPKfC5IxbISc-Lc2babC7VOh9Vbe3c0sO-YDLA,3333
|
@@ -40,7 +40,7 @@ pycityagent/cli/wrapper.py,sha256=2Tb52gOlEVgn11Ekt6ZkRXr_BGzte-EPyBKnR6g6hQ4,11
|
|
40
40
|
pycityagent/workflow/__init__.py,sha256=QNkUV-9mACMrR8c0cSKna2gC1mMZdxXbxWzjE-Uods0,621
|
41
41
|
pycityagent/workflow/prompt.py,sha256=6jI0Rq54JLv3-IXqZLYug62vse10wTI83xvf4ZX42nk,2929
|
42
42
|
pycityagent/workflow/block.py,sha256=8pK17DGX8MnFJHq5lJ4susdZ-CDAEIjlTV_2mJxhbbw,9600
|
43
|
-
pycityagent/workflow/tool.py,sha256=
|
43
|
+
pycityagent/workflow/tool.py,sha256=ChuN5Sm-yltesemewjnTOYaxN6NUjfi2MezVuclf6Tc,8776
|
44
44
|
pycityagent/workflow/trigger.py,sha256=Df-MOBEDWBbM-v0dFLQLXteLsipymT4n8vqexmK2GiQ,5643
|
45
45
|
pycityagent/environment/__init__.py,sha256=awHxlOud-btWbk0FCS4RmGJ13W84oVCkbGfcrhKqihA,240
|
46
46
|
pycityagent/environment/simulator.py,sha256=1OUfODDzM4EN6Lw_Wzq4KeQb-EpcUBioZYc9fxfSPn0,12070
|
@@ -92,9 +92,9 @@ pycityagent/cityagent/blocks/mobility_block.py,sha256=ZebloDhvZJYbV0YSWhAbnOLToi
|
|
92
92
|
pycityagent/survey/models.py,sha256=YE50UUt5qJ0O_lIUsSY6XFCGUTkJVNu_L1gAhaCJ2fs,3546
|
93
93
|
pycityagent/survey/__init__.py,sha256=rxwou8U9KeFSP7rMzXtmtp2fVFZxK4Trzi-psx9LPIs,153
|
94
94
|
pycityagent/survey/manager.py,sha256=S5IkwTdelsdtZETChRcfCEczzwSrry_Fly9MY4s3rbk,1681
|
95
|
-
pycityagent-2.0.
|
96
|
-
pycityagent-2.0.
|
97
|
-
pycityagent-2.0.
|
98
|
-
pycityagent-2.0.
|
99
|
-
pycityagent-2.0.
|
100
|
-
pycityagent-2.0.
|
95
|
+
pycityagent-2.0.0a49.dist-info/RECORD,,
|
96
|
+
pycityagent-2.0.0a49.dist-info/LICENSE,sha256=n2HPXiupinpyHMnIkbCf3OTYd3KMqbmldu1e7av0CAU,1084
|
97
|
+
pycityagent-2.0.0a49.dist-info/WHEEL,sha256=a0tp6wW3m4fTciuZVKNaKeUIqeByIUk8AhIZrYTzSyA,107
|
98
|
+
pycityagent-2.0.0a49.dist-info/entry_points.txt,sha256=BZcne49AAIFv-hawxGnPbblea7X3MtAtoPyDX8L4OC4,132
|
99
|
+
pycityagent-2.0.0a49.dist-info/top_level.txt,sha256=yOmeu6cSXmiUtScu53a3s0p7BGtLMaV0aff83EHCTic,43
|
100
|
+
pycityagent-2.0.0a49.dist-info/METADATA,sha256=AArJCX11voHGW5AlMrin1qZoj8iVGdOD9XLODRcQwUY,9139
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|