pycityagent 2.0.0a52__cp310-cp310-macosx_11_0_arm64.whl → 2.0.0a53__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.
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 -9
  29. pycityagent/workflow/block.py +11 -4
  30. {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a53.dist-info}/METADATA +1 -1
  31. {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a53.dist-info}/RECORD +35 -35
  32. pycityagent/cityagent/blocks/time_block.py +0 -116
  33. {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a53.dist-info}/LICENSE +0 -0
  34. {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a53.dist-info}/WHEEL +0 -0
  35. {pycityagent-2.0.0a52.dist-info → pycityagent-2.0.0a53.dist-info}/entry_points.txt +0 -0
  36. {pycityagent-2.0.0a52.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,
@@ -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
1
  Metadata-Version: 2.2
2
2
  Name: pycityagent
3
- Version: 2.0.0a52
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,10 +1,10 @@
1
- pycityagent-2.0.0a52.dist-info/RECORD,,
2
- pycityagent-2.0.0a52.dist-info/LICENSE,sha256=n2HPXiupinpyHMnIkbCf3OTYd3KMqbmldu1e7av0CAU,1084
3
- pycityagent-2.0.0a52.dist-info/WHEEL,sha256=ezfKMaDztqf77C8lvQ0NCnZxkTaOaKLprqJ8q932MhU,109
4
- pycityagent-2.0.0a52.dist-info/entry_points.txt,sha256=BZcne49AAIFv-hawxGnPbblea7X3MtAtoPyDX8L4OC4,132
5
- pycityagent-2.0.0a52.dist-info/top_level.txt,sha256=yOmeu6cSXmiUtScu53a3s0p7BGtLMaV0aff83EHCTic,43
6
- pycityagent-2.0.0a52.dist-info/METADATA,sha256=WBBdIOQzkArKVtcDejBHFlvBAyVJlfpBhIN3e8kvOQE,9110
7
- 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
8
8
  pycityagent/__init__.py,sha256=PUKWTXc-xdMG7px8oTNclodsILUgypANj2Z647sY63k,808
9
9
  pycityagent/pycityagent-ui,sha256=cHZjqtrQ4Fh4qtRahFNCNbT2DNHLmUexiDAa-72Z3RQ,40333378
10
10
  pycityagent/metrics/mlflow_client.py,sha256=g_tHxWkWTDijtbGL74-HmiYzWVKb1y8-w12QrY9jL30,4449
@@ -13,24 +13,24 @@ pycityagent/metrics/utils/const.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
13
13
  pycityagent/economy/__init__.py,sha256=aonY4WHnx-6EGJ4WKrx4S-2jAkYNLtqUA04jp6q8B7w,75
14
14
  pycityagent/economy/econ_client.py,sha256=GuHK9ZBnhqW3Z7F8ViDJn_iN73yOBbbwFyJv1wLEBDk,12211
15
15
  pycityagent/tools/__init__.py,sha256=XtdtGyWeFyK1YOUvWkykBWxemtmwQjWUIuuyU1-gosQ,261
16
- pycityagent/tools/tool.py,sha256=qhjvPMKsGQ02oIGLl6ZdETTAR0q_av2qK2Ovf1XS_so,8758
16
+ pycityagent/tools/tool.py,sha256=D-ESFlX7EESm5mcvs2zRlGEQTzXbVfQc8G7Vpz8TmAw,8651
17
17
  pycityagent/llm/llmconfig.py,sha256=4Ylf4OFSBEFy8jrOneeX0HvPhWEaF5jGvy1HkXK08Ro,436
18
18
  pycityagent/llm/__init__.py,sha256=iWs6FLgrbRVIiqOf4ILS89gkVCTvS7HFC3vG-MWuyko,205
19
19
  pycityagent/llm/llm.py,sha256=owTYuXmnHZnvXaAvwiiyD511P3wpU3K04xZArhhiJF0,15700
20
- pycityagent/llm/embeddings.py,sha256=Nhf_tUIlaYJAZ93wW2QTCtS1wq7e8fUgdn2JketEAuQ,7600
20
+ pycityagent/llm/embeddings.py,sha256=2_P4TWm3sJKFdGDx2Q1a2AEapFopDctIXsGuntvmP6E,6816
21
21
  pycityagent/llm/utils.py,sha256=hoNPhvomb1u6lhFX0GctFipw74hVKb7bvUBDqwBzBYw,160
22
- pycityagent/memory/memory.py,sha256=RV54r9uE3H7RIfz5ifaeXiD7RrOJotxJNhAOguZrYUk,17273
22
+ pycityagent/memory/memory.py,sha256=suU6mZIYvGySQGyNrYiqdobuTgjSHyI_PahIeRVShiQ,34506
23
23
  pycityagent/memory/profile.py,sha256=q8ZS9IBmHCg_X1GONUvXK85P6tCepTKQgXKuvuXYNXw,5203
24
24
  pycityagent/memory/__init__.py,sha256=_Vfdo1HcLWsuuz34_i8e91nnLVYADpMlHHSVaB3xgIk,297
25
25
  pycityagent/memory/memory_base.py,sha256=QG_j3BxZvkadFEeE3uBR_kjl_xcXD1aHUVs8GEF3d6w,5654
26
26
  pycityagent/memory/self_define.py,sha256=vpZ6CIxR2grNXEIOScdpsSc59FBg0mOKelwQuTElbtQ,5200
27
27
  pycityagent/memory/utils.py,sha256=oJWLdPeJy_jcdKcDTo9JAH9kDZhqjoQhhv_zT9qWC0w,877
28
28
  pycityagent/memory/const.py,sha256=6zpJPJXWoH9-yf4RARYYff586agCoud9BRn7sPERB1g,932
29
- pycityagent/memory/faiss_query.py,sha256=Z0JS4udyPYCIzHMq464QtHscnswu35gh9fQptikAwkQ,12976
29
+ pycityagent/memory/faiss_query.py,sha256=V3rIw6d1_xcpNqZBbAYz3qfjVNE7NfJ7xOS5SibPtVU,13180
30
30
  pycityagent/memory/state.py,sha256=TYItiyDtehMEQaSBN7PpNrnNxdDM5jGppr9R9Ufv3kA,5134
31
- pycityagent/simulation/simulation.py,sha256=DkTYkdNknz2d7hIdYhxxLewUkYwmS9uOxnmEGTwbL_Q,26098
31
+ pycityagent/simulation/simulation.py,sha256=Fm6Y54gc4wAlVhMvqlUhbDRG0tKt6OpHdGsI8as9jqs,29662
32
32
  pycityagent/simulation/__init__.py,sha256=P5czbcg2d8S0nbbnsQXFIhwzO4CennAhZM8OmKvAeYw,194
33
- pycityagent/simulation/agentgroup.py,sha256=fMTN9xDC-PdTGZ4KCMovZeGjzv8HIQJ1AGVG7iAJnD4,29351
33
+ pycityagent/simulation/agentgroup.py,sha256=F1LJq-4xq3E7NmhmBT8j9wsJuuRmU5rGFzNgeOCwOSI,29701
34
34
  pycityagent/simulation/storage/pg.py,sha256=5itxKOkNPlOzN7z2_3oKU1ZK0uLTDugfld8ZkRbD69I,8407
35
35
  pycityagent/message/__init__.py,sha256=TCjazxqb5DVwbTu1fF0sNvaH_EPXVuj2XQ0p6W-QCLU,55
36
36
  pycityagent/message/messager.py,sha256=78K31EPKfC5IxbISc-Lc2babC7VOh9Vbe3c0sO-YDLA,3333
@@ -43,16 +43,16 @@ pycityagent/utils/parsers/__init__.py,sha256=AN2xgiPxszWK4rpX7zrqRsqNwfGF3WnCA5-
43
43
  pycityagent/utils/parsers/code_block_parser.py,sha256=Cs2Z_hm9VfNCpPPll1TwteaJF-HAQPs-3RApsOekFm4,1173
44
44
  pycityagent/utils/parsers/parser_base.py,sha256=KBKO4zLZPNdGjPAGqIus8LseZ8W3Tlt2y0QxqeCd25Q,1713
45
45
  pycityagent/utils/parsers/json_parser.py,sha256=tjwyPluYfkWgsvLi0hzfJwFhO3L6yQfZMKza20HaGrY,2911
46
- pycityagent/agent/agent_base.py,sha256=78J6np8XrFXTUXTC9x_O28EUmyWsdgtARd1KfNcC0cI,23073
46
+ pycityagent/agent/agent_base.py,sha256=FP2h3abIQ1Kp9qCzrzwa7tO82graDAWVg30HqYaQcPE,23620
47
47
  pycityagent/agent/__init__.py,sha256=U20yKu9QwSqAx_PHk5JwipfODkDfxONtumVfnsKjWFg,180
48
- pycityagent/agent/agent.py,sha256=8biuC44Yx4T8Fntlj_RGTlnKWwS0XDNkfYQrv5xXUwE,11548
48
+ pycityagent/agent/agent.py,sha256=rYUC6idFb2dCRa7H7-0ZFPn4UB7MSTigHXOjNSK5B2Y,10702
49
49
  pycityagent/cli/wrapper.py,sha256=2Tb52gOlEVgn11Ekt6ZkRXr_BGzte-EPyBKnR6g6hQ4,1143
50
50
  pycityagent/workflow/__init__.py,sha256=H08Ko3eliZvuuCMajbEri-IP4-SeswYU6UjHBNA4Ze0,490
51
51
  pycityagent/workflow/prompt.py,sha256=6jI0Rq54JLv3-IXqZLYug62vse10wTI83xvf4ZX42nk,2929
52
- pycityagent/workflow/block.py,sha256=3X6qzpYmmMyZyXA6Dxl4lS-mNR0eLzLoiRhHY-H1rzE,9667
52
+ pycityagent/workflow/block.py,sha256=REetWNdCF_fUGKVH-LWgDZ1lK2Bt0tJJ0kV20eWa4_A,9890
53
53
  pycityagent/workflow/trigger.py,sha256=Df-MOBEDWBbM-v0dFLQLXteLsipymT4n8vqexmK2GiQ,5643
54
54
  pycityagent/environment/__init__.py,sha256=awHxlOud-btWbk0FCS4RmGJ13W84oVCkbGfcrhKqihA,240
55
- pycityagent/environment/simulator.py,sha256=1OUfODDzM4EN6Lw_Wzq4KeQb-EpcUBioZYc9fxfSPn0,12070
55
+ pycityagent/environment/simulator.py,sha256=pARK08PzqiAysy6VOR2KZAgEG7auVzt_Tecy5MBL55Q,12157
56
56
  pycityagent/environment/message/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
57
  pycityagent/environment/utils/port.py,sha256=3OM6kSUt3PxvDUOlgyiendBtETaWU8Mzk_8H0TzTmYg,295
58
58
  pycityagent/environment/utils/grpc.py,sha256=6EJwKXXktIWb1NcUiJzIRmfrY0S03QAXXGcCDHqAT00,1998
@@ -66,38 +66,38 @@ pycityagent/environment/sence/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5N
66
66
  pycityagent/environment/sence/static.py,sha256=9s7jz8HitstTrk-GqpnVB26oPrjuTyNeL7hcoxjPhV4,29104
67
67
  pycityagent/environment/sidecar/__init__.py,sha256=RFbOf40aYBP4WwRpFkua5tlRE_OtMcMNyp1Lew_aaAU,235
68
68
  pycityagent/environment/sidecar/sidecarv2.py,sha256=beKlYZgt38EQbV1x6NWQo7xVXyB-5QHfbwJexyXu7Tg,3252
69
+ pycityagent/environment/sim/pause_service.py,sha256=DcAOVRxNkHGk4jyzFkxHMUPgp0Ck4mYHoPh6qxjhhLQ,1744
69
70
  pycityagent/environment/sim/person_service.py,sha256=5r1F2Itn7dKJ2U4hSLovrk5p4qy-2n77MTAv_OlTIwA,10673
70
71
  pycityagent/environment/sim/aoi_service.py,sha256=2UjvUTF4CW4E_L30IRcdwv6t_q1ZdXN3TTLOKSOaaXE,1230
71
72
  pycityagent/environment/sim/sim_env.py,sha256=HI1LcS_FotDKQ6vBnx0e49prXSABOfA20aU9KM-ZkCY,4625
72
73
  pycityagent/environment/sim/lane_service.py,sha256=N2dUe-3XuqqKLsNXt1k4NN8uV-J_ruo08yhaUd_hwOI,3916
73
- pycityagent/environment/sim/client.py,sha256=MHR7Hhu-Cr7B61d3K_QDpSJh4HrUU9JQf6Cu7_8pdsE,3493
74
+ pycityagent/environment/sim/client.py,sha256=j0f8qjR1nIava4VkoZNEPqW5h08WPdcC5wzM9DP3tIs,3772
74
75
  pycityagent/environment/sim/__init__.py,sha256=JVG6sSD2Hbohl1TtKjuQi7_M7tKMrFh9vl3QV3VA5O0,724
75
76
  pycityagent/environment/sim/social_service.py,sha256=9EFJAwVdUuUQkNkFRn9qZRDfD1brh2fqkvasnXUEBhQ,2014
76
77
  pycityagent/environment/sim/economy_services.py,sha256=xoc-1_H8JmQwJ24oWRS1fD-hGYtz2I-x6BOkQ4yENzU,7106
77
78
  pycityagent/environment/sim/light_service.py,sha256=KVwt7ii_iLGA7gANZe3n6-4RiiPQt1w9H6ZOoizMI04,4242
78
- pycityagent/environment/sim/clock_service.py,sha256=fgYXacf_-ixhVAn5uKUvqvemBS6A0oQK8JOZukkhXyY,1353
79
+ pycityagent/environment/sim/clock_service.py,sha256=gBUujvX_vIFMKVfcLRyk1GcpRRL606opLhNjCYL7Gt4,1363
79
80
  pycityagent/environment/sim/road_service.py,sha256=bKyn3_me0sGmaJVyF6eNeFbdU-9C1yWsa9L7pieDJzg,1285
80
81
  pycityagent/environment/interact/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
82
  pycityagent/environment/interact/interact.py,sha256=ifxPPzuHeqLHIZ_6zvfXMoBOnBsXNIP4bYp7OJ7pnEQ,6588
82
- pycityagent/cityagent/memory_config.py,sha256=6dkgqPczANUqZpqGXDOt7wrS6vHdFSMNkWvEVwo6VIQ,10672
83
- 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
84
85
  pycityagent/cityagent/__init__.py,sha256=gcBQ-a50XegFtjigQ7xDXRBZrywBKqifiQFSRnEF8gM,572
85
- pycityagent/cityagent/firmagent.py,sha256=Mtb58YfW3V696gXA6TRw1qUL1WIzthahDBv2X5x_Iyg,4176
86
- pycityagent/cityagent/nbsagent.py,sha256=SIOigR8eiSHC0Gi8kg32hLxsqPKDgCHWF0HA89EU7eA,5202
86
+ pycityagent/cityagent/firmagent.py,sha256=UVlNN0lpa4cC4PZVqYzQhbc5VJ2oGsA1731mhbCjnR8,4109
87
+ pycityagent/cityagent/nbsagent.py,sha256=WIXW__6dZ5IrqBqDCjvGbrCshpXzuFRV3Ww6gkYw7p4,4387
87
88
  pycityagent/cityagent/initial.py,sha256=7hgCt_tGdnVTXGfEQOn1GTW5dAs1b-ru_FwXxRLI6tM,4549
88
- pycityagent/cityagent/societyagent.py,sha256=oVDWt-DDGMDxh_LpqMs4_CX-5hVQORyPC1ZW2a8CrhI,14960
89
- 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
90
91
  pycityagent/cityagent/blocks/dispatcher.py,sha256=mEa1r3tRS3KI1BMZR_w_sbUGzOj6aUJuiUrsHv1n2n0,2943
91
- pycityagent/cityagent/blocks/needs_block.py,sha256=pPPjdVFCqFvAV0RM1LVevQIH5d0GALnB6xLekvplutE,13113
92
- pycityagent/cityagent/blocks/cognition_block.py,sha256=CGIYwuF1twS5g3DNhCkaSFT2s1IQXF5NjJO38EX6FLg,15633
93
- pycityagent/cityagent/blocks/time_block.py,sha256=M7ng1jQ14gz4Xle0DC-kWeZmetq9lYQ2HzgEgsu-eX8,4337
94
- pycityagent/cityagent/blocks/social_block.py,sha256=AkI9wLm9WUEFe5Hc5uDfLfwJtWe1TpLLsWdjm__9KM0,14012
95
- pycityagent/cityagent/blocks/__init__.py,sha256=j8aKIrSEkoMjoWKPQbyRqmeHaB-bjaJObyfrEagq8MI,503
96
- pycityagent/cityagent/blocks/economy_block.py,sha256=yysi4E_k47sNmeMorbHVJydYymyTqo9J6hdQnzJ4HN8,20793
97
- pycityagent/cityagent/blocks/utils.py,sha256=BYf15pDynAQw8eeXyn1iVfVDDdkkoRz9e6eiSGUnz4g,2031
98
- pycityagent/cityagent/blocks/other_block.py,sha256=ETgtj_EpYbAocIJq12LB-SPcHAY-b7TRsm9llo3ZIrc,3845
99
- pycityagent/cityagent/blocks/plan_block.py,sha256=Ad_K2m0gYwH5qJi1HOETgEe83uRX06TXconAR8RIZHU,11479
100
- 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
101
101
  pycityagent/survey/models.py,sha256=YE50UUt5qJ0O_lIUsSY6XFCGUTkJVNu_L1gAhaCJ2fs,3546
102
102
  pycityagent/survey/__init__.py,sha256=rxwou8U9KeFSP7rMzXtmtp2fVFZxK4Trzi-psx9LPIs,153
103
103
  pycityagent/survey/manager.py,sha256=S5IkwTdelsdtZETChRcfCEczzwSrry_Fly9MY4s3rbk,1681
@@ -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