pycityagent 2.0.0a47__cp311-cp311-macosx_11_0_arm64.whl → 2.0.0a49__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/__init__.py +3 -2
- pycityagent/agent.py +109 -4
- pycityagent/cityagent/__init__.py +20 -0
- pycityagent/cityagent/bankagent.py +54 -0
- pycityagent/cityagent/blocks/__init__.py +20 -0
- pycityagent/cityagent/blocks/cognition_block.py +304 -0
- pycityagent/cityagent/blocks/dispatcher.py +78 -0
- pycityagent/cityagent/blocks/economy_block.py +356 -0
- pycityagent/cityagent/blocks/mobility_block.py +258 -0
- pycityagent/cityagent/blocks/needs_block.py +305 -0
- pycityagent/cityagent/blocks/other_block.py +103 -0
- pycityagent/cityagent/blocks/plan_block.py +309 -0
- pycityagent/cityagent/blocks/social_block.py +345 -0
- pycityagent/cityagent/blocks/time_block.py +116 -0
- pycityagent/cityagent/blocks/utils.py +66 -0
- pycityagent/cityagent/firmagent.py +75 -0
- pycityagent/cityagent/governmentagent.py +60 -0
- pycityagent/cityagent/initial.py +98 -0
- pycityagent/cityagent/memory_config.py +202 -0
- pycityagent/cityagent/nbsagent.py +92 -0
- pycityagent/cityagent/societyagent.py +291 -0
- pycityagent/memory/memory.py +0 -18
- pycityagent/message/messager.py +6 -3
- pycityagent/simulation/agentgroup.py +123 -37
- pycityagent/simulation/simulation.py +311 -316
- pycityagent/workflow/block.py +66 -1
- pycityagent/workflow/tool.py +9 -4
- {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a49.dist-info}/METADATA +2 -2
- {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a49.dist-info}/RECORD +33 -14
- {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a49.dist-info}/LICENSE +0 -0
- {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a49.dist-info}/WHEEL +0 -0
- {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a49.dist-info}/entry_points.txt +0 -0
- {pycityagent-2.0.0a47.dist-info → pycityagent-2.0.0a49.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
import asyncio
|
2
|
+
from typing import Optional
|
3
|
+
|
4
|
+
import numpy as np
|
5
|
+
from pycityagent import Simulator, InstitutionAgent
|
6
|
+
from pycityagent.llm.llm import LLM
|
7
|
+
from pycityagent.economy import EconomyClient
|
8
|
+
from pycityagent.message import Messager
|
9
|
+
from pycityagent.memory import Memory
|
10
|
+
from pycityagent.workflow.tool import ExportMlflowMetrics
|
11
|
+
import logging
|
12
|
+
|
13
|
+
logger = logging.getLogger("pycityagent")
|
14
|
+
|
15
|
+
class NBSAgent(InstitutionAgent):
|
16
|
+
export_metrics = ExportMlflowMetrics(log_batch_size=3)
|
17
|
+
|
18
|
+
def __init__(self,
|
19
|
+
name: str,
|
20
|
+
llm_client: Optional[LLM] = None,
|
21
|
+
simulator: Optional[Simulator] = None,
|
22
|
+
memory: Optional[Memory] = None,
|
23
|
+
economy_client: Optional[EconomyClient] = None,
|
24
|
+
messager: Optional[Messager] = None,
|
25
|
+
avro_file: Optional[dict] = None,
|
26
|
+
) -> None:
|
27
|
+
super().__init__(name=name, llm_client=llm_client, simulator=simulator, memory=memory, economy_client=economy_client, messager=messager, avro_file=avro_file)
|
28
|
+
self.initailzed = False
|
29
|
+
self.last_time_trigger = None
|
30
|
+
self.time_diff = 30 * 24 * 60 * 60
|
31
|
+
self.forward_times = 0
|
32
|
+
self.num_labor_hours = 168
|
33
|
+
self.productivity_per_labor = 1
|
34
|
+
self.price = 1
|
35
|
+
async def month_trigger(self):
|
36
|
+
now_time = await self.simulator.get_time()
|
37
|
+
if self.last_time_trigger is None:
|
38
|
+
self.last_time_trigger = now_time
|
39
|
+
return False
|
40
|
+
if now_time - self.last_time_trigger >= self.time_diff:
|
41
|
+
self.last_time_trigger = now_time
|
42
|
+
return True
|
43
|
+
return False
|
44
|
+
|
45
|
+
async def gather_messages(self, agent_ids, content):
|
46
|
+
infos = await super().gather_messages(agent_ids, content)
|
47
|
+
return [info['content'] for info in infos]
|
48
|
+
|
49
|
+
async def forward(self):
|
50
|
+
if await self.month_trigger():
|
51
|
+
citizens = await self.memory.get("citizens")
|
52
|
+
while True:
|
53
|
+
agents_forward = await self.gather_messages(citizens, 'forward')
|
54
|
+
if np.all(np.array(agents_forward) > self.forward_times):
|
55
|
+
break
|
56
|
+
await asyncio.sleep(1)
|
57
|
+
work_propensity = await self.gather_messages(citizens, "work_propensity")
|
58
|
+
working_hours = np.mean(work_propensity)*self.num_labor_hours
|
59
|
+
firm_id = await self.memory.get("firm_id")
|
60
|
+
price = await self.economy_client.get(firm_id, "price")
|
61
|
+
prices = await self.economy_client.get(self._agent_id, "prices")
|
62
|
+
initial_price = prices[0]
|
63
|
+
nominal_gdp = working_hours*len(citizens)*self.productivity_per_labor*price
|
64
|
+
real_gdp = working_hours*len(citizens)*self.productivity_per_labor*initial_price
|
65
|
+
await self.economy_client.update(self._agent_id, 'nominal_gdp', [nominal_gdp], mode='merge')
|
66
|
+
await self.economy_client.update(self._agent_id, 'real_gdp', [real_gdp], mode='merge')
|
67
|
+
await self.economy_client.update(self._agent_id, 'working_hours', [working_hours], mode='merge')
|
68
|
+
await self.economy_client.update(self._agent_id, 'prices', [price], mode='merge')
|
69
|
+
depression = await self.gather_messages(citizens, 'depression')
|
70
|
+
depression = np.mean(depression)
|
71
|
+
await self.economy_client.update(self._agent_id, 'depression', [depression], mode='merge')
|
72
|
+
consumption_currency = await self.gather_messages(citizens, 'consumption_currency')
|
73
|
+
consumption_currency = np.mean(consumption_currency)
|
74
|
+
await self.economy_client.update(self._agent_id, 'consumption_currency', [consumption_currency], mode='merge')
|
75
|
+
income_currency = await self.gather_messages(citizens, 'income_currency')
|
76
|
+
income_currency = np.mean(income_currency)
|
77
|
+
await self.economy_client.update(self._agent_id, 'income_currency', [income_currency], mode='merge')
|
78
|
+
self.forward_times += 1
|
79
|
+
for uuid in citizens:
|
80
|
+
await self.send_message_to_agent(uuid, f"nbs_forward@{self.forward_times}")
|
81
|
+
|
82
|
+
metrics = {'nominal_gdp': nominal_gdp, 'working_hours': working_hours, 'price': price,
|
83
|
+
'depression': depression, 'consumption': consumption_currency, 'income': income_currency}
|
84
|
+
for k, v in metrics.items():
|
85
|
+
await self.export_metrics(
|
86
|
+
metric={
|
87
|
+
"key": k,
|
88
|
+
"value": v,
|
89
|
+
"step": self.forward_times,
|
90
|
+
},
|
91
|
+
clear_cache=True,
|
92
|
+
)
|
@@ -0,0 +1,291 @@
|
|
1
|
+
import asyncio
|
2
|
+
import json
|
3
|
+
from typing import Optional
|
4
|
+
from pycityagent import Simulator, CitizenAgent
|
5
|
+
from pycityagent.agent import Agent
|
6
|
+
from pycityagent.llm.llm import LLM
|
7
|
+
from pycityagent.economy import EconomyClient
|
8
|
+
from pycityagent.message import Messager
|
9
|
+
from pycityagent.memory import Memory
|
10
|
+
from pycityagent.workflow.tool import UpdateWithSimulator
|
11
|
+
from pycityagent.workflow import Block
|
12
|
+
from .blocks import CognitionBlock, EconomyBlock, MobilityBlock, NeedsBlock, OtherBlock, PlanBlock, SocialBlock
|
13
|
+
from .blocks.economy_block import MonthPlanBlock
|
14
|
+
import logging
|
15
|
+
|
16
|
+
logger = logging.getLogger("pycityagent")
|
17
|
+
|
18
|
+
class PlanAndActionBlock(Block):
|
19
|
+
"""主动工作流"""
|
20
|
+
longTermDecisionBlock: MonthPlanBlock
|
21
|
+
needsBlock: NeedsBlock
|
22
|
+
planBlock: PlanBlock
|
23
|
+
mobilityBlock: MobilityBlock
|
24
|
+
socialBlock: SocialBlock
|
25
|
+
economyBlock: EconomyBlock
|
26
|
+
otherBlock: OtherBlock
|
27
|
+
|
28
|
+
def __init__(self, agent: Agent, llm: LLM, memory: Memory, simulator: Simulator, economy_client: EconomyClient):
|
29
|
+
super().__init__(name="plan_and_action_block", llm=llm, memory=memory, simulator=simulator)
|
30
|
+
self._agent = agent
|
31
|
+
self.longTermDecisionBlock = MonthPlanBlock(llm=llm, memory=memory, simulator=simulator, economy_client=economy_client)
|
32
|
+
self.needsBlock = NeedsBlock(llm=llm, memory=memory, simulator=simulator)
|
33
|
+
self.planBlock = PlanBlock(llm=llm, memory=memory, simulator=simulator)
|
34
|
+
self.mobilityBlock = MobilityBlock(llm=llm, memory=memory, simulator=simulator)
|
35
|
+
self.socialBlock = SocialBlock(agent=self, llm=llm, memory=memory, simulator=simulator)
|
36
|
+
self.economyBlock = EconomyBlock(llm=llm, memory=memory, simulator=simulator, economy_client=economy_client)
|
37
|
+
self.otherBlock = OtherBlock(llm=llm, memory=memory)
|
38
|
+
|
39
|
+
async def check_and_update_step(self):
|
40
|
+
status = await self.memory.get('status')
|
41
|
+
if status == 2:
|
42
|
+
# 正在运动
|
43
|
+
logger.info("Agent is moving")
|
44
|
+
await asyncio.sleep(1)
|
45
|
+
return False
|
46
|
+
|
47
|
+
# 获取上一步信息
|
48
|
+
current_step = await self.memory.get("current_step")
|
49
|
+
if current_step['intention'] == "" or current_step['type'] == "":
|
50
|
+
# 没有上一步,直接返回
|
51
|
+
return True
|
52
|
+
time_now = int(await self.simulator.get_time())
|
53
|
+
step_start_time = current_step['start_time']
|
54
|
+
step_consumed_time = current_step['evaluation']['consumed_time']
|
55
|
+
time_end_plan = step_start_time + int(step_consumed_time)*60
|
56
|
+
if time_now >= time_end_plan:
|
57
|
+
# 上一步执行完成
|
58
|
+
current_plan = await self.memory.get("current_plan")
|
59
|
+
current_step['evaluation']['consumed_time'] = (time_now - step_start_time)/60
|
60
|
+
current_step_index = next((i for i, step in enumerate(current_plan["steps"]) if step['intention'] == current_step['intention'] and step['type'] == current_step['type']), None)
|
61
|
+
current_plan["steps"][current_step_index] = current_step
|
62
|
+
await self.memory.update("current_plan", current_plan)
|
63
|
+
if current_step_index is not None and current_step_index + 1 < len(current_plan["steps"]):
|
64
|
+
next_step = current_plan["steps"][current_step_index + 1]
|
65
|
+
await self.memory.update("current_step", next_step)
|
66
|
+
else:
|
67
|
+
# 标记计划完成
|
68
|
+
current_plan["completed"] = True
|
69
|
+
current_plan["end_time"] = await self.simulator.get_time(format_time=True)
|
70
|
+
await self.memory.update("current_plan", current_plan)
|
71
|
+
await self.memory.update("current_step", {"intention": "", "type": ""})
|
72
|
+
logger.info("Current plan execution completed.\n")
|
73
|
+
return True
|
74
|
+
# 上一步未执行完成
|
75
|
+
return False
|
76
|
+
|
77
|
+
async def forward(self):
|
78
|
+
# 与模拟器同步智能体的状态
|
79
|
+
await self._agent.update_with_sim()
|
80
|
+
# 检测上一步是否执行完成
|
81
|
+
if not await self.check_and_update_step():
|
82
|
+
return
|
83
|
+
|
84
|
+
# 长期决策
|
85
|
+
await self.longTermDecisionBlock.forward()
|
86
|
+
|
87
|
+
# 需求更新
|
88
|
+
time_now = await self.simulator.get_time(format_time=True)
|
89
|
+
logger.info(f"Current time: {time_now}")
|
90
|
+
await self.needsBlock.forward()
|
91
|
+
current_need = await self.memory.get("current_need")
|
92
|
+
logger.info(f"Current need: {current_need}")
|
93
|
+
|
94
|
+
# 计划生成
|
95
|
+
current_plan = await self.memory.get("current_plan")
|
96
|
+
if current_need != "none" and not current_plan:
|
97
|
+
await self.planBlock.forward()
|
98
|
+
current_plan = await self.memory.get("current_plan")
|
99
|
+
execution_context = await self.memory.get("execution_context")
|
100
|
+
current_step = await self.memory.get("current_step")
|
101
|
+
# 检查 current_step 是否有效(不为空)
|
102
|
+
if current_step and current_step.get("type") and current_step.get("intention"):
|
103
|
+
step_type = current_step.get("type")
|
104
|
+
position = await self.memory.get("position")
|
105
|
+
if 'aoi_position' in position:
|
106
|
+
current_step['position'] = position['aoi_position']['aoi_id']
|
107
|
+
current_step['start_time'] = int(await self.simulator.get_time())
|
108
|
+
logger.info(f"Executing step: {current_step['intention']} - Type: {step_type}")
|
109
|
+
result = None
|
110
|
+
if step_type == "mobility":
|
111
|
+
result = await self.mobilityBlock.forward(current_step, execution_context)
|
112
|
+
elif step_type == "social":
|
113
|
+
result = await self.socialBlock.forward(current_step, execution_context)
|
114
|
+
elif step_type == "economy":
|
115
|
+
result = await self.economyBlock.forward(current_step, execution_context)
|
116
|
+
elif step_type == "other":
|
117
|
+
result = await self.otherBlock.forward(current_step, execution_context)
|
118
|
+
if result != None:
|
119
|
+
logger.info(f"Execution result: {result}")
|
120
|
+
current_step['evaluation'] = result
|
121
|
+
|
122
|
+
# 更新current_step信息,plan信息以及execution_context信息
|
123
|
+
current_step_index = next((i for i, step in enumerate(current_plan["steps"]) if step['intention'] == current_step['intention'] and step['type'] == current_step['type']), None)
|
124
|
+
current_plan["steps"][current_step_index] = current_step
|
125
|
+
await self.memory.update("current_step", current_step)
|
126
|
+
await self.memory.update("current_plan", current_plan)
|
127
|
+
await self.memory.update("execution_context", execution_context)
|
128
|
+
|
129
|
+
class MindBlock(Block):
|
130
|
+
"""认知工作流"""
|
131
|
+
cognitionBlock: CognitionBlock
|
132
|
+
|
133
|
+
def __init__(self, llm: LLM, memory: Memory, simulator: Simulator):
|
134
|
+
super().__init__(name="mind_block", llm=llm, memory=memory, simulator=simulator)
|
135
|
+
self.cognitionBlock = CognitionBlock(llm=llm, memory=memory, simulator=simulator)
|
136
|
+
|
137
|
+
async def forward(self):
|
138
|
+
await self.cognitionBlock.forward()
|
139
|
+
|
140
|
+
class SocietyAgent(CitizenAgent):
|
141
|
+
mindBlock: MindBlock
|
142
|
+
planAndActionBlock: PlanAndActionBlock
|
143
|
+
update_with_sim = UpdateWithSimulator()
|
144
|
+
|
145
|
+
def __init__(self,
|
146
|
+
name: str,
|
147
|
+
llm_client: Optional[LLM] = None,
|
148
|
+
simulator: Optional[Simulator] = None,
|
149
|
+
memory: Optional[Memory] = None,
|
150
|
+
economy_client: Optional[EconomyClient] = None,
|
151
|
+
) -> None:
|
152
|
+
super().__init__(name=name, llm_client=llm_client, simulator=simulator, memory=memory, economy_client=economy_client)
|
153
|
+
self.mindBlock = MindBlock(llm=self._llm_client, memory=self._memory, simulator=self._simulator)
|
154
|
+
self.planAndActionBlock = PlanAndActionBlock(agent=self, llm=self._llm_client, memory=self._memory, simulator=self._simulator, economy_client=self._economy_client)
|
155
|
+
self.step_count = -1
|
156
|
+
|
157
|
+
# Main workflow
|
158
|
+
async def forward(self):
|
159
|
+
logger.info(f"Agent {self._uuid} forward")
|
160
|
+
self.step_count += 1
|
161
|
+
# 多工作流并发执行
|
162
|
+
task_list = [
|
163
|
+
asyncio.create_task(self.mindBlock.forward()),
|
164
|
+
asyncio.create_task(self.planAndActionBlock.forward()),
|
165
|
+
]
|
166
|
+
await asyncio.gather(*task_list)
|
167
|
+
|
168
|
+
async def process_agent_chat_response(self, payload: dict) -> str:
|
169
|
+
if payload['type'] == 'social':
|
170
|
+
resp = f"Agent {self._uuid} received agent chat response: {payload}"
|
171
|
+
logger.info(resp)
|
172
|
+
try:
|
173
|
+
# Extract basic info
|
174
|
+
sender_id = payload.get("from")
|
175
|
+
if not sender_id:
|
176
|
+
return ""
|
177
|
+
|
178
|
+
raw_content = payload.get("content", "")
|
179
|
+
|
180
|
+
# Parse message content
|
181
|
+
try:
|
182
|
+
message_data = json.loads(raw_content)
|
183
|
+
content = message_data["content"]
|
184
|
+
propagation_count = message_data.get("propagation_count", 1)
|
185
|
+
except (json.JSONDecodeError, TypeError, KeyError):
|
186
|
+
content = raw_content
|
187
|
+
propagation_count = 1
|
188
|
+
|
189
|
+
if not content:
|
190
|
+
return ""
|
191
|
+
|
192
|
+
# Get chat histories and ensure proper format
|
193
|
+
chat_histories = await self._memory.get("chat_histories") or {}
|
194
|
+
if not isinstance(chat_histories, dict):
|
195
|
+
chat_histories = {}
|
196
|
+
|
197
|
+
# Update chat history with received message
|
198
|
+
if sender_id not in chat_histories:
|
199
|
+
chat_histories[sender_id] = ""
|
200
|
+
if chat_histories[sender_id]:
|
201
|
+
chat_histories[sender_id] += ","
|
202
|
+
chat_histories[sender_id] += f"them: {content}"
|
203
|
+
|
204
|
+
# Check propagation limit
|
205
|
+
if propagation_count > 5:
|
206
|
+
await self._memory.update("chat_histories", chat_histories)
|
207
|
+
logger.info(f"Message propagation limit reached ({propagation_count} > 5), stopping propagation")
|
208
|
+
return ""
|
209
|
+
|
210
|
+
# Get relationship score
|
211
|
+
relationships = await self._memory.get("relationships") or {}
|
212
|
+
relationship_score = relationships.get(sender_id, 50)
|
213
|
+
|
214
|
+
# Decision prompt
|
215
|
+
should_respond_prompt = f"""Based on:
|
216
|
+
- Received message: "{content}"
|
217
|
+
- Our relationship score: {relationship_score}/100
|
218
|
+
- My profile: {{
|
219
|
+
"gender": "{await self._memory.get("gender") or ""}",
|
220
|
+
"education": "{await self._memory.get("education") or ""}",
|
221
|
+
"personality": "{await self._memory.get("personality") or ""}",
|
222
|
+
"occupation": "{await self._memory.get("occupation") or ""}"
|
223
|
+
}}
|
224
|
+
- Recent chat history: {chat_histories.get(sender_id, "")}
|
225
|
+
|
226
|
+
Should I respond to this message? Consider:
|
227
|
+
1. Is this a message that needs/deserves a response?
|
228
|
+
2. Would it be natural for someone with my personality to respond?
|
229
|
+
3. Is our relationship close enough to warrant a response?
|
230
|
+
|
231
|
+
Answer only YES or NO."""
|
232
|
+
|
233
|
+
should_respond = await self._llm_client.atext_request([
|
234
|
+
{"role": "system", "content": "You are helping decide whether to respond to a message."},
|
235
|
+
{"role": "user", "content": should_respond_prompt}
|
236
|
+
])
|
237
|
+
|
238
|
+
if should_respond.strip().upper() != "YES":
|
239
|
+
await self._memory.update("chat_histories", chat_histories)
|
240
|
+
return ""
|
241
|
+
|
242
|
+
response_prompt = f"""Based on:
|
243
|
+
- Received message: "{content}"
|
244
|
+
- Our relationship score: {relationship_score}/100
|
245
|
+
- My profile: {{
|
246
|
+
"gender": "{await self._memory.get("gender") or ""}",
|
247
|
+
"education": "{await self._memory.get("education") or ""}",
|
248
|
+
"personality": "{await self._memory.get("personality") or ""}",
|
249
|
+
"occupation": "{await self._memory.get("occupation") or ""}"
|
250
|
+
}}
|
251
|
+
- Recent chat history: {chat_histories.get(sender_id, "")}
|
252
|
+
|
253
|
+
Generate an appropriate response that:
|
254
|
+
1. Matches my personality and background
|
255
|
+
2. Maintains natural conversation flow
|
256
|
+
3. Is concise (under 100 characters)
|
257
|
+
4. Reflects our relationship level
|
258
|
+
|
259
|
+
Response should be ONLY the message text, no explanations."""
|
260
|
+
|
261
|
+
response = await self._llm_client.atext_request([
|
262
|
+
{"role": "system", "content": "You are helping generate a chat response."},
|
263
|
+
{"role": "user", "content": response_prompt}
|
264
|
+
])
|
265
|
+
|
266
|
+
if response:
|
267
|
+
# Update chat history with response
|
268
|
+
chat_histories[sender_id] += f",me: {response}"
|
269
|
+
await self._memory.update("chat_histories", chat_histories)
|
270
|
+
|
271
|
+
# Send response
|
272
|
+
serialized_response = json.dumps({
|
273
|
+
"content": response,
|
274
|
+
"propagation_count": propagation_count + 1
|
275
|
+
}, ensure_ascii=False)
|
276
|
+
await self.send_message_to_agent(sender_id, serialized_response)
|
277
|
+
logger.info('sender_id',sender_id)
|
278
|
+
logger.info('message',serialized_response)
|
279
|
+
return response
|
280
|
+
|
281
|
+
except Exception as e:
|
282
|
+
logger.warning(f"Error in process_agent_chat_response: {str(e)}")
|
283
|
+
return ""
|
284
|
+
else:
|
285
|
+
content = payload['content']
|
286
|
+
key, value = content.split("@")
|
287
|
+
if '.' in value:
|
288
|
+
value = float(value)
|
289
|
+
else:
|
290
|
+
value = int(value)
|
291
|
+
await self.memory.update(key, value)
|
pycityagent/memory/memory.py
CHANGED
@@ -395,24 +395,6 @@ class Memory:
|
|
395
395
|
if _snapshot:
|
396
396
|
await _mem.load(snapshots=_snapshot, reset_memory=reset_memory)
|
397
397
|
|
398
|
-
# async def add(self, content: str, metadata: Optional[dict] = None) -> None:
|
399
|
-
# """添加新的记忆
|
400
|
-
|
401
|
-
# Args:
|
402
|
-
# content: 记忆内容
|
403
|
-
# metadata: 相关元数据,如时间、地点等
|
404
|
-
# """
|
405
|
-
# embedding = await self.embedding_model.aembed_query(content)
|
406
|
-
# self.memories.append(
|
407
|
-
# {
|
408
|
-
# "content": content,
|
409
|
-
# "metadata": metadata or {},
|
410
|
-
# "timestamp": datetime.now(),
|
411
|
-
# "embedding": embedding,
|
412
|
-
# }
|
413
|
-
# )
|
414
|
-
# self.embeddings.append(embedding)
|
415
|
-
|
416
398
|
@lock_decorator
|
417
399
|
async def search(
|
418
400
|
self, query: str, top_k: int = 3, filter: Optional[dict] = None
|
pycityagent/message/messager.py
CHANGED
@@ -25,6 +25,9 @@ class Messager:
|
|
25
25
|
async def __aexit__(self, exc_type, exc_value, traceback):
|
26
26
|
await self.stop()
|
27
27
|
|
28
|
+
async def ping(self):
|
29
|
+
await self.client.publish(topic="ping", payload="ping", qos=1)
|
30
|
+
|
28
31
|
async def connect(self):
|
29
32
|
for i in range(3):
|
30
33
|
try:
|
@@ -43,14 +46,14 @@ class Messager:
|
|
43
46
|
self.connected = False
|
44
47
|
logger.info("Disconnected from MQTT Broker")
|
45
48
|
|
46
|
-
def is_connected(self):
|
49
|
+
async def is_connected(self):
|
47
50
|
"""检查是否成功连接到 Broker"""
|
48
51
|
return self.connected
|
49
52
|
|
50
53
|
async def subscribe(
|
51
54
|
self, topics: Union[str, List[str]], agents: Union[Any, List[Any]]
|
52
55
|
):
|
53
|
-
if not self.is_connected():
|
56
|
+
if not await self.is_connected():
|
54
57
|
logger.error(
|
55
58
|
f"Cannot subscribe to {topics} because not connected to the Broker."
|
56
59
|
)
|
@@ -81,7 +84,7 @@ class Messager:
|
|
81
84
|
|
82
85
|
async def start_listening(self):
|
83
86
|
"""启动消息监听任务"""
|
84
|
-
if self.is_connected():
|
87
|
+
if await self.is_connected():
|
85
88
|
self.receive_messages_task = asyncio.create_task(self.receive_messages())
|
86
89
|
else:
|
87
90
|
logger.error("Cannot start listening because not connected to the Broker.")
|