pycityagent 2.0.0a12__tar.gz → 2.0.0a13__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.
Files changed (70) hide show
  1. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/PKG-INFO +1 -1
  2. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/agent.py +39 -8
  3. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/simulation/agentgroup.py +38 -40
  4. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pyproject.toml +1 -1
  5. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/README.md +0 -0
  6. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/__init__.py +0 -0
  7. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/economy/__init__.py +0 -0
  8. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/economy/econ_client.py +0 -0
  9. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/__init__.py +0 -0
  10. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/interact/__init__.py +0 -0
  11. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/interact/interact.py +0 -0
  12. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/message/__init__.py +0 -0
  13. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/sence/__init__.py +0 -0
  14. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/sence/static.py +0 -0
  15. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/sidecar/__init__.py +0 -0
  16. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/sidecar/sidecarv2.py +0 -0
  17. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/sim/__init__.py +0 -0
  18. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/sim/aoi_service.py +0 -0
  19. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/sim/client.py +0 -0
  20. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/sim/clock_service.py +0 -0
  21. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/sim/economy_services.py +0 -0
  22. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/sim/lane_service.py +0 -0
  23. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/sim/light_service.py +0 -0
  24. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/sim/person_service.py +0 -0
  25. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/sim/road_service.py +0 -0
  26. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/sim/sim_env.py +0 -0
  27. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/sim/social_service.py +0 -0
  28. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/simulator.py +0 -0
  29. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/utils/__init__.py +0 -0
  30. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/utils/base64.py +0 -0
  31. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/utils/const.py +0 -0
  32. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/utils/geojson.py +0 -0
  33. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/utils/grpc.py +0 -0
  34. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/utils/map_utils.py +0 -0
  35. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/utils/port.py +0 -0
  36. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/environment/utils/protobuf.py +0 -0
  37. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/llm/__init__.py +0 -0
  38. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/llm/embedding.py +0 -0
  39. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/llm/llm.py +0 -0
  40. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/llm/llmconfig.py +0 -0
  41. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/llm/utils.py +0 -0
  42. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/memory/__init__.py +0 -0
  43. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/memory/const.py +0 -0
  44. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/memory/memory.py +0 -0
  45. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/memory/memory_base.py +0 -0
  46. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/memory/profile.py +0 -0
  47. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/memory/self_define.py +0 -0
  48. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/memory/state.py +0 -0
  49. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/memory/utils.py +0 -0
  50. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/message/__init__.py +0 -0
  51. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/message/messager.py +0 -0
  52. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/simulation/__init__.py +0 -0
  53. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/simulation/interview.py +0 -0
  54. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/simulation/simulation.py +0 -0
  55. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/simulation/survey/__init__.py +0 -0
  56. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/simulation/survey/manager.py +0 -0
  57. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/simulation/survey/models.py +0 -0
  58. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/simulation/ui/__init__.py +0 -0
  59. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/simulation/ui/interface.py +0 -0
  60. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/utils/__init__.py +0 -0
  61. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/utils/decorators.py +0 -0
  62. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/utils/parsers/__init__.py +0 -0
  63. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/utils/parsers/code_block_parser.py +0 -0
  64. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/utils/parsers/json_parser.py +0 -0
  65. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/utils/parsers/parser_base.py +0 -0
  66. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/workflow/__init__.py +0 -0
  67. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/workflow/block.py +0 -0
  68. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/workflow/prompt.py +0 -0
  69. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/workflow/tool.py +0 -0
  70. {pycityagent-2.0.0a12 → pycityagent-2.0.0a13}/pycityagent/workflow/trigger.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pycityagent
3
- Version: 2.0.0a12
3
+ Version: 2.0.0a13
4
4
  Summary: LLM-based城市环境agent构建库
5
5
  License: MIT
6
6
  Author: Yuwei Yan
@@ -427,7 +427,9 @@ class InstitutionAgent(Agent):
427
427
  simulator,
428
428
  memory,
429
429
  )
430
-
430
+ # 添加响应收集器
431
+ self._gather_responses: Dict[str, asyncio.Future] = {}
432
+
431
433
  async def bind_to_simulator(self):
432
434
  await self._bind_to_economy()
433
435
 
@@ -514,18 +516,47 @@ class InstitutionAgent(Agent):
514
516
 
515
517
  async def handle_gather_message(self, payload: dict):
516
518
  """处理收到的消息,识别发送者"""
517
- # 从消息中解析发送者 ID 和消息内容
518
519
  content = payload["content"]
519
520
  sender_id = payload["from"]
520
- print(
521
- f"Agent {self._uuid} received gather message: '{content}' from Agent {sender_id}"
522
- )
523
-
524
- async def gather_messages(self, agent_ids: list[UUID], target: str):
525
- """从多个智能体收集消息"""
521
+
522
+ # 将响应存储到对应的Future中
523
+ response_key = str(sender_id)
524
+ if response_key in self._gather_responses:
525
+ self._gather_responses[response_key].set_result({
526
+ "from": sender_id,
527
+ "content": content,
528
+ })
529
+
530
+ async def gather_messages(self, agent_ids: list[UUID], target: str) -> List[dict]:
531
+ """从多个智能体收集消息
532
+
533
+ Args:
534
+ agent_ids: 目标智能体ID列表
535
+ target: 要收集的信息类型
536
+
537
+ Returns:
538
+ List[dict]: 收集到的所有响应
539
+ """
540
+ # 为每个agent创建Future
541
+ futures = {}
542
+ for agent_id in agent_ids:
543
+ response_key = str(agent_id)
544
+ futures[response_key] = asyncio.Future()
545
+ self._gather_responses[response_key] = futures[response_key]
546
+
547
+ # 发送gather请求
526
548
  payload = {
527
549
  "from": self._uuid,
528
550
  "target": target,
529
551
  }
