pycityagent 1.0.0__py3-none-any.whl → 2.0.0a2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. pycityagent/__init__.py +7 -3
  2. pycityagent/agent.py +180 -284
  3. pycityagent/economy/__init__.py +5 -0
  4. pycityagent/economy/econ_client.py +307 -0
  5. pycityagent/environment/__init__.py +7 -0
  6. pycityagent/environment/interact/interact.py +141 -0
  7. pycityagent/environment/sence/__init__.py +0 -0
  8. pycityagent/{brain → environment/sence}/static.py +1 -1
  9. pycityagent/environment/sidecar/__init__.py +8 -0
  10. pycityagent/environment/sidecar/sidecarv2.py +109 -0
  11. pycityagent/environment/sim/__init__.py +29 -0
  12. pycityagent/environment/sim/aoi_service.py +38 -0
  13. pycityagent/environment/sim/client.py +126 -0
  14. pycityagent/environment/sim/clock_service.py +43 -0
  15. pycityagent/environment/sim/economy_services.py +191 -0
  16. pycityagent/environment/sim/lane_service.py +110 -0
  17. pycityagent/environment/sim/light_service.py +120 -0
  18. pycityagent/environment/sim/person_service.py +294 -0
  19. pycityagent/environment/sim/road_service.py +38 -0
  20. pycityagent/environment/sim/sim_env.py +145 -0
  21. pycityagent/environment/sim/social_service.py +58 -0
  22. pycityagent/environment/simulator.py +320 -0
  23. pycityagent/environment/utils/__init__.py +10 -0
  24. pycityagent/environment/utils/base64.py +16 -0
  25. pycityagent/environment/utils/const.py +242 -0
  26. pycityagent/environment/utils/geojson.py +26 -0
  27. pycityagent/environment/utils/grpc.py +57 -0
  28. pycityagent/environment/utils/map_utils.py +157 -0
  29. pycityagent/environment/utils/port.py +11 -0
  30. pycityagent/environment/utils/protobuf.py +39 -0
  31. pycityagent/llm/__init__.py +6 -0
  32. pycityagent/llm/embedding.py +136 -0
  33. pycityagent/llm/llm.py +430 -0
  34. pycityagent/llm/llmconfig.py +15 -0
  35. pycityagent/llm/utils.py +6 -0
  36. pycityagent/memory/__init__.py +11 -0
  37. pycityagent/memory/const.py +41 -0
  38. pycityagent/memory/memory.py +453 -0
  39. pycityagent/memory/memory_base.py +168 -0
  40. pycityagent/memory/profile.py +165 -0
  41. pycityagent/memory/self_define.py +165 -0
  42. pycityagent/memory/state.py +173 -0
  43. pycityagent/memory/utils.py +27 -0
  44. pycityagent/message/__init__.py +0 -0
  45. pycityagent/simulation/__init__.py +7 -0
  46. pycityagent/simulation/interview.py +36 -0
  47. pycityagent/simulation/simulation.py +352 -0
  48. pycityagent/simulation/survey/__init__.py +9 -0
  49. pycityagent/simulation/survey/manager.py +67 -0
  50. pycityagent/simulation/survey/models.py +49 -0
  51. pycityagent/simulation/ui/__init__.py +3 -0
  52. pycityagent/simulation/ui/interface.py +602 -0
  53. pycityagent/utils/__init__.py +0 -0
  54. pycityagent/utils/decorators.py +89 -0
  55. pycityagent/utils/parsers/__init__.py +12 -0
  56. pycityagent/utils/parsers/code_block_parser.py +37 -0
  57. pycityagent/utils/parsers/json_parser.py +86 -0
  58. pycityagent/utils/parsers/parser_base.py +60 -0
  59. pycityagent/workflow/__init__.py +24 -0
  60. pycityagent/workflow/block.py +164 -0
  61. pycityagent/workflow/prompt.py +72 -0
  62. pycityagent/workflow/tool.py +246 -0
  63. pycityagent/workflow/trigger.py +150 -0
  64. pycityagent-2.0.0a2.dist-info/METADATA +208 -0
  65. pycityagent-2.0.0a2.dist-info/RECORD +69 -0
  66. {pycityagent-1.0.0.dist-info → pycityagent-2.0.0a2.dist-info}/WHEEL +1 -2
  67. pycityagent/ac/__init__.py +0 -6
  68. pycityagent/ac/ac.py +0 -50
  69. pycityagent/ac/action.py +0 -14
  70. pycityagent/ac/controled.py +0 -13
  71. pycityagent/ac/converse.py +0 -31
  72. pycityagent/ac/idle.py +0 -17
  73. pycityagent/ac/shop.py +0 -80
  74. pycityagent/ac/trip.py +0 -37
  75. pycityagent/brain/__init__.py +0 -10
  76. pycityagent/brain/brain.py +0 -52
  77. pycityagent/brain/brainfc.py +0 -10
  78. pycityagent/brain/memory.py +0 -541
  79. pycityagent/brain/persistence/social.py +0 -1
  80. pycityagent/brain/persistence/spatial.py +0 -14
  81. pycityagent/brain/reason/shop.py +0 -37
  82. pycityagent/brain/reason/social.py +0 -148
  83. pycityagent/brain/reason/trip.py +0 -67
  84. pycityagent/brain/reason/user.py +0 -122
  85. pycityagent/brain/retrive/social.py +0 -6
  86. pycityagent/brain/scheduler.py +0 -408
  87. pycityagent/brain/sence.py +0 -375
  88. pycityagent/cc/__init__.py +0 -5
  89. pycityagent/cc/cc.py +0 -102
  90. pycityagent/cc/conve.py +0 -6
  91. pycityagent/cc/idle.py +0 -20
  92. pycityagent/cc/shop.py +0 -6
  93. pycityagent/cc/trip.py +0 -13
  94. pycityagent/cc/user.py +0 -13
  95. pycityagent/hubconnector/__init__.py +0 -3
  96. pycityagent/hubconnector/hubconnector.py +0 -137
  97. pycityagent/image/__init__.py +0 -3
  98. pycityagent/image/image.py +0 -158
  99. pycityagent/simulator.py +0 -161
  100. pycityagent/st/__init__.py +0 -4
  101. pycityagent/st/st.py +0 -96
  102. pycityagent/urbanllm/__init__.py +0 -3
  103. pycityagent/urbanllm/urbanllm.py +0 -132
  104. pycityagent-1.0.0.dist-info/LICENSE +0 -21
  105. pycityagent-1.0.0.dist-info/METADATA +0 -181
  106. pycityagent-1.0.0.dist-info/RECORD +0 -48
  107. pycityagent-1.0.0.dist-info/top_level.txt +0 -1
  108. /pycityagent/{brain/persistence/__init__.py → config.py} +0 -0
  109. /pycityagent/{brain/reason → environment/interact}/__init__.py +0 -0
  110. /pycityagent/{brain/retrive → environment/message}/__init__.py +0 -0
