pycityagent 2.0.0a51__cp310-cp310-macosx_11_0_arm64.whl → 2.0.0a53__cp310-cp310-macosx_11_0_arm64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. pycityagent/agent/agent.py +48 -62
  2. pycityagent/agent/agent_base.py +66 -53
  3. pycityagent/cityagent/bankagent.py +5 -7
  4. pycityagent/cityagent/blocks/__init__.py +0 -2
  5. pycityagent/cityagent/blocks/cognition_block.py +149 -172
  6. pycityagent/cityagent/blocks/economy_block.py +90 -129
  7. pycityagent/cityagent/blocks/mobility_block.py +56 -29
  8. pycityagent/cityagent/blocks/needs_block.py +163 -145
  9. pycityagent/cityagent/blocks/other_block.py +17 -9
  10. pycityagent/cityagent/blocks/plan_block.py +44 -56
  11. pycityagent/cityagent/blocks/social_block.py +70 -51
  12. pycityagent/cityagent/blocks/utils.py +2 -0
  13. pycityagent/cityagent/firmagent.py +6 -7
  14. pycityagent/cityagent/governmentagent.py +7 -9
  15. pycityagent/cityagent/memory_config.py +48 -48
  16. pycityagent/cityagent/nbsagent.py +6 -29
  17. pycityagent/cityagent/societyagent.py +204 -119
  18. pycityagent/environment/sim/client.py +10 -1
  19. pycityagent/environment/sim/clock_service.py +2 -2
  20. pycityagent/environment/sim/pause_service.py +61 -0
  21. pycityagent/environment/simulator.py +17 -12
  22. pycityagent/llm/embeddings.py +0 -24
  23. pycityagent/memory/faiss_query.py +29 -26
  24. pycityagent/memory/memory.py +720 -272
  25. pycityagent/pycityagent-sim +0 -0
  26. pycityagent/simulation/agentgroup.py +92 -99
  27. pycityagent/simulation/simulation.py +115 -40
  28. pycityagent/tools/tool.py +7 -10
  29. pycityagent/workflow/block.py +11 -4
  30. {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/METADATA +2 -2
  31. {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/RECORD +35 -35
  32. {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/WHEEL +1 -1
  33. pycityagent/cityagent/blocks/time_block.py +0 -116
  34. {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/LICENSE +0 -0
  35. {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/entry_points.txt +0 -0
  36. {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/top_level.txt +0 -0
@@ -20,9 +20,8 @@ from ..cityagent import (BankAgent, FirmAgent, GovernmentAgent, NBSAgent,
20
20
  from ..cityagent.initial import bind_agent_info, initialize_social_network
21
21
  from ..environment.simulator import Simulator
22
22
  from ..llm import SimpleEmbedding
23
- from ..memory import Memory
24
23
  from ..message.messager import Messager
25
- from ..metrics import init_mlflow_connection
24
+ from ..metrics import MlflowClient, init_mlflow_connection
26
25
  from ..survey import Survey
27
26
  from ..utils import TO_UPDATE_EXP_INFO_KEYS_AND_TYPES
28
27
  from .agentgroup import AgentGroup
@@ -39,6 +38,7 @@ class AgentSimulation:
39
38
  config: dict,
40
39
  agent_class: Union[None, type[Agent], list[type[Agent]]] = None,
41
40
  agent_config_file: Optional[dict] = None,
41
+ metric_extractor: Optional[list[tuple[int, Callable]]] = None,
42
42
  enable_economy: bool = True,
43
43
  agent_prefix: str = "agent_",
44
44
  exp_name: str = "default_experiment",
@@ -89,6 +89,8 @@ class AgentSimulation:
89
89
  self._user_survey_topics: dict[str, str] = {}
90
90
  self._user_interview_topics: dict[str, str] = {}
91
91
  self._loop = asyncio.get_event_loop()
92
+ self._total_steps = 0
93
+ self._simulator_day = 0
92
94
  # self._last_asyncio_pg_task = None # 将SQL写入的IO隐藏到计算任务后
93
95
 
94
96
  self._messager = Messager.remote(
@@ -102,6 +104,7 @@ class AgentSimulation:
102
104
  _storage_config: dict[str, Any] = config.get("storage", {})
103
105
  if _storage_config is None:
104
106
  _storage_config = {}
107
+
105
108
  # avro
106
109
  _avro_config: dict[str, Any] = _storage_config.get("avro", {})
107
110
  self._enable_avro = _avro_config.get("enabled", False)
@@ -112,6 +115,27 @@ class AgentSimulation:
112
115
  self._avro_path = Path(_avro_config["path"]) / f"{self.exp_id}"
113
116
  self._avro_path.mkdir(parents=True, exist_ok=True)
114
117
 
118
+ # mlflow
119
+ _mlflow_config: dict[str, Any] = config.get("metric_request", {}).get("mlflow")
120
+ mlflow_run_id, _ = init_mlflow_connection(
121
+ config=_mlflow_config,
122
+ mlflow_run_name=f"EXP_{self.exp_name}_{1000*int(time.time())}",
123
+ experiment_name=self.exp_name,
124
+ )
125
+ if _mlflow_config:
126
+ logger.info(f"-----Creating Mlflow client...")
127
+ self.mlflow_client = MlflowClient(
128
+ config=_mlflow_config,
129
+ mlflow_run_name=f"EXP_{exp_name}_{1000*int(time.time())}",
130
+ experiment_name=exp_name,
131
+ run_id=mlflow_run_id,
132
+ )
133
+ self.metric_extractor = metric_extractor
134
+ else:
135
+ logger.warning("Mlflow is not enabled, NO MLFLOW STORAGE")
136
+ self.mlflow_client = None
137
+ self.metric_extractor = None
138
+
115
139
  # pg
116
140
  _pgsql_config: dict[str, Any] = _storage_config.get("pgsql", {})
117
141
  self._enable_pgsql = _pgsql_config.get("enabled", False)
@@ -167,11 +191,11 @@ class AgentSimulation:
167
191
  - workflow:
168
192
  - list[Step]
169
193
  - Step:
170
- - type: str, "step", "run", "interview", "survey", "intervene"
194
+ - type: str, "step", "run", "interview", "survey", "intervene", "pause", "resume"
171
195
  - day: int if type is "run", else None
172
- - time: int if type is "step", else None
196
+ - times: int if type is "step", else None
173
197
  - description: Optional[str], description of the step
174
- - step_func: Optional[Callable[AgentSimulation, None]], only used when type is "interview", "survey" and "intervene"
198
+ - func: Optional[Callable[AgentSimulation, None]], only used when type is "interview", "survey" and "intervene"
175
199
  - logging_level: Optional[int]
176
200
  - exp_name: Optional[str]
177
201
  """
@@ -224,10 +248,15 @@ class AgentSimulation:
224
248
  if step["type"] == "run":
225
249
  await simulation.run(step.get("day", 1))
226
250
  elif step["type"] == "step":
227
- # await simulation.step(step.get("time", 1))
228
- await simulation.step()
251
+ times = step.get("times", 1)
252
+ for _ in range(times):
253
+ await simulation.step()
254
+ elif step["type"] == "pause":
255
+ await simulation.pause_simulator()
256
+ elif step["type"] == "resume":
257
+ await simulation.resume_simulator()
229
258
  else:
230
- await step["step_func"](simulation)
259
+ await step["func"](simulation)
231
260
  logger.info("Simulation finished")
232
261
 
233
262
  @property
@@ -331,6 +360,12 @@ class AgentSimulation:
331
360
  # 如果没有发生异常且状态不是错误,则更新为完成
332
361
  await self._update_exp_status(2)
333
362
 
363
+ async def pause_simulator(self):
364
+ await self._simulator.pause()
365
+
366
+ async def resume_simulator(self):
367
+ await self._simulator.resume()
368
+
334
369
  async def init_agents(
335
370
  self,
336
371
  agent_count: Union[int, list[int]],
@@ -353,12 +388,12 @@ class AgentSimulation:
353
388
  raise ValueError("agent_class和agent_count的长度不一致")
354
389
 
355
390
  if memory_config_func is None:
356
- logger.warning(
357
- "memory_config_func is None, using default memory config function"
358
- )
359
391
  memory_config_func = self.default_memory_config_func
360
392
 
361
393
  elif not isinstance(memory_config_func, list):
394
+ logger.warning(
395
+ "memory_config_func is not a list, using specific memory config function"
396
+ )
362
397
  memory_config_func = [memory_config_func]
363
398
 
364
399
  if len(memory_config_func) != len(agent_count):
@@ -465,16 +500,6 @@ class AgentSimulation:
465
500
  )
466
501
  )
467
502
 
468
- # 初始化mlflow连接
469
- _mlflow_config = self.config.get("metric_request", {}).get("mlflow")
470
- if _mlflow_config:
471
- mlflow_run_id, _ = init_mlflow_connection(
472
- config=_mlflow_config,
473
- mlflow_run_name=f"EXP_{self.exp_name}_{1000*int(time.time())}",
474
- experiment_name=self.exp_name,
475
- )
476
- else:
477
- mlflow_run_id = None
478
503
  # 建表
479
504
  if self.enable_pgsql:
480
505
  _num_workers = min(1, pg_sql_writers)
@@ -505,12 +530,10 @@ class AgentSimulation:
505
530
  memory_config_function_group,
506
531
  self.config,
507
532
  self.exp_id,
508
- self.exp_name,
509
533
  self.enable_avro,
510
534
  self.avro_path,
511
535
  self.enable_pgsql,
512
536
  _workers[i % _num_workers], # type:ignore
513
- mlflow_run_id, # type:ignore
514
537
  embedding_model,
515
538
  self.logging_level,
516
539
  config_file,
@@ -536,16 +559,20 @@ class AgentSimulation:
536
559
  self._type2group[agent_type].append(group)
537
560
 
538
561
  # 并行初始化所有组的agents
562
+ await self.resume_simulator()
539
563
  init_tasks = []
540
564
  for group in self._groups.values():
541
565
  init_tasks.append(group.init_agents.remote())
542
566
  ray.get(init_tasks)
567
+ await self.messager.connect.remote()
568
+ await self.messager.subscribe.remote([(f"exps/{self.exp_id}/user_payback", 1)], [self.exp_id])
569
+ await self.messager.start_listening.remote()
543
570
 
544
- async def gather(self, content: str):
571
+ async def gather(self, content: str, target_agent_uuids: Optional[list[str]] = None):
545
572
  """收集智能体的特定信息"""
546
573
  gather_tasks = []
547
574
  for group in self._groups.values():
548
- gather_tasks.append(group.gather.remote(content))
575
+ gather_tasks.append(group.gather.remote(content, target_agent_uuids))
549
576
  return await asyncio.gather(*gather_tasks)
550
577
 
551
578
  async def filter(
@@ -585,7 +612,6 @@ class AgentSimulation:
585
612
  self, survey: Survey, agent_uuids: Optional[list[str]] = None
586
613
  ):
587
614
  """发送问卷"""
588
- await self.messager.connect()
589
615
  survey_dict = survey.to_dict()
590
616
  if agent_uuids is None:
591
617
  agent_uuids = self._agent_uuids
@@ -599,13 +625,20 @@ class AgentSimulation:
599
625
  }
600
626
  for uuid in agent_uuids:
601
627
  topic = self._user_survey_topics[uuid]
602
- await self.messager.send_message(topic, payload)
628
+ await self.messager.send_message.remote(topic, payload)
629
+ remain_payback = len(agent_uuids)
630
+ while True:
631
+ messages = await self.messager.fetch_messages.remote()
632
+ logger.info(f"Received {len(messages)} payback messages [survey]")
633
+ remain_payback -= len(messages)
634
+ if remain_payback <= 0:
635
+ break
636
+ await asyncio.sleep(3)
603
637
 
604
638
  async def send_interview_message(
605
639
  self, content: str, agent_uuids: Union[str, list[str]]
606
640
  ):
607
641
  """发送采访消息"""
608
- await self.messager.connect()
609
642
  _date_time = datetime.now(timezone.utc)
610
643
  payload = {
611
644
  "from": "none",
@@ -617,24 +650,67 @@ class AgentSimulation:
617
650
  agent_uuids = [agent_uuids]
618
651
  for uuid in agent_uuids:
619
652
  topic = self._user_chat_topics[uuid]
620
- await self.messager.send_message(topic, payload)
653
+ await self.messager.send_message.remote(topic, payload)
654
+ remain_payback = len(agent_uuids)
655
+ while True:
656
+ messages = await self.messager.fetch_messages.remote()
657
+ logger.info(f"Received {len(messages)} payback messages [interview]")
658
+ remain_payback -= len(messages)
659
+ if remain_payback <= 0:
660
+ break
661
+ await asyncio.sleep(3)
662
+
663
+ async def extract_metric(self, metric_extractor: list[Callable]):
664
+ """提取指标"""
665
+ for metric_extractor in metric_extractor:
666
+ await metric_extractor(self)
621
667
 
622
668
  async def step(self):
623
- """运行一步, 即每个智能体执行一次forward"""
669
+ """Run one step, each agent execute one forward"""
624
670
  try:
671
+ # check whether insert agents
672
+ simulator_day = await self._simulator.get_simulator_day()
673
+ print(f"simulator_day: {simulator_day}, self._simulator_day: {self._simulator_day}")
674
+ need_insert_agents = False
675
+ if simulator_day > self._simulator_day:
676
+ need_insert_agents = True
677
+ self._simulator_day = simulator_day
678
+ if need_insert_agents:
679
+ await self.resume_simulator()
680
+ insert_tasks = []
681
+ for group in self._groups.values():
682
+ insert_tasks.append(group.insert_agents.remote())
683
+ await asyncio.gather(*insert_tasks)
684
+
685
+ # step
625
686
  tasks = []
626
687
  for group in self._groups.values():
627
688
  tasks.append(group.step.remote())
628
689
  await asyncio.gather(*tasks)
690
+ # save
691
+ simulator_day = await self._simulator.get_simulator_day()
692
+ simulator_time = int(await self._simulator.get_time())
693
+ save_tasks = []
694
+ for group in self._groups.values():
695
+ save_tasks.append(group.save.remote(simulator_day, simulator_time))
696
+ await asyncio.gather(*save_tasks)
697
+ self._total_steps += 1
698
+ if self.metric_extractor is not None:
699
+ print(f"total_steps: {self._total_steps}, excute metric")
700
+ to_excute_metric = [
701
+ metric[1] for metric in self.metric_extractor if self._total_steps % metric[0] == 0
702
+ ]
703
+ await self.extract_metric(to_excute_metric)
629
704
  except Exception as e:
630
- logger.error(f"运行错误: {str(e)}")
631
- raise
705
+ import traceback
706
+ logger.error(f"模拟器运行错误: {str(e)}\n{traceback.format_exc()}")
707
+ raise RuntimeError(str(e)) from e
632
708
 
633
709
  async def run(
634
710
  self,
635
711
  day: int = 1,
636
712
  ):
637
- """运行模拟器"""
713
+ """Run the simulation by days"""
638
714
  try:
639
715
  self._exp_info["num_day"] += day
640
716
  await self._update_exp_status(1) # 更新状态为运行中
@@ -645,13 +721,12 @@ class AgentSimulation:
645
721
  monitor_task = asyncio.create_task(self._monitor_exp_status(stop_event))
646
722
 
647
723
  try:
648
- for _ in range(day):
649
- tasks = []
650
- for group in self._groups.values():
651
- tasks.append(group.run.remote())
652
- # 等待所有group运行完成
653
- await asyncio.gather(*tasks)
654
-
724
+ end_time = await self._simulator.get_time() + day * 24 * 3600
725
+ while True:
726
+ current_time = await self._simulator.get_time()
727
+ if current_time >= end_time:
728
+ break
729
+ await self.step()
655
730
  finally:
656
731
  # 设置停止事件
657
732
  stop_event.set()
pycityagent/tools/tool.py CHANGED
@@ -119,7 +119,7 @@ class SencePOI(Tool):
119
119
  if agent.memory is None or agent.simulator is None:
120
120
  raise ValueError("Memory or Simulator is not set.")
121
121
  if radius is None and category_prefix is None:
122
- position = await agent.memory.get("position")
122
+ position = await agent.status.get("position")
123
123
  resp = []
124
124
  for prefix in self.category_prefix:
125
125
  resp += agent.simulator.map.query_pois(
@@ -146,17 +146,15 @@ class UpdateWithSimulator(Tool):
146
146
  agent = self.agent
147
147
  if agent._simulator is None:
148
148
  return
149
- if not agent._has_bound_to_simulator:
150
- await agent._bind_to_simulator() # type: ignore
151
149
  simulator = agent.simulator
152
- memory = agent.memory
153
- person_id = await memory.get("id")
150
+ status = agent.status
151
+ person_id = await status.get("id")
154
152
  resp = await simulator.get_person(person_id)
155
153
  resp_dict = resp["person"]
156
154
  for k, v in resp_dict.get("motion", {}).items():
157
155
  try:
158
- await memory.get(k)
159
- await memory.update(
156
+ await status.get(k)
157
+ await status.update(
160
158
  k, v, mode="replace", protect_llm_read_only_fields=False
161
159
  )
162
160
  except KeyError as e:
@@ -183,9 +181,9 @@ class ResetAgentPosition(Tool):
183
181
  s: Optional[float] = None,
184
182
  ):
185
183
  agent = self.agent
186
- memory = agent.memory
184
+ status = agent.status
187
185
  await agent.simulator.reset_person_position(
188
- person_id=await memory.get("id"),
186
+ person_id=await status.get("id"),
189
187
  aoi_id=aoi_id,
190
188
  poi_id=poi_id,
191
189
  lane_id=lane_id,
@@ -233,7 +231,6 @@ class ExportMlflowMetrics(Tool):
233
231
  if clear_cache:
234
232
  await self._clear_cache()
235
233
 
236
- @lock_decorator
237
234
  async def _clear_cache(
238
235
  self,
239
236
  ):
@@ -146,6 +146,7 @@ def trigger_class():
146
146
  class Block:
147
147
  configurable_fields: list[str] = []
148
148
  default_values: dict[str, Any] = {}
149
+ fields_description: dict[str, str] = {}
149
150
 
150
151
  def __init__(
151
152
  self,
@@ -173,10 +174,16 @@ class Block:
173
174
 
174
175
  @classmethod
175
176
  def export_class_config(cls) -> dict[str, str]:
176
- return {
177
- field: cls.default_values.get(field, "default_value")
178
- for field in cls.configurable_fields
179
- }
177
+ return (
178
+ {
179
+ field: cls.default_values.get(field, "default_value")
180
+ for field in cls.configurable_fields
181
+ },
182
+ {
183
+ field: cls.fields_description.get(field, "")
184
+ for field in cls.configurable_fields
185
+ }
186
+ )
180
187
 
181
188
  @classmethod
182
189
  def import_config(cls, config: dict[str, Union[str, dict]]) -> Block:
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: pycityagent
3
- Version: 2.0.0a51
3
+ Version: 2.0.0a53
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,4 +1,10 @@
1
- pycityagent/pycityagent-sim,sha256=n96jlVZRINlBec5SPOGAdUmeLWMoEKGgoH29iOVJ0wE,34081890
1
+ pycityagent-2.0.0a53.dist-info/RECORD,,
2
+ pycityagent-2.0.0a53.dist-info/LICENSE,sha256=n2HPXiupinpyHMnIkbCf3OTYd3KMqbmldu1e7av0CAU,1084
3
+ pycityagent-2.0.0a53.dist-info/WHEEL,sha256=ezfKMaDztqf77C8lvQ0NCnZxkTaOaKLprqJ8q932MhU,109
4
+ pycityagent-2.0.0a53.dist-info/entry_points.txt,sha256=BZcne49AAIFv-hawxGnPbblea7X3MtAtoPyDX8L4OC4,132
5
+ pycityagent-2.0.0a53.dist-info/top_level.txt,sha256=yOmeu6cSXmiUtScu53a3s0p7BGtLMaV0aff83EHCTic,43
6
+ pycityagent-2.0.0a53.dist-info/METADATA,sha256=7iSDzvMMlwpY7leIIjVm-3V7lZ92R0uHetTQlk0PCb0,9110
7
+ pycityagent/pycityagent-sim,sha256=1Nu-QYC0AuZyVWciGNa2XkYsUntbwAS15Bo7l-y6eok,35449490
2
8
  pycityagent/__init__.py,sha256=PUKWTXc-xdMG7px8oTNclodsILUgypANj2Z647sY63k,808
3
9
  pycityagent/pycityagent-ui,sha256=cHZjqtrQ4Fh4qtRahFNCNbT2DNHLmUexiDAa-72Z3RQ,40333378
4
10
  pycityagent/metrics/mlflow_client.py,sha256=g_tHxWkWTDijtbGL74-HmiYzWVKb1y8-w12QrY9jL30,4449
@@ -7,24 +13,24 @@ pycityagent/metrics/utils/const.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
7
13
  pycityagent/economy/__init__.py,sha256=aonY4WHnx-6EGJ4WKrx4S-2jAkYNLtqUA04jp6q8B7w,75
8
14
  pycityagent/economy/econ_client.py,sha256=GuHK9ZBnhqW3Z7F8ViDJn_iN73yOBbbwFyJv1wLEBDk,12211
9
15
  pycityagent/tools/__init__.py,sha256=XtdtGyWeFyK1YOUvWkykBWxemtmwQjWUIuuyU1-gosQ,261
10
- pycityagent/tools/tool.py,sha256=JD5APkoWqnS46gyimI17no2fPknjwkk173AFt-oFv_c,8778
16
+ pycityagent/tools/tool.py,sha256=D-ESFlX7EESm5mcvs2zRlGEQTzXbVfQc8G7Vpz8TmAw,8651
11
17
  pycityagent/llm/llmconfig.py,sha256=4Ylf4OFSBEFy8jrOneeX0HvPhWEaF5jGvy1HkXK08Ro,436
12
18
  pycityagent/llm/__init__.py,sha256=iWs6FLgrbRVIiqOf4ILS89gkVCTvS7HFC3vG-MWuyko,205
13
19
  pycityagent/llm/llm.py,sha256=owTYuXmnHZnvXaAvwiiyD511P3wpU3K04xZArhhiJF0,15700
14
- pycityagent/llm/embeddings.py,sha256=Nhf_tUIlaYJAZ93wW2QTCtS1wq7e8fUgdn2JketEAuQ,7600
20
+ pycityagent/llm/embeddings.py,sha256=2_P4TWm3sJKFdGDx2Q1a2AEapFopDctIXsGuntvmP6E,6816
15
21
  pycityagent/llm/utils.py,sha256=hoNPhvomb1u6lhFX0GctFipw74hVKb7bvUBDqwBzBYw,160
16
- pycityagent/memory/memory.py,sha256=RV54r9uE3H7RIfz5ifaeXiD7RrOJotxJNhAOguZrYUk,17273
22
+ pycityagent/memory/memory.py,sha256=suU6mZIYvGySQGyNrYiqdobuTgjSHyI_PahIeRVShiQ,34506
17
23
  pycityagent/memory/profile.py,sha256=q8ZS9IBmHCg_X1GONUvXK85P6tCepTKQgXKuvuXYNXw,5203
18
24
  pycityagent/memory/__init__.py,sha256=_Vfdo1HcLWsuuz34_i8e91nnLVYADpMlHHSVaB3xgIk,297
19
25
  pycityagent/memory/memory_base.py,sha256=QG_j3BxZvkadFEeE3uBR_kjl_xcXD1aHUVs8GEF3d6w,5654
20
26
  pycityagent/memory/self_define.py,sha256=vpZ6CIxR2grNXEIOScdpsSc59FBg0mOKelwQuTElbtQ,5200
21
27
  pycityagent/memory/utils.py,sha256=oJWLdPeJy_jcdKcDTo9JAH9kDZhqjoQhhv_zT9qWC0w,877
22
28
  pycityagent/memory/const.py,sha256=6zpJPJXWoH9-yf4RARYYff586agCoud9BRn7sPERB1g,932
23
- pycityagent/memory/faiss_query.py,sha256=Z0JS4udyPYCIzHMq464QtHscnswu35gh9fQptikAwkQ,12976
29
+ pycityagent/memory/faiss_query.py,sha256=V3rIw6d1_xcpNqZBbAYz3qfjVNE7NfJ7xOS5SibPtVU,13180
24
30
  pycityagent/memory/state.py,sha256=TYItiyDtehMEQaSBN7PpNrnNxdDM5jGppr9R9Ufv3kA,5134
25
- pycityagent/simulation/simulation.py,sha256=DkTYkdNknz2d7hIdYhxxLewUkYwmS9uOxnmEGTwbL_Q,26098
31
+ pycityagent/simulation/simulation.py,sha256=Fm6Y54gc4wAlVhMvqlUhbDRG0tKt6OpHdGsI8as9jqs,29662
26
32
  pycityagent/simulation/__init__.py,sha256=P5czbcg2d8S0nbbnsQXFIhwzO4CennAhZM8OmKvAeYw,194
27
- pycityagent/simulation/agentgroup.py,sha256=fMTN9xDC-PdTGZ4KCMovZeGjzv8HIQJ1AGVG7iAJnD4,29351
33
+ pycityagent/simulation/agentgroup.py,sha256=F1LJq-4xq3E7NmhmBT8j9wsJuuRmU5rGFzNgeOCwOSI,29701
28
34
  pycityagent/simulation/storage/pg.py,sha256=5itxKOkNPlOzN7z2_3oKU1ZK0uLTDugfld8ZkRbD69I,8407
29
35
  pycityagent/message/__init__.py,sha256=TCjazxqb5DVwbTu1fF0sNvaH_EPXVuj2XQ0p6W-QCLU,55
30
36
  pycityagent/message/messager.py,sha256=78K31EPKfC5IxbISc-Lc2babC7VOh9Vbe3c0sO-YDLA,3333
@@ -37,16 +43,16 @@ pycityagent/utils/parsers/__init__.py,sha256=AN2xgiPxszWK4rpX7zrqRsqNwfGF3WnCA5-
37
43
  pycityagent/utils/parsers/code_block_parser.py,sha256=Cs2Z_hm9VfNCpPPll1TwteaJF-HAQPs-3RApsOekFm4,1173
38
44
  pycityagent/utils/parsers/parser_base.py,sha256=KBKO4zLZPNdGjPAGqIus8LseZ8W3Tlt2y0QxqeCd25Q,1713
39
45
  pycityagent/utils/parsers/json_parser.py,sha256=tjwyPluYfkWgsvLi0hzfJwFhO3L6yQfZMKza20HaGrY,2911
40
- pycityagent/agent/agent_base.py,sha256=78J6np8XrFXTUXTC9x_O28EUmyWsdgtARd1KfNcC0cI,23073
46
+ pycityagent/agent/agent_base.py,sha256=FP2h3abIQ1Kp9qCzrzwa7tO82graDAWVg30HqYaQcPE,23620
41
47
  pycityagent/agent/__init__.py,sha256=U20yKu9QwSqAx_PHk5JwipfODkDfxONtumVfnsKjWFg,180
42
- pycityagent/agent/agent.py,sha256=8biuC44Yx4T8Fntlj_RGTlnKWwS0XDNkfYQrv5xXUwE,11548
48
+ pycityagent/agent/agent.py,sha256=rYUC6idFb2dCRa7H7-0ZFPn4UB7MSTigHXOjNSK5B2Y,10702
43
49
  pycityagent/cli/wrapper.py,sha256=2Tb52gOlEVgn11Ekt6ZkRXr_BGzte-EPyBKnR6g6hQ4,1143
44
50
  pycityagent/workflow/__init__.py,sha256=H08Ko3eliZvuuCMajbEri-IP4-SeswYU6UjHBNA4Ze0,490
45
51
  pycityagent/workflow/prompt.py,sha256=6jI0Rq54JLv3-IXqZLYug62vse10wTI83xvf4ZX42nk,2929
46
- pycityagent/workflow/block.py,sha256=3X6qzpYmmMyZyXA6Dxl4lS-mNR0eLzLoiRhHY-H1rzE,9667
52
+ pycityagent/workflow/block.py,sha256=REetWNdCF_fUGKVH-LWgDZ1lK2Bt0tJJ0kV20eWa4_A,9890
47
53
  pycityagent/workflow/trigger.py,sha256=Df-MOBEDWBbM-v0dFLQLXteLsipymT4n8vqexmK2GiQ,5643
48
54
  pycityagent/environment/__init__.py,sha256=awHxlOud-btWbk0FCS4RmGJ13W84oVCkbGfcrhKqihA,240
49
- pycityagent/environment/simulator.py,sha256=1OUfODDzM4EN6Lw_Wzq4KeQb-EpcUBioZYc9fxfSPn0,12070
55
+ pycityagent/environment/simulator.py,sha256=pARK08PzqiAysy6VOR2KZAgEG7auVzt_Tecy5MBL55Q,12157
50
56
  pycityagent/environment/message/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
57
  pycityagent/environment/utils/port.py,sha256=3OM6kSUt3PxvDUOlgyiendBtETaWU8Mzk_8H0TzTmYg,295
52
58
  pycityagent/environment/utils/grpc.py,sha256=6EJwKXXktIWb1NcUiJzIRmfrY0S03QAXXGcCDHqAT00,1998
@@ -60,44 +66,38 @@ pycityagent/environment/sence/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
60
66
  pycityagent/environment/sence/static.py,sha256=9s7jz8HitstTrk-GqpnVB26oPrjuTyNeL7hcoxjPhV4,29104
61
67
  pycityagent/environment/sidecar/__init__.py,sha256=RFbOf40aYBP4WwRpFkua5tlRE_OtMcMNyp1Lew_aaAU,235
62
68
  pycityagent/environment/sidecar/sidecarv2.py,sha256=beKlYZgt38EQbV1x6NWQo7xVXyB-5QHfbwJexyXu7Tg,3252
69
+ pycityagent/environment/sim/pause_service.py,sha256=DcAOVRxNkHGk4jyzFkxHMUPgp0Ck4mYHoPh6qxjhhLQ,1744
63
70
  pycityagent/environment/sim/person_service.py,sha256=5r1F2Itn7dKJ2U4hSLovrk5p4qy-2n77MTAv_OlTIwA,10673
64
71
  pycityagent/environment/sim/aoi_service.py,sha256=2UjvUTF4CW4E_L30IRcdwv6t_q1ZdXN3TTLOKSOaaXE,1230
65
72
  pycityagent/environment/sim/sim_env.py,sha256=HI1LcS_FotDKQ6vBnx0e49prXSABOfA20aU9KM-ZkCY,4625
66
73
  pycityagent/environment/sim/lane_service.py,sha256=N2dUe-3XuqqKLsNXt1k4NN8uV-J_ruo08yhaUd_hwOI,3916
67
- pycityagent/environment/sim/client.py,sha256=MHR7Hhu-Cr7B61d3K_QDpSJh4HrUU9JQf6Cu7_8pdsE,3493
74
+ pycityagent/environment/sim/client.py,sha256=j0f8qjR1nIava4VkoZNEPqW5h08WPdcC5wzM9DP3tIs,3772
68
75
  pycityagent/environment/sim/__init__.py,sha256=JVG6sSD2Hbohl1TtKjuQi7_M7tKMrFh9vl3QV3VA5O0,724
69
76
  pycityagent/environment/sim/social_service.py,sha256=9EFJAwVdUuUQkNkFRn9qZRDfD1brh2fqkvasnXUEBhQ,2014
70
77
  pycityagent/environment/sim/economy_services.py,sha256=xoc-1_H8JmQwJ24oWRS1fD-hGYtz2I-x6BOkQ4yENzU,7106
71
78
  pycityagent/environment/sim/light_service.py,sha256=KVwt7ii_iLGA7gANZe3n6-4RiiPQt1w9H6ZOoizMI04,4242
72
- pycityagent/environment/sim/clock_service.py,sha256=fgYXacf_-ixhVAn5uKUvqvemBS6A0oQK8JOZukkhXyY,1353
79
+ pycityagent/environment/sim/clock_service.py,sha256=gBUujvX_vIFMKVfcLRyk1GcpRRL606opLhNjCYL7Gt4,1363
73
80
  pycityagent/environment/sim/road_service.py,sha256=bKyn3_me0sGmaJVyF6eNeFbdU-9C1yWsa9L7pieDJzg,1285
74
81
  pycityagent/environment/interact/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
82
  pycityagent/environment/interact/interact.py,sha256=ifxPPzuHeqLHIZ_6zvfXMoBOnBsXNIP4bYp7OJ7pnEQ,6588
76
- pycityagent/cityagent/memory_config.py,sha256=6dkgqPczANUqZpqGXDOt7wrS6vHdFSMNkWvEVwo6VIQ,10672
77
- pycityagent/cityagent/bankagent.py,sha256=9J0c_r6m0OJH2KpXxeCWstLqZVpjQ67xuWmDTbVm7KM,2217
83
+ pycityagent/cityagent/memory_config.py,sha256=yZdtfXz5VaASKRUiiotHXGVc8axCiCsTNGvoSkTWWgk,10861
84
+ pycityagent/cityagent/bankagent.py,sha256=lr4GEcqt-iwA7DXoDry0WXkV6benmdaAyLpswqSpKlY,2120
78
85
  pycityagent/cityagent/__init__.py,sha256=gcBQ-a50XegFtjigQ7xDXRBZrywBKqifiQFSRnEF8gM,572
79
- pycityagent/cityagent/firmagent.py,sha256=Mtb58YfW3V696gXA6TRw1qUL1WIzthahDBv2X5x_Iyg,4176
80
- pycityagent/cityagent/nbsagent.py,sha256=SIOigR8eiSHC0Gi8kg32hLxsqPKDgCHWF0HA89EU7eA,5202
86
+ pycityagent/cityagent/firmagent.py,sha256=UVlNN0lpa4cC4PZVqYzQhbc5VJ2oGsA1731mhbCjnR8,4109
87
+ pycityagent/cityagent/nbsagent.py,sha256=WIXW__6dZ5IrqBqDCjvGbrCshpXzuFRV3Ww6gkYw7p4,4387
81
88
  pycityagent/cityagent/initial.py,sha256=7hgCt_tGdnVTXGfEQOn1GTW5dAs1b-ru_FwXxRLI6tM,4549
82
- pycityagent/cityagent/societyagent.py,sha256=oVDWt-DDGMDxh_LpqMs4_CX-5hVQORyPC1ZW2a8CrhI,14960
83
- pycityagent/cityagent/governmentagent.py,sha256=9fjGueVmYok7zca14E1VL4N3ENEhnq2nubI6ab7Hzp0,2825
89
+ pycityagent/cityagent/societyagent.py,sha256=QKzZecyN5npMi2IJlxei9MrJ1yJWJPCogXrNIP1VnFQ,19598
90
+ pycityagent/cityagent/governmentagent.py,sha256=HJLuhvEmllu_1KnFEJsYCIasaBJT0BV9Cn_4Y2QGPqg,2791
84
91
  pycityagent/cityagent/blocks/dispatcher.py,sha256=mEa1r3tRS3KI1BMZR_w_sbUGzOj6aUJuiUrsHv1n2n0,2943
85
- pycityagent/cityagent/blocks/needs_block.py,sha256=pPPjdVFCqFvAV0RM1LVevQIH5d0GALnB6xLekvplutE,13113
86
- pycityagent/cityagent/blocks/cognition_block.py,sha256=CGIYwuF1twS5g3DNhCkaSFT2s1IQXF5NjJO38EX6FLg,15633
87
- pycityagent/cityagent/blocks/time_block.py,sha256=M7ng1jQ14gz4Xle0DC-kWeZmetq9lYQ2HzgEgsu-eX8,4337
88
- pycityagent/cityagent/blocks/social_block.py,sha256=AkI9wLm9WUEFe5Hc5uDfLfwJtWe1TpLLsWdjm__9KM0,14012
89
- pycityagent/cityagent/blocks/__init__.py,sha256=j8aKIrSEkoMjoWKPQbyRqmeHaB-bjaJObyfrEagq8MI,503
90
- pycityagent/cityagent/blocks/economy_block.py,sha256=yysi4E_k47sNmeMorbHVJydYymyTqo9J6hdQnzJ4HN8,20793
91
- pycityagent/cityagent/blocks/utils.py,sha256=BYf15pDynAQw8eeXyn1iVfVDDdkkoRz9e6eiSGUnz4g,2031
92
- pycityagent/cityagent/blocks/other_block.py,sha256=ETgtj_EpYbAocIJq12LB-SPcHAY-b7TRsm9llo3ZIrc,3845
93
- pycityagent/cityagent/blocks/plan_block.py,sha256=Ad_K2m0gYwH5qJi1HOETgEe83uRX06TXconAR8RIZHU,11479
94
- pycityagent/cityagent/blocks/mobility_block.py,sha256=ZebloDhvZJYbV0YSWhAbnOLToiL-4fG7vKNq3kh37M4,10788
92
+ pycityagent/cityagent/blocks/needs_block.py,sha256=s8LikgtKORfo_Sw9SQ5_3biNPTof15QuUs4cDynXCyM,15332
93
+ pycityagent/cityagent/blocks/cognition_block.py,sha256=aeDIWbEmlcqmXyxeEiewXJyV0te3L6k95Kec12mUSM0,14954
94
+ pycityagent/cityagent/blocks/social_block.py,sha256=y46mPK9SLvcOHYB64l6qz5ZgT0dWNmX-C3Cusj_44mE,15540
95
+ pycityagent/cityagent/blocks/__init__.py,sha256=wydR0s-cCRWgdvQetkfQnD_PU8vC3eTmt2zntcb4fSA,452
96
+ pycityagent/cityagent/blocks/economy_block.py,sha256=m5B67cgGZ9nKWtrYeak5gxMoCoKlRbATAsXpFajYKyg,19129
97
+ pycityagent/cityagent/blocks/utils.py,sha256=8O5p1B8JlreIJTGXKAP03rTcn7MvFSR8qJ1_hhszboU,2065
98
+ pycityagent/cityagent/blocks/other_block.py,sha256=NnDwxQAO5XZ7Uxe-n3qtrfNItHlwFYk2MQsh2GYDKMQ,4338
99
+ pycityagent/cityagent/blocks/plan_block.py,sha256=Mtbc26xZjx-HpmBYZD12rVNK09WgDPCkwLseLiJ1mS0,10995
100
+ pycityagent/cityagent/blocks/mobility_block.py,sha256=xWbARMfJ3-6fddrW3VOUKJrXfMGmroiSN0B8t8lVYXA,12725
95
101
  pycityagent/survey/models.py,sha256=YE50UUt5qJ0O_lIUsSY6XFCGUTkJVNu_L1gAhaCJ2fs,3546
96
102
  pycityagent/survey/__init__.py,sha256=rxwou8U9KeFSP7rMzXtmtp2fVFZxK4Trzi-psx9LPIs,153
97
103
  pycityagent/survey/manager.py,sha256=S5IkwTdelsdtZETChRcfCEczzwSrry_Fly9MY4s3rbk,1681
98
- pycityagent-2.0.0a51.dist-info/RECORD,,
99
- pycityagent-2.0.0a51.dist-info/LICENSE,sha256=n2HPXiupinpyHMnIkbCf3OTYd3KMqbmldu1e7av0CAU,1084
100
- pycityagent-2.0.0a51.dist-info/WHEEL,sha256=dR1rljx09yOIlNsXrycFk73TFOGzVWewMxAF8RkAwcI,109
101
- pycityagent-2.0.0a51.dist-info/entry_points.txt,sha256=BZcne49AAIFv-hawxGnPbblea7X3MtAtoPyDX8L4OC4,132
102
- pycityagent-2.0.0a51.dist-info/top_level.txt,sha256=yOmeu6cSXmiUtScu53a3s0p7BGtLMaV0aff83EHCTic,43
103
- pycityagent-2.0.0a51.dist-info/METADATA,sha256=zmYO5Z37qS-ENVQomAcXnJA_8TD1RDSe6IGkmYHq3MM,9110
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.7.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: false
4
4
  Tag: cp310-cp310-macosx_11_0_arm64
5
5
 
@@ -1,116 +0,0 @@
1
- import asyncio
2
- from datetime import datetime
3
- import json
4
- from pycityagent.workflow import Block
5
- from pycityagent.llm.llm import LLM
6
- from pycityagent.memory import Memory
7
- from pycityagent.environment import Simulator
8
- from pycityagent.workflow.prompt import FormatPrompt
9
- from .utils import clean_json_response
10
-
11
- class WorkReflectionBlock(Block):
12
- """
13
- 反馈工作感受
14
- WorkReflectionBlock
15
- """
16
- def __init__(self, llm: LLM, memory: Memory, simulator: Simulator):
17
- super().__init__("WorkReflectionBlock", llm, memory, simulator)
18
- self.description = "Feedback on work experience"
19
-
20
- async def forward(self):
21
- prompt = """
22
- You are a {gender}, your consumption level is {consumption} and your education level is {education}.
23
- Today's working experience:
24
- {working_experience}
25
-
26
- How is your feeling of work today?
27
-
28
- Your answer should be one of the following:
29
- - excellent
30
- - good
31
- - soso
32
- - bad
33
- - very bad
34
- Answer in JSON format:
35
- {{
36
- "evaluation": "good",
37
- }}
38
- """
39
- prompt = FormatPrompt(prompt)
40
- prompt.format(
41
- **{key: await self.memory.get(key) for key in prompt.variables}
42
- )
43
- evaluation = await self.llm.atext_request(prompt.to_dialog(), timeout=300)
44
- evaluation = clean_json_response(evaluation)
45
- try:
46
- evaluation = json.loads(evaluation)
47
- except Exception as e:
48
- evaluation = {'evaluation': 'soso'}
49
- if evaluation['evaluation'] == 'excellent':
50
- safe_improve = 0.2
51
- elif evaluation['evaluation'] == 'good':
52
- safe_improve = 0.1
53
- elif evaluation['evaluation'] == 'soso':
54
- safe_improve = 0.0
55
- elif evaluation['evaluation'] == 'bad':
56
- safe_improve = -0.1
57
- elif evaluation['evaluation'] == 'very bad':
58
- safe_improve = -0.2
59
- else:
60
- safe_improve = 0.0
61
-
62
- needs = await self.memory.get("needs")
63
- needs['safe'] += safe_improve
64
- await self.memory.update("needs", needs)
65
- await self.memory.update("working_experience", [])
66
- return
67
-
68
-
69
- class TimeBlock(Block):
70
- """固定时间trigger的工作流"""
71
- def __init__(self, llm: LLM, memory: Memory, simulator: Simulator):
72
- super().__init__(name="time_block", llm=llm, memory=memory, simulator=simulator)
73
- self.blocks = []
74
- self.work_reflection_block = WorkReflectionBlock(llm, memory, simulator)
75
- self.blocks.append((self.work_reflection_block, self.str_to_time('23:59:59'))) # end of day
76
- self.last_check_time = None
77
- self.trigger_time = 0
78
- self.token_consumption = 0
79
-
80
- def str_to_time(self, time_str: str):
81
- time_obj = datetime.strptime(time_str, '%H:%M:%S')
82
- return time_obj.hour * 3600 + time_obj.minute * 60 + time_obj.second
83
-
84
- async def blocks_to_trigger(self):
85
- trigger_blocks = []
86
- now_time = await self.simulator.get_time(format_time=True)
87
- now_time = self.str_to_time(now_time)
88
- if self.last_check_time is None:
89
- self.last_check_time = now_time
90
- else:
91
- whether_cross_day = True if now_time < self.last_check_time else False
92
- for block, trigger_time in self.blocks:
93
- if whether_cross_day and trigger_time > self.last_check_time:
94
- trigger_blocks.append(block)
95
- elif not whether_cross_day and trigger_time > self.last_check_time and trigger_time <= now_time:
96
- trigger_blocks.append(block)
97
- self.last_check_time = now_time
98
- return trigger_blocks
99
-
100
- async def forward(self):
101
- while True:
102
- if len(self.blocks) == 0:
103
- await asyncio.sleep(30)
104
- continue
105
- trigger_blocks = await self.blocks_to_trigger()
106
- if len(trigger_blocks) == 0:
107
- await asyncio.sleep(30)
108
- continue
109
- self.trigger_time += 1
110
- consumption_start = self.llm.prompt_tokens_used + self.llm.completion_tokens_used
111
- tasks = []
112
- for block in trigger_blocks:
113
- tasks.append(block.forward())
114
- await asyncio.gather(*tasks)
115
- consumption_end = self.llm.prompt_tokens_used + self.llm.completion_tokens_used
116
- self.token_consumption += consumption_end - consumption_start