530
552
  for agent_id in agent_ids:
531
553
  await self._send_message(agent_id, payload, "gather")
554
+
555
+ try:
556
+ # 等待所有响应
557
+ responses = await asyncio.gather(*futures.values())
558
+ return responses
559
+ finally:
560
+ # 清理Future
561
+ for key in futures:
562
+ self._gather_responses.pop(key, None)
@@ -71,7 +71,8 @@ class AgentGroup:
71
71
  topic = f"exps/{self.exp_id}/agents/{agent._uuid}/gather"
72
72
  await self.messager.subscribe(topic, agent)
73
73
  self.initialized = True
74
-
74
+ self.message_dispatch_task = asyncio.create_task(self.message_dispatch())
75
+
75
76
  async def gather(self, content: str):
76
77
  results = {}
77
78
  for agent in self.agents:
@@ -82,49 +83,46 @@ class AgentGroup:
82
83
  agent = self.id2agent[target_agent_uuid]
83
84
  await agent.memory.update(target_key, content)
84
85
 
86
+ async def message_dispatch(self):
87
+ while True:
88
+ if not self.messager.is_connected():
89
+ logging.warning("Messager is not connected. Skipping message processing.")
90
+
91
+ # Step 1: 获取消息
92
+ messages = await self.messager.fetch_messages()
93
+ logging.info(f"Group {self._uuid} received {len(messages)} messages")
94
+
95
+ # Step 2: 分发消息到对应的 Agent
96
+ for message in messages:
97
+ topic = message.topic.value
98
+ payload = message.payload
99
+
100
+ # 添加解码步骤,将bytes转换为str
101
+ if isinstance(payload, bytes):
102
+ payload = payload.decode("utf-8")
103
+ payload = json.loads(payload)
104
+
105
+ # 提取 agent_id(主题格式为 "exps/{exp_id}/agents/{agent_uuid}/{topic_type}")
106
+ _, _, _, agent_uuid, topic_type = topic.strip("/").split("/")
107
+
108
+ if uuid.UUID(agent_uuid) in self.id2agent:
109
+ agent = self.id2agent[uuid.UUID(agent_uuid)]
110
+ # topic_type: agent-chat, user-chat, user-survey, gather
111
+ if topic_type == "agent-chat":
112
+ await agent.handle_agent_chat_message(payload)
113
+ elif topic_type == "user-chat":
114
+ await agent.handle_user_chat_message(payload)
115
+ elif topic_type == "user-survey":
116
+ await agent.handle_user_survey_message(payload)
117
+ elif topic_type == "gather":
118
+ await agent.handle_gather_message(payload)
119
+
120
+ await asyncio.sleep(1)
121
+
85
122
  async def step(self):
86
123
  if not self.initialized:
87
124
  await self.init_agents()
88
125
 
89
- # Step 1: 如果 Messager 无法连接,则跳过消息接收
90
- if not self.messager.is_connected():
91
- logging.warning("Messager is not connected. Skipping message processing.")
92
- # 跳过接收和分发消息
93
- tasks = [agent.run() for agent in self.agents]
94
- await asyncio.gather(*tasks)
95
- return
96
-
97
- # Step 2: 从 Messager 获取消息
98
- messages = await self.messager.fetch_messages()
99
-
100
- logging.info(f"Group {self._uuid} received {len(messages)} messages")
101
-
102
- # Step 3: 分发消息到对应的 Agent
103
- for message in messages:
104
- topic = message.topic.value
105
- payload = message.payload
106
-
107
- # 添加解码步骤,将bytes转换为str
108
- if isinstance(payload, bytes):
109
- payload = payload.decode("utf-8")
110
- payload = json.loads(payload)
111
-
112
- # 提取 agent_id(主题格式为 "exps/{exp_id}/agents/{agent_uuid}/{topic_type}")
113
- _, _, _, agent_uuid, topic_type = topic.strip("/").split("/")
114
-
115
- if uuid.UUID(agent_uuid) in self.id2agent:
116
- agent = self.id2agent[uuid.UUID(agent_uuid)]
117
- # topic_type: agent-chat, user-chat, user-survey, gather
118
- if topic_type == "agent-chat":
119
- await agent.handle_agent_chat_message(payload)
120
- elif topic_type == "user-chat":
121
- await agent.handle_user_chat_message(payload)
122
- elif topic_type == "user-survey":
123
- await agent.handle_user_survey_message(payload)
124
- elif topic_type == "gather":
125
- await agent.handle_gather_message(payload)
126
-
127
- # Step 4: 调用每个 Agent 的运行逻辑
128
126
  tasks = [agent.run() for agent in self.agents]
129
127
  await asyncio.gather(*tasks)
130
128
 
@@ -3,7 +3,7 @@ in-project = true
3
3
 
4
4
  [tool.poetry]
5
5
  name = "pycityagent"
6
- version = "2.0.0a12"
6
+ version = "2.0.0a13"
7
7
  description = "LLM-based城市环境agent构建库"
8
8
  authors = ["Yuwei Yan <pinkgranite86@gmail.com>","Junbo Yan <yanjb20thu@gmali.com>"]
9
9
  license = "MIT"
File without changes