pycityagent 2.0.0a53__cp310-cp310-macosx_11_0_arm64.whl → 2.0.0a55__cp310-cp310-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
pycityagent/cli/wrapper.py
CHANGED
@@ -6,6 +6,7 @@ import signal
|
|
6
6
|
_script_dir = os.path.dirname(os.path.abspath(__file__))
|
7
7
|
_parent_dir = os.path.dirname(_script_dir)
|
8
8
|
|
9
|
+
|
9
10
|
def wrapper(bin: str):
|
10
11
|
binary_path = os.path.join(_parent_dir, bin)
|
11
12
|
if not os.path.exists(binary_path):
|
@@ -21,12 +22,14 @@ def wrapper(bin: str):
|
|
21
22
|
stdout=sys.stdout,
|
22
23
|
stderr=sys.stderr,
|
23
24
|
)
|
25
|
+
|
24
26
|
# register signal handler
|
25
27
|
def signal_handler(sig, frame):
|
26
28
|
if p.poll() is None:
|
27
29
|
p.send_signal(sig)
|
28
30
|
else:
|
29
31
|
sys.exit(p.poll())
|
32
|
+
|
30
33
|
signals = [signal.SIGINT, signal.SIGTERM, signal.SIGHUP]
|
31
34
|
for sig in signals:
|
32
35
|
signal.signal(sig, signal_handler)
|
@@ -40,5 +43,6 @@ def wrapper(bin: str):
|
|
40
43
|
def pycityagent_sim():
|
41
44
|
wrapper("pycityagent-sim")
|
42
45
|
|
46
|
+
|
43
47
|
def pycityagent_ui():
|
44
48
|
wrapper("pycityagent-ui")
|
@@ -4,4 +4,10 @@ from .sence.static import LEVEL_ONE_PRE, POI_TYPE_DICT
|
|
4
4
|
from .sim import AoiService, PersonService
|
5
5
|
from .simulator import Simulator
|
6
6
|
|
7
|
-
__all__ = [
|
7
|
+
__all__ = [
|
8
|
+
"Simulator",
|
9
|
+
"POI_TYPE_DICT",
|
10
|
+
"LEVEL_ONE_PRE",
|
11
|
+
"PersonService",
|
12
|
+
"AoiService",
|
13
|
+
]
|
@@ -1,7 +1,8 @@
|
|
1
|
+
import atexit
|
1
2
|
import logging
|
2
3
|
import os
|
3
4
|
import time
|
4
|
-
import
|
5
|
+
import warnings
|
5
6
|
from subprocess import DEVNULL, Popen
|
6
7
|
from typing import Optional
|
7
8
|
|
@@ -51,7 +52,7 @@ class ControlSimEnv:
|
|
51
52
|
log_dir: str,
|
52
53
|
min_step_time: int = 1000,
|
53
54
|
timeout: int = 5,
|
54
|
-
|
55
|
+
sim_addr: Optional[str] = None,
|
55
56
|
):
|
56
57
|
self._task_name = task_name
|
57
58
|
self._map_file = map_file
|
@@ -66,47 +67,38 @@ class ControlSimEnv:
|
|
66
67
|
地图数据
|
67
68
|
"""
|
68
69
|
|
69
|
-
|
70
|
-
#
|
71
|
-
self.
|
72
|
-
|
73
|
-
raise FileNotFoundError("simulet-go not found, please install it first")
|
74
|
-
|
75
|
-
self._simuletgo_config = _generate_yaml_config(map_file, start_step, total_step)
|
76
|
-
self.simuletgo_port = None
|
77
|
-
self._simuletgo_proc = None
|
78
|
-
self._traffic_client = None
|
79
|
-
|
70
|
+
self._sim_config = _generate_yaml_config(map_file, start_step, total_step)
|
71
|
+
# sim
|
72
|
+
self.sim_port = None
|
73
|
+
self._sim_proc = None
|
80
74
|
os.makedirs(log_dir, exist_ok=True)
|
81
75
|
|
82
|
-
self.
|
76
|
+
self.sim_addr = self.reset(sim_addr)
|
83
77
|
|
84
78
|
def reset(
|
85
79
|
self,
|
86
|
-
|
80
|
+
sim_addr: Optional[str] = None,
|
87
81
|
):
|
88
82
|
"""
|
89
83
|
Args:
|
90
|
-
-
|
84
|
+
- sim_addr: str, pycityagent-sim的地址。如果为None,则启动一个新的pycityagent-sim
|
91
85
|
"""
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
self.
|
100
|
-
config_base64 = encode_to_base64(self._simuletgo_config)
|
101
|
-
self._simuletgo_proc = Popen(
|
86
|
+
if sim_addr is None:
|
87
|
+
# 启动pycityagent-sim
|
88
|
+
# pycityagent-sim -config-data configbase64 -job test -listen :51102
|
89
|
+
assert self.sim_port is None
|
90
|
+
assert self._sim_proc is None
|
91
|
+
self.sim_port = find_free_port()
|
92
|
+
config_base64 = encode_to_base64(self._sim_config)
|
93
|
+
self._sim_proc = Popen(
|
102
94
|
[
|
103
|
-
|
95
|
+
"pycityagent-sim",
|
104
96
|
"-config-data",
|
105
97
|
config_base64,
|
106
98
|
"-job",
|
107
99
|
self._task_name,
|
108
100
|
"-listen",
|
109
|
-
f":{self.
|
101
|
+
f":{self.sim_port}",
|
110
102
|
"-run.min_step_time",
|
111
103
|
f"{self._min_step_time}",
|
112
104
|
"-output",
|
@@ -120,26 +112,22 @@ class ControlSimEnv:
|
|
120
112
|
# stdout=DEVNULL,
|
121
113
|
)
|
122
114
|
logging.info(
|
123
|
-
f"start
|
115
|
+
f"start pycityagent-sim at localhost:{self.sim_port}, PID={self._sim_proc.pid}"
|
124
116
|
)
|
125
|
-
|
117
|
+
sim_addr = f"http://localhost:{self.sim_port}"
|
126
118
|
atexit.register(self.close)
|
127
|
-
time.sleep(
|
128
|
-
elif simuletgo_addr is not None:
|
129
|
-
pass
|
119
|
+
time.sleep(0.3)
|
130
120
|
else:
|
131
|
-
|
132
|
-
# "simuletgo_addr, syncer_addr, routing_addr must be all None or all not None"
|
133
|
-
# )
|
134
|
-
pass
|
135
|
-
return simuletgo_addr
|
121
|
+
warnings.warn("单独启动模拟器模拟将被弃用", DeprecationWarning)
|
136
122
|
|
137
|
-
|
138
|
-
if self._simuletgo_proc is not None:
|
139
|
-
self._simuletgo_proc.terminate()
|
140
|
-
simuletgo_code = self._simuletgo_proc.wait()
|
141
|
-
logging.info(f"simulet-go exit with code {simuletgo_code}")
|
123
|
+
return sim_addr
|
142
124
|
|
143
|
-
|
144
|
-
self.
|
145
|
-
|
125
|
+
def close(self):
|
126
|
+
if self._sim_proc is not None:
|
127
|
+
self._sim_proc.terminate()
|
128
|
+
sim_code = self._sim_proc.wait()
|
129
|
+
logging.info(f"pycityagent-sim exit with code {sim_code}")
|
130
|
+
|
131
|
+
# sim
|
132
|
+
self.sim_port = None
|
133
|
+
self._sim_proc = None
|
@@ -60,11 +60,11 @@ class Simulator:
|
|
60
60
|
total_step=2147000000,
|
61
61
|
log_dir=config["simulator"].get("log_dir", "./log"),
|
62
62
|
min_step_time=config["simulator"].get("min_step_time", 1000),
|
63
|
-
|
63
|
+
sim_addr=config["simulator"].get("server", None),
|
64
64
|
)
|
65
65
|
|
66
66
|
# using local client
|
67
|
-
self._client = CityClient(sim_env.
|
67
|
+
self._client = CityClient(sim_env.sim_addr, secure=False)
|
68
68
|
"""
|
69
69
|
- 模拟器grpc客户端
|
70
70
|
- grpc client of simulator
|
@@ -173,7 +173,6 @@ class Simulator:
|
|
173
173
|
return formatted_time
|
174
174
|
else:
|
175
175
|
return int(now["t"])
|
176
|
-
|
177
176
|
async def pause(self):
|
178
177
|
await self._client.pause_service.pause()
|
179
178
|
|
pycityagent/llm/llm.py
CHANGED
@@ -1,25 +1,27 @@
|
|
1
1
|
"""UrbanLLM: 智能能力类及其定义"""
|
2
2
|
|
3
3
|
import json
|
4
|
-
from openai import OpenAI, AsyncOpenAI, APIConnectionError, OpenAIError
|
5
|
-
from zhipuai import ZhipuAI
|
6
4
|
import logging
|
7
5
|
|
6
|
+
from openai import APIConnectionError, AsyncOpenAI, OpenAI, OpenAIError
|
7
|
+
from zhipuai import ZhipuAI
|
8
|
+
|
8
9
|
logging.getLogger("zhipuai").setLevel(logging.WARNING)
|
9
10
|
|
10
11
|
import asyncio
|
12
|
+
import os
|
11
13
|
from http import HTTPStatus
|
14
|
+
from io import BytesIO
|
15
|
+
from typing import Any, Optional, Union
|
16
|
+
|
12
17
|
import dashscope
|
13
18
|
import requests
|
14
19
|
from dashscope import ImageSynthesis
|
15
20
|
from PIL import Image
|
16
|
-
|
17
|
-
from typing import Any, Optional, Union
|
21
|
+
|
18
22
|
from .llmconfig import *
|
19
23
|
from .utils import *
|
20
24
|
|
21
|
-
import os
|
22
|
-
|
23
25
|
os.environ["GRPC_VERBOSITY"] = "ERROR"
|
24
26
|
|
25
27
|
|
@@ -38,13 +40,13 @@ class LLM:
|
|
38
40
|
self.request_number = 0
|
39
41
|
self.semaphore = None
|
40
42
|
self._current_client_index = 0
|
41
|
-
|
43
|
+
|
42
44
|
api_keys = self.config.text["api_key"]
|
43
45
|
if not isinstance(api_keys, list):
|
44
46
|
api_keys = [api_keys]
|
45
|
-
|
47
|
+
|
46
48
|
self._aclients = []
|
47
|
-
|
49
|
+
|
48
50
|
for api_key in api_keys:
|
49
51
|
if self.config.text["request_type"] == "openai":
|
50
52
|
client = AsyncOpenAI(api_key=api_key, timeout=300)
|
@@ -62,6 +64,10 @@ class LLM:
|
|
62
64
|
)
|
63
65
|
elif self.config.text["request_type"] == "zhipuai":
|
64
66
|
client = ZhipuAI(api_key=api_key, timeout=300)
|
67
|
+
else:
|
68
|
+
raise ValueError(
|
69
|
+
f"Unsupported `request_type` {self.config.text['request_type']}!"
|
70
|
+
)
|
65
71
|
self._aclients.append(client)
|
66
72
|
|
67
73
|
def set_semaphore(self, number_of_coroutine: int):
|
@@ -118,7 +124,9 @@ Token Usage:
|
|
118
124
|
def _get_next_client(self):
|
119
125
|
"""获取下一个要使用的客户端"""
|
120
126
|
client = self._aclients[self._current_client_index]
|
121
|
-
self._current_client_index = (self._current_client_index + 1) % len(
|
127
|
+
self._current_client_index = (self._current_client_index + 1) % len(
|
128
|
+
self._aclients
|
129
|
+
)
|
122
130
|
return client
|
123
131
|
|
124
132
|
async def atext_request(
|