pycityagent 1.0.0__tar.gz → 1.1.0__tar.gz
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.
- {pycityagent-1.0.0 → pycityagent-1.1.0}/PKG-INFO +46 -18
- {pycityagent-1.0.0 → pycityagent-1.1.0}/README.md +44 -16
- pycityagent-1.1.0/pycityagent/__init__.py +6 -0
- pycityagent-1.1.0/pycityagent/ac/__init__.py +8 -0
- pycityagent-1.1.0/pycityagent/ac/ac.py +67 -0
- pycityagent-1.1.0/pycityagent/ac/action.py +55 -0
- pycityagent-1.1.0/pycityagent/ac/action_stream.py +25 -0
- pycityagent-1.1.0/pycityagent/ac/citizen_actions/controled.py +16 -0
- pycityagent-1.1.0/pycityagent/ac/citizen_actions/converse.py +34 -0
- pycityagent-1.1.0/pycityagent/ac/citizen_actions/idle.py +20 -0
- pycityagent-1.1.0/pycityagent/ac/citizen_actions/shop.py +82 -0
- pycityagent-1.1.0/pycityagent/ac/citizen_actions/trip.py +41 -0
- pycityagent-1.1.0/pycityagent/ac/hub_actions.py +93 -0
- pycityagent-1.1.0/pycityagent/ac/sim_actions.py +80 -0
- pycityagent-1.1.0/pycityagent/agent.py +272 -0
- pycityagent-1.1.0/pycityagent/agent_citizen.py +158 -0
- pycityagent-1.1.0/pycityagent/agent_func.py +115 -0
- pycityagent-1.1.0/pycityagent/brain/__init__.py +10 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/brain/memory.py +200 -106
- pycityagent-1.1.0/pycityagent/brain/sence.py +669 -0
- pycityagent-1.1.0/pycityagent/cc/__init__.py +5 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/cc/cc.py +40 -36
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/hubconnector/hubconnector.py +23 -31
- pycityagent-1.1.0/pycityagent/image/__init__.py +3 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/image/image.py +48 -44
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/simulator.py +39 -39
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/st/st.py +44 -7
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent.egg-info/PKG-INFO +46 -18
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent.egg-info/SOURCES.txt +10 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent.egg-info/requires.txt +1 -1
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pyproject.toml +1 -1
- pycityagent-1.0.0/pycityagent/__init__.py +0 -4
- pycityagent-1.0.0/pycityagent/ac/__init__.py +0 -6
- pycityagent-1.0.0/pycityagent/ac/ac.py +0 -50
- pycityagent-1.0.0/pycityagent/ac/action.py +0 -14
- pycityagent-1.0.0/pycityagent/agent.py +0 -318
- pycityagent-1.0.0/pycityagent/brain/__init__.py +0 -10
- pycityagent-1.0.0/pycityagent/brain/sence.py +0 -375
- pycityagent-1.0.0/pycityagent/cc/__init__.py +0 -5
- pycityagent-1.0.0/pycityagent/image/__init__.py +0 -3
- {pycityagent-1.0.0 → pycityagent-1.1.0}/LICENSE +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/ac/controled.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/ac/converse.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/ac/idle.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/ac/shop.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/ac/trip.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/brain/brain.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/brain/brainfc.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/brain/persistence/__init__.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/brain/persistence/social.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/brain/persistence/spatial.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/brain/reason/__init__.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/brain/reason/shop.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/brain/reason/social.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/brain/reason/trip.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/brain/reason/user.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/brain/retrive/__init__.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/brain/retrive/social.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/brain/scheduler.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/brain/static.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/cc/conve.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/cc/idle.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/cc/shop.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/cc/trip.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/cc/user.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/hubconnector/__init__.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/st/__init__.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/urbanllm/__init__.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent/urbanllm/urbanllm.py +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent.egg-info/dependency_links.txt +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/pycityagent.egg-info/top_level.txt +0 -0
- {pycityagent-1.0.0 → pycityagent-1.1.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: pycityagent
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.1.0
|
4
4
|
Summary: LLM-based城市模拟器agent构建库
|
5
5
|
Author-email: Yuwei Yan <pinkgranite86@gmail.com>
|
6
6
|
License: MIT License
|
@@ -39,7 +39,7 @@ Requires-Dist: geojson>=3.1.0
|
|
39
39
|
Requires-Dist: numpy>=1.26.3
|
40
40
|
Requires-Dist: openai>=1.8.0
|
41
41
|
Requires-Dist: Pillow>=10.2.0
|
42
|
-
Requires-Dist: pycitysim>=1.
|
42
|
+
Requires-Dist: pycitysim>=1.12.2
|
43
43
|
Requires-Dist: citystreetview>=1.1.0
|
44
44
|
Requires-Dist: PyYAML>=6.0.1
|
45
45
|
Requires-Dist: Requests>=2.31.0
|
@@ -92,10 +92,12 @@ citysim_request:
|
|
92
92
|
map_request:
|
93
93
|
mongo_coll: map_beijing_extend_20240205
|
94
94
|
cache_dir: ./cache
|
95
|
+
route_request:
|
96
|
+
server: http://api-opencity-2x.fiblab.net:58082
|
95
97
|
streetview_request:
|
96
98
|
engine: baidumap / googlemap
|
97
|
-
mapAK:
|
98
|
-
proxy:
|
99
|
+
mapAK: baidumap api-key (if you use baidumap engine)
|
100
|
+
proxy: googlemap proxy (if you use googlemap engine)
|
99
101
|
|
100
102
|
apphub_request:
|
101
103
|
hub_url: https://api-opencity-2x.fiblab.net:58080
|
@@ -106,31 +108,56 @@ apphub_request:
|
|
106
108
|
- Forget about **citysim_request**, let's focus on the other two.
|
107
109
|
|
108
110
|
#### LLM_REQUEST
|
109
|
-
- As you can
|
111
|
+
- As you can see, the whole CityAgent is based on the LLM, by now, there are three different parts of config items: **text_request**, **img_understand_request** and **img_generate_request**
|
110
112
|
- By now, we support [**qwen**](https://tongyi.aliyun.com/) and [**openai**](https://openai.com/)
|
111
113
|
- `Notice: Our environments are basically conducted with qwen. If you prefer to use openai, then you may encounter hardships. AND fell free to issue us.`
|
112
114
|
- Get your **api_key** and chooce your **model**s
|
113
115
|
|
114
|
-
|
115
|
-
-
|
116
|
-
-
|
117
|
-
|
118
|
-
-
|
119
|
-
|
116
|
+
#### CITYSIM_REQUEST
|
117
|
+
- Most of the configuration options in this part are determined, such as **simulator.server**, **map_request.mongo_coll**, **route_request.server**
|
118
|
+
- **map_request.cache_dir**: used for storing map data your machine, you can justify the target dir as you wish (**create the dir first**)
|
119
|
+
- **streetview_request**: used for obtaining streetview images, by now, we support baidumap engine and googlemap engine
|
120
|
+
- if you choose baidumap engine, you need to get a baidumap api-key
|
121
|
+
``` yaml
|
122
|
+
streetview_request:
|
123
|
+
engine: baidumap
|
124
|
+
mapAK: xxxx
|
125
|
+
```
|
126
|
+
- if you choose googlemap engine, you need to provide your proxy address, for example:
|
127
|
+
``` yaml
|
128
|
+
streetview_request:
|
129
|
+
engine: googlemap
|
130
|
+
proxy:
|
131
|
+
http: http://xxxx
|
132
|
+
https: https://xxxx
|
133
|
+
```
|
120
134
|
|
121
135
|
#### APPHUB_REQUEST
|
122
|
-
-
|
136
|
+
- Used for creating the connection between backend server and client.
|
123
137
|
- Put your **app_id** and **app_secret** here.
|
138
|
+
- Create your account and apply in [Opencity website](https://opencity.fiblab.net/)
|
124
139
|
|
125
140
|
### Installation
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
141
|
+
#### PyPI Installation
|
142
|
+
- Install from **pip** easily.
|
143
|
+
```shell
|
144
|
+
pip install pycityagent
|
145
|
+
```
|
146
|
+
|
147
|
+
#### Install from source code
|
148
|
+
- Clone this repo
|
149
|
+
- Install required packages
|
150
|
+
``` shell
|
151
|
+
pip install -r requirements.txt
|
152
|
+
```
|
153
|
+
- Install **libGL.so.1**, if you ara using Linux with a suitable package manager: (apt for instance)
|
154
|
+
``` shell
|
155
|
+
apt-get install libgl1
|
156
|
+
```
|
130
157
|
|
131
158
|
### CODE and RUN
|
132
159
|
- Check the **example** folder and copy files from it (`Remember replace the config file`)
|
133
|
-
- Look at the Demo:
|
160
|
+
- Look at the Demo: (A citizen Agent demo)
|
134
161
|
```python
|
135
162
|
import yaml
|
136
163
|
from pycityagent.simulator import Simulator
|
@@ -147,7 +174,7 @@ async def main():
|
|
147
174
|
smi = Simulator(config['citysim_request'])
|
148
175
|
|
149
176
|
# get the person by person_id, return agent
|
150
|
-
agent = await smi.
|
177
|
+
agent = await smi.GetCitizenAgent("name_of_agent", 8)
|
151
178
|
|
152
179
|
# Help you build unique agent by scratch/profile
|
153
180
|
agent.Image.load_scratch('scratch_template.json')
|
@@ -158,6 +185,7 @@ async def main():
|
|
158
185
|
|
159
186
|
# Connect to apphub so you can interact with your agent in front end
|
160
187
|
agent.ConnectToHub(config['apphub_request'])
|
188
|
+
agent.Bind()
|
161
189
|
|
162
190
|
# Creat the soul (a LLM processor actually)
|
163
191
|
llmConfig = LLMConfig(config['llm_request'])
|
@@ -45,10 +45,12 @@ citysim_request:
|
|
45
45
|
map_request:
|
46
46
|
mongo_coll: map_beijing_extend_20240205
|
47
47
|
cache_dir: ./cache
|
48
|
+
route_request:
|
49
|
+
server: http://api-opencity-2x.fiblab.net:58082
|
48
50
|
streetview_request:
|
49
51
|
engine: baidumap / googlemap
|
50
|
-
mapAK:
|
51
|
-
proxy:
|
52
|
+
mapAK: baidumap api-key (if you use baidumap engine)
|
53
|
+
proxy: googlemap proxy (if you use googlemap engine)
|
52
54
|
|
53
55
|
apphub_request:
|
54
56
|
hub_url: https://api-opencity-2x.fiblab.net:58080
|
@@ -59,31 +61,56 @@ apphub_request:
|
|
59
61
|
- Forget about **citysim_request**, let's focus on the other two.
|
60
62
|
|
61
63
|
#### LLM_REQUEST
|
62
|
-
- As you can
|
64
|
+
- As you can see, the whole CityAgent is based on the LLM, by now, there are three different parts of config items: **text_request**, **img_understand_request** and **img_generate_request**
|
63
65
|
- By now, we support [**qwen**](https://tongyi.aliyun.com/) and [**openai**](https://openai.com/)
|
64
66
|
- `Notice: Our environments are basically conducted with qwen. If you prefer to use openai, then you may encounter hardships. AND fell free to issue us.`
|
65
67
|
- Get your **api_key** and chooce your **model**s
|
66
68
|
|
67
|
-
|
68
|
-
-
|
69
|
-
-
|
70
|
-
|
71
|
-
-
|
72
|
-
|
69
|
+
#### CITYSIM_REQUEST
|
70
|
+
- Most of the configuration options in this part are determined, such as **simulator.server**, **map_request.mongo_coll**, **route_request.server**
|
71
|
+
- **map_request.cache_dir**: used for storing map data your machine, you can justify the target dir as you wish (**create the dir first**)
|
72
|
+
- **streetview_request**: used for obtaining streetview images, by now, we support baidumap engine and googlemap engine
|
73
|
+
- if you choose baidumap engine, you need to get a baidumap api-key
|
74
|
+
``` yaml
|
75
|
+
streetview_request:
|
76
|
+
engine: baidumap
|
77
|
+
mapAK: xxxx
|
78
|
+
```
|
79
|
+
- if you choose googlemap engine, you need to provide your proxy address, for example:
|
80
|
+
``` yaml
|
81
|
+
streetview_request:
|
82
|
+
engine: googlemap
|
83
|
+
proxy:
|
84
|
+
http: http://xxxx
|
85
|
+
https: https://xxxx
|
86
|
+
```
|
73
87
|
|
74
88
|
#### APPHUB_REQUEST
|
75
|
-
-
|
89
|
+
- Used for creating the connection between backend server and client.
|
76
90
|
- Put your **app_id** and **app_secret** here.
|
91
|
+
- Create your account and apply in [Opencity website](https://opencity.fiblab.net/)
|
77
92
|
|
78
93
|
### Installation
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
94
|
+
#### PyPI Installation
|
95
|
+
- Install from **pip** easily.
|
96
|
+
```shell
|
97
|
+
pip install pycityagent
|
98
|
+
```
|
99
|
+
|
100
|
+
#### Install from source code
|
101
|
+
- Clone this repo
|
102
|
+
- Install required packages
|
103
|
+
``` shell
|
104
|
+
pip install -r requirements.txt
|
105
|
+
```
|
106
|
+
- Install **libGL.so.1**, if you ara using Linux with a suitable package manager: (apt for instance)
|
107
|
+
``` shell
|
108
|
+
apt-get install libgl1
|
109
|
+
```
|
83
110
|
|
84
111
|
### CODE and RUN
|
85
112
|
- Check the **example** folder and copy files from it (`Remember replace the config file`)
|
86
|
-
- Look at the Demo:
|
113
|
+
- Look at the Demo: (A citizen Agent demo)
|
87
114
|
```python
|
88
115
|
import yaml
|
89
116
|
from pycityagent.simulator import Simulator
|
@@ -100,7 +127,7 @@ async def main():
|
|
100
127
|
smi = Simulator(config['citysim_request'])
|
101
128
|
|
102
129
|
# get the person by person_id, return agent
|
103
|
-
agent = await smi.
|
130
|
+
agent = await smi.GetCitizenAgent("name_of_agent", 8)
|
104
131
|
|
105
132
|
# Help you build unique agent by scratch/profile
|
106
133
|
agent.Image.load_scratch('scratch_template.json')
|
@@ -111,6 +138,7 @@ async def main():
|
|
111
138
|
|
112
139
|
# Connect to apphub so you can interact with your agent in front end
|
113
140
|
agent.ConnectToHub(config['apphub_request'])
|
141
|
+
agent.Bind()
|
114
142
|
|
115
143
|
# Creat the soul (a LLM processor actually)
|
116
144
|
llmConfig = LLMConfig(config['llm_request'])
|
@@ -0,0 +1,8 @@
|
|
1
|
+
'''Action Control - 最终进行simulator以及AppHub对接'''
|
2
|
+
|
3
|
+
from .ac import *
|
4
|
+
from .action import *
|
5
|
+
from .hub_actions import *
|
6
|
+
from .sim_actions import *
|
7
|
+
|
8
|
+
__all__ = [ActionController, Action, HubAction, SimAction, SendUserMessage, SendStreetview, SendPop, PositionUpdate, ShowPath, ShowPosition, SetSchedule, SendAgentMessage]
|
@@ -0,0 +1,67 @@
|
|
1
|
+
from typing import Any, Optional, Union
|
2
|
+
from .action import Action
|
3
|
+
from .citizen_actions.trip import TripAction
|
4
|
+
from .citizen_actions.shop import ShopAction
|
5
|
+
from .citizen_actions.converse import ConverseAction
|
6
|
+
from .citizen_actions.controled import ControledAction
|
7
|
+
from .citizen_actions.idle import IdleAction
|
8
|
+
|
9
|
+
class ActionController:
|
10
|
+
"""
|
11
|
+
Agent行为控制器: 与AppHub(simulator)对接
|
12
|
+
Agent Controller: Connect with AppHub and Simulator
|
13
|
+
Note: Actions are predefined. By now, user defined actions are not supported
|
14
|
+
"""
|
15
|
+
def __init__(self, agent) -> None:
|
16
|
+
self._agent = agent
|
17
|
+
self.action_chain = {}
|
18
|
+
self.reset_ac()
|
19
|
+
self._init_actions()
|
20
|
+
|
21
|
+
async def Run(self):
|
22
|
+
agent_state = self._agent.state
|
23
|
+
if agent_state in self.action_chain.keys():
|
24
|
+
for action in self.action_chain[agent_state]:
|
25
|
+
await action.Forward()
|
26
|
+
|
27
|
+
def clear_ac(self):
|
28
|
+
"""
|
29
|
+
清空AC
|
30
|
+
"""
|
31
|
+
self.action_chain.clear()
|
32
|
+
|
33
|
+
def reset_ac(self):
|
34
|
+
"""
|
35
|
+
重置Action Controller
|
36
|
+
Reset action controller
|
37
|
+
"""
|
38
|
+
self.action_chain.clear()
|
39
|
+
for state in self._agent._st.machine.states.keys():
|
40
|
+
self.action_chain[state] = []
|
41
|
+
|
42
|
+
def set_ac(self, states:list[str]):
|
43
|
+
"""
|
44
|
+
设置ac
|
45
|
+
"""
|
46
|
+
self.action_chain.clear()
|
47
|
+
for state in states:
|
48
|
+
self.action_chain[state] = []
|
49
|
+
|
50
|
+
def add_actions(self, state:str, actions:Union[Action, list[Action]]):
|
51
|
+
"""
|
52
|
+
添加Action到目标动作链
|
53
|
+
"""
|
54
|
+
if issubclass(type(actions), Action) or isinstance(actions, Action):
|
55
|
+
self.action_chain[state].append(actions)
|
56
|
+
else:
|
57
|
+
self.action_chain[state] += actions
|
58
|
+
|
59
|
+
def _init_actions(self):
|
60
|
+
"""
|
61
|
+
构建初始化动作链——适用于citizen类型的agent
|
62
|
+
"""
|
63
|
+
self.action_chain['trip'] = [TripAction(self._agent)]
|
64
|
+
self.action_chain['shop'] = [ShopAction(self._agent)]
|
65
|
+
self.action_chain['conve'] = [ConverseAction(self._agent)]
|
66
|
+
self.action_chain['controled'] = [ControledAction(self._agent)]
|
67
|
+
self.action_chain['idle'] = [IdleAction(self._agent)]
|
@@ -0,0 +1,55 @@
|
|
1
|
+
from abc import ABC, abstractclassmethod
|
2
|
+
from typing import Callable, Any
|
3
|
+
|
4
|
+
class ActionType:
|
5
|
+
"""
|
6
|
+
行动类型枚举 所有行动本质上为数据推送
|
7
|
+
Action Type enumeration, all actions are essentially data push
|
8
|
+
|
9
|
+
Types:
|
10
|
+
- Sim = 1, 用于表示与模拟器对接的行动
|
11
|
+
- Hub = 2, 用于表示与AppHub(前端)对接的行动
|
12
|
+
- Comp = 3, 表示综合类型 (可能同时包含与Sim以及Hub的交互)
|
13
|
+
"""
|
14
|
+
Sim = 1
|
15
|
+
Hub = 2
|
16
|
+
Comp = 3
|
17
|
+
class Action:
|
18
|
+
def __init__(self, agent, type:ActionType, source: str = None, before:Callable[[list], Any] = None) -> None:
|
19
|
+
'''
|
20
|
+
默认初始化
|
21
|
+
|
22
|
+
Args:
|
23
|
+
- agent (Agent): the related agent
|
24
|
+
- type (ActionType)
|
25
|
+
- source (str): 数据来源, 默认为None, 如果为None则会从接收用户传入的数据作为Forward函数参数, 否则从WM.Reason数据缓存中取对应数据作为参数
|
26
|
+
- before (function): 数据处理方法, 用于当Reason缓存中的参数与标准格式不符时使用
|
27
|
+
'''
|
28
|
+
self._agent = agent
|
29
|
+
self._type = type
|
30
|
+
self._source = source
|
31
|
+
self._before = before
|
32
|
+
|
33
|
+
def get_source(self):
|
34
|
+
"""
|
35
|
+
获取source数据
|
36
|
+
"""
|
37
|
+
if self._source != None:
|
38
|
+
source = self._agent.Brain.Memory.Working.Reason[self._source]
|
39
|
+
if self._before != None:
|
40
|
+
source = self._before(source)
|
41
|
+
return source
|
42
|
+
else:
|
43
|
+
return None
|
44
|
+
|
45
|
+
@abstractclassmethod
|
46
|
+
async def Forward(self):
|
47
|
+
'''接口函数'''
|
48
|
+
|
49
|
+
class SimAction(Action):
|
50
|
+
def __init__(self, agent, source: str = None, before: Callable[[list], Any] = None) -> None:
|
51
|
+
super().__init__(agent, ActionType.Sim, source, before)
|
52
|
+
|
53
|
+
class HubAction(Action):
|
54
|
+
def __init__(self, agent, source: str = None, before: Callable[[list], Any] = None) -> None:
|
55
|
+
super().__init__(agent, ActionType.Hub, source, before)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
from abc import ABC, abstractclassmethod
|
2
|
+
from typing import Any, Optional
|
3
|
+
from action import Action
|
4
|
+
|
5
|
+
class ActionStream:
|
6
|
+
"""
|
7
|
+
可以将多个Action聚合在一起构成一个ActionStream, Stream中的Action会顺序执行
|
8
|
+
You can collect multiple Actions into a ActionStream, actions in stream will be activated in sequence
|
9
|
+
注意: 该部分内容目前没有使用
|
10
|
+
"""
|
11
|
+
def __init__(self, actions:Optional[list[Action]]=[]) -> None:
|
12
|
+
self.actions = actions
|
13
|
+
|
14
|
+
def add_actions(self, actions:list[Action]):
|
15
|
+
"""
|
16
|
+
添加Action至当前stream
|
17
|
+
|
18
|
+
Args:
|
19
|
+
- actions (list(Action)): a list of action
|
20
|
+
"""
|
21
|
+
self.actions += actions
|
22
|
+
|
23
|
+
def __call__(self) -> Any:
|
24
|
+
for action in self.actions:
|
25
|
+
action()
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import time
|
2
|
+
from typing import Callable, Any
|
3
|
+
|
4
|
+
from pycityagent.ac.action import ActionType
|
5
|
+
from ..action import Action
|
6
|
+
from pycitysim.apphub import AgentMessage
|
7
|
+
|
8
|
+
class ControledAction(Action):
|
9
|
+
'''Converse行为控制器'''
|
10
|
+
def __init__(self, agent, sources: list[str] = None, before: Callable[[list], Any] = None) -> None:
|
11
|
+
super().__init__(agent, ActionType.Comp, sources, before)
|
12
|
+
|
13
|
+
async def Forward(self):
|
14
|
+
req = {'person_id': self._agent._id, 'schedules': []}
|
15
|
+
await self._agent._client.person_service.SetSchedule(req)
|
16
|
+
self._agent.Hub.Update([AgentMessage(self._agent.Hub._agent_id, int(time.time()*1000), '我已理解您的意思,正在修改我的行程', None, None)])
|
@@ -0,0 +1,34 @@
|
|
1
|
+
import time
|
2
|
+
from typing import Callable, Any
|
3
|
+
|
4
|
+
from pycityagent.ac.action import ActionType
|
5
|
+
from ..action import Action
|
6
|
+
from pycitysim.apphub import AgentMessage
|
7
|
+
|
8
|
+
class ConverseAction(Action):
|
9
|
+
'''Converse行为控制器'''
|
10
|
+
def __init__(self, agent, sources: list[str] = None, before: Callable[[list], Any] = None) -> None:
|
11
|
+
super().__init__(agent, ActionType.Comp, sources, before)
|
12
|
+
|
13
|
+
async def Forward(self):
|
14
|
+
target_agent_ids = self._agent.Brain.Memory.Working.Reason['agent_message_handle_resp'][0]
|
15
|
+
if len(target_agent_ids) == 0:
|
16
|
+
return
|
17
|
+
messages = self._agent.Brain.Memory.Working.Reason['agent_message_handle_resp'][1]
|
18
|
+
req = {'messages': []}
|
19
|
+
if len(target_agent_ids) != len(messages):
|
20
|
+
print("Warning: the number of target agent and message are not aligned, only sends matched messages")
|
21
|
+
rng = min(len(target_agent_ids), len(messages))
|
22
|
+
for i in range(rng):
|
23
|
+
dic = {}
|
24
|
+
dic['from'] = self._agent._id
|
25
|
+
dic['to'] = target_agent_ids[i]
|
26
|
+
dic['message'] = messages[i]
|
27
|
+
req['messages'].append(dic)
|
28
|
+
# * 发送至模拟器
|
29
|
+
await self._agent._client.social_service.Send(req=req)
|
30
|
+
|
31
|
+
# * 发送至AppHub
|
32
|
+
if self._agent.Hub != None and messages[0] != 'End':
|
33
|
+
# * 将信息中的第一条不同至pop
|
34
|
+
self._agent.Hub.Update(pop=messages[0])
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import time
|
2
|
+
from typing import Callable, Any
|
3
|
+
|
4
|
+
from pycityagent.ac.action import ActionType
|
5
|
+
from ..action import Action
|
6
|
+
from pycitysim.apphub import AgentMessage
|
7
|
+
|
8
|
+
class IdleAction(Action):
|
9
|
+
'''idle行为控制器'''
|
10
|
+
def __init__(self, agent, sources: list[str] = None, before: Callable[[list], Any] = None) -> None:
|
11
|
+
super().__init__(agent, ActionType.Comp, sources, before)
|
12
|
+
|
13
|
+
async def Forward(self):
|
14
|
+
if len(self._agent.base['schedules']) > 0:
|
15
|
+
req = {'person_id': self._agent._id, 'schedules': []}
|
16
|
+
await self._agent._client.person_service.SetSchedule(req)
|
17
|
+
if self._agent.Hub != None:
|
18
|
+
self._agent.Hub.Update()
|
19
|
+
|
20
|
+
|
@@ -0,0 +1,82 @@
|
|
1
|
+
from typing import Callable, Any
|
2
|
+
from pycityagent.ac.action import ActionType
|
3
|
+
from ..action import Action
|
4
|
+
from pycitysim.apphub import AgentMessage
|
5
|
+
import time
|
6
|
+
|
7
|
+
def encap_msg(msg, role='user', **kwargs):
|
8
|
+
dialog = {'role': role, 'content': msg}
|
9
|
+
dialog.update(kwargs)
|
10
|
+
return dialog
|
11
|
+
|
12
|
+
class ShopAction(Action):
|
13
|
+
'''Shop行为控制器'''
|
14
|
+
def __init__(self, agent, sources: list[str] = None, before: Callable[[list], Any] = None) -> None:
|
15
|
+
super().__init__(agent, ActionType.Comp, sources, before)
|
16
|
+
|
17
|
+
async def Forward(self):
|
18
|
+
# * 与模拟器对接 - 暂时没有
|
19
|
+
# * 与AppHub对接
|
20
|
+
profile = self._agent.Image.get_profile()
|
21
|
+
self.consumption(profile)
|
22
|
+
|
23
|
+
def consumption(self, profile, mall_info):
|
24
|
+
dialogs = []
|
25
|
+
system_prompt = f'''
|
26
|
+
你是一个在北京工作和生活的人。
|
27
|
+
{profile}
|
28
|
+
现在是2024年1月。
|
29
|
+
你需要为下一周的基本生活购买必需品。
|
30
|
+
'''
|
31
|
+
dialogs.append(encap_msg(system_prompt, 'system'))
|
32
|
+
actions_format = ['''{{'商品': 购买的商品的列表,'购买量': 每个商品的购买量,一个列表, '解释': '这种购买方式的原因'}}''']
|
33
|
+
actions_candidates = ['''【食品】
|
34
|
+
米:10元/公斤
|
35
|
+
面粉:7.5元/公斤
|
36
|
+
新鲜蔬菜(如菠菜):7元/500克
|
37
|
+
水果(如苹果):15元/公斤
|
38
|
+
猪肉:30元/公斤
|
39
|
+
鸡肉:20元/公斤
|
40
|
+
鸡蛋:1.5元/个
|
41
|
+
牛奶:10元/升''',
|
42
|
+
'''【清洁用品】
|
43
|
+
洗衣液:30元/瓶
|
44
|
+
洗洁精:20元/瓶
|
45
|
+
垃圾袋:0.3元/个''',
|
46
|
+
'''【个人护理用品】
|
47
|
+
牙膏:10元/支
|
48
|
+
洗发水:30元/瓶
|
49
|
+
沐浴露:35元/瓶
|
50
|
+
面巾纸:5元/包''',
|
51
|
+
'''【其他】
|
52
|
+
矿泉水:1.7元/瓶
|
53
|
+
面包:8元/个
|
54
|
+
辣条:3元/包''']
|
55
|
+
|
56
|
+
user_prompt = f'''
|
57
|
+
首先确定你的消费预算。以如下格式回答,不要有冗余的文本!
|
58
|
+
{{'消费预算': 一个代表购买必需品需要消耗的钱的数量的数字}}
|
59
|
+
'''
|
60
|
+
dialogs.append(encap_msg(user_prompt))
|
61
|
+
# * 对接一:确定消费预算
|
62
|
+
self._agent.Hub.Update([AgentMessage(self._agent.Hub._agent_id, int(time.time()*1000), '我正在确定消费预算......', None, None)])
|
63
|
+
msg = self._agent._soul.text_request(dialogs)
|
64
|
+
self._agent.Hub.Update([AgentMessage(self._agent.Hub._agent_id, int(time.time()*1000), f'我的消费预算是: {msg}'), None, None])
|
65
|
+
|
66
|
+
dialogs.append(encap_msg(msg, 'assistant'))
|
67
|
+
|
68
|
+
# * 对接二:购物选择
|
69
|
+
for cand in actions_candidates:
|
70
|
+
user_prompt = f'''
|
71
|
+
购物中心里有
|
72
|
+
{cand}
|
73
|
+
你要买哪些商品,以如下格式回答,不要有冗余的文本!
|
74
|
+
{actions_format[0]}
|
75
|
+
'''
|
76
|
+
self._agent.Hub.Update([AgentMessage(self._agent.Hub._agent_id, int(time.time()*1000), f'我看到了\n {cand}', None, None)])
|
77
|
+
dialogs.append(encap_msg(user_prompt))
|
78
|
+
msg = self._agent._soul.text_request(dialogs)
|
79
|
+
self._agent.Hub.Update([AgentMessage(self._agent.Hub._agent_id, int(time.time()*1000), f'我的购买选择是: {msg}', None, None)])
|
80
|
+
dialogs.append(encap_msg(msg, 'assistant'))
|
81
|
+
|
82
|
+
self._agent.Hub.Update([AgentMessage(self._agent.Hub._agent_id, int(time.time()*1000), '购物完成', None, None)])
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import time
|
2
|
+
from typing import Callable, Any
|
3
|
+
|
4
|
+
from pycityagent.ac.action import ActionType
|
5
|
+
from ..action import Action
|
6
|
+
from pycitysim.apphub import AgentMessage
|
7
|
+
|
8
|
+
class TripAction(Action):
|
9
|
+
'''Trip行为控制器'''
|
10
|
+
def __init__(self, agent, sources: list[str] = None, before: Callable[[list], Any] = None) -> None:
|
11
|
+
super().__init__(agent, ActionType.Comp, sources, before)
|
12
|
+
|
13
|
+
async def Forward(self):
|
14
|
+
now = self._agent.Scheduler.now
|
15
|
+
if now.is_set:
|
16
|
+
# TODO: 目前仅支持传输一张图片至前端
|
17
|
+
'''之前已经将schedule同步至模拟器了'''
|
18
|
+
if self._agent.Hub != None:
|
19
|
+
self._agent.Hub.Update(streetview=self._agent.Brain.Sence.sence_buffer['streetview'][0])
|
20
|
+
else:
|
21
|
+
'''同步schedule至模拟器'''
|
22
|
+
self._agent.Scheduler.now.is_set = True
|
23
|
+
departure_time = now.time
|
24
|
+
mode = now.mode
|
25
|
+
aoi_id = now.target_id_aoi
|
26
|
+
poi_id = now.target_id_poi
|
27
|
+
end = {'aoi_position': {'aoi_id': aoi_id, 'poi_id': poi_id}}
|
28
|
+
activity = now.description
|
29
|
+
trips = [{'mode': mode, 'end': end, 'departure_time': departure_time, 'activity': activity}]
|
30
|
+
set_schedule = [{'trips': trips, 'loop_count': 1, 'departure_time': departure_time}]
|
31
|
+
|
32
|
+
# * 与模拟器对接
|
33
|
+
req = {'person_id': self._agent._id, 'schedules': set_schedule}
|
34
|
+
await self._agent._client.person_service.SetSchedule(req)
|
35
|
+
|
36
|
+
# * 与AppHub对接
|
37
|
+
if self._agent.Hub != None:
|
38
|
+
messages = [AgentMessage(self._agent.Hub._agent_id, int(time.time()*1000), f'已到达出发时间, {activity}', None, None)]
|
39
|
+
self._agent.Hub.Update(messages)
|
40
|
+
|
41
|
+
|