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.
- pycityagent/__init__.py +7 -3
- pycityagent/agent.py +180 -284
- pycityagent/economy/__init__.py +5 -0
- pycityagent/economy/econ_client.py +307 -0
- pycityagent/environment/__init__.py +7 -0
- pycityagent/environment/interact/interact.py +141 -0
- pycityagent/environment/sence/__init__.py +0 -0
- pycityagent/{brain → environment/sence}/static.py +1 -1
- pycityagent/environment/sidecar/__init__.py +8 -0
- pycityagent/environment/sidecar/sidecarv2.py +109 -0
- pycityagent/environment/sim/__init__.py +29 -0
- pycityagent/environment/sim/aoi_service.py +38 -0
- pycityagent/environment/sim/client.py +126 -0
- pycityagent/environment/sim/clock_service.py +43 -0
- pycityagent/environment/sim/economy_services.py +191 -0
- pycityagent/environment/sim/lane_service.py +110 -0
- pycityagent/environment/sim/light_service.py +120 -0
- pycityagent/environment/sim/person_service.py +294 -0
- pycityagent/environment/sim/road_service.py +38 -0
- pycityagent/environment/sim/sim_env.py +145 -0
- pycityagent/environment/sim/social_service.py +58 -0
- pycityagent/environment/simulator.py +320 -0
- pycityagent/environment/utils/__init__.py +10 -0
- pycityagent/environment/utils/base64.py +16 -0
- pycityagent/environment/utils/const.py +242 -0
- pycityagent/environment/utils/geojson.py +26 -0
- pycityagent/environment/utils/grpc.py +57 -0
- pycityagent/environment/utils/map_utils.py +157 -0
- pycityagent/environment/utils/port.py +11 -0
- pycityagent/environment/utils/protobuf.py +39 -0
- pycityagent/llm/__init__.py +6 -0
- pycityagent/llm/embedding.py +136 -0
- pycityagent/llm/llm.py +430 -0
- pycityagent/llm/llmconfig.py +15 -0
- pycityagent/llm/utils.py +6 -0
- pycityagent/memory/__init__.py +11 -0
- pycityagent/memory/const.py +41 -0
- pycityagent/memory/memory.py +453 -0
- pycityagent/memory/memory_base.py +168 -0
- pycityagent/memory/profile.py +165 -0
- pycityagent/memory/self_define.py +165 -0
- pycityagent/memory/state.py +173 -0
- pycityagent/memory/utils.py +27 -0
- pycityagent/message/__init__.py +0 -0
- pycityagent/simulation/__init__.py +7 -0
- pycityagent/simulation/interview.py +36 -0
- pycityagent/simulation/simulation.py +352 -0
- pycityagent/simulation/survey/__init__.py +9 -0
- pycityagent/simulation/survey/manager.py +67 -0
- pycityagent/simulation/survey/models.py +49 -0
- pycityagent/simulation/ui/__init__.py +3 -0
- pycityagent/simulation/ui/interface.py +602 -0
- pycityagent/utils/__init__.py +0 -0
- pycityagent/utils/decorators.py +89 -0
- pycityagent/utils/parsers/__init__.py +12 -0
- pycityagent/utils/parsers/code_block_parser.py +37 -0
- pycityagent/utils/parsers/json_parser.py +86 -0
- pycityagent/utils/parsers/parser_base.py +60 -0
- pycityagent/workflow/__init__.py +24 -0
- pycityagent/workflow/block.py +164 -0
- pycityagent/workflow/prompt.py +72 -0
- pycityagent/workflow/tool.py +246 -0
- pycityagent/workflow/trigger.py +150 -0
- pycityagent-2.0.0a2.dist-info/METADATA +208 -0
- pycityagent-2.0.0a2.dist-info/RECORD +69 -0
- {pycityagent-1.0.0.dist-info → pycityagent-2.0.0a2.dist-info}/WHEEL +1 -2
- pycityagent/ac/__init__.py +0 -6
- pycityagent/ac/ac.py +0 -50
- pycityagent/ac/action.py +0 -14
- pycityagent/ac/controled.py +0 -13
- pycityagent/ac/converse.py +0 -31
- pycityagent/ac/idle.py +0 -17
- pycityagent/ac/shop.py +0 -80
- pycityagent/ac/trip.py +0 -37
- pycityagent/brain/__init__.py +0 -10
- pycityagent/brain/brain.py +0 -52
- pycityagent/brain/brainfc.py +0 -10
- pycityagent/brain/memory.py +0 -541
- pycityagent/brain/persistence/social.py +0 -1
- pycityagent/brain/persistence/spatial.py +0 -14
- pycityagent/brain/reason/shop.py +0 -37
- pycityagent/brain/reason/social.py +0 -148
- pycityagent/brain/reason/trip.py +0 -67
- pycityagent/brain/reason/user.py +0 -122
- pycityagent/brain/retrive/social.py +0 -6
- pycityagent/brain/scheduler.py +0 -408
- pycityagent/brain/sence.py +0 -375
- pycityagent/cc/__init__.py +0 -5
- pycityagent/cc/cc.py +0 -102
- pycityagent/cc/conve.py +0 -6
- pycityagent/cc/idle.py +0 -20
- pycityagent/cc/shop.py +0 -6
- pycityagent/cc/trip.py +0 -13
- pycityagent/cc/user.py +0 -13
- pycityagent/hubconnector/__init__.py +0 -3
- pycityagent/hubconnector/hubconnector.py +0 -137
- pycityagent/image/__init__.py +0 -3
- pycityagent/image/image.py +0 -158
- pycityagent/simulator.py +0 -161
- pycityagent/st/__init__.py +0 -4
- pycityagent/st/st.py +0 -96
- pycityagent/urbanllm/__init__.py +0 -3
- pycityagent/urbanllm/urbanllm.py +0 -132
- pycityagent-1.0.0.dist-info/LICENSE +0 -21
- pycityagent-1.0.0.dist-info/METADATA +0 -181
- pycityagent-1.0.0.dist-info/RECORD +0 -48
- pycityagent-1.0.0.dist-info/top_level.txt +0 -1
- /pycityagent/{brain/persistence/__init__.py → config.py} +0 -0
- /pycityagent/{brain/reason → environment/interact}/__init__.py +0 -0
- /pycityagent/{brain/retrive → environment/message}/__init__.py +0 -0
pycityagent/image/__init__.py
DELETED
pycityagent/image/image.py
DELETED
@@ -1,158 +0,0 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
import json
|
3
|
-
from abc import ABC, abstractclassmethod
|
4
|
-
|
5
|
-
class ProfileTemplate:
|
6
|
-
"""
|
7
|
-
profile模板类
|
8
|
-
The template class of Agent Profile
|
9
|
-
"""
|
10
|
-
def __init__(self) -> None:
|
11
|
-
pass
|
12
|
-
|
13
|
-
@abstractclassmethod
|
14
|
-
def to_dialog(self) -> list[dict]:
|
15
|
-
"""
|
16
|
-
将Profile转化为LLM可用的dialog的抽象函数
|
17
|
-
The abstract method that turns Agent's profile to LLM standard dialog
|
18
|
-
"""
|
19
|
-
|
20
|
-
class AgentImage:
|
21
|
-
"""
|
22
|
-
Agent Image模块: 用户画像控制
|
23
|
-
Agent's Image module: Defines the uniqueness of Agent
|
24
|
-
"""
|
25
|
-
def __init__(self, agent, scratch_file:str=None, selfie:bool=False) -> None:
|
26
|
-
self._agent = agent
|
27
|
-
self.scratch = AgentScratch()
|
28
|
-
"""
|
29
|
-
Agent的Scratch信息: 用于描述Agent的基本属性
|
30
|
-
Scratch: Used to describe the basic info of Agent
|
31
|
-
- name (str): the name of Agent
|
32
|
-
- age (int): the age of Agent
|
33
|
-
- education (str): the education level, ['低等教育水平', '中等教育水平', '高等教育水平']
|
34
|
-
- gender (str): the gender of Agent, ['男', '女']
|
35
|
-
- consumption (str): the consumption level , ['低等消费水平', '中等消费水平', '高等消费水平']
|
36
|
-
- innate (str): the innate of Agent, '乐观积极' for instance
|
37
|
-
- learned (str): the learned info of Agent, '我是一名教师, 就职于xxx' for instance
|
38
|
-
- currently (str): the currently plan of Agent, '写一篇关于社会科学的研究报告' for instance
|
39
|
-
- lifestyle (str): the lifestyle of Agent, '早上7点起床, 晚上11点睡觉' for instance
|
40
|
-
"""
|
41
|
-
self.selfie = None
|
42
|
-
"""
|
43
|
-
Agent自画像
|
44
|
-
Selfie of Agent
|
45
|
-
Not implement yet!!!
|
46
|
-
"""
|
47
|
-
profile = self._agent.base['profile']
|
48
|
-
if scratch_file != None:
|
49
|
-
self.scratch.load(scratch_file)
|
50
|
-
else:
|
51
|
-
self.scratch.name = self._agent.agent_name
|
52
|
-
self.scratch.age = profile['age']
|
53
|
-
education = profile['education']
|
54
|
-
if education < 3:
|
55
|
-
self.scratch.education = '低等教育水平'
|
56
|
-
elif education < 5:
|
57
|
-
self.scratch.education = '中等教育水平'
|
58
|
-
else:
|
59
|
-
self.scratch.education = '高等教育水平'
|
60
|
-
if profile['gender'] == 1:
|
61
|
-
self.scratch.gender = '男'
|
62
|
-
else:
|
63
|
-
self.scratch.gender = '女'
|
64
|
-
consumption = profile['consumption']
|
65
|
-
if consumption < 3:
|
66
|
-
self.scratch.consumption = '低等消费水平'
|
67
|
-
elif consumption < 5:
|
68
|
-
self.scratch.consumption = '高等消费水平'
|
69
|
-
else:
|
70
|
-
self.scratch.consumption = '高等消费水平'
|
71
|
-
if selfie:
|
72
|
-
# TODO: 补充自拍
|
73
|
-
pass
|
74
|
-
|
75
|
-
def get_profile(self):
|
76
|
-
"""
|
77
|
-
获取Agent的Scratch Profile信息
|
78
|
-
Get the Scratch Profile message
|
79
|
-
|
80
|
-
Returns:
|
81
|
-
- (str)
|
82
|
-
"""
|
83
|
-
return self.scratch.get_profile_content()
|
84
|
-
|
85
|
-
def load_scratch(self, scratch_file:str):
|
86
|
-
"""
|
87
|
-
加载基于文件的Profile加载
|
88
|
-
Load Profile based on file
|
89
|
-
|
90
|
-
Args:
|
91
|
-
- scratch_file (str): the path of scratch_file
|
92
|
-
"""
|
93
|
-
self.scratch.load(scratch_file)
|
94
|
-
|
95
|
-
def load_selfie(self, selfie_file:str):
|
96
|
-
"""
|
97
|
-
基于图像的Selfie加载
|
98
|
-
Load Selfie based on selfie file
|
99
|
-
Not implemented yet!!!
|
100
|
-
|
101
|
-
Args:
|
102
|
-
- selfie_file (str): the path of selfie_file
|
103
|
-
"""
|
104
|
-
print("Not Implemented")
|
105
|
-
|
106
|
-
class AgentScratch():
|
107
|
-
def __init__(self, scratch:Optional[dict]=None) -> None:
|
108
|
-
self.name = None
|
109
|
-
self.age = None
|
110
|
-
self.education = None
|
111
|
-
self.gender = None
|
112
|
-
self.consumption = None
|
113
|
-
self.innate = ''
|
114
|
-
self.learned = ''
|
115
|
-
self.currently = ''
|
116
|
-
self.lifestyle = ''
|
117
|
-
if scratch != None:
|
118
|
-
self.forward(scratch)
|
119
|
-
|
120
|
-
def forward(self, x:dict):
|
121
|
-
"""Scratch记忆更新"""
|
122
|
-
for k in x.keys():
|
123
|
-
self.__dict__[k] = x[k]
|
124
|
-
|
125
|
-
def save(self, output_path:str):
|
126
|
-
"""Scratch记忆持久化"""
|
127
|
-
with open(output_path, 'w') as f:
|
128
|
-
json.dumps(self.__dict__, f, 4)
|
129
|
-
|
130
|
-
def load(self, x:str):
|
131
|
-
"""Scratch记忆恢复"""
|
132
|
-
with open(x, 'r') as f:
|
133
|
-
json_str = f.read()
|
134
|
-
scratch = json.loads(json_str)
|
135
|
-
self.forward(scratch)
|
136
|
-
|
137
|
-
def get_str_lifestyle(self):
|
138
|
-
return self.lifestyle
|
139
|
-
|
140
|
-
def get_str_firstname(self):
|
141
|
-
return self.first_name
|
142
|
-
|
143
|
-
def get_profile_content(self):
|
144
|
-
text = ''''''
|
145
|
-
text += f'姓名: {self.name}\n'
|
146
|
-
text += f'年龄: {self.age}\n'
|
147
|
-
text += f'性别: {self.gender}\n'
|
148
|
-
text += f'受教育水平: {self.education}\n'
|
149
|
-
text += f'消费能力: {self.consumption}\n'
|
150
|
-
text += f'性格特点: {self.innate}\n'
|
151
|
-
text += f'爱好与习惯: {self.learned}\n'
|
152
|
-
text += f'近期状态: {self.currently}\n'
|
153
|
-
text += f'生活习惯: {self.lifestyle}\n'
|
154
|
-
return text
|
155
|
-
|
156
|
-
|
157
|
-
def __str__(self):
|
158
|
-
return str(self.__dict__)
|
pycityagent/simulator.py
DELETED
@@ -1,161 +0,0 @@
|
|
1
|
-
from pycitysim import *
|
2
|
-
from pycitysim.sidecar import OnlyClientSidecar
|
3
|
-
from pycitysim.sim import CityClient
|
4
|
-
from typing import Optional, Union
|
5
|
-
from datetime import datetime, timedelta
|
6
|
-
import asyncio
|
7
|
-
from .agent import Agent
|
8
|
-
|
9
|
-
class SimPerceive:
|
10
|
-
"""
|
11
|
-
模拟器感知
|
12
|
-
Simulator Perceive
|
13
|
-
"""
|
14
|
-
def __init__(self, simualtor) -> None:
|
15
|
-
self._simulator=simualtor
|
16
|
-
|
17
|
-
async def PerceiveAoisByIds(self, ids:Optional[list[int]]):
|
18
|
-
"""
|
19
|
-
Simulator视角下的AOI感知
|
20
|
-
Perceive AOI from Simulator
|
21
|
-
|
22
|
-
Args:
|
23
|
-
- ids list[int]: list of aoi id
|
24
|
-
|
25
|
-
Returns:
|
26
|
-
- https://cityproto.sim.fiblab.net/#city.map.v2.GetAoiResponse
|
27
|
-
"""
|
28
|
-
req = {'aoi_ids': ids}
|
29
|
-
resp = await self._simulator._client.aoi_service.GetAoi(req)
|
30
|
-
return resp
|
31
|
-
|
32
|
-
class Simulator:
|
33
|
-
"""
|
34
|
-
模拟器
|
35
|
-
Simulator
|
36
|
-
"""
|
37
|
-
def __init__(self, config) -> None:
|
38
|
-
self.config = config
|
39
|
-
self._client = CityClient(self.config['simulator']['server'], secure=True)
|
40
|
-
self._perceive = SimPerceive(self)
|
41
|
-
self.map = map.Map(
|
42
|
-
mongo_uri = "mongodb://sim:FiblabSim1001@mgo.db.fiblab.tech:8635/",
|
43
|
-
mongo_db = "srt",
|
44
|
-
mongo_coll = config['map_request']['mongo_coll'],
|
45
|
-
cache_dir = config['map_request']['cache_dir'],
|
46
|
-
)
|
47
|
-
self.time = 0
|
48
|
-
|
49
|
-
# * Agent相关
|
50
|
-
def FindAgentsByArea(self, req: dict, status=None):
|
51
|
-
"""
|
52
|
-
通过区域范围查找agent/person
|
53
|
-
Get agents/persons in the provided area
|
54
|
-
|
55
|
-
Args:
|
56
|
-
- req (dict): 用于描述区域的请求 https://cityproto.sim.fiblab.net/#city.person.1.GetPersonByLongLatBBoxRequest
|
57
|
-
- status (int): 用于限制agent/person状态 if 'status' is not None, then you get those persons in 'status' https://cityproto.sim.fiblab.net/#city.agent.v2.Status
|
58
|
-
|
59
|
-
Returns:
|
60
|
-
- https://cityproto.sim.fiblab.net/#city.person.1.GetPersonByLongLatBBoxResponse
|
61
|
-
"""
|
62
|
-
loop = asyncio.get_event_loop()
|
63
|
-
resp = loop.run_until_complete(self._client.person_service.GetPersonByLongLatBBox(req=req))
|
64
|
-
loop.close()
|
65
|
-
if status == None:
|
66
|
-
return resp
|
67
|
-
else:
|
68
|
-
motions = []
|
69
|
-
for agent in resp.motions:
|
70
|
-
if agent.status in status:
|
71
|
-
motions.append(agent)
|
72
|
-
resp.motions = motions
|
73
|
-
return resp
|
74
|
-
|
75
|
-
async def GetAgent(self, name:str=None, id:int=None):
|
76
|
-
"""
|
77
|
-
获取agent
|
78
|
-
Get Agent
|
79
|
-
|
80
|
-
Args:
|
81
|
-
- name str: 你为agent取的名字 the name of your agent
|
82
|
-
- id int: 即绑定的person的id the id of person that you try to bind with
|
83
|
-
|
84
|
-
Returns:
|
85
|
-
- Agent
|
86
|
-
"""
|
87
|
-
await self.GetTime()
|
88
|
-
name_ = "张三"
|
89
|
-
if name != None:
|
90
|
-
name_ = name
|
91
|
-
if id == None:
|
92
|
-
base = self._client.person_service.default_person()
|
93
|
-
agent = Agent(
|
94
|
-
name_,
|
95
|
-
self.config['simulator']['server'],
|
96
|
-
simulator=self,
|
97
|
-
id=id,
|
98
|
-
base=base,
|
99
|
-
)
|
100
|
-
else:
|
101
|
-
resp = await self._client.person_service.GetPerson({"person_id": id})
|
102
|
-
base = resp['base']
|
103
|
-
motion = resp['motion']
|
104
|
-
agent = Agent(
|
105
|
-
name_,
|
106
|
-
self.config['simulator']['server'],
|
107
|
-
simulator=self,
|
108
|
-
id=id,
|
109
|
-
base=base,
|
110
|
-
motion=motion,
|
111
|
-
)
|
112
|
-
if 'streetview_request' in self.config.keys():
|
113
|
-
agent.Brain.Sence._streetview_engine = self.config['streetview_request']['engine']
|
114
|
-
if agent.Brain.Sence._streetview_engine == 'baidumap':
|
115
|
-
agent.Brain.Sence._streetviewAK = self.config['streetview_request']['mapAK']
|
116
|
-
elif agent.Brain.Sence._streetview_engine == 'googlemap':
|
117
|
-
if 'proxy' in self.config['streetview_request'].keys():
|
118
|
-
agent.Brain.Sence._streetviewProxy = self.config['streetview_request']['proxy']
|
119
|
-
else:
|
120
|
-
agent.Brain.Sence._streetview_engine = ""
|
121
|
-
print("Wrong Streetview Engine")
|
122
|
-
return agent
|
123
|
-
|
124
|
-
def InsertAgent(self, profile):
|
125
|
-
"""
|
126
|
-
插入agent
|
127
|
-
Insert Agent
|
128
|
-
Not implemented yet
|
129
|
-
"""
|
130
|
-
print("Not Implemented Yet")
|
131
|
-
pass
|
132
|
-
|
133
|
-
async def GetTime(self, format_time:bool=False, format:Optional[str]="%H:%M:%S") -> Union[int, str]:
|
134
|
-
"""
|
135
|
-
获取模拟器当前时间 Get current time of simulator
|
136
|
-
默认返回以00:00:00为始的, 以s为单位的时间(int)
|
137
|
-
支持格式化时间
|
138
|
-
|
139
|
-
Args:
|
140
|
-
- format_time (bool): 是否格式化 format or not
|
141
|
-
- format (str): 格式化模板,默认为"Hour:Minute:Second" the formation
|
142
|
-
|
143
|
-
Returns:
|
144
|
-
- time Union[int, str]: 时间 time in second(int) or formated time(str)
|
145
|
-
"""
|
146
|
-
t_sec = await self._client.clock_service.Now({})
|
147
|
-
self.time = t_sec['t']
|
148
|
-
if format_time:
|
149
|
-
current_date = datetime.now().date()
|
150
|
-
start_of_day = datetime.combine(current_date, datetime.min.time())
|
151
|
-
current_time = start_of_day + timedelta(seconds=t_sec['t'])
|
152
|
-
formatted_time = current_time.strftime(format)
|
153
|
-
return formatted_time
|
154
|
-
else:
|
155
|
-
return t_sec['t']
|
156
|
-
|
157
|
-
|
158
|
-
@property
|
159
|
-
def Perceive(self):
|
160
|
-
"""模拟器感知模块"""
|
161
|
-
return self._perceive
|
pycityagent/st/__init__.py
DELETED
pycityagent/st/st.py
DELETED
@@ -1,96 +0,0 @@
|
|
1
|
-
from transitions import Machine
|
2
|
-
from abc import ABC, abstractmethod
|
3
|
-
|
4
|
-
class StateTransformer:
|
5
|
-
"""
|
6
|
-
State Transformer模块: 控制agent状态转移
|
7
|
-
The State Transformer module: used to control the transformation of agent's state
|
8
|
-
|
9
|
-
Doc:
|
10
|
-
- 基于transitions()构建 https://github.com/tyarkoni/transitions
|
11
|
-
- Agent的状态不仅表征着用户当前的行为, 同时也起到了串联/控制Agent行为的功能
|
12
|
-
- 状态信息:
|
13
|
-
- idle: 空闲状态
|
14
|
-
- trip: 出行状态
|
15
|
-
- shop: 购物状态
|
16
|
-
- conve: 社交状态
|
17
|
-
- paused: 暂停状态
|
18
|
-
- controled: 受控状态, 即用户通过OpenCity website console控制Agent
|
19
|
-
- 状态转移:
|
20
|
-
- idle:
|
21
|
-
- gotrip: idle -> trip
|
22
|
-
- goshop: idel -> shop
|
23
|
-
- goconverse: idel -> conve
|
24
|
-
- pause: idle -> paused
|
25
|
-
- gousercontrol: idle -> controled
|
26
|
-
- trip:
|
27
|
-
- arrived: trip -> idle
|
28
|
-
- routefailed: trip -> idle (导航失败)
|
29
|
-
- pause: idle -> paused
|
30
|
-
- gousercontrol: idle -> controled
|
31
|
-
- shop:
|
32
|
-
- shopdone: shop -> idle
|
33
|
-
- pause: idle -> paused
|
34
|
-
- gousercontrol: idle -> controled
|
35
|
-
- conve:
|
36
|
-
- convedone: conve -> idle
|
37
|
-
- pause: idle -> paused
|
38
|
-
- gousercontrol: idle -> controled
|
39
|
-
- paused:
|
40
|
-
- active*: paused -> *
|
41
|
-
- controled:
|
42
|
-
- controlback: controled -> idle
|
43
|
-
- Note: 目前不支持状态扩展
|
44
|
-
"""
|
45
|
-
states = ['idle', 'trip', 'shop', 'conve', 'paused', 'controled']
|
46
|
-
|
47
|
-
def __init__(self, config=None):
|
48
|
-
self.pre_state = None
|
49
|
-
# TODO: 后续添加扩展接口
|
50
|
-
# Initialize the state machine
|
51
|
-
self.machine = Machine(model=self, states=StateTransformer.states, initial='idle')
|
52
|
-
|
53
|
-
# idle
|
54
|
-
self.machine.add_transition(trigger='gotrip', source='idle', dest='trip')
|
55
|
-
self.machine.add_transition(trigger='goshop', source='idle', dest='shop')
|
56
|
-
self.machine.add_transition(trigger='goconverse', source='idle', dest='conve')
|
57
|
-
|
58
|
-
# trip
|
59
|
-
self.machine.add_transition(trigger='arrived', source='trip', dest='idle')
|
60
|
-
self.machine.add_transition(trigger='routefailed', source='trip', dest='idle')
|
61
|
-
|
62
|
-
# shop
|
63
|
-
self.machine.add_transition(trigger='shopdone', source='shop', dest='idle')
|
64
|
-
|
65
|
-
# conve
|
66
|
-
self.machine.add_transition(trigger='convedone', source='conve', dest='idle')
|
67
|
-
|
68
|
-
# pause
|
69
|
-
self.machine.add_transition(trigger='pause', source='*', dest='paused', before='state_remember')
|
70
|
-
|
71
|
-
# active
|
72
|
-
self.machine.add_transition(trigger='active_trip', source='paused', dest='trip')
|
73
|
-
self.machine.add_transition(trigger='active_idle', source='paused', dest='idle')
|
74
|
-
self.machine.add_transition(trigger='active_shop', source='paused', dest='shop')
|
75
|
-
self.machine.add_transition(trigger='active_conve', source='paused', dest='conve')
|
76
|
-
|
77
|
-
# nothing
|
78
|
-
self.machine.add_transition(trigger='nothing', source='*', dest='=')
|
79
|
-
|
80
|
-
# controled
|
81
|
-
self.machine.add_transition(trigger='gousercontrol', source='*', dest='controled')
|
82
|
-
self.machine.add_transition(trigger='controlback', source='controled', dest='idle')
|
83
|
-
|
84
|
-
def state_remember(self):
|
85
|
-
if self.state != 'paused': # 避免重复Pause
|
86
|
-
self.pre_state = self.state
|
87
|
-
|
88
|
-
def pause_back(self):
|
89
|
-
if self.pre_state == 'trip':
|
90
|
-
self.active_trip()
|
91
|
-
elif self.pre_state == 'shop':
|
92
|
-
self.active_shop()
|
93
|
-
elif self.pre_state == 'conve':
|
94
|
-
self.active_conve()
|
95
|
-
elif self.pre_sate == 'idle':
|
96
|
-
self.active_idle()
|
pycityagent/urbanllm/__init__.py
DELETED
pycityagent/urbanllm/urbanllm.py
DELETED
@@ -1,132 +0,0 @@
|
|
1
|
-
from openai import OpenAI
|
2
|
-
from http import HTTPStatus
|
3
|
-
import dashscope
|
4
|
-
from urllib.parse import urlparse, unquote
|
5
|
-
from pathlib import PurePosixPath
|
6
|
-
import requests
|
7
|
-
from dashscope import ImageSynthesis
|
8
|
-
from PIL import Image
|
9
|
-
from io import BytesIO
|
10
|
-
|
11
|
-
class LLMConfig:
|
12
|
-
"""
|
13
|
-
大语言模型相关配置
|
14
|
-
The config of LLM
|
15
|
-
"""
|
16
|
-
def __init__(
|
17
|
-
self,
|
18
|
-
config: dict
|
19
|
-
) -> None:
|
20
|
-
self.config = config
|
21
|
-
self.text = config['text_request']
|
22
|
-
self.image_u = config['img_understand_request']
|
23
|
-
self.image_g = config['img_generate_request']
|
24
|
-
|
25
|
-
class UrbanLLM:
|
26
|
-
"""
|
27
|
-
大语言模型对象
|
28
|
-
The LLM Object used by Agent(Soul)
|
29
|
-
"""
|
30
|
-
def __init__(self, config: LLMConfig) -> None:
|
31
|
-
self.config = config
|
32
|
-
|
33
|
-
def text_request(self, dialog:list[dict]) -> str:
|
34
|
-
"""
|
35
|
-
文本相关请求
|
36
|
-
Text request
|
37
|
-
|
38
|
-
Args:
|
39
|
-
- dialog (list[dict]): 标准的LLM文本dialog. The standard text LLM dialog
|
40
|
-
|
41
|
-
Returns:
|
42
|
-
- (str): the response content
|
43
|
-
"""
|
44
|
-
if self.config.text['request_type'] == 'openai':
|
45
|
-
client = OpenAI(
|
46
|
-
api_key=self.config.text['api_key'],
|
47
|
-
base_url=self.config.text['api_base']
|
48
|
-
)
|
49
|
-
response = client.chat.completions.create(
|
50
|
-
model=self.config.text['model'],
|
51
|
-
messages=dialog,
|
52
|
-
temperature=1.0,
|
53
|
-
)
|
54
|
-
return response.choices[0].message.content
|
55
|
-
elif self.config.text['request_type'] == 'qwen':
|
56
|
-
|
57
|
-
response = dashscope.Generation.call(
|
58
|
-
model=self.config.text['model'],
|
59
|
-
api_key=self.config.text['api_key'],
|
60
|
-
messages=dialog,
|
61
|
-
result_format='message'
|
62
|
-
)
|
63
|
-
if response.status_code == HTTPStatus.OK:
|
64
|
-
return response.output.choices[0]['message']['content']
|
65
|
-
else:
|
66
|
-
return "Error: {}".format(response.status_code)
|
67
|
-
else:
|
68
|
-
print("ERROR: Wrong Config")
|
69
|
-
return "wrong config"
|
70
|
-
|
71
|
-
def img_understand(self, img_path:str, prompt:str=None) -> str:
|
72
|
-
"""
|
73
|
-
图像理解
|
74
|
-
Image understanding
|
75
|
-
|
76
|
-
Args:
|
77
|
-
- img_path: 图像的绝对路径. The absolute path of selected Image
|
78
|
-
- prompt: 理解提示词 - 例如理解方向. The understanding prompts
|
79
|
-
|
80
|
-
Returns:
|
81
|
-
- (str): the understanding content
|
82
|
-
"""
|
83
|
-
ppt = "如何理解这幅图像?"
|
84
|
-
if prompt != None:
|
85
|
-
ppt += prompt
|
86
|
-
dialog = [{
|
87
|
-
'role': 'user',
|
88
|
-
'content': [
|
89
|
-
{'image': 'file://' + img_path},
|
90
|
-
{'text': ppt}
|
91
|
-
]
|
92
|
-
}]
|
93
|
-
response = dashscope.MultiModalConversation.call(
|
94
|
-
model=self.config.image_u['model'],
|
95
|
-
api_key=self.config.image_u['api_key'],
|
96
|
-
messages=dialog
|
97
|
-
)
|
98
|
-
if response.status_code == HTTPStatus.OK:
|
99
|
-
return response.output.choices[0]['message']['content']
|
100
|
-
else:
|
101
|
-
print(response.code) # The error code.
|
102
|
-
return "Error"
|
103
|
-
|
104
|
-
def img_generate(self, prompt, size:str='512*512', quantity:int = 1):
|
105
|
-
"""
|
106
|
-
图像生成
|
107
|
-
Image generation
|
108
|
-
|
109
|
-
Args:
|
110
|
-
- prompt (str): 图像生成提示词. The image generation prompts
|
111
|
-
- size (str): 生成图像尺寸, 默认为'512*512'. The image size, default: '512*512'
|
112
|
-
- quantity (int): 生成图像数量, 默认为1. The quantity of generated images, default: 1
|
113
|
-
|
114
|
-
Returns:
|
115
|
-
- (list[PIL.Image.Image]): 生成的图像列表. The list of generated Images.
|
116
|
-
"""
|
117
|
-
rsp = ImageSynthesis.call(
|
118
|
-
model=self.config.image_g['model'],
|
119
|
-
api_key=self.config.image_g['api_key'],
|
120
|
-
prompt=prompt,
|
121
|
-
n=quantity,
|
122
|
-
size=size
|
123
|
-
)
|
124
|
-
if rsp.status_code == HTTPStatus.OK:
|
125
|
-
res = []
|
126
|
-
for result in rsp.output.results:
|
127
|
-
res.append(Image.open(BytesIO(requests.get(result.url).content)))
|
128
|
-
return res
|
129
|
-
else:
|
130
|
-
print('Failed, status_code: %s, code: %s, message: %s' %
|
131
|
-
(rsp.status_code, rsp.code, rsp.message))
|
132
|
-
return None
|
@@ -1,21 +0,0 @@
|
|
1
|
-
MIT License
|
2
|
-
|
3
|
-
Copyright (c) 2024 FIBLAB
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
7
|
-
in the Software without restriction, including without limitation the rights
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
10
|
-
furnished to do so, subject to the following conditions:
|
11
|
-
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
13
|
-
copies or substantial portions of the Software.
|
14
|
-
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
-
SOFTWARE.
|