pycityagent 2.0.0a66__cp311-cp311-macosx_11_0_arm64.whl → 2.0.0a67__cp311-cp311-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 (87) hide show
  1. pycityagent/agent/agent.py +157 -57
  2. pycityagent/agent/agent_base.py +316 -43
  3. pycityagent/cityagent/bankagent.py +49 -9
  4. pycityagent/cityagent/blocks/__init__.py +1 -2
  5. pycityagent/cityagent/blocks/cognition_block.py +54 -31
  6. pycityagent/cityagent/blocks/dispatcher.py +22 -17
  7. pycityagent/cityagent/blocks/economy_block.py +46 -32
  8. pycityagent/cityagent/blocks/mobility_block.py +130 -100
  9. pycityagent/cityagent/blocks/needs_block.py +101 -44
  10. pycityagent/cityagent/blocks/other_block.py +42 -33
  11. pycityagent/cityagent/blocks/plan_block.py +59 -42
  12. pycityagent/cityagent/blocks/social_block.py +167 -116
  13. pycityagent/cityagent/blocks/utils.py +13 -6
  14. pycityagent/cityagent/firmagent.py +17 -35
  15. pycityagent/cityagent/governmentagent.py +3 -3
  16. pycityagent/cityagent/initial.py +79 -44
  17. pycityagent/cityagent/memory_config.py +108 -88
  18. pycityagent/cityagent/message_intercept.py +0 -4
  19. pycityagent/cityagent/metrics.py +41 -0
  20. pycityagent/cityagent/nbsagent.py +24 -36
  21. pycityagent/cityagent/societyagent.py +7 -3
  22. pycityagent/cli/wrapper.py +2 -2
  23. pycityagent/economy/econ_client.py +407 -81
  24. pycityagent/environment/__init__.py +0 -3
  25. pycityagent/environment/sim/__init__.py +0 -3
  26. pycityagent/environment/sim/aoi_service.py +2 -2
  27. pycityagent/environment/sim/client.py +3 -31
  28. pycityagent/environment/sim/clock_service.py +2 -2
  29. pycityagent/environment/sim/lane_service.py +8 -8
  30. pycityagent/environment/sim/light_service.py +8 -8
  31. pycityagent/environment/sim/pause_service.py +9 -10
  32. pycityagent/environment/sim/person_service.py +20 -20
  33. pycityagent/environment/sim/road_service.py +2 -2
  34. pycityagent/environment/sim/sim_env.py +21 -5
  35. pycityagent/environment/sim/social_service.py +4 -4
  36. pycityagent/environment/simulator.py +249 -27
  37. pycityagent/environment/utils/__init__.py +2 -2
  38. pycityagent/environment/utils/geojson.py +2 -2
  39. pycityagent/environment/utils/grpc.py +4 -4
  40. pycityagent/environment/utils/map_utils.py +2 -2
  41. pycityagent/llm/embeddings.py +147 -28
  42. pycityagent/llm/llm.py +122 -77
  43. pycityagent/llm/llmconfig.py +5 -0
  44. pycityagent/llm/utils.py +4 -0
  45. pycityagent/memory/__init__.py +0 -4
  46. pycityagent/memory/const.py +2 -2
  47. pycityagent/memory/faiss_query.py +140 -61
  48. pycityagent/memory/memory.py +393 -90
  49. pycityagent/memory/memory_base.py +140 -34
  50. pycityagent/memory/profile.py +13 -13
  51. pycityagent/memory/self_define.py +13 -13
  52. pycityagent/memory/state.py +14 -14
  53. pycityagent/message/message_interceptor.py +253 -3
  54. pycityagent/message/messager.py +133 -6
  55. pycityagent/metrics/mlflow_client.py +47 -4
  56. pycityagent/pycityagent-sim +0 -0
  57. pycityagent/pycityagent-ui +0 -0
  58. pycityagent/simulation/__init__.py +3 -2
  59. pycityagent/simulation/agentgroup.py +145 -52
  60. pycityagent/simulation/simulation.py +257 -62
  61. pycityagent/survey/manager.py +45 -3
  62. pycityagent/survey/models.py +42 -2
  63. pycityagent/tools/__init__.py +1 -2
  64. pycityagent/tools/tool.py +93 -69
  65. pycityagent/utils/avro_schema.py +2 -2
  66. pycityagent/utils/parsers/code_block_parser.py +1 -1
  67. pycityagent/utils/parsers/json_parser.py +2 -2
  68. pycityagent/utils/parsers/parser_base.py +2 -2
  69. pycityagent/workflow/block.py +64 -13
  70. pycityagent/workflow/prompt.py +31 -23
  71. pycityagent/workflow/trigger.py +91 -24
  72. {pycityagent-2.0.0a66.dist-info → pycityagent-2.0.0a67.dist-info}/METADATA +2 -2
  73. pycityagent-2.0.0a67.dist-info/RECORD +97 -0
  74. pycityagent/environment/interact/__init__.py +0 -0
  75. pycityagent/environment/interact/interact.py +0 -198
  76. pycityagent/environment/message/__init__.py +0 -0
  77. pycityagent/environment/sence/__init__.py +0 -0
  78. pycityagent/environment/sence/static.py +0 -416
  79. pycityagent/environment/sidecar/__init__.py +0 -8
  80. pycityagent/environment/sidecar/sidecarv2.py +0 -109
  81. pycityagent/environment/sim/economy_services.py +0 -192
  82. pycityagent/metrics/utils/const.py +0 -0
  83. pycityagent-2.0.0a66.dist-info/RECORD +0 -105
  84. {pycityagent-2.0.0a66.dist-info → pycityagent-2.0.0a67.dist-info}/LICENSE +0 -0
  85. {pycityagent-2.0.0a66.dist-info → pycityagent-2.0.0a67.dist-info}/WHEEL +0 -0
  86. {pycityagent-2.0.0a66.dist-info → pycityagent-2.0.0a67.dist-info}/entry_points.txt +0 -0
  87. {pycityagent-2.0.0a66.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
- self,
80
- key: Any,
81
- metric: Callable[[Any], Any],
82
- top_k: Optional[int] = None,
83
- preserve_order: bool = True,
84
- ) -> Union[Sequence[Any], Any]:
85
- await self._lock.acquire()
86
- values = self._content[key]
87
- if not isinstance(values, Sequence):
88
- logger.warning(
89
- f"the value stored in key `{key}` is not `sequence`, return value `{values}` instead!"
90
- )
91
- return values
92
- else:
93
- _values_with_idx = [(i, v) for i, v in enumerate(values)]
94
- _sorted_values_with_idx = sorted(
95
- _values_with_idx, key=lambda i_v: -metric(i_v[1])
96
- )
97
- top_k = len(values) if top_k is None else top_k
98
- if len(_sorted_values_with_idx) < top_k:
99
- logger.debug(
100
- f"Length of values {len(_sorted_values_with_idx)} is less than top_k {top_k}, returning all values."
101
- )
102
- self._lock.release()
103
- if preserve_order:
104
- return [
105
- i_v[1]
106
- for i_v in sorted(
107
- _sorted_values_with_idx[:top_k], key=lambda i_v: i_v[0]
108
- )
109
- ]
110
- else:
111
- return [i_v[1] for i_v in _sorted_values_with_idx[:top_k]]
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:
@@ -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
- 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
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
- 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
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):
@@ -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
- 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
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):