pycityagent 2.0.0a65__cp312-cp312-macosx_11_0_arm64.whl → 2.0.0a67__cp312-cp312-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
@@ -15,12 +15,34 @@ logger = logging.getLogger("pycityagent")
|
|
15
15
|
|
16
16
|
|
17
17
|
class MemoryUnit:
|
18
|
+
"""
|
19
|
+
A class used to manage a unit of memory that can be updated asynchronously.
|
20
|
+
|
21
|
+
- **Description**:
|
22
|
+
- This class allows for the storage of content within a dictionary-like structure,
|
23
|
+
with optional required attributes and timestamp tracking. It provides methods to
|
24
|
+
safely update or clear the stored content using an internal lock to prevent race conditions.
|
25
|
+
|
26
|
+
- **Attributes**:
|
27
|
+
- `_content`: Internal dictionary storing the content of the memory unit.
|
28
|
+
- `_lock`: An asyncio Lock object used to ensure thread-safe operations on `_content`.
|
29
|
+
- `_activate_timestamp`: Boolean flag indicating whether to track changes with timestamps.
|
30
|
+
"""
|
31
|
+
|
18
32
|
def __init__(
|
19
33
|
self,
|
20
34
|
content: Optional[dict] = None,
|
21
35
|
required_attributes: Optional[dict] = None,
|
22
36
|
activate_timestamp: bool = False,
|
23
37
|
) -> None:
|
38
|
+
"""
|
39
|
+
Initialize a new instance of MemoryUnit.
|
40
|
+
|
41
|
+
- **Args**:
|
42
|
+
- `content` (Optional[Dict[Any, Any]], optional): Initial content to store in the memory unit. Defaults to an empty dictionary.
|
43
|
+
- `required_attributes` (Optional[Dict[Any, Any]], optional): Attributes that must be present in the memory unit. Defaults to None.
|
44
|
+
- `activate_timestamp` (bool, optional): Whether to track changes with timestamps. Defaults to False.
|
45
|
+
"""
|
24
46
|
self._content = {}
|
25
47
|
self._lock = asyncio.Lock()
|
26
48
|
self._activate_timestamp = activate_timestamp
|
@@ -54,6 +76,16 @@ class MemoryUnit:
|
|
54
76
|
setattr(self, f"{SELF_DEFINE_PREFIX}{property_name}", property_value)
|
55
77
|
|
56
78
|
async def update(self, content: dict) -> None:
|
79
|
+
"""
|
80
|
+
Update the memory unit's content with the provided dictionary, respecting type consistency.
|
81
|
+
|
82
|
+
- **Args**:
|
83
|
+
- `content` (Dict[Any, Any]): A dictionary containing the updates to apply.
|
84
|
+
|
85
|
+
- **Notes**:
|
86
|
+
- If `activate_timestamp` is True, the timestamp will be updated after the operation.
|
87
|
+
- Type warnings are logged when the type of a value changes.
|
88
|
+
"""
|
57
89
|
await self._lock.acquire()
|
58
90
|
for k, v in content.items():
|
59
91
|
if k in self._content:
|
@@ -71,82 +103,139 @@ class MemoryUnit:
|
|
71
103
|
self._lock.release()
|
72
104
|
|
73
105
|
async def clear(self) -> None:
|
106
|
+
"""
|
107
|
+
Clear all content from the memory unit.
|
108
|
+
"""
|
74
109
|
await self._lock.acquire()
|
75
110
|
self._content = {}
|
76
111
|
self._lock.release()
|
77
112
|
|
78
|
-
async def top_k_values(
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
) -> Union[Sequence[Any], Any]:
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
113
|
+
# async def top_k_values(
|
114
|
+
# self,
|
115
|
+
# key: Any,
|
116
|
+
# metric: Callable[[Any], Any],
|
117
|
+
# top_k: Optional[int] = None,
|
118
|
+
# preserve_order: bool = True,
|
119
|
+
# ) -> Union[Sequence[Any], Any]:
|
120
|
+
# await self._lock.acquire()
|
121
|
+
# values = self._content[key]
|
122
|
+
# if not isinstance(values, Sequence):
|
123
|
+
# logger.warning(
|
124
|
+
# f"the value stored in key `{key}` is not `sequence`, return value `{values}` instead!"
|
125
|
+
# )
|
126
|
+
# return values
|
127
|
+
# else:
|
128
|
+
# _values_with_idx = [(i, v) for i, v in enumerate(values)]
|
129
|
+
# _sorted_values_with_idx = sorted(
|
130
|
+
# _values_with_idx, key=lambda i_v: -metric(i_v[1])
|
131
|
+
# )
|
132
|
+
# top_k = len(values) if top_k is None else top_k
|
133
|
+
# if len(_sorted_values_with_idx) < top_k:
|
134
|
+
# logger.debug(
|
135
|
+
# f"Length of values {len(_sorted_values_with_idx)} is less than top_k {top_k}, returning all values."
|
136
|
+
# )
|
137
|
+
# self._lock.release()
|
138
|
+
# if preserve_order:
|
139
|
+
# return [
|
140
|
+
# i_v[1]
|
141
|
+
# for i_v in sorted(
|
142
|
+
# _sorted_values_with_idx[:top_k], key=lambda i_v: i_v[0]
|
143
|
+
# )
|
144
|
+
# ]
|
145
|
+
# else:
|
146
|
+
# return [i_v[1] for i_v in _sorted_values_with_idx[:top_k]]
|
112
147
|
|
113
148
|
async def dict_values(
|
114
149
|
self,
|
115
150
|
) -> dict[Any, Any]:
|
151
|
+
"""
|
152
|
+
Return the dict value of the memory unit.
|
153
|
+
"""
|
116
154
|
return self._content
|
117
155
|
|
118
156
|
|
119
157
|
class MemoryBase(ABC):
|
158
|
+
"""
|
159
|
+
An abstract base class for managing a memory system.
|
160
|
+
|
161
|
+
This class defines the interface for adding, popping, loading, exporting,
|
162
|
+
and resetting memory items. It also includes methods for fetching recent
|
163
|
+
memories and interacting with specific memory entries.
|
164
|
+
"""
|
120
165
|
|
121
166
|
def __init__(self) -> None:
|
167
|
+
"""
|
168
|
+
Initialize a new instance of MemoryBase.
|
169
|
+
|
170
|
+
- **Attributes**:
|
171
|
+
- `_memories`: A dictionary that stores memory items.
|
172
|
+
- `_lock`: An asyncio Lock object to ensure thread-safe operations on `_memories`.
|
173
|
+
"""
|
122
174
|
self._memories: dict[Any, dict] = {}
|
123
175
|
self._lock = asyncio.Lock()
|
124
176
|
|
125
177
|
@abstractmethod
|
126
178
|
async def add(self, msg: Union[Any, Sequence[Any]]) -> None:
|
179
|
+
"""
|
180
|
+
Add one or more items to the memory.
|
181
|
+
|
182
|
+
- **Args**:
|
183
|
+
- `msg` (Union[Any, Sequence[Any]]): The item or sequence of items to add.
|
184
|
+
"""
|
127
185
|
raise NotImplementedError
|
128
186
|
|
129
187
|
@abstractmethod
|
130
188
|
async def pop(self, index: int) -> Any:
|
189
|
+
"""
|
190
|
+
Remove and return an item from the memory at the specified index.
|
191
|
+
|
192
|
+
- **Args**:
|
193
|
+
- `index` (int): The index of the item to remove.
|
194
|
+
"""
|
131
195
|
pass
|
132
196
|
|
133
197
|
@abstractmethod
|
134
198
|
async def load(
|
135
199
|
self, snapshots: Union[Any, Sequence[Any]], reset_memory: bool = False
|
136
200
|
) -> None:
|
201
|
+
"""
|
202
|
+
Load one or more snapshots into the memory.
|
203
|
+
|
204
|
+
- **Args**:
|
205
|
+
- `snapshots` (Union[Any, Sequence[Any]]): The snapshot(s) to load.
|
206
|
+
- `reset_memory` (bool, optional): Whether to clear existing memory before loading. Defaults to False.
|
207
|
+
"""
|
137
208
|
raise NotImplementedError
|
138
209
|
|
139
210
|
@abstractmethod
|
140
211
|
async def export(
|
141
212
|
self,
|
142
213
|
) -> Sequence[Any]:
|
214
|
+
"""
|
215
|
+
Export all items currently stored in the memory.
|
216
|
+
|
217
|
+
- **Returns**:
|
218
|
+
- `Sequence[Any]`: A sequence of memory items.
|
219
|
+
"""
|
143
220
|
raise NotImplementedError
|
144
221
|
|
145
222
|
@abstractmethod
|
146
223
|
async def reset(self) -> None:
|
224
|
+
"""
|
225
|
+
Reset the memory by clearing all items.
|
226
|
+
"""
|
147
227
|
raise NotImplementedError
|
148
228
|
|
149
229
|
def _fetch_recent_memory(self, recent_n: Optional[int] = None) -> Sequence[Any]:
|
230
|
+
"""
|
231
|
+
Fetch the most recent N memory entries.
|
232
|
+
|
233
|
+
- **Args**:
|
234
|
+
- `recent_n` (Optional[int], optional): The number of recent entries to fetch. If not provided, returns all available entries.
|
235
|
+
|
236
|
+
- **Returns**:
|
237
|
+
- `Sequence[Any]`: A sequence of recent memory keys.
|
238
|
+
"""
|
150
239
|
_memories = self._memories
|
151
240
|
_list_units = list(_memories.keys())
|
152
241
|
if recent_n is None:
|
@@ -160,10 +249,27 @@ class MemoryBase(ABC):
|
|
160
249
|
# interact
|
161
250
|
@abstractmethod
|
162
251
|
async def get(self, key: Any):
|
252
|
+
"""
|
253
|
+
Retrieve an item from the memory by its key.
|
254
|
+
|
255
|
+
- **Args**:
|
256
|
+
- `key` (Any): The key of the item to retrieve.
|
257
|
+
|
258
|
+
- **Returns**:
|
259
|
+
- `Any`: The retrieved memory item.
|
260
|
+
"""
|
163
261
|
raise NotImplementedError
|
164
262
|
|
165
263
|
@abstractmethod
|
166
264
|
async def update(self, key: Any, value: Any, store_snapshot: bool):
|
265
|
+
"""
|
266
|
+
Update an existing item in the memory with a new value.
|
267
|
+
|
268
|
+
- **Args**:
|
269
|
+
- `key` (Any): The key of the item to update.
|
270
|
+
- `value` (Any): The new value for the item.
|
271
|
+
- `store_snapshot` (bool): Whether to store a snapshot after updating.
|
272
|
+
"""
|
167
273
|
raise NotImplementedError
|
168
274
|
|
169
275
|
def __getitem__(self, index: Any) -> Any:
|
pycityagent/memory/profile.py
CHANGED
@@ -111,19 +111,19 @@ class ProfileMemory(MemoryBase):
|
|
111
111
|
_latest_memory: ProfileMemoryUnit = _latest_memories[-1]
|
112
112
|
return _latest_memory[key]
|
113
113
|
|
114
|
-
@lock_decorator
|
115
|
-
async def get_top_k(
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
) -> Union[Sequence[Any], Any]:
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
114
|
+
# @lock_decorator
|
115
|
+
# async def get_top_k(
|
116
|
+
# self,
|
117
|
+
# key: Any,
|
118
|
+
# metric: Callable[[Any], Any],
|
119
|
+
# top_k: Optional[int] = None,
|
120
|
+
# preserve_order: bool = True,
|
121
|
+
# ) -> Union[Sequence[Any], Any]:
|
122
|
+
# _latest_memories = self._fetch_recent_memory()
|
123
|
+
# _latest_memory: ProfileMemoryUnit = _latest_memories[-1]
|
124
|
+
# _top_k = await _latest_memory.top_k_values(key, metric, top_k, preserve_order)
|
125
|
+
|
126
|
+
# return _top_k
|
127
127
|
|
128
128
|
@lock_decorator
|
129
129
|
async def update(self, key: Any, value: Any, store_snapshot: bool = False):
|
@@ -107,19 +107,19 @@ class DynamicMemory(MemoryBase):
|
|
107
107
|
|
108
108
|
return _latest_memory[key]
|
109
109
|
|
110
|
-
@lock_decorator
|
111
|
-
async def get_top_k(
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
) -> Union[Sequence[Any], Any]:
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
110
|
+
# @lock_decorator
|
111
|
+
# async def get_top_k(
|
112
|
+
# self,
|
113
|
+
# key: Any,
|
114
|
+
# metric: Callable[[Any], Any],
|
115
|
+
# top_k: Optional[int] = None,
|
116
|
+
# preserve_order: bool = True,
|
117
|
+
# ) -> Union[Sequence[Any], Any]:
|
118
|
+
# _latest_memories = self._fetch_recent_memory()
|
119
|
+
# _latest_memory: DynamicMemoryUnit = _latest_memories[-1]
|
120
|
+
# _top_k = await _latest_memory.top_k_values(key, metric, top_k, preserve_order)
|
121
|
+
|
122
|
+
# return _top_k
|
123
123
|
|
124
124
|
@lock_decorator
|
125
125
|
async def update(self, key: Any, value: Any, store_snapshot: bool = False):
|
pycityagent/memory/state.py
CHANGED
@@ -115,20 +115,20 @@ class StateMemory(MemoryBase):
|
|
115
115
|
|
116
116
|
return _latest_memory[key]
|
117
117
|
|
118
|
-
@lock_decorator
|
119
|
-
async def get_top_k(
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
) -> Union[Sequence[Any], Any]:
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
118
|
+
# @lock_decorator
|
119
|
+
# async def get_top_k(
|
120
|
+
# self,
|
121
|
+
# key: Any,
|
122
|
+
# metric: Callable[[Any], Any],
|
123
|
+
# top_k: Optional[int] = None,
|
124
|
+
# preserve_order: bool = True,
|
125
|
+
# ) -> Union[Sequence[Any], Any]:
|
126
|
+
|
127
|
+
# _latest_memories = self._fetch_recent_memory()
|
128
|
+
# _latest_memory: StateMemoryUnit = _latest_memories[-1]
|
129
|
+
# _top_k = await _latest_memory.top_k_values(key, metric, top_k, preserve_order)
|
130
|
+
|
131
|
+
# return _top_k
|
132
132
|
|
133
133
|
@lock_decorator
|
134
134
|
async def update(self, key: Any, value: Any, store_snapshot: bool = False):
|