@@ -1,408 +0,0 @@
1
- from enum import Enum
2
- import random
3
- import time as Time
4
- import json
5
- from .brainfc import BrainFunction
6
- from pycitysim.apphub import AgentMessage
7
-
8
- # 1: walk; 2: drive
9
- MODE = [1, 2]
10
-
11
- class ScheduleType(Enum):
12
- """
13
- 枚举规划类型
14
- Enum: the schedule type
15
- - Trip: 出行规划. Trip Schedule
16
- - Shop: 购物规划. Shop Schedule
17
- - Other: 其他规划. Other Schedule
18
- """
19
- TRIP = 1
20
- SHOP = 2
21
- OTHER = 3
22
-
23
- class Schedule:
24
- def __init__(self, type) -> None:
25
- '''默认初始化'''
26
- self.type = type
27
-
28
- class TripSchedule(Schedule):
29
- """
30
- 出行规划
31
- Trip Schedule
32
- """
33
- def __init__(self, target_id_aoi:int, target_id_poi:int, name:str, mode:int, time:float, description:str) -> None:
34
- super().__init__(ScheduleType.TRIP)
35
- self.target_id_aoi = target_id_aoi
36
- """the aoi id of destination"""
37
- self.target_id_poi = target_id_poi
38
- """the poi id of destination"""
39
- self.name = name
40
- """the name of destination"""
41
- self.mode = mode
42
- """the trip mode of destination, 1:walk, 2:drive"""
43
- self.time = time
44
- """the start time of trip"""
45
- self.description = description
46
- """the desctiption of the trip"""
47
- self.is_set = False
48
- """whether this trip has sync to AppHub/simulator"""
49
- self.arrived = False
50
- """whether has arrived"""
51
- self.route_chance = 10
52
- """the chance for route, subtract 1 each time, if reduced to 0 then route failed"""
53
- self.route_failed = False
54
- """whether route failed"""
55
-
56
- def __str__(self) -> str:
57
- text = ''''''
58
- text += f'[类型: {self.type}, 目的地: {self.target_id_aoi}-{self.target_id_poi}-{self.name}, 方式: {self.mode}, 时间: {self.time}, 描述: {self.description}, 是否同步至模拟器: {self.is_set}]\n'
59
- return text
60
-
61
- class ShopSchedule(Schedule):
62
- """
63
- 购物规划
64
- Shop Schedule
65
- """
66
- def __init__(self, target_id_aoi:int, target_id_poi:int, name:str, description:str) -> None:
67
- super().__init__(ScheduleType.SHOP)
68
- self.target_id_aoi = target_id_aoi
69
- """the aoi id of destination"""
70
- self.target_id_poi = target_id_poi
71
- """the poi id of destination"""
72
- self.name = name
73
- """the name of destination"""
74
- self.description = description
75
- """the description of this schedule"""
76
- self.arrived = False
77
- """whether arrived destination"""
78
- self.finished = False
79
- """whether finished shop"""
80
-
81
- def __str__(self) -> str:
82
- text = ''''''
83
- text += f'[类型: {self.type}, 目的地: {self.target_id_aoi}-{self.target_id_poi}-{self.name}, 描述: {self.description}]\n'
84
- return text
85
-
86
- class OtherSchdule(Schedule):
87
- """
88
- 其他规划
89
- Other Schedule
90
- """
91
- def __init__(self, target_id_aoi:int, target_id_poi:int, name:str, description:str, duration:int) -> None:
92
- super().__init__(ScheduleType.OTHER)
93
- self.target_id_aoi = target_id_aoi
94
- """the aoi id of destination"""
95
- self.target_id_poi = target_id_poi
96
- """the poi id of destination"""
97
- self.name = name
98
- """the name of destination"""
99
- self.description = description
100
- """the desctription of this schedule"""
101
- self.duration = duration
102
- """the duration of activity"""
103
- self.remain = duration
104
- """the remaining time of activity"""
105
- self.finished = False
106
- """whether finished this schedule"""
107
-
108
- def __str__(self) -> str:
109
- text = ''''''
110
- text += f'[类型: {self.type}, 描述: {self.description}, 持续时间: {self.duration}]\n'
111
- return text
112
-
113
- class Scheduler(BrainFunction):
114
- """
115
- 规划器
116
- Agent Scheduler
117
- """
118
- def __init__(self, agent) -> None:
119
- super().__init__(agent)
120
- self.base_schedule = []
121
- """the basic schedules, which sync from databse"""
122
- self.base_schedule_index = -1
123
- """the index of current base schedule"""
124
- self.is_controled = False
125
- """whether the agent in 'controled' state"""
126
- self.user_commond_schedule = []
127
- """the user commond schedules, which are generated from user commond"""
128
- self.commond_schedule_index = -1
129
- """the index of user schedules"""
130
- self.now = None
131
- """the current schedule"""
132
- self.history = []
133
- """the history schedules"""
134
- self.need_schedule = False
135
- """whether need schedule"""
136
- self.pre_time = None
137
-
138
- def clear_user_schedule(self):
139
- """
140
- 清空用户规划
141
- Clear user commond scheudles
142
- - set is_controled to False
143
- - clear user_commond_schedule
144
- - set commond_schedule_index to 0
145
- """
146
- self.is_controled = False
147
- self.user_commond_schedule = []
148
- self.commond_schedule_index = 0
149
-
150
- def clear_base_schedule(self):
151
- """
152
- 清空基础规划
153
- Clear base schedules
154
- """
155
- for sche in self.base_schedule:
156
- if sche.type.value == ScheduleType.TRIP.value:
157
- sche.route_change = 10
158
- sche.route_failed = False
159
- sche.is_set = False
160
- sche.arrived = False
161
- elif sche.type.value == ScheduleType.SHOP.value:
162
- sche.arrived = False
163
- sche.finished = False
164
- elif sche.type.value == ScheduleType.OTHER.value:
165
- sche.fnished = False
166
-
167
- def unset_schedule(self):
168
- """
169
- 重设规划标志
170
- Unset schedule attributes
171
- """
172
- if self.now != None and self.now.type.value == ScheduleType.TRIP.value:
173
- self.now.is_set = False
174
- for sche in self.user_commond_schedule:
175
- if sche.type.value == ScheduleType.TRIP.value:
176
- sche.is_set = False
177
-
178
- async def schedule(self, current_target: str, commond:bool=True):
179
- """
180
- 规划
181
- Schedule function
182
-
183
- Args:
184
- - current_target (str): 规划目标. the schedule target
185
- - commond (str): 是否基于用户命令进行规划. whether based on user commond, default: True
186
-
187
- Returns:
188
- - int: return 0 if success, else failed
189
- """
190
- # * 前置配置流程
191
- if commond:
192
- self.clear_user_schedule()
193
- else:
194
- pass
195
- schedules = []
196
-
197
- # * 主行程规划流程
198
- dialog = [
199
- {'role': 'system', 'content': '你是一名行程规划大师, 行程表示一次出行,你需要基于用户提供的基本信息帮助用户完成行程规划.'},
200
- {'role': 'system', 'content': '用户输入信息包含四部分: [用户基本信息], [空间信息], [当前时间], [行程规划目标]'},
201
- {'role': 'system', 'content': '''[用户基本信息]中包含用户的个人基本信息'''},
202
- {'role': 'system', 'content': '''[空间信息]包含所有可选的, 可能出现在你的回答中的地点信息.
203
- 空间信息中对每个地点的描述格式如下:
204
- {"id": 地点对应的id, "name": 地点对应的名称, "category": 地点对应的类型, "aoi_id": 与地点关联的AOI id, "relation": 该地点与用户的关系}'''},
205
- {'role': 'system', 'content': '[当前时间]以从当前00:00:00开始到目前时间的以秒为单位的整数表达: 例如21600表示实际当前时间为6:00:00'},
206
- {'role': 'system', 'content': '[行程规划目标]表示用户当前最急切的行程需求, 你的回答应尽可能满足用户的行程规划目标'},
207
- {'role': 'system', 'content': '''你的回答应该严格按照规定格式给出, 一条行程安排的格式为(请勿包含冗余信息!):
208
- {"id": 目标地点的id, "aoi_id": 与目标地点关联的AOI id, "time": 开始该行程的时间, 请用与当前时间相同的格式给出(一个整数), "explaination": 安排该行程的理由(从用户的第一视角回答, 以[我]为主语)}'''},
209
- {'role': 'system', 'content': '''如你需要给出多条行程安排, 请以列表形式给出, 例如: [行程1, 行程2]'''}
210
- ]
211
- user_profile = self._agent.Image.get_profile()
212
- dialog += [{'role': 'user', 'content': f'[用户基本信息]: \n{user_profile}'}]
213
- user_spatial_knowledge = self._agent.Brain.Memory.Spatial.to_dialog_str()
214
- dialog += [{'role': 'user', 'content': f'[空间信息]: \n{user_spatial_knowledge}'}]
215
- current_time = self._agent._simulator.time
216
- dialog += [{'role': 'user', 'content': f'[当前时间]: {int(current_time)}'}]
217
- dialog += [{'role': 'user', 'content': f'[行程规划目标]: {current_target}'}]
218
- print(f'''
219
- ==============================================
220
- {dialog}
221
- ==============================================
222
- ''')
223
- try:
224
- resp = self._agent._soul.text_request(dialog)
225
- print(f'规划结果: 【{resp}】')
226
- resp_dict = json.loads(resp)
227
- except:
228
- print("行程规划失败")
229
- return -1
230
-
231
- # * 进行解析
232
- for trip in resp_dict:
233
- poi_id = trip['id']
234
- aoi_id = trip['aoi_id']
235
- time = trip['time']
236
- description = trip['explaination']
237
- if poi_id in self._agent.Brain.Memory.Spatial.spatial_dict.keys():
238
- name = self._agent.Brain.Memory.Spatial.spatial_dict[poi_id]['name']
239
- else:
240
- name = '未知地点'
241
- mesg = f'''前往{name}-({aoi_id}), {description}'''
242
- self._agent.Hub.Update([AgentMessage(self._agent.Hub._agent_id, int(Time.time()*1000), mesg, None, None)])
243
- if 'aoi_position' in self._agent.motion['position'].keys():
244
- mode = random.choice(MODE)
245
- else:
246
- lane_id = self._agent.motion['position']['lane_position']['lane_id']
247
- if self._agent._simulator.map.lanes[lane_id]['type'] == 1:
248
- mode = 2
249
- else:
250
- mode = 1
251
- schedule = TripSchedule(aoi_id, poi_id, name, mode, time, description)
252
- schedules.append(schedule)
253
- # * 后续行程推理
254
- contin_dialog = [
255
- {'role': 'system', 'content': '''你是一名活动预测大师, 你将基于用户输入的当前行程描述, 判断用户在该行程结束后将进行何种活动, 并从用户的第一视角对该活动进行解释'''},
256
- {'role': 'system', 'content': '''你的输出需要严格按照以下格式给出:
257
- {"type": 表示活动类型, 可选结果包括[购物, 工作, 休息, 其他](其中之一), "duration": 该项活动的持续时间(以秒为单位表示的整数), "description": 第用户视角出发的对该活动的解释}'''},
258
- {'role': 'system', 'content': '''例如用户输入: 我要去学校工作,你将输出: {'type': "工作", "duration": 7200, "description": "在学校工作"}'''},
259
- {'role': 'system', 'content': '''例如用户输入: 我要去周围购买生活用品, 你将输出: {"type": "购物", "duration": 1800, "description": "购买生活用品"}'''}
260
- ]
261
- contin_dialog += [{'role': 'user', 'content': description}]
262
- print(contin_dialog)
263
- resp_more = self._agent._soul.text_request(contin_dialog)
264
- print(resp_more)
265
- try:
266
- resp_more_dict = json.loads(resp_more)
267
- print(resp_more_dict)
268
- if resp_more_dict['type'] == '购物':
269
- schedule = ShopSchedule(aoi_id, poi_id, name, resp_more_dict['description'])
270
- else:
271
- schedule = OtherSchdule(aoi_id, poi_id, name, resp_more_dict['description'], resp_more_dict['duration'])
272
- schedules.append(schedule)
273
- except:
274
- print("后续行程推理失败")
275
-
276
- # * 后处理流
277
- if commond:
278
- self.user_commond_schedule = schedules
279
- self.is_controled = True
280
- self.now = None
281
- else:
282
- pass
283
- return 0
284
-
285
- async def schedule_forward(self):
286
- """
287
- 基于规划集合的执行流
288
- The stream function based on schedule collection
289
- """
290
- now_time = self._agent._simulator.time
291
- # * check new day
292
- if self.pre_time != None and now_time < self.pre_time:
293
- # 新的一天重设标志
294
- self.clear_base_schedule()
295
- self.base_schedule_index = 0
296
-
297
- if self._agent.state == 'trip' and self.now != None:
298
- # * 判断是否达到目的地
299
- if 'aoi_position' in self._agent.motion['position'].keys() and self._agent.motion['position']['aoi_position']['aoi_id'] == self.now.target_id_aoi:
300
- self.now.arrived = True
301
- # * 判断导航请求是否失败
302
- if self._agent.motion['status'] == 6:
303
- # 重试机会
304
- self.now.route_chance -= 1
305
- if self.now.route_chance <= 0:
306
- # 导航请求失败
307
- self.now.route_failed = True
308
- elif self._agent.state == 'idle':
309
- # * 在idle状态下进行行程检查与调整
310
- # * new day
311
- if self.now == None:
312
- # * 当前无行程
313
- if self.is_controled:
314
- # * 用户行程注册
315
- if self.user_commond_schedule[self.commond_schedule_index].type.value == ScheduleType.TRIP.value:
316
- # * 对于trip类型的schedule
317
- if self.user_commond_schedule[self.commond_schedule_index].time <= self._agent._simulator.time:
318
- self.now = self.user_commond_schedule[self.commond_schedule_index]
319
- if 'aoi_position' in self._agent.motion['position'].keys() and self._agent.motion['position']['aoi_position']['aoi_id'] == self.now.target_id_aoi:
320
- # 如果当前已经在目的地 直接跳过该行程
321
- self.schedule_set()
322
- else:
323
- # * 对于其他类型schedule 判断是否到达目的地 - 如果没有达到目的地 说明前置行程被取消 直接跳过
324
- self.now = self.user_commond_schedule[self.commond_schedule_index]
325
- if 'aoi_position' not in self._agent.motion['position'].keys() or self.now.target_id_aoi != self._agent.motion['position']['aoi_position']['aoi_id']:
326
- self.schedule_set(True)
327
- else:
328
- # * 基本行程注册
329
- if self.base_schedule_index >=0 and self.base_schedule[self.base_schedule_index].time <= self._agent._simulator.time:
330
- self.now = self.base_schedule[self.base_schedule_index]
331
- if 'aoi_position' in self._agent.motion['position'].keys() and self._agent.motion['position']['aoi_position']['aoi_id'] == self.now.target_id_aoi:
332
- # 直接跳过该行程
333
- self.schedule_set()
334
- else:
335
- if self.now.type.value == ScheduleType.TRIP.value:
336
- if self.now.arrived:
337
- self.schedule_set()
338
- elif self.now.route_failed:
339
- self.schedule_set(True)
340
- elif self.now.type.value == ScheduleType.SHOP.value:
341
- if not self.now.arrived:
342
- self.now.arrived = True
343
- else:
344
- self.now.finished = True
345
- self.schedule_set()
346
- elif self.now.type.value == ScheduleType.OTHER.value:
347
- self.now.remain -= 1
348
- if self.now.remain <= 0:
349
- self.schedule_set()
350
- self.pre_time = now_time
351
-
352
- def schedule_set(self, need_pass:bool=False):
353
- if not need_pass:
354
- self.history.append(self.now)
355
- if self.is_controled:
356
- if self.commond_schedule_index >= len(self.user_commond_schedule)-1:
357
- # * 已完成用户行程
358
- self.clear_user_schedule()
359
- else:
360
- self.commond_schedule_index += 1
361
- else:
362
- if self.base_schedule_index < len(self.base_schedule)-1:
363
- self.base_schedule_index += 1
364
- else:
365
- # * 已完成基础行程
366
- self.base_schedule_index = -1
367
- self.now = None
368
-
369
- def schedule_init(self):
370
- '''基于base的行程初始化 - base schedule'''
371
- for tp in self._agent.base['schedules']:
372
- trip = tp['trips'][0]
373
- mode = trip['mode']
374
- target_aoi_id = trip['end']['aoi_position']['aoi_id']
375
- target_poi_id = trip['end']['aoi_position']['poi_id']
376
- time = tp['departure_time']
377
- description = trip['activity']
378
- t_init = TripSchedule(target_aoi_id, target_poi_id, "None", mode, time, description)
379
- self.base_schedule.append(t_init)
380
-
381
- if len(self.base_schedule) > 1:
382
- now_idx = 0
383
- for idx in range(len(self.base_schedule)-1):
384
- # * 排除已完成的schedule
385
- if self.base_schedule[idx+1].time <= self._agent._simulator.time:
386
- self.base_schedule[idx].arrived = True
387
- self.history.append(self.base_schedule[idx])
388
- now_idx = idx+1
389
- else:
390
- continue
391
- self.base_schedule_index = now_idx
392
- else:
393
- self.base_schedule_index = 0
394
-
395
- def __str__(self) -> str:
396
- text = '''【Schedule Message】: \n'''
397
- text += '''[Basic Schedules]: \n'''
398
- for sche in self.base_schedule:
399
- text += " " + sche.__str__()
400
- if self.is_controled:
401
- text += '''[User Schedule]: \n'''
402
- for sche in self.user_commond_schedule:
403
- text += " " + sche.__str__()
404
- text += '''[History Schedule]: \n'''
405
- for sche in self.history:
406
- text += " " + sche.__str__()
407
- text += f'''[Now Schedule]: \n {self.now.__str__()}\n'''
408
- return text