pycityagent 2.0.0a51__cp312-cp312-macosx_11_0_arm64.whl → 2.0.0a53__cp312-cp312-macosx_11_0_arm64.whl
Sign up to get free protection for your applications and to get access to all the features.
- pycityagent/agent/agent.py +48 -62
- pycityagent/agent/agent_base.py +66 -53
- pycityagent/cityagent/bankagent.py +5 -7
- pycityagent/cityagent/blocks/__init__.py +0 -2
- pycityagent/cityagent/blocks/cognition_block.py +149 -172
- pycityagent/cityagent/blocks/economy_block.py +90 -129
- pycityagent/cityagent/blocks/mobility_block.py +56 -29
- pycityagent/cityagent/blocks/needs_block.py +163 -145
- pycityagent/cityagent/blocks/other_block.py +17 -9
- pycityagent/cityagent/blocks/plan_block.py +44 -56
- pycityagent/cityagent/blocks/social_block.py +70 -51
- pycityagent/cityagent/blocks/utils.py +2 -0
- pycityagent/cityagent/firmagent.py +6 -7
- pycityagent/cityagent/governmentagent.py +7 -9
- pycityagent/cityagent/memory_config.py +48 -48
- pycityagent/cityagent/nbsagent.py +6 -29
- pycityagent/cityagent/societyagent.py +204 -119
- pycityagent/environment/sim/client.py +10 -1
- pycityagent/environment/sim/clock_service.py +2 -2
- pycityagent/environment/sim/pause_service.py +61 -0
- pycityagent/environment/simulator.py +17 -12
- pycityagent/llm/embeddings.py +0 -24
- pycityagent/memory/faiss_query.py +29 -26
- pycityagent/memory/memory.py +720 -272
- pycityagent/pycityagent-sim +0 -0
- pycityagent/simulation/agentgroup.py +92 -99
- pycityagent/simulation/simulation.py +115 -40
- pycityagent/tools/tool.py +7 -10
- pycityagent/workflow/block.py +11 -4
- {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/METADATA +2 -2
- {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/RECORD +35 -35
- {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/WHEEL +1 -1
- pycityagent/cityagent/blocks/time_block.py +0 -116
- {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/LICENSE +0 -0
- {pycityagent-2.0.0a51.dist-info → pycityagent-2.0.0a53.dist-info}/entry_points.txt +0 -0
- {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
|
-
-
|
196
|
+
- times: int if type is "step", else None
|
173
197
|
- description: Optional[str], description of the step
|
174
|
-
-
|
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
|
-
|
228
|
-
|
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["
|
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
|
-
"""
|
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
|
-
|
631
|
-
|
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
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
await
|
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.
|
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
|
-
|
153
|
-
person_id = await
|
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
|
159
|
-
await
|
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
|
-
|
184
|
+
status = agent.status
|
187
185
|
await agent.simulator.reset_person_position(
|
188
|
-
person_id=await
|
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
|
):
|
pycityagent/workflow/block.py
CHANGED
@@ -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
|
-
|
178
|
-
|
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
|
+
Metadata-Version: 2.2
|
2
2
|
Name: pycityagent
|
3
|
-
Version: 2.0.
|
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/
|
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=VujM3ypTCyUW6hcTDdK2ej0ARVMxlU1Djlh_zWnDgqk,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=
|
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=
|
20
|
+
pycityagent/llm/embeddings.py,sha256=2_P4TWm3sJKFdGDx2Q1a2AEapFopDctIXsGuntvmP6E,6816
|
15
21
|
pycityagent/llm/utils.py,sha256=hoNPhvomb1u6lhFX0GctFipw74hVKb7bvUBDqwBzBYw,160
|
16
|
-
pycityagent/memory/memory.py,sha256=
|
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=
|
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=
|
31
|
+
pycityagent/simulation/simulation.py,sha256=Fm6Y54gc4wAlVhMvqlUhbDRG0tKt6OpHdGsI8as9jqs,29662
|
26
32
|
pycityagent/simulation/__init__.py,sha256=P5czbcg2d8S0nbbnsQXFIhwzO4CennAhZM8OmKvAeYw,194
|
27
|
-
pycityagent/simulation/agentgroup.py,sha256=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
77
|
-
pycityagent/cityagent/bankagent.py,sha256=
|
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=
|
80
|
-
pycityagent/cityagent/nbsagent.py,sha256=
|
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=
|
83
|
-
pycityagent/cityagent/governmentagent.py,sha256=
|
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=
|
86
|
-
pycityagent/cityagent/blocks/cognition_block.py,sha256=
|
87
|
-
pycityagent/cityagent/blocks/
|
88
|
-
pycityagent/cityagent/blocks/
|
89
|
-
pycityagent/cityagent/blocks/
|
90
|
-
pycityagent/cityagent/blocks/
|
91
|
-
pycityagent/cityagent/blocks/
|
92
|
-
pycityagent/cityagent/blocks/
|
93
|
-
pycityagent/cityagent/blocks/
|
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=76LiH1wuDHqtCdrF20bc1KNGPhF-AWvwbfgCxtm-4DY,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,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
|
File without changes
|
File without changes
|
File without changes
|