pycityagent 2.0.0a53__cp311-cp311-macosx_11_0_arm64.whl → 2.0.0a55__cp311-cp311-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 +39 -4
- pycityagent/agent/agent_base.py +39 -25
- pycityagent/cityagent/blocks/plan_block.py +1 -1
- pycityagent/cityagent/message_intercept.py +99 -0
- pycityagent/cityagent/societyagent.py +145 -32
- pycityagent/cli/wrapper.py +4 -0
- pycityagent/economy/econ_client.py +0 -2
- pycityagent/environment/__init__.py +7 -1
- pycityagent/environment/sim/sim_env.py +34 -46
- pycityagent/environment/simulator.py +2 -3
- pycityagent/llm/llm.py +18 -10
- pycityagent/memory/memory.py +151 -113
- pycityagent/message/__init__.py +8 -1
- pycityagent/message/message_interceptor.py +322 -0
- pycityagent/message/messager.py +42 -11
- pycityagent/metrics/mlflow_client.py +4 -0
- pycityagent/simulation/agentgroup.py +62 -14
- pycityagent/simulation/simulation.py +103 -29
- pycityagent/simulation/storage/pg.py +2 -2
- pycityagent/utils/__init__.py +7 -2
- pycityagent/utils/pg_query.py +1 -0
- pycityagent/utils/survey_util.py +26 -23
- pycityagent/workflow/block.py +3 -3
- {pycityagent-2.0.0a53.dist-info → pycityagent-2.0.0a55.dist-info}/METADATA +2 -2
- {pycityagent-2.0.0a53.dist-info → pycityagent-2.0.0a55.dist-info}/RECORD +29 -27
- {pycityagent-2.0.0a53.dist-info → pycityagent-2.0.0a55.dist-info}/LICENSE +0 -0
- {pycityagent-2.0.0a53.dist-info → pycityagent-2.0.0a55.dist-info}/WHEEL +0 -0
- {pycityagent-2.0.0a53.dist-info → pycityagent-2.0.0a55.dist-info}/entry_points.txt +0 -0
- {pycityagent-2.0.0a53.dist-info → pycityagent-2.0.0a55.dist-info}/top_level.txt +0 -0
@@ -18,12 +18,15 @@ from ..cityagent import (BankAgent, FirmAgent, GovernmentAgent, NBSAgent,
|
|
18
18
|
memory_config_government, memory_config_nbs,
|
19
19
|
memory_config_societyagent)
|
20
20
|
from ..cityagent.initial import bind_agent_info, initialize_social_network
|
21
|
-
from ..environment
|
22
|
-
from ..llm import SimpleEmbedding
|
23
|
-
from ..
|
24
|
-
from ..
|
21
|
+
from ..environment import Simulator
|
22
|
+
from ..llm import LLM, LLMConfig, SimpleEmbedding
|
23
|
+
from ..memory import Memory
|
24
|
+
from ..message import (MessageBlockBase, MessageBlockListenerBase,
|
25
|
+
MessageInterceptor, Messager)
|
26
|
+
from ..metrics import init_mlflow_connection
|
27
|
+
from ..metrics.mlflow_client import MlflowClient
|
25
28
|
from ..survey import Survey
|
26
|
-
from ..utils import TO_UPDATE_EXP_INFO_KEYS_AND_TYPES
|
29
|
+
from ..utils import SURVEY_SENDER_UUID, TO_UPDATE_EXP_INFO_KEYS_AND_TYPES
|
27
30
|
from .agentgroup import AgentGroup
|
28
31
|
from .storage.pg import PgWriter, create_pg_tables
|
29
32
|
|
@@ -80,6 +83,15 @@ class AgentSimulation:
|
|
80
83
|
self.config = config
|
81
84
|
self.exp_name = exp_name
|
82
85
|
self._simulator = Simulator(config["simulator_request"])
|
86
|
+
if enable_economy:
|
87
|
+
self._economy_env = self._simulator._sim_env
|
88
|
+
_req_dict = self.config["simulator_request"]
|
89
|
+
if "economy" in _req_dict:
|
90
|
+
_req_dict["economy"]["server"] = self._economy_env.sim_addr
|
91
|
+
else:
|
92
|
+
_req_dict["economy"] = {
|
93
|
+
"server": self._economy_env.sim_addr,
|
94
|
+
}
|
83
95
|
self.agent_prefix = agent_prefix
|
84
96
|
self._groups: dict[str, AgentGroup] = {} # type:ignore
|
85
97
|
self._agent_uuid2group: dict[str, AgentGroup] = {} # type:ignore
|
@@ -117,15 +129,17 @@ class AgentSimulation:
|
|
117
129
|
|
118
130
|
# mlflow
|
119
131
|
_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
132
|
if _mlflow_config:
|
126
133
|
logger.info(f"-----Creating Mlflow client...")
|
134
|
+
mlflow_run_id, _ = init_mlflow_connection(
|
135
|
+
config=_mlflow_config,
|
136
|
+
experiment_uuid=self.exp_id,
|
137
|
+
mlflow_run_name=f"EXP_{self.exp_name}_{1000*int(time.time())}",
|
138
|
+
experiment_name=self.exp_name,
|
139
|
+
)
|
127
140
|
self.mlflow_client = MlflowClient(
|
128
141
|
config=_mlflow_config,
|
142
|
+
experiment_uuid=self.exp_id,
|
129
143
|
mlflow_run_name=f"EXP_{exp_name}_{1000*int(time.time())}",
|
130
144
|
experiment_name=exp_name,
|
131
145
|
run_id=mlflow_run_id,
|
@@ -225,6 +239,7 @@ class AgentSimulation:
|
|
225
239
|
agent_count.append(config["agent_config"]["number_of_government"])
|
226
240
|
agent_count.append(config["agent_config"]["number_of_bank"])
|
227
241
|
agent_count.append(config["agent_config"]["number_of_nbs"])
|
242
|
+
# TODO(yanjunbo): support MessageInterceptor
|
228
243
|
await simulation.init_agents(
|
229
244
|
agent_count=agent_count,
|
230
245
|
group_size=config["agent_config"].get("group_size", 10000),
|
@@ -290,9 +305,13 @@ class AgentSimulation:
|
|
290
305
|
return self._agent_uuid2group
|
291
306
|
|
292
307
|
@property
|
293
|
-
def messager(self):
|
308
|
+
def messager(self) -> ray.ObjectRef:
|
294
309
|
return self._messager
|
295
310
|
|
311
|
+
@property
|
312
|
+
def message_interceptor(self) -> ray.ObjectRef:
|
313
|
+
return self._message_interceptors[0] # type:ignore
|
314
|
+
|
296
315
|
async def _save_exp_info(self) -> None:
|
297
316
|
"""异步保存实验信息到YAML文件"""
|
298
317
|
try:
|
@@ -371,6 +390,10 @@ class AgentSimulation:
|
|
371
390
|
agent_count: Union[int, list[int]],
|
372
391
|
group_size: int = 10000,
|
373
392
|
pg_sql_writers: int = 32,
|
393
|
+
message_interceptors: int = 1,
|
394
|
+
message_interceptor_blocks: Optional[list[MessageBlockBase]] = None,
|
395
|
+
social_black_list: Optional[list[tuple[str, str]]] = None,
|
396
|
+
message_listener: Optional[MessageBlockListenerBase] = None,
|
374
397
|
embedding_model: Embeddings = SimpleEmbedding(),
|
375
398
|
memory_config_func: Optional[Union[Callable, list[Callable]]] = None,
|
376
399
|
) -> None:
|
@@ -379,6 +402,8 @@ class AgentSimulation:
|
|
379
402
|
Args:
|
380
403
|
agent_count: 要创建的总智能体数量, 如果为列表,则每个元素表示一个智能体类创建的智能体数量
|
381
404
|
group_size: 每个组的智能体数量,每一个组为一个独立的ray actor
|
405
|
+
pg_sql_writers: 独立的PgSQL writer数量
|
406
|
+
message_interceptors: message拦截器数量
|
382
407
|
memory_config_func: 返回Memory配置的函数,需要返回(EXTRA_ATTRIBUTES, PROFILE, BASE)元组, 如果为列表,则每个元素表示一个智能体类创建的Memory配置函数
|
383
408
|
"""
|
384
409
|
if not isinstance(agent_count, list):
|
@@ -499,7 +524,17 @@ class AgentSimulation:
|
|
499
524
|
config_files,
|
500
525
|
)
|
501
526
|
)
|
502
|
-
|
527
|
+
# 初始化mlflow连接
|
528
|
+
_mlflow_config = self.config.get("metric_request", {}).get("mlflow")
|
529
|
+
if _mlflow_config:
|
530
|
+
mlflow_run_id, _ = init_mlflow_connection(
|
531
|
+
experiment_uuid=self.exp_id,
|
532
|
+
config=_mlflow_config,
|
533
|
+
mlflow_run_name=f"{self.exp_name}_{1000*int(time.time())}",
|
534
|
+
experiment_name=self.exp_name,
|
535
|
+
)
|
536
|
+
else:
|
537
|
+
mlflow_run_id = None
|
503
538
|
# 建表
|
504
539
|
if self.enable_pgsql:
|
505
540
|
_num_workers = min(1, pg_sql_writers)
|
@@ -514,7 +549,31 @@ class AgentSimulation:
|
|
514
549
|
else:
|
515
550
|
_num_workers = 1
|
516
551
|
self._pgsql_writers = _workers = [None for _ in range(_num_workers)]
|
517
|
-
|
552
|
+
# message interceptor
|
553
|
+
if message_listener is not None:
|
554
|
+
self._message_abort_listening_queue = _queue = ray.util.queue.Queue() # type: ignore
|
555
|
+
await message_listener.set_queue(_queue)
|
556
|
+
else:
|
557
|
+
self._message_abort_listening_queue = _queue = None
|
558
|
+
_interceptor_blocks = message_interceptor_blocks
|
559
|
+
_black_list = [] if social_black_list is None else social_black_list
|
560
|
+
_llm_config = self.config.get("llm_request", {})
|
561
|
+
if message_interceptor_blocks is not None:
|
562
|
+
_num_interceptors = min(1, message_interceptors)
|
563
|
+
self._message_interceptors = _interceptors = [
|
564
|
+
MessageInterceptor.remote(
|
565
|
+
_interceptor_blocks, # type:ignore
|
566
|
+
_black_list,
|
567
|
+
_llm_config,
|
568
|
+
_queue,
|
569
|
+
)
|
570
|
+
for _ in range(_num_interceptors)
|
571
|
+
]
|
572
|
+
else:
|
573
|
+
_num_interceptors = 1
|
574
|
+
self._message_interceptors = _interceptors = [
|
575
|
+
None for _ in range(_num_interceptors)
|
576
|
+
]
|
518
577
|
creation_tasks = []
|
519
578
|
for i, (
|
520
579
|
agent_class,
|
@@ -529,11 +588,14 @@ class AgentSimulation:
|
|
529
588
|
number_of_agents,
|
530
589
|
memory_config_function_group,
|
531
590
|
self.config,
|
591
|
+
self.exp_name,
|
532
592
|
self.exp_id,
|
533
593
|
self.enable_avro,
|
534
594
|
self.avro_path,
|
535
595
|
self.enable_pgsql,
|
536
596
|
_workers[i % _num_workers], # type:ignore
|
597
|
+
self.message_interceptor,
|
598
|
+
mlflow_run_id,
|
537
599
|
embedding_model,
|
538
600
|
self.logging_level,
|
539
601
|
config_file,
|
@@ -564,11 +626,15 @@ class AgentSimulation:
|
|
564
626
|
for group in self._groups.values():
|
565
627
|
init_tasks.append(group.init_agents.remote())
|
566
628
|
ray.get(init_tasks)
|
567
|
-
await self.messager.connect.remote()
|
568
|
-
await self.messager.subscribe.remote(
|
569
|
-
|
629
|
+
await self.messager.connect.remote() # type:ignore
|
630
|
+
await self.messager.subscribe.remote( # type:ignore
|
631
|
+
[(f"exps/{self.exp_id}/user_payback", 1)], [self.exp_id]
|
632
|
+
)
|
633
|
+
await self.messager.start_listening.remote() # type:ignore
|
570
634
|
|
571
|
-
async def gather(
|
635
|
+
async def gather(
|
636
|
+
self, content: str, target_agent_uuids: Optional[list[str]] = None
|
637
|
+
):
|
572
638
|
"""收集智能体的特定信息"""
|
573
639
|
gather_tasks = []
|
574
640
|
for group in self._groups.values():
|
@@ -612,12 +678,13 @@ class AgentSimulation:
|
|
612
678
|
self, survey: Survey, agent_uuids: Optional[list[str]] = None
|
613
679
|
):
|
614
680
|
"""发送问卷"""
|
681
|
+
await self.messager.connect.remote() # type:ignore
|
615
682
|
survey_dict = survey.to_dict()
|
616
683
|
if agent_uuids is None:
|
617
684
|
agent_uuids = self._agent_uuids
|
618
685
|
_date_time = datetime.now(timezone.utc)
|
619
686
|
payload = {
|
620
|
-
"from":
|
687
|
+
"from": SURVEY_SENDER_UUID,
|
621
688
|
"survey_id": survey_dict["id"],
|
622
689
|
"timestamp": int(_date_time.timestamp() * 1000),
|
623
690
|
"data": survey_dict,
|
@@ -625,10 +692,10 @@ class AgentSimulation:
|
|
625
692
|
}
|
626
693
|
for uuid in agent_uuids:
|
627
694
|
topic = self._user_survey_topics[uuid]
|
628
|
-
await self.messager.send_message.remote(topic, payload)
|
695
|
+
await self.messager.send_message.remote(topic, payload) # type:ignore
|
629
696
|
remain_payback = len(agent_uuids)
|
630
697
|
while True:
|
631
|
-
messages = await self.messager.fetch_messages.remote()
|
698
|
+
messages = await self.messager.fetch_messages.remote() # type:ignore
|
632
699
|
logger.info(f"Received {len(messages)} payback messages [survey]")
|
633
700
|
remain_payback -= len(messages)
|
634
701
|
if remain_payback <= 0:
|
@@ -641,7 +708,7 @@ class AgentSimulation:
|
|
641
708
|
"""发送采访消息"""
|
642
709
|
_date_time = datetime.now(timezone.utc)
|
643
710
|
payload = {
|
644
|
-
"from":
|
711
|
+
"from": SURVEY_SENDER_UUID,
|
645
712
|
"content": content,
|
646
713
|
"timestamp": int(_date_time.timestamp() * 1000),
|
647
714
|
"_date_time": _date_time,
|
@@ -650,19 +717,19 @@ class AgentSimulation:
|
|
650
717
|
agent_uuids = [agent_uuids]
|
651
718
|
for uuid in agent_uuids:
|
652
719
|
topic = self._user_chat_topics[uuid]
|
653
|
-
await self.messager.send_message.remote(topic, payload)
|
720
|
+
await self.messager.send_message.remote(topic, payload) # type:ignore
|
654
721
|
remain_payback = len(agent_uuids)
|
655
722
|
while True:
|
656
|
-
messages = await self.messager.fetch_messages.remote()
|
723
|
+
messages = await self.messager.fetch_messages.remote() # type:ignore
|
657
724
|
logger.info(f"Received {len(messages)} payback messages [interview]")
|
658
725
|
remain_payback -= len(messages)
|
659
726
|
if remain_payback <= 0:
|
660
727
|
break
|
661
728
|
await asyncio.sleep(3)
|
662
729
|
|
663
|
-
async def extract_metric(self,
|
730
|
+
async def extract_metric(self, metric_extractors: list[Callable]):
|
664
731
|
"""提取指标"""
|
665
|
-
for metric_extractor in
|
732
|
+
for metric_extractor in metric_extractors:
|
666
733
|
await metric_extractor(self)
|
667
734
|
|
668
735
|
async def step(self):
|
@@ -670,7 +737,9 @@ class AgentSimulation:
|
|
670
737
|
try:
|
671
738
|
# check whether insert agents
|
672
739
|
simulator_day = await self._simulator.get_simulator_day()
|
673
|
-
print(
|
740
|
+
print(
|
741
|
+
f"simulator_day: {simulator_day}, self._simulator_day: {self._simulator_day}"
|
742
|
+
)
|
674
743
|
need_insert_agents = False
|
675
744
|
if simulator_day > self._simulator_day:
|
676
745
|
need_insert_agents = True
|
@@ -698,11 +767,14 @@ class AgentSimulation:
|
|
698
767
|
if self.metric_extractor is not None:
|
699
768
|
print(f"total_steps: {self._total_steps}, excute metric")
|
700
769
|
to_excute_metric = [
|
701
|
-
metric[1]
|
770
|
+
metric[1]
|
771
|
+
for metric in self.metric_extractor
|
772
|
+
if self._total_steps % metric[0] == 0
|
702
773
|
]
|
703
774
|
await self.extract_metric(to_excute_metric)
|
704
775
|
except Exception as e:
|
705
776
|
import traceback
|
777
|
+
|
706
778
|
logger.error(f"模拟器运行错误: {str(e)}\n{traceback.format_exc()}")
|
707
779
|
raise RuntimeError(str(e)) from e
|
708
780
|
|
@@ -721,10 +793,12 @@ class AgentSimulation:
|
|
721
793
|
monitor_task = asyncio.create_task(self._monitor_exp_status(stop_event))
|
722
794
|
|
723
795
|
try:
|
724
|
-
end_time =
|
796
|
+
end_time = (
|
797
|
+
await self._simulator.get_time() + day * 24 * 3600
|
798
|
+
) # type:ignore
|
725
799
|
while True:
|
726
800
|
current_time = await self._simulator.get_time()
|
727
|
-
if current_time >= end_time:
|
801
|
+
if current_time >= end_time: # type:ignore
|
728
802
|
break
|
729
803
|
await self.step()
|
730
804
|
finally:
|
@@ -71,11 +71,11 @@ class PgWriter:
|
|
71
71
|
|
72
72
|
@lock_decorator
|
73
73
|
async def async_write_status(self, rows: list[tuple]):
|
74
|
-
_tuple_types = [str, int, float, float, float, int, str, str, None]
|
74
|
+
_tuple_types = [str, int, float, float, float, int, list, str, str, None]
|
75
75
|
table_name = f"socialcity_{self.exp_id.replace('-', '_')}_agent_status"
|
76
76
|
async with await psycopg.AsyncConnection.connect(self._dsn) as aconn:
|
77
77
|
copy_sql = psycopg.sql.SQL(
|
78
|
-
"COPY {} (id, day, t, lng, lat, parent_id, action, status, created_at) FROM STDIN"
|
78
|
+
"COPY {} (id, day, t, lng, lat, parent_id, friend_ids, action, status, created_at) FROM STDIN"
|
79
79
|
).format(psycopg.sql.Identifier(table_name))
|
80
80
|
_rows: list[Any] = []
|
81
81
|
async with aconn.cursor() as cur:
|
pycityagent/utils/__init__.py
CHANGED
@@ -1,11 +1,16 @@
|
|
1
1
|
from .avro_schema import (DIALOG_SCHEMA, INSTITUTION_STATUS_SCHEMA,
|
2
2
|
PROFILE_SCHEMA, STATUS_SCHEMA, SURVEY_SCHEMA)
|
3
3
|
from .pg_query import PGSQL_DICT, TO_UPDATE_EXP_INFO_KEYS_AND_TYPES
|
4
|
-
from .survey_util import process_survey_for_llm
|
4
|
+
from .survey_util import SURVEY_SENDER_UUID, process_survey_for_llm
|
5
5
|
|
6
6
|
__all__ = [
|
7
|
-
"PROFILE_SCHEMA",
|
7
|
+
"PROFILE_SCHEMA",
|
8
|
+
"DIALOG_SCHEMA",
|
9
|
+
"STATUS_SCHEMA",
|
10
|
+
"SURVEY_SCHEMA",
|
11
|
+
"INSTITUTION_STATUS_SCHEMA",
|
8
12
|
"process_survey_for_llm",
|
9
13
|
"TO_UPDATE_EXP_INFO_KEYS_AND_TYPES",
|
10
14
|
"PGSQL_DICT",
|
15
|
+
"SURVEY_SENDER_UUID",
|
11
16
|
]
|
pycityagent/utils/pg_query.py
CHANGED
pycityagent/utils/survey_util.py
CHANGED
@@ -8,40 +8,40 @@ Survey Description: {survey_dict['description']}
|
|
8
8
|
Please answer each question in the following format:
|
9
9
|
|
10
10
|
"""
|
11
|
-
|
11
|
+
|
12
12
|
question_count = 1
|
13
|
-
for page in survey_dict[
|
14
|
-
for question in page[
|
13
|
+
for page in survey_dict["pages"]:
|
14
|
+
for question in page["elements"]:
|
15
15
|
prompt += f"Question {question_count}: {question['title']}\n"
|
16
|
-
|
16
|
+
|
17
17
|
# 根据不同类型的问题生成不同的提示
|
18
|
-
if question[
|
19
|
-
prompt += "Options: " + ", ".join(question[
|
18
|
+
if question["type"] == "radiogroup":
|
19
|
+
prompt += "Options: " + ", ".join(question["choices"]) + "\n"
|
20
20
|
prompt += "Please select ONE option\n"
|
21
|
-
|
22
|
-
elif question[
|
23
|
-
prompt += "Options: " + ", ".join(question[
|
21
|
+
|
22
|
+
elif question["type"] == "checkbox":
|
23
|
+
prompt += "Options: " + ", ".join(question["choices"]) + "\n"
|
24
24
|
prompt += "You can select MULTIPLE options\n"
|
25
|
-
|
26
|
-
elif question[
|
25
|
+
|
26
|
+
elif question["type"] == "rating":
|
27
27
|
prompt += f"Rating range: {question.get('min_rating', 1)} - {question.get('max_rating', 5)}\n"
|
28
28
|
prompt += "Please provide a rating within the range\n"
|
29
|
-
|
30
|
-
elif question[
|
31
|
-
prompt += "Rows: " + ", ".join(question[
|
32
|
-
prompt += "Columns: " + ", ".join(question[
|
29
|
+
|
30
|
+
elif question["type"] == "matrix":
|
31
|
+
prompt += "Rows: " + ", ".join(question["rows"]) + "\n"
|
32
|
+
prompt += "Columns: " + ", ".join(question["columns"]) + "\n"
|
33
33
|
prompt += "Please select ONE column option for EACH row\n"
|
34
|
-
|
35
|
-
elif question[
|
34
|
+
|
35
|
+
elif question["type"] == "text":
|
36
36
|
prompt += "Please provide a text response\n"
|
37
|
-
|
38
|
-
elif question[
|
37
|
+
|
38
|
+
elif question["type"] == "boolean":
|
39
39
|
prompt += "Options: Yes, No\n"
|
40
40
|
prompt += "Please select either Yes or No\n"
|
41
|
-
|
41
|
+
|
42
42
|
prompt += "\nAnswer: [Your response here]\n\n---\n\n"
|
43
43
|
question_count += 1
|
44
|
-
|
44
|
+
|
45
45
|
# 添加总结提示
|
46
46
|
prompt += """Please ensure:
|
47
47
|
1. All required questions are answered
|
@@ -49,5 +49,8 @@ Please answer each question in the following format:
|
|
49
49
|
3. Answers are clear and specific
|
50
50
|
|
51
51
|
Format your responses exactly as requested above."""
|
52
|
-
|
53
|
-
return prompt
|
52
|
+
|
53
|
+
return prompt
|
54
|
+
|
55
|
+
|
56
|
+
SURVEY_SENDER_UUID = "none"
|
pycityagent/workflow/block.py
CHANGED
@@ -187,7 +187,7 @@ class Block:
|
|
187
187
|
|
188
188
|
@classmethod
|
189
189
|
def import_config(cls, config: dict[str, Union[str, dict]]) -> Block:
|
190
|
-
instance = cls(name=config["name"])
|
190
|
+
instance = cls(name=config["name"]) # type: ignore
|
191
191
|
assert isinstance(config["config"], dict)
|
192
192
|
for field, value in config["config"].items():
|
193
193
|
if field in cls.configurable_fields:
|
@@ -195,12 +195,12 @@ class Block:
|
|
195
195
|
|
196
196
|
# 递归创建子Block
|
197
197
|
for child_config in config.get("children", []):
|
198
|
-
child_block = Block.import_config(child_config)
|
198
|
+
child_block = Block.import_config(child_config) # type: ignore
|
199
199
|
setattr(instance, child_block.name.lower(), child_block)
|
200
200
|
|
201
201
|
return instance
|
202
202
|
|
203
|
-
def load_from_config(self, config: dict[str, list[
|
203
|
+
def load_from_config(self, config: dict[str, list[dict]]) -> None:
|
204
204
|
"""
|
205
205
|
使用配置更新当前Block实例的参数,并递归更新子Block。
|
206
206
|
"""
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: pycityagent
|
3
|
-
Version: 2.0.
|
3
|
+
Version: 2.0.0a55
|
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
|
@@ -45,7 +45,7 @@ Requires-Dist: openai>=1.58.1
|
|
45
45
|
Requires-Dist: Pillow<12.0.0,>=11.0.0
|
46
46
|
Requires-Dist: protobuf<5.0.0,<=4.24.0
|
47
47
|
Requires-Dist: pycitydata>=1.0.3
|
48
|
-
Requires-Dist: pycityproto>=2.
|
48
|
+
Requires-Dist: pycityproto>=2.2.0
|
49
49
|
Requires-Dist: requests>=2.32.3
|
50
50
|
Requires-Dist: Shapely>=2.0.6
|
51
51
|
Requires-Dist: PyYAML>=6.0.2
|
@@ -1,25 +1,25 @@
|
|
1
|
-
pycityagent-2.0.
|
2
|
-
pycityagent-2.0.
|
3
|
-
pycityagent-2.0.
|
4
|
-
pycityagent-2.0.
|
5
|
-
pycityagent-2.0.
|
6
|
-
pycityagent-2.0.
|
1
|
+
pycityagent-2.0.0a55.dist-info/RECORD,,
|
2
|
+
pycityagent-2.0.0a55.dist-info/LICENSE,sha256=n2HPXiupinpyHMnIkbCf3OTYd3KMqbmldu1e7av0CAU,1084
|
3
|
+
pycityagent-2.0.0a55.dist-info/WHEEL,sha256=NW1RskY9zow1Y68W-gXg0oZyBRAugI1JHywIzAIai5o,109
|
4
|
+
pycityagent-2.0.0a55.dist-info/entry_points.txt,sha256=BZcne49AAIFv-hawxGnPbblea7X3MtAtoPyDX8L4OC4,132
|
5
|
+
pycityagent-2.0.0a55.dist-info/top_level.txt,sha256=yOmeu6cSXmiUtScu53a3s0p7BGtLMaV0aff83EHCTic,43
|
6
|
+
pycityagent-2.0.0a55.dist-info/METADATA,sha256=NI-t0FkdHsFWQ4aFpPz0i7Jg0qOS16AGo2IOiMwYG44,9110
|
7
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
|
-
pycityagent/metrics/mlflow_client.py,sha256=
|
10
|
+
pycityagent/metrics/mlflow_client.py,sha256=bTrqYsRfNfjJd6l91hU8vN7JXzJC7DHiM2XbkhMuXIU,4613
|
11
11
|
pycityagent/metrics/__init__.py,sha256=X08PaBbGVAd7_PRGLREXWxaqm7nS82WBQpD1zvQzcqc,128
|
12
12
|
pycityagent/metrics/utils/const.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
13
|
pycityagent/economy/__init__.py,sha256=aonY4WHnx-6EGJ4WKrx4S-2jAkYNLtqUA04jp6q8B7w,75
|
14
|
-
pycityagent/economy/econ_client.py,sha256=
|
14
|
+
pycityagent/economy/econ_client.py,sha256=Nf73GPFJgiDbisi8ghmv_Dz6iUlNE2Ey62B-eJ-tQ84,12186
|
15
15
|
pycityagent/tools/__init__.py,sha256=XtdtGyWeFyK1YOUvWkykBWxemtmwQjWUIuuyU1-gosQ,261
|
16
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
|
-
pycityagent/llm/llm.py,sha256=
|
19
|
+
pycityagent/llm/llm.py,sha256=4AJlTj9llT909gzx9SfcBvbUJrWqHzEo3DaHWgQ3-3I,15852
|
20
20
|
pycityagent/llm/embeddings.py,sha256=2_P4TWm3sJKFdGDx2Q1a2AEapFopDctIXsGuntvmP6E,6816
|
21
21
|
pycityagent/llm/utils.py,sha256=hoNPhvomb1u6lhFX0GctFipw74hVKb7bvUBDqwBzBYw,160
|
22
|
-
pycityagent/memory/memory.py,sha256=
|
22
|
+
pycityagent/memory/memory.py,sha256=MusbnD-Us5IF16CkYRSlcer-TEbaPsHxQEYzcugo0N4,34589
|
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
|
@@ -28,31 +28,32 @@ pycityagent/memory/utils.py,sha256=oJWLdPeJy_jcdKcDTo9JAH9kDZhqjoQhhv_zT9qWC0w,8
|
|
28
28
|
pycityagent/memory/const.py,sha256=6zpJPJXWoH9-yf4RARYYff586agCoud9BRn7sPERB1g,932
|
29
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=
|
31
|
+
pycityagent/simulation/simulation.py,sha256=hoWOXcc5bqt-_S2MiYrtg2YWuw3A-KlBG9D_kFzk-fU,32936
|
32
32
|
pycityagent/simulation/__init__.py,sha256=P5czbcg2d8S0nbbnsQXFIhwzO4CennAhZM8OmKvAeYw,194
|
33
|
-
pycityagent/simulation/agentgroup.py,sha256=
|
34
|
-
pycityagent/simulation/storage/pg.py,sha256=
|
35
|
-
pycityagent/message/
|
36
|
-
pycityagent/message/
|
33
|
+
pycityagent/simulation/agentgroup.py,sha256=ANTQA2OFQpuNZBz2VRhy60pTPUM1lXHFJLzFgK1SvxQ,31633
|
34
|
+
pycityagent/simulation/storage/pg.py,sha256=xRshSOGttW-p0re0fNBOjOpb-nQ5msIE2LsdT79_E_Y,8425
|
35
|
+
pycityagent/message/message_interceptor.py,sha256=w8XTyZStQtMjILpeAX3VMhAWcYAuaxCgSMwXQU1OryM,8951
|
36
|
+
pycityagent/message/__init__.py,sha256=f5QH7DKPqEAMyfSlBMnl3uouOKlsoel909STlIe7nUk,276
|
37
|
+
pycityagent/message/messager.py,sha256=8mhTU2bb9K405_lwd9tN2ha7cCQ9m6hPFxf2fYxRjVg,4368
|
37
38
|
pycityagent/utils/avro_schema.py,sha256=AlADbzV8FxiSfvhQhiX9KhrwMjrx0lGT-lED4TI1gJM,4152
|
38
|
-
pycityagent/utils/__init__.py,sha256=
|
39
|
-
pycityagent/utils/survey_util.py,sha256=
|
40
|
-
pycityagent/utils/pg_query.py,sha256=
|
39
|
+
pycityagent/utils/__init__.py,sha256=GQEa4x_uJBK19Z57vfm9Omvqg1c4ysi3QJ9wx8xiDhI,524
|
40
|
+
pycityagent/utils/survey_util.py,sha256=o-gvmmfus3vMIN-EMWPzfLbHkDH4DfZb8B-yBd_mGYk,2076
|
41
|
+
pycityagent/utils/pg_query.py,sha256=KAcnBDLyzUu2il18SGXxk8dySdBen_8ejfpxiWuKUMA,2225
|
41
42
|
pycityagent/utils/decorators.py,sha256=Gk3r41hfk6awui40tbwpq3C7wC7jHaRmLRlcJFlLQCE,3160
|
42
43
|
pycityagent/utils/parsers/__init__.py,sha256=AN2xgiPxszWK4rpX7zrqRsqNwfGF3WnCA5-PFTvbaKk,281
|
43
44
|
pycityagent/utils/parsers/code_block_parser.py,sha256=Cs2Z_hm9VfNCpPPll1TwteaJF-HAQPs-3RApsOekFm4,1173
|
44
45
|
pycityagent/utils/parsers/parser_base.py,sha256=KBKO4zLZPNdGjPAGqIus8LseZ8W3Tlt2y0QxqeCd25Q,1713
|
45
46
|
pycityagent/utils/parsers/json_parser.py,sha256=tjwyPluYfkWgsvLi0hzfJwFhO3L6yQfZMKza20HaGrY,2911
|
46
|
-
pycityagent/agent/agent_base.py,sha256=
|
47
|
+
pycityagent/agent/agent_base.py,sha256=vC1nMWahwi_nVBUXVdC1CnZpqimKZApixD2m2Iqu_bg,24196
|
47
48
|
pycityagent/agent/__init__.py,sha256=U20yKu9QwSqAx_PHk5JwipfODkDfxONtumVfnsKjWFg,180
|
48
|
-
pycityagent/agent/agent.py,sha256=
|
49
|
-
pycityagent/cli/wrapper.py,sha256=
|
49
|
+
pycityagent/agent/agent.py,sha256=FNon_OPvGrh976AEHpaAQyLQN7erbGOX-BxGnCVZza8,12038
|
50
|
+
pycityagent/cli/wrapper.py,sha256=9aG6D2cnmh6aIhiVXKPGKuMjVcdAa-TwzANudb2q_FU,1147
|
50
51
|
pycityagent/workflow/__init__.py,sha256=H08Ko3eliZvuuCMajbEri-IP4-SeswYU6UjHBNA4Ze0,490
|
51
52
|
pycityagent/workflow/prompt.py,sha256=6jI0Rq54JLv3-IXqZLYug62vse10wTI83xvf4ZX42nk,2929
|
52
|
-
pycityagent/workflow/block.py,sha256=
|
53
|
+
pycityagent/workflow/block.py,sha256=4QufS8XnyP6SYp8g1gDODW-H0nAHA7lvivrPGUq1p-w,9922
|
53
54
|
pycityagent/workflow/trigger.py,sha256=Df-MOBEDWBbM-v0dFLQLXteLsipymT4n8vqexmK2GiQ,5643
|
54
|
-
pycityagent/environment/__init__.py,sha256=
|
55
|
-
pycityagent/environment/simulator.py,sha256=
|
55
|
+
pycityagent/environment/__init__.py,sha256=MyZBwsweDIHOKSX2iSZs748foNtaiyEcyg6sc747T2g,263
|
56
|
+
pycityagent/environment/simulator.py,sha256=gqkECMzhXRh4WHTyLFEL1_X1R7F1aX4g9881zUFv7DI,12136
|
56
57
|
pycityagent/environment/message/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
57
58
|
pycityagent/environment/utils/port.py,sha256=3OM6kSUt3PxvDUOlgyiendBtETaWU8Mzk_8H0TzTmYg,295
|
58
59
|
pycityagent/environment/utils/grpc.py,sha256=6EJwKXXktIWb1NcUiJzIRmfrY0S03QAXXGcCDHqAT00,1998
|
@@ -69,7 +70,7 @@ pycityagent/environment/sidecar/sidecarv2.py,sha256=beKlYZgt38EQbV1x6NWQo7xVXyB-
|
|
69
70
|
pycityagent/environment/sim/pause_service.py,sha256=DcAOVRxNkHGk4jyzFkxHMUPgp0Ck4mYHoPh6qxjhhLQ,1744
|
70
71
|
pycityagent/environment/sim/person_service.py,sha256=5r1F2Itn7dKJ2U4hSLovrk5p4qy-2n77MTAv_OlTIwA,10673
|
71
72
|
pycityagent/environment/sim/aoi_service.py,sha256=2UjvUTF4CW4E_L30IRcdwv6t_q1ZdXN3TTLOKSOaaXE,1230
|
72
|
-
pycityagent/environment/sim/sim_env.py,sha256=
|
73
|
+
pycityagent/environment/sim/sim_env.py,sha256=V3Pf_nsebs07-ZaXPSCaA1HBGv4n7v8yxMz6GKQaZPk,3908
|
73
74
|
pycityagent/environment/sim/lane_service.py,sha256=N2dUe-3XuqqKLsNXt1k4NN8uV-J_ruo08yhaUd_hwOI,3916
|
74
75
|
pycityagent/environment/sim/client.py,sha256=j0f8qjR1nIava4VkoZNEPqW5h08WPdcC5wzM9DP3tIs,3772
|
75
76
|
pycityagent/environment/sim/__init__.py,sha256=JVG6sSD2Hbohl1TtKjuQi7_M7tKMrFh9vl3QV3VA5O0,724
|
@@ -86,7 +87,8 @@ pycityagent/cityagent/__init__.py,sha256=gcBQ-a50XegFtjigQ7xDXRBZrywBKqifiQFSRnE
|
|
86
87
|
pycityagent/cityagent/firmagent.py,sha256=UVlNN0lpa4cC4PZVqYzQhbc5VJ2oGsA1731mhbCjnR8,4109
|
87
88
|
pycityagent/cityagent/nbsagent.py,sha256=WIXW__6dZ5IrqBqDCjvGbrCshpXzuFRV3Ww6gkYw7p4,4387
|
88
89
|
pycityagent/cityagent/initial.py,sha256=7hgCt_tGdnVTXGfEQOn1GTW5dAs1b-ru_FwXxRLI6tM,4549
|
89
|
-
pycityagent/cityagent/societyagent.py,sha256=
|
90
|
+
pycityagent/cityagent/societyagent.py,sha256=vvFGAr8wlZ82f4qHvpawa1VsHungDegjKn1E51bDUnc,24767
|
91
|
+
pycityagent/cityagent/message_intercept.py,sha256=HiNOtBXKq40LCmvsw2KMLxMsbmXSVcbRytAO-eI-1sU,3279
|
90
92
|
pycityagent/cityagent/governmentagent.py,sha256=HJLuhvEmllu_1KnFEJsYCIasaBJT0BV9Cn_4Y2QGPqg,2791
|
91
93
|
pycityagent/cityagent/blocks/dispatcher.py,sha256=mEa1r3tRS3KI1BMZR_w_sbUGzOj6aUJuiUrsHv1n2n0,2943
|
92
94
|
pycityagent/cityagent/blocks/needs_block.py,sha256=s8LikgtKORfo_Sw9SQ5_3biNPTof15QuUs4cDynXCyM,15332
|
@@ -96,7 +98,7 @@ pycityagent/cityagent/blocks/__init__.py,sha256=wydR0s-cCRWgdvQetkfQnD_PU8vC3eTm
|
|
96
98
|
pycityagent/cityagent/blocks/economy_block.py,sha256=m5B67cgGZ9nKWtrYeak5gxMoCoKlRbATAsXpFajYKyg,19129
|
97
99
|
pycityagent/cityagent/blocks/utils.py,sha256=8O5p1B8JlreIJTGXKAP03rTcn7MvFSR8qJ1_hhszboU,2065
|
98
100
|
pycityagent/cityagent/blocks/other_block.py,sha256=NnDwxQAO5XZ7Uxe-n3qtrfNItHlwFYk2MQsh2GYDKMQ,4338
|
99
|
-
pycityagent/cityagent/blocks/plan_block.py,sha256=
|
101
|
+
pycityagent/cityagent/blocks/plan_block.py,sha256=YEU0pHK_fB1lvvml9u7bGz-2bzM2axE9jW-aSgPYs6M,10996
|
100
102
|
pycityagent/cityagent/blocks/mobility_block.py,sha256=xWbARMfJ3-6fddrW3VOUKJrXfMGmroiSN0B8t8lVYXA,12725
|
101
103
|
pycityagent/survey/models.py,sha256=YE50UUt5qJ0O_lIUsSY6XFCGUTkJVNu_L1gAhaCJ2fs,3546
|
102
104
|
pycityagent/survey/__init__.py,sha256=rxwou8U9KeFSP7rMzXtmtp2fVFZxK4Trzi-psx9LPIs,153
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|