pycityagent 2.0.0a9__tar.gz → 2.0.0a10__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-2.0.0a9 → pycityagent-2.0.0a10}/PKG-INFO +1 -1
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/agent.py +135 -8
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/simulator.py +0 -1
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/llm/llm.py +20 -125
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/memory/memory_base.py +1 -1
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/memory/profile.py +1 -1
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/memory/self_define.py +1 -1
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/memory/state.py +1 -1
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/memory/utils.py +1 -1
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/message/messager.py +1 -1
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/simulation/agentgroup.py +8 -5
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/simulation/simulation.py +6 -6
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pyproject.toml +1 -1
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/README.md +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/economy/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/economy/econ_client.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/interact/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/interact/interact.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/message/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/sence/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/sence/static.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/sidecar/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/sidecar/sidecarv2.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/sim/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/sim/aoi_service.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/sim/client.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/sim/clock_service.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/sim/economy_services.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/sim/lane_service.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/sim/light_service.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/sim/person_service.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/sim/road_service.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/sim/sim_env.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/sim/social_service.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/utils/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/utils/base64.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/utils/const.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/utils/geojson.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/utils/grpc.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/utils/map_utils.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/utils/port.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/utils/protobuf.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/llm/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/llm/embedding.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/llm/llmconfig.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/llm/utils.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/memory/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/memory/const.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/memory/memory.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/message/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/simulation/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/simulation/interview.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/simulation/survey/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/simulation/survey/manager.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/simulation/survey/models.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/simulation/ui/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/simulation/ui/interface.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/utils/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/utils/decorators.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/utils/parsers/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/utils/parsers/code_block_parser.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/utils/parsers/json_parser.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/utils/parsers/parser_base.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/workflow/__init__.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/workflow/block.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/workflow/prompt.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/workflow/tool.py +0 -0
- {pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/workflow/trigger.py +0 -0
@@ -2,10 +2,12 @@
|
|
2
2
|
|
3
3
|
from abc import ABC, abstractmethod
|
4
4
|
import asyncio
|
5
|
+
from uuid import UUID
|
5
6
|
from copy import deepcopy
|
6
7
|
from datetime import datetime
|
7
8
|
from enum import Enum
|
8
9
|
import logging
|
10
|
+
import random
|
9
11
|
from typing import Dict, List, Optional
|
10
12
|
|
11
13
|
from pycityagent.environment.sim.person_service import PersonService
|
@@ -80,10 +82,6 @@ class Agent(ABC):
|
|
80
82
|
del state["_llm_client"]
|
81
83
|
return state
|
82
84
|
|
83
|
-
async def bind_to_simulator(self):
|
84
|
-
await self._bind_to_simulator()
|
85
|
-
await self._bind_to_economy()
|
86
|
-
|
87
85
|
def set_messager(self, messager: Messager):
|
88
86
|
"""
|
89
87
|
Set the messager of the agent.
|
@@ -114,7 +112,7 @@ class Agent(ABC):
|
|
114
112
|
"""
|
115
113
|
self._memory = memory
|
116
114
|
|
117
|
-
def set_exp_id(self, exp_id: str):
|
115
|
+
def set_exp_id(self, exp_id: str|UUID):
|
118
116
|
"""
|
119
117
|
Set the exp_id of the agent.
|
120
118
|
"""
|
@@ -141,7 +139,7 @@ class Agent(ABC):
|
|
141
139
|
"bike_attribute",
|
142
140
|
}
|
143
141
|
simulator = self._simulator
|
144
|
-
memory = self.
|
142
|
+
memory = self.memory
|
145
143
|
person_id = await memory.get("id")
|
146
144
|
# ATTENTION:模拟器分配的id从0开始
|
147
145
|
if person_id >= 0:
|
@@ -178,11 +176,11 @@ class Agent(ABC):
|
|
178
176
|
await self._economy_client.remove_agents([self._agent_id])
|
179
177
|
except:
|
180
178
|
pass
|
181
|
-
person_id = await self.
|
179
|
+
person_id = await self.memory.get("id")
|
182
180
|
await self._economy_client.add_agents(
|
183
181
|
{
|
184
182
|
"id": person_id,
|
185
|
-
"currency": await self.
|
183
|
+
"currency": await self.memory.get("currency"),
|
186
184
|
}
|
187
185
|
)
|
188
186
|
self._has_bound_to_economy = True
|
@@ -300,6 +298,9 @@ class Agent(ABC):
|
|
300
298
|
async def forward(self) -> None:
|
301
299
|
"""智能体行为逻辑"""
|
302
300
|
raise NotImplementedError
|
301
|
+
|
302
|
+
async def handle_gather_message(self, payload: str):
|
303
|
+
raise NotImplementedError
|
303
304
|
|
304
305
|
async def run(self) -> None:
|
305
306
|
"""
|
@@ -334,6 +335,81 @@ class CitizenAgent(Agent):
|
|
334
335
|
memory,
|
335
336
|
)
|
336
337
|
|
338
|
+
async def bind_to_simulator(self):
|
339
|
+
await self._bind_to_simulator()
|
340
|
+
await self._bind_to_economy()
|
341
|
+
|
342
|
+
async def _bind_to_simulator(self):
|
343
|
+
"""
|
344
|
+
Bind Agent to Simulator
|
345
|
+
|
346
|
+
Args:
|
347
|
+
person_template (dict, optional): The person template in dict format. Defaults to PersonService.default_dict_person().
|
348
|
+
"""
|
349
|
+
if self._simulator is None:
|
350
|
+
logging.warning("Simulator is not set")
|
351
|
+
return
|
352
|
+
if not self._has_bound_to_simulator:
|
353
|
+
FROM_MEMORY_KEYS = {
|
354
|
+
"attribute",
|
355
|
+
"home",
|
356
|
+
"work",
|
357
|
+
"vehicle_attribute",
|
358
|
+
"bus_attribute",
|
359
|
+
"pedestrian_attribute",
|
360
|
+
"bike_attribute",
|
361
|
+
}
|
362
|
+
simulator = self._simulator
|
363
|
+
memory = self._memory
|
364
|
+
person_id = await memory.get("id")
|
365
|
+
# ATTENTION:模拟器分配的id从0开始
|
366
|
+
if person_id >= 0:
|
367
|
+
await simulator.get_person(person_id)
|
368
|
+
logging.debug(f"Binding to Person `{person_id}` already in Simulator")
|
369
|
+
else:
|
370
|
+
dict_person = deepcopy(self._person_template)
|
371
|
+
for _key in FROM_MEMORY_KEYS:
|
372
|
+
try:
|
373
|
+
_value = await memory.get(_key)
|
374
|
+
if _value:
|
375
|
+
dict_person[_key] = _value
|
376
|
+
except KeyError as e:
|
377
|
+
continue
|
378
|
+
resp = await simulator.add_person(
|
379
|
+
dict2pb(dict_person, person_pb2.Person())
|
380
|
+
)
|
381
|
+
person_id = resp["person_id"]
|
382
|
+
await memory.update("id", person_id, protect_llm_read_only_fields=False)
|
383
|
+
logging.debug(
|
384
|
+
f"Binding to Person `{person_id}` just added to Simulator"
|
385
|
+
)
|
386
|
+
# 防止模拟器还没有到prepare阶段导致get_person出错
|
387
|
+
self._has_bound_to_simulator = True
|
388
|
+
self._agent_id = person_id
|
389
|
+
|
390
|
+
async def _bind_to_economy(self):
|
391
|
+
if self._economy_client is None:
|
392
|
+
logging.warning("Economy client is not set")
|
393
|
+
return
|
394
|
+
if not self._has_bound_to_economy:
|
395
|
+
if self._has_bound_to_simulator:
|
396
|
+
try:
|
397
|
+
await self._economy_client.remove_agents([self._agent_id])
|
398
|
+
except:
|
399
|
+
pass
|
400
|
+
person_id = await self._memory.get("id")
|
401
|
+
await self._economy_client.add_agents(
|
402
|
+
{
|
403
|
+
"id": person_id,
|
404
|
+
"currency": await self._memory.get("currency"),
|
405
|
+
}
|
406
|
+
)
|
407
|
+
self._has_bound_to_economy = True
|
408
|
+
else:
|
409
|
+
logging.debug(
|
410
|
+
f"Binding to Economy before binding to Simulator, skip binding to Economy Simulator"
|
411
|
+
)
|
412
|
+
|
337
413
|
async def handle_gather_message(self, payload: str):
|
338
414
|
"""处理收到的消息,识别发送者"""
|
339
415
|
# 从消息中解析发送者 ID 和消息内容
|
@@ -366,6 +442,57 @@ class InstitutionAgent(Agent):
|
|
366
442
|
memory,
|
367
443
|
)
|
368
444
|
|
445
|
+
async def bind_to_simulator(self):
|
446
|
+
await self._bind_to_economy()
|
447
|
+
|
448
|
+
async def _bind_to_economy(self):
|
449
|
+
if self._economy_client is None:
|
450
|
+
logging.debug("Economy client is not set")
|
451
|
+
return
|
452
|
+
if not self._has_bound_to_economy:
|
453
|
+
# TODO: More general id generation
|
454
|
+
_id = random.randint(100000, 999999)
|
455
|
+
self._agent_id = _id
|
456
|
+
await self._memory.update("id", _id, protect_llm_read_only_fields=False)
|
457
|
+
try:
|
458
|
+
await self._economy_client.remove_agents([self._agent_id])
|
459
|
+
except:
|
460
|
+
pass
|
461
|
+
try:
|
462
|
+
id = await self._memory.get("id")
|
463
|
+
type = await self._memory.get("type")
|
464
|
+
nominal_gdp = await self._memory.get("nominal_gdp")
|
465
|
+
real_gdp = await self._memory.get("real_gdp")
|
466
|
+
unemployment = await self._memory.get("unemployment")
|
467
|
+
wages = await self._memory.get("wages")
|
468
|
+
prices = await self._memory.get("prices")
|
469
|
+
inventory = await self._memory.get("inventory")
|
470
|
+
price = await self._memory.get("price")
|
471
|
+
currency = await self._memory.get("currency")
|
472
|
+
interest_rate = await self._memory.get("interest_rate")
|
473
|
+
bracket_cutoffs = await self._memory.get("bracket_cutoffs")
|
474
|
+
bracket_rates = await self._memory.get("bracket_rates")
|
475
|
+
await self._economy_client.add_orgs(
|
476
|
+
{
|
477
|
+
"id": id,
|
478
|
+
"type": type,
|
479
|
+
"currency": currency,
|
480
|
+
"nominal_gdp": nominal_gdp,
|
481
|
+
"real_gdp": real_gdp,
|
482
|
+
"unemployment": unemployment,
|
483
|
+
"wages": wages,
|
484
|
+
"prices": prices,
|
485
|
+
"inventory": inventory,
|
486
|
+
"price": price,
|
487
|
+
"interest_rate": interest_rate,
|
488
|
+
"bracket_cutoffs": bracket_cutoffs,
|
489
|
+
"bracket_rates": bracket_rates,
|
490
|
+
}
|
491
|
+
)
|
492
|
+
except Exception as e:
|
493
|
+
logging.error(f"Failed to bind to Economy: {e}")
|
494
|
+
self._has_bound_to_economy = True
|
495
|
+
|
369
496
|
async def handle_gather_message(self, payload: str):
|
370
497
|
"""处理收到的消息,识别发送者"""
|
371
498
|
# 从消息中解析发送者 ID 和消息内容
|
@@ -15,7 +15,6 @@ from dashscope import ImageSynthesis
|
|
15
15
|
from PIL import Image
|
16
16
|
from io import BytesIO
|
17
17
|
from typing import Any, Optional, Union, List, Dict
|
18
|
-
import aiohttp
|
19
18
|
from .llmconfig import *
|
20
19
|
from .utils import *
|
21
20
|
|
@@ -45,7 +44,13 @@ class LLM:
|
|
45
44
|
elif self.config.text["request_type"] == "deepseek":
|
46
45
|
self._aclient = AsyncOpenAI(
|
47
46
|
api_key=self.config.text["api_key"],
|
48
|
-
base_url="https://api.deepseek.com/
|
47
|
+
base_url="https://api.deepseek.com/v1",
|
48
|
+
timeout=300,
|
49
|
+
)
|
50
|
+
elif self.config.text["request_type"] == "qwen":
|
51
|
+
self._aclient = AsyncOpenAI(
|
52
|
+
api_key=self.config.text["api_key"],
|
53
|
+
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
|
49
54
|
timeout=300,
|
50
55
|
)
|
51
56
|
elif self.config.text["request_type"] == "zhipuai":
|
@@ -102,106 +107,6 @@ Token Usage:
|
|
102
107
|
"ratio": rate,
|
103
108
|
}
|
104
109
|
|
105
|
-
def text_request(
|
106
|
-
self,
|
107
|
-
dialog: Any,
|
108
|
-
temperature: float = 1,
|
109
|
-
max_tokens: Optional[int] = None,
|
110
|
-
top_p: Optional[float] = None,
|
111
|
-
frequency_penalty: Optional[float] = None,
|
112
|
-
presence_penalty: Optional[float] = None,
|
113
|
-
tools: Optional[List[Dict[str, Any]]] = None,
|
114
|
-
tool_choice: Optional[Dict[str, Any]] = None,
|
115
|
-
) -> Optional[str]:
|
116
|
-
"""
|
117
|
-
文本相关请求
|
118
|
-
Text request
|
119
|
-
|
120
|
-
Args:
|
121
|
-
- dialog (list[dict]): 标准的LLM文本dialog. The standard text LLM dialog
|
122
|
-
- temperature (float): default 1, used in openai
|
123
|
-
- max_tokens (int): default None, used in openai
|
124
|
-
- top_p (float): default None, used in openai
|
125
|
-
- frequency_penalty (float): default None, used in openai
|
126
|
-
- presence_penalty (float): default None, used in openai
|
127
|
-
|
128
|
-
Returns:
|
129
|
-
- (str): the response content
|
130
|
-
"""
|
131
|
-
if "api_base" in self.config.text.keys():
|
132
|
-
api_base = self.config.text["api_base"]
|
133
|
-
else:
|
134
|
-
api_base = None
|
135
|
-
if self.config.text["request_type"] == "openai":
|
136
|
-
client = OpenAI(
|
137
|
-
api_key=self.config.text["api_key"],
|
138
|
-
base_url=api_base,
|
139
|
-
)
|
140
|
-
response = client.chat.completions.create(
|
141
|
-
model=self.config.text["model"],
|
142
|
-
messages=dialog,
|
143
|
-
temperature=temperature,
|
144
|
-
max_tokens=max_tokens,
|
145
|
-
top_p=top_p,
|
146
|
-
frequency_penalty=frequency_penalty,
|
147
|
-
presence_penalty=presence_penalty,
|
148
|
-
tools=tools,
|
149
|
-
tool_choice=tool_choice,
|
150
|
-
)
|
151
|
-
self.prompt_tokens_used += response.usage.prompt_tokens # type: ignore
|
152
|
-
self.completion_tokens_used += response.usage.completion_tokens # type: ignore
|
153
|
-
self.request_number += 1
|
154
|
-
if tools != None:
|
155
|
-
return response.tool_calls[0].function.arguments
|
156
|
-
else:
|
157
|
-
return response.choices[0].message.content
|
158
|
-
elif self.config.text["request_type"] == "qwen":
|
159
|
-
response = dashscope.Generation.call(
|
160
|
-
model=self.config.text["model"],
|
161
|
-
api_key=self.config.text["api_key"],
|
162
|
-
messages=dialog,
|
163
|
-
result_format="message",
|
164
|
-
)
|
165
|
-
if response.status_code == HTTPStatus.OK: # type: ignore
|
166
|
-
return response.output.choices[0]["message"]["content"] # type: ignore
|
167
|
-
else:
|
168
|
-
return "Error: {}, {}".format(response.status_code, response.message) # type: ignore
|
169
|
-
elif self.config.text["request_type"] == "deepseek":
|
170
|
-
client = OpenAI(
|
171
|
-
api_key=self.config.text["api_key"],
|
172
|
-
base_url="https://api.deepseek.com/beta",
|
173
|
-
)
|
174
|
-
response = client.chat.completions.create(
|
175
|
-
model=self.config.text["model"],
|
176
|
-
messages=dialog,
|
177
|
-
temperature=temperature,
|
178
|
-
max_tokens=max_tokens,
|
179
|
-
top_p=top_p,
|
180
|
-
frequency_penalty=frequency_penalty,
|
181
|
-
presence_penalty=presence_penalty,
|
182
|
-
stream=False,
|
183
|
-
)
|
184
|
-
self.prompt_tokens_used += response.usage.prompt_tokens # type: ignore
|
185
|
-
self.completion_tokens_used += response.usage.completion_tokens # type: ignore
|
186
|
-
self.request_number += 1
|
187
|
-
return response.choices[0].message.content
|
188
|
-
elif self.config.text["request_type"] == "zhipuai":
|
189
|
-
client = ZhipuAI(api_key=self.config.text["api_key"])
|
190
|
-
response = client.chat.completions.create(
|
191
|
-
model=self.config.text["model"],
|
192
|
-
messages=dialog,
|
193
|
-
temperature=temperature,
|
194
|
-
top_p=top_p,
|
195
|
-
stream=False,
|
196
|
-
)
|
197
|
-
self.prompt_tokens_used += response.usage.prompt_tokens # type: ignore
|
198
|
-
self.completion_tokens_used += response.usage.completion_tokens # type: ignore
|
199
|
-
self.request_number += 1
|
200
|
-
return response.choices[0].message.content # type: ignore
|
201
|
-
else:
|
202
|
-
print("ERROR: Wrong Config")
|
203
|
-
return "wrong config"
|
204
|
-
|
205
110
|
async def atext_request(
|
206
111
|
self,
|
207
112
|
dialog: Any,
|
@@ -221,6 +126,7 @@ Token Usage:
|
|
221
126
|
if (
|
222
127
|
self.config.text["request_type"] == "openai"
|
223
128
|
or self.config.text["request_type"] == "deepseek"
|
129
|
+
or self.config.text["request_type"] == "qwen"
|
224
130
|
):
|
225
131
|
for attempt in range(retries):
|
226
132
|
try:
|
@@ -242,8 +148,12 @@ Token Usage:
|
|
242
148
|
self.prompt_tokens_used += response.usage.prompt_tokens # type: ignore
|
243
149
|
self.completion_tokens_used += response.usage.completion_tokens # type: ignore
|
244
150
|
self.request_number += 1
|
245
|
-
if tools
|
246
|
-
return
|
151
|
+
if tools and response.choices[0].message.tool_calls:
|
152
|
+
return json.loads(
|
153
|
+
response.choices[0]
|
154
|
+
.message.tool_calls[0]
|
155
|
+
.function.arguments
|
156
|
+
)
|
247
157
|
else:
|
248
158
|
return response.choices[0].message.content
|
249
159
|
else:
|
@@ -263,8 +173,12 @@ Token Usage:
|
|
263
173
|
self.prompt_tokens_used += response.usage.prompt_tokens # type: ignore
|
264
174
|
self.completion_tokens_used += response.usage.completion_tokens # type: ignore
|
265
175
|
self.request_number += 1
|
266
|
-
if tools
|
267
|
-
return
|
176
|
+
if tools and response.choices[0].message.tool_calls:
|
177
|
+
return json.loads(
|
178
|
+
response.choices[0]
|
179
|
+
.message.tool_calls[0]
|
180
|
+
.function.arguments
|
181
|
+
)
|
268
182
|
else:
|
269
183
|
return response.choices[0].message.content
|
270
184
|
except APIConnectionError as e:
|
@@ -327,25 +241,6 @@ Token Usage:
|
|
327
241
|
await asyncio.sleep(2**attempt)
|
328
242
|
else:
|
329
243
|
raise e
|
330
|
-
elif self.config.text["request_type"] == "qwen":
|
331
|
-
async with aiohttp.ClientSession() as session:
|
332
|
-
api_url = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation"
|
333
|
-
headers = {
|
334
|
-
"Content-Type": "application/json",
|
335
|
-
"Authorization": f"{self.config.text['api_key']}",
|
336
|
-
}
|
337
|
-
payload = {
|
338
|
-
"model": self.config.text["model"],
|
339
|
-
"input": {"messages": dialog},
|
340
|
-
}
|
341
|
-
async with session.post(api_url, json=payload, headers=headers) as resp:
|
342
|
-
response_json = await resp.json()
|
343
|
-
if "code" in response_json.keys():
|
344
|
-
raise Exception(
|
345
|
-
f"Error: {response_json['code']}, {response_json['message']}"
|
346
|
-
)
|
347
|
-
else:
|
348
|
-
return response_json["output"]["text"]
|
349
244
|
else:
|
350
245
|
print("ERROR: Wrong Config")
|
351
246
|
return "wrong config"
|
@@ -6,7 +6,7 @@ import asyncio
|
|
6
6
|
import logging
|
7
7
|
import time
|
8
8
|
from abc import ABC, abstractmethod
|
9
|
-
from typing import Any, Callable, Dict,
|
9
|
+
from typing import Any, Callable, Dict, Optional, Sequence, Union
|
10
10
|
|
11
11
|
from .const import *
|
12
12
|
|
@@ -3,7 +3,7 @@ Agent Profile
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
from copy import deepcopy
|
6
|
-
from typing import Any, Callable, Dict,
|
6
|
+
from typing import Any, Callable, Dict, Optional, Sequence, Union, cast
|
7
7
|
|
8
8
|
from ..utils.decorators import lock_decorator
|
9
9
|
from .const import *
|
@@ -3,7 +3,7 @@ Self Define Data
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
from copy import deepcopy
|
6
|
-
from typing import Any, Callable, Dict,
|
6
|
+
from typing import Any, Callable, Dict, Optional, Sequence, Union, cast
|
7
7
|
|
8
8
|
from ..utils.decorators import lock_decorator
|
9
9
|
from .const import *
|
@@ -3,7 +3,7 @@ Agent State
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
from copy import deepcopy
|
6
|
-
from typing import Any, Callable, Dict,
|
6
|
+
from typing import Any, Callable, Dict, Optional, Sequence, Union, cast
|
7
7
|
|
8
8
|
from ..utils.decorators import lock_decorator
|
9
9
|
from .const import *
|
@@ -7,7 +7,7 @@ from aiomqtt import Client
|
|
7
7
|
|
8
8
|
class Messager:
|
9
9
|
def __init__(
|
10
|
-
self, hostname, port=1883, username=None, password=None, timeout=math.inf
|
10
|
+
self, hostname:str, port:int=1883, username=None, password=None, timeout=math.inf
|
11
11
|
):
|
12
12
|
self.client = Client(
|
13
13
|
hostname, port=port, username=username, password=password, timeout=timeout
|
@@ -1,17 +1,18 @@
|
|
1
1
|
import asyncio
|
2
2
|
import logging
|
3
3
|
import ray
|
4
|
+
from uuid import UUID
|
4
5
|
from pycityagent.agent import Agent
|
5
6
|
from pycityagent.economy.econ_client import EconomyClient
|
6
7
|
from pycityagent.environment.simulator import Simulator
|
7
8
|
from pycityagent.llm.llm import LLM
|
8
9
|
from pycityagent.llm.llmconfig import LLMConfig
|
9
10
|
from pycityagent.message import Messager
|
10
|
-
|
11
|
+
from typing import Any
|
11
12
|
|
12
13
|
@ray.remote
|
13
14
|
class AgentGroup:
|
14
|
-
def __init__(self, agents: list[Agent], config: dict, exp_id: str):
|
15
|
+
def __init__(self, agents: list[Agent], config: dict, exp_id: str|UUID):
|
15
16
|
self.agents = agents
|
16
17
|
self.config = config
|
17
18
|
self.exp_id = exp_id
|
@@ -45,7 +46,8 @@ class AgentGroup:
|
|
45
46
|
agent.set_exp_id(self.exp_id)
|
46
47
|
agent.set_llm_client(self.llm)
|
47
48
|
agent.set_simulator(self.simulator)
|
48
|
-
|
49
|
+
if self.economy_client is not None:
|
50
|
+
agent.set_economy_client(self.economy_client)
|
49
51
|
agent.set_messager(self.messager)
|
50
52
|
|
51
53
|
async def init_agents(self):
|
@@ -69,7 +71,7 @@ class AgentGroup:
|
|
69
71
|
results[agent._agent_id] = await agent.memory.get(content)
|
70
72
|
return results
|
71
73
|
|
72
|
-
async def update(self, target_agent_id: str, target_key: str, content:
|
74
|
+
async def update(self, target_agent_id: str, target_key: str, content: Any):
|
73
75
|
agent = self.id2agent[target_agent_id]
|
74
76
|
await agent.memory.update(target_key, content)
|
75
77
|
|
@@ -123,14 +125,15 @@ class AgentGroup:
|
|
123
125
|
try:
|
124
126
|
# 获取开始时间
|
125
127
|
start_time = await self.simulator.get_time()
|
128
|
+
assert type(start_time)==int
|
126
129
|
# 计算结束时间(秒)
|
127
130
|
end_time = start_time + day * 24 * 3600 # 将天数转换为秒
|
128
131
|
|
129
132
|
while True:
|
130
133
|
current_time = await self.simulator.get_time()
|
134
|
+
assert type(current_time)==int
|
131
135
|
if current_time >= end_time:
|
132
136
|
break
|
133
|
-
|
134
137
|
await self.step()
|
135
138
|
|
136
139
|
except Exception as e:
|
@@ -4,7 +4,7 @@ import logging
|
|
4
4
|
import uuid
|
5
5
|
from datetime import datetime
|
6
6
|
import random
|
7
|
-
from typing import Dict, List, Optional, Callable, Union
|
7
|
+
from typing import Dict, List, Optional, Callable, Union,Any
|
8
8
|
from mosstool.map._map_util.const import AOI_START_ID
|
9
9
|
|
10
10
|
from pycityagent.memory.memory import Memory
|
@@ -41,7 +41,7 @@ class AgentSimulation:
|
|
41
41
|
self.config = config
|
42
42
|
self.agent_prefix = agent_prefix
|
43
43
|
self._agents: Dict[str, Agent] = {}
|
44
|
-
self._groups: Dict[str, AgentGroup] = {}
|
44
|
+
self._groups: Dict[str, AgentGroup] = {} # type:ignore
|
45
45
|
self._interview_manager = InterviewManager()
|
46
46
|
self._interview_lock = asyncio.Lock()
|
47
47
|
self._start_time = datetime.now()
|
@@ -50,14 +50,14 @@ class AgentSimulation:
|
|
50
50
|
self._loop = asyncio.get_event_loop()
|
51
51
|
self._blocked_agents: List[str] = [] # 新增:持续阻塞的智能体列表
|
52
52
|
self._survey_manager = SurveyManager()
|
53
|
-
self._agentid2group: Dict[str, AgentGroup] = {}
|
53
|
+
self._agentid2group: Dict[str, AgentGroup] = {}# type:ignore
|
54
54
|
self._agent_ids: List[str] = []
|
55
55
|
|
56
56
|
async def init_agents(
|
57
57
|
self,
|
58
58
|
agent_count: Union[int, list[int]],
|
59
59
|
group_size: int = 1000,
|
60
|
-
memory_config_func: Union[Callable, list[Callable]] = None,
|
60
|
+
memory_config_func: Optional[Union[Callable, list[Callable]]] = None,
|
61
61
|
) -> None:
|
62
62
|
"""初始化智能体
|
63
63
|
|
@@ -139,13 +139,13 @@ class AgentSimulation:
|
|
139
139
|
self._agentid2group[agent_id] = group
|
140
140
|
|
141
141
|
async def gather(self, content: str):
|
142
|
-
"""
|
142
|
+
"""收集智能体的特定信息"""
|
143
143
|
gather_tasks = []
|
144
144
|
for group in self._groups.values():
|
145
145
|
gather_tasks.append(group.gather.remote(content))
|
146
146
|
return await asyncio.gather(*gather_tasks)
|
147
147
|
|
148
|
-
async def update(self, target_agent_id: str, target_key: str, content:
|
148
|
+
async def update(self, target_agent_id: str, target_key: str, content: Any):
|
149
149
|
"""更新指定智能体的记忆"""
|
150
150
|
group = self._agentid2group[target_agent_id]
|
151
151
|
await group.update.remote(target_agent_id, target_key, content)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{pycityagent-2.0.0a9 → pycityagent-2.0.0a10}/pycityagent/environment/sim/economy_services.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|