pycityagent 2.0.0a82__cp310-cp310-macosx_11_0_arm64.whl → 2.0.0a84__cp310-cp310-macosx_11_0_arm64.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.
@@ -112,6 +112,14 @@ class ConsumptionBlock(Block):
112
112
  for i in range(len(firms_id)):
113
113
  demand_each_firm.append(int(consumption_each_firm[i]//prices[i]))
114
114
  real_consumption = await self.economy_client.calculate_consumption(firms_id, agent_id, demand_each_firm)
115
+ if real_consumption == -1:
116
+ node_id = await self.memory.stream.add_economy(description=f"I failed to buy goods, cause I do not have enough money.")
117
+ return {
118
+ 'success': False,
119
+ 'evaluation': f"I failed to buy goods, cause I do not have enough money.",
120
+ 'consumed_time': 0,
121
+ 'node_id': node_id
122
+ }
115
123
  node_id = await self.memory.stream.add_economy(description=f"I bought some goods, and spent {real_consumption:.1f} on {intention}")
116
124
  evaluation = {
117
125
  'success': True,
@@ -163,6 +171,22 @@ class EconomyBlock(Block):
163
171
 
164
172
  class MonthPlanBlock(Block):
165
173
  """Monthly Planning"""
174
+ configurable_fields = [
175
+ "UBI",
176
+ "num_labor_hours",
177
+ "productivity_per_labor",
178
+ ]
179
+ default_values = {
180
+ "UBI": 0,
181
+ "num_labor_hours": 168,
182
+ "productivity_per_labor": 1,
183
+ }
184
+ fields_description = {
185
+ "UBI": "Universal Basic Income",
186
+ "num_labor_hours": "Number of labor hours per month",
187
+ "productivity_per_labor": "Productivity per labor hour",
188
+ }
189
+
166
190
  def __init__(self, llm: LLM, memory: Memory, simulator: Simulator, economy_client: EconomyClient):
167
191
  super().__init__("MonthPlanBlock", llm=llm, memory=memory, simulator=simulator)
168
192
  self.economy_client = economy_client
@@ -170,6 +194,12 @@ class MonthPlanBlock(Block):
170
194
  self.last_time_trigger = None
171
195
  self.time_diff = 30 * 24 * 60 * 60
172
196
  self.forward_times = 0
197
+
198
+ # configurable fields
199
+ self.UBI = 0
200
+ self.num_labor_hours = 168
201
+ self.productivity_per_labor = 1
202
+
173
203
 
174
204
  async def month_trigger(self):
175
205
  now_time = await self.simulator.get_time()
@@ -216,8 +246,8 @@ class MonthPlanBlock(Block):
216
246
  Besides, your consumption was ${consumption:.2f}.
217
247
  '''
218
248
  tax_prompt = f'''Your tax deduction amounted to ${tax_paid:.2f}, and the government uses the tax revenue to provide social services to all citizens.'''
219
- if UBI and self.forward_times >= 96:
220
- tax_prompt = f'{tax_prompt} Specifically, the government directly provides ${UBI} per capita in each month.'
249
+ if self.UBI and self.forward_times >= 96:
250
+ tax_prompt = f'{tax_prompt} Specifically, the government directly provides ${self.UBI} per capita in each month.'
221
251
  price_prompt = f'''Meanwhile, in the consumption market, the average price of essential goods is now at ${price:.2f}.'''
222
252
  job_prompt = prettify_document(job_prompt)
223
253
  obs_prompt = f'''
@@ -250,18 +280,18 @@ class MonthPlanBlock(Block):
250
280
  work_skill = await self.economy_client.get(agent_id, 'skill')
251
281
  work_propensity = await self.memory.status.get('work_propensity')
252
282
  consumption_propensity = await self.memory.status.get('consumption_propensity')
253
- work_hours = work_propensity * num_labor_hours
283
+ work_hours = work_propensity * self.num_labor_hours
254
284
  income = await self.economy_client.get(agent_id, 'income')
255
285
  income += work_hours * work_skill
256
286
 
257
287
  wealth = await self.economy_client.get(agent_id, 'currency')
258
288
  wealth += work_hours * work_skill
259
289
  await self.economy_client.update(agent_id, 'currency', wealth)
260
- await self.economy_client.add_delta_value(firm_id, 'inventory', int(work_hours*productivity_per_labor))
290
+ await self.economy_client.add_delta_value(firm_id, 'inventory', int(work_hours*self.productivity_per_labor))
261
291
 
262
- if UBI and self.forward_times >= 96:
263
- income += UBI
264
- wealth += UBI
292
+ if self.UBI and self.forward_times >= 96:
293
+ income += self.UBI
294
+ wealth += self.UBI
265
295
 
266
296
  await self.memory.status.update('to_consumption_currency', consumption_propensity*wealth)
267
297
 
@@ -318,7 +348,7 @@ class MonthPlanBlock(Block):
318
348
  except:
319
349
  self.llm_error += 1
320
350
 
321
- if UBI and self.forward_times >= 96 and self.forward_times % 12:
351
+ if self.UBI and self.forward_times >= 96 and self.forward_times % 12:
322
352
  obs_prompt = f'''
323
353
  {problem_prompt} {job_prompt} {consumption_prompt} {tax_prompt} {price_prompt}
324
354
  Your current savings account balance is ${wealth:.2f}. Interest rates, as set by your bank, stand at {interest_rate*100:.2f}%.
@@ -23,19 +23,6 @@ Please return the result in JSON format (Do not return any other text):
23
23
  }}
24
24
  """
25
25
 
26
- num_labor_hours = 168
27
- productivity_per_labor = 1
28
- max_price_inflation = 0.1
29
- max_wage_inflation = 0.05
30
- natural_interest_rate = 0.01
31
- target_inflation = 0.02
32
- natural_unemployment_rate = 0.04
33
- inflation_coeff, unemployment_coeff = 0.5, 0.5
34
- tao = 1
35
- period = 3
36
- UBI = 0
37
-
38
-
39
26
  def prettify_document(document: str) -> str:
40
27
  # Remove sequences of whitespace characters (including newlines)
41
28
  cleaned = re.sub(r"\s+", " ", document).strip()
@@ -22,7 +22,7 @@ logger = logging.getLogger("pycityagent")
22
22
  class PlanAndActionBlock(Block):
23
23
  """Active workflow based on needs model and plan behavior model"""
24
24
 
25
- longTermDecisionBlock: MonthPlanBlock
25
+ monthPlanBlock: MonthPlanBlock
26
26
  needsBlock: NeedsBlock
27
27
  planBlock: PlanBlock
28
28
  mobilityBlock: MobilityBlock
@@ -50,7 +50,7 @@ class PlanAndActionBlock(Block):
50
50
  self.enable_social = enable_social
51
51
  self.enable_economy = enable_economy
52
52
  self.enable_cognition = enable_cognition
53
- self.longTermDecisionBlock = MonthPlanBlock(
53
+ self.monthPlanBlock = MonthPlanBlock(
54
54
  llm=llm, memory=memory, simulator=simulator, economy_client=economy_client
55
55
  )
56
56
  self.needsBlock = NeedsBlock(llm=llm, memory=memory, simulator=simulator)
@@ -141,7 +141,7 @@ class PlanAndActionBlock(Block):
141
141
 
142
142
  async def forward(self):
143
143
  # Long-term decision
144
- await self.longTermDecisionBlock.forward()
144
+ await self.monthPlanBlock.forward()
145
145
 
146
146
  # update needs
147
147
  await self.needsBlock.forward()
@@ -504,7 +504,7 @@ class EconomyClient:
504
504
 
505
505
  async def calculate_taxes_due(
506
506
  self,
507
- org_id: Union[int, list[int]],
507
+ org_id: int,
508
508
  agent_ids: list[int],
509
509
  incomes: list[float],
510
510
  enable_redistribution: bool,
@@ -523,7 +523,6 @@ class EconomyClient:
523
523
  """
524
524
  start_time = time.time()
525
525
  log = {"req": "calculate_taxes_due", "start_time": start_time, "consumption": 0}
526
- # TODO: support multiple org
527
526
  request = org_service.CalculateTaxesDueRequest(
528
527
  government_id=org_id,
529
528
  agent_ids=agent_ids,
@@ -569,7 +568,11 @@ class EconomyClient:
569
568
  )
570
569
  log["consumption"] = time.time() - start_time
571
570
  self._log_list.append(log)
572
- return response.actual_consumption
571
+ if response.success:
572
+ return response.actual_consumption
573
+ else:
574
+ return -1
575
+
573
576
 
574
577
  async def calculate_real_gdp(self, nbs_id: int):
575
578
  start_time = time.time()
@@ -114,7 +114,7 @@ class Simulator:
114
114
  map_file=_map_pb_path,
115
115
  max_day=config["simulator"].get("max_day", 1000),
116
116
  start_step=config["simulator"].get("start_step", 28800),
117
- total_step=24*60*60,
117
+ total_step=config["simulator"].get("total_step", 24*60*60*365),
118
118
  log_dir=config["simulator"].get("log_dir", "./log"),
119
119
  min_step_time=config["simulator"].get("min_step_time", 1000),
120
120
  sim_addr=config["simulator"].get("server", None),
@@ -363,7 +363,7 @@ class Simulator:
363
363
  log = {"req": "get_simulator_day", "start_time": start_time, "consumption": 0}
364
364
  now = await self._client.clock_service.Now({})
365
365
  now = cast(dict[str, int], now)
366
- day = now["day"]
366
+ day = int(now["t"]//(24*60*60))
367
367
  log["consumption"] = time.time() - start_time
368
368
  self._log_list.append(log)
369
369
  return day
@@ -385,7 +385,7 @@ class Simulator:
385
385
  now = cast(dict[str, int], now)
386
386
  log["consumption"] = time.time() - start_time
387
387
  self._log_list.append(log)
388
- return now["t"] % 86400
388
+ return now["t"]%(24*60*60)
389
389
 
390
390
  async def get_person(self, person_id: int) -> dict:
391
391
  """
Binary file
@@ -1019,24 +1019,9 @@ class AgentSimulation:
1019
1019
  - None
1020
1020
  """
1021
1021
  try:
1022
- # check whether insert agents
1023
- simulator_day = await self._simulator.get_simulator_day()
1024
- need_insert_agents = False
1025
- if simulator_day > self._simulator_day:
1026
- need_insert_agents = True
1027
- self._simulator_day = simulator_day
1028
- if need_insert_agents:
1029
- await self.resume_simulator()
1030
- insert_tasks = []
1031
- for group in self._groups.values():
1032
- insert_tasks.append(group.insert_agent.remote())
1033
- await asyncio.gather(*insert_tasks)
1034
-
1035
1022
  # step
1036
1023
  simulator_day = await self._simulator.get_simulator_day()
1037
- simulator_time = int(
1038
- await self._simulator.get_simulator_second_from_start_of_day()
1039
- )
1024
+ simulator_time = int(await self._simulator.get_simulator_second_from_start_of_day())
1040
1025
  logger.info(
1041
1026
  f"Start simulation day {simulator_day} at {simulator_time}, step {self._total_steps}"
1042
1027
  )
@@ -1113,12 +1098,20 @@ class AgentSimulation:
1113
1098
  monitor_task = asyncio.create_task(self._monitor_exp_status(stop_event))
1114
1099
 
1115
1100
  try:
1116
- end_time = (
1117
- await self._simulator.get_time() + day * 24 * 3600
1118
- ) # type:ignore
1101
+ end_day = self._simulator_day + day
1119
1102
  while True:
1120
- current_time = await self._simulator.get_time()
1121
- if current_time >= end_time: # type:ignore
1103
+ current_day = await self._simulator.get_simulator_day()
1104
+ # check whether insert agents
1105
+ need_insert_agents = False
1106
+ if current_day > self._simulator_day:
1107
+ self._simulator_day = current_day
1108
+ # if need_insert_agents:
1109
+ # insert_tasks = []
1110
+ # for group in self._groups.values():
1111
+ # insert_tasks.append(group.insert_agent.remote())
1112
+ # await asyncio.gather(*insert_tasks)
1113
+
1114
+ if current_day >= end_day: # type:ignore
1122
1115
  break
1123
1116
  (
1124
1117
  llm_log_list,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pycityagent
3
- Version: 2.0.0a82
3
+ Version: 2.0.0a84
4
4
  Summary: LLM-based city environment agent building library
5
5
  Author-email: Yuwei Yan <pinkgranite86@gmail.com>, Junbo Yan <yanjb20thu@gmali.com>, Jun Zhang <zhangjun990222@gmali.com>
6
6
  License: MIT License
@@ -45,7 +45,7 @@ Requires-Dist: openai>=1.58.1
45
45
  Requires-Dist: Pillow<12.0.0,>=11.0.0
46
46
  Requires-Dist: protobuf<5.0.0,<=4.24.0
47
47
  Requires-Dist: pycitydata>=1.0.3
48
- Requires-Dist: pycityproto>=2.2.3
48
+ Requires-Dist: pycityproto>=2.2.4
49
49
  Requires-Dist: requests>=2.32.3
50
50
  Requires-Dist: Shapely>=2.0.6
51
51
  Requires-Dist: PyYAML>=6.0.2
@@ -1,10 +1,10 @@
1
- pycityagent/pycityagent-sim,sha256=MmiGNhZgGjXYLJ2EYTGMhfGAZU8TnU7ORsJ6kdtzjDs,36973378
1
+ pycityagent/pycityagent-sim,sha256=Ax6cjHjT8VcT5t07VboL_Ruor2eXSdSEml4Jvv-L5dQ,36972594
2
2
  pycityagent/__init__.py,sha256=PUKWTXc-xdMG7px8oTNclodsILUgypANj2Z647sY63k,808
3
3
  pycityagent/pycityagent-ui,sha256=Ur95yZygIaZ5l_CDqP9394M5GQ66iV5PkcNPYFWqzvk,41225346
4
4
  pycityagent/metrics/mlflow_client.py,sha256=-iyh4BPVnBkluhmfucUzibCUnBX2iftkz4tVJJVxwHw,6958
5
5
  pycityagent/metrics/__init__.py,sha256=X08PaBbGVAd7_PRGLREXWxaqm7nS82WBQpD1zvQzcqc,128
6
6
  pycityagent/economy/__init__.py,sha256=aonY4WHnx-6EGJ4WKrx4S-2jAkYNLtqUA04jp6q8B7w,75
7
- pycityagent/economy/econ_client.py,sha256=jDF_KAqFwM-vrFNRHiinYJEPEbzfaU2gRp_hIMk27O4,29208
7
+ pycityagent/economy/econ_client.py,sha256=NUzrFzl0EL4UkMscGRRSu1JQmeCPwIkPvTbJDRefUcQ,29231
8
8
  pycityagent/tools/__init__.py,sha256=y7sMVMHf0AbivlczM2h-kr7mkgXK-WAx3S9BXLXkWvw,235
9
9
  pycityagent/tools/tool.py,sha256=4ZJSHbNM8dfAVwZEw8T0a2_9OuPsPQpKSVL4WxZVBUc,9022
10
10
  pycityagent/llm/llmconfig.py,sha256=6AqCMV4B_JqBD2mb98bLGzpUdlOCnziQKae-Hhxxp-E,469
@@ -21,7 +21,7 @@ pycityagent/memory/utils.py,sha256=oJWLdPeJy_jcdKcDTo9JAH9kDZhqjoQhhv_zT9qWC0w,8
21
21
  pycityagent/memory/const.py,sha256=nFmjvt-8FEB0hc0glOH3lliqJhkhf3D_NKxWI0pf6TY,936
22
22
  pycityagent/memory/faiss_query.py,sha256=KPeyzIjD0dzkxr-TlOeCiIlkdh1WAyyipCAXUEt97Lk,17350
23
23
  pycityagent/memory/state.py,sha256=JFCBuK1AS-HqscvdGS9ATF9AUU8t29_2leDY_6iO2_4,5158
24
- pycityagent/simulation/simulation.py,sha256=_dmTQDVaKHpmAljKxQBFkVk9FDSBJg_PA5PMyphQ5D4,49525
24
+ pycityagent/simulation/simulation.py,sha256=08xtIVwmO35r5XbUW9nMDo9rL_6mtDtjWbeXnUyNR6c,49340
25
25
  pycityagent/simulation/__init__.py,sha256=u1WpgwVxPboXWMxrUQKMXJNmTKQYAeCaqZv9HmSxESY,118
26
26
  pycityagent/simulation/agentgroup.py,sha256=oXo2iRUThh_96JhXHMufT8_BPx0PrlwqbMpiVqK_viA,36957
27
27
  pycityagent/simulation/storage/pg.py,sha256=xRshSOGttW-p0re0fNBOjOpb-nQ5msIE2LsdT79_E_Y,8425
@@ -46,7 +46,7 @@ pycityagent/workflow/prompt.py,sha256=rzenP4EFGxbWE1aq-x2036b6umKvi5cQx2xtWULwgI
46
46
  pycityagent/workflow/block.py,sha256=WJfCeL8e117GzkVPJCRNsQZZinccMnVyEubkwrf-17U,12295
47
47
  pycityagent/workflow/trigger.py,sha256=4nzAwywGQsFabgo6gzp-vD2EV4wII7Z0LHGEAsflSEY,7608
48
48
  pycityagent/environment/__init__.py,sha256=fFIth2jxxgZ92cXm-aoM2igHgaSqsYGwtBhyb7opjzk,166
49
- pycityagent/environment/simulator.py,sha256=I5xDg-1Cn32qvKN7X_6SklA_d_iPFS9THsZqbZreJDU,22606
49
+ pycityagent/environment/simulator.py,sha256=qiqeRQDm7cprFJhAkxtdBNAvohiGGUaNIPGyFXmPdZU,22667
50
50
  pycityagent/environment/utils/port.py,sha256=3OM6kSUt3PxvDUOlgyiendBtETaWU8Mzk_8H0TzTmYg,295
51
51
  pycityagent/environment/utils/grpc.py,sha256=_lB4-k4dTKuNvApaDiYgFxiLTPtYG42DVQtG9yOj9pQ,2022
52
52
  pycityagent/environment/utils/base64.py,sha256=hoREzQo3FXMN79pqQLO2jgsDEvudciomyKii7MWljAM,374
@@ -73,7 +73,7 @@ pycityagent/cityagent/__init__.py,sha256=gcBQ-a50XegFtjigQ7xDXRBZrywBKqifiQFSRnE
73
73
  pycityagent/cityagent/firmagent.py,sha256=vZr7kdjnxcCZ5qX7hmUIYuQQWd44GcRPbdi76WGSFy4,3760
74
74
  pycityagent/cityagent/nbsagent.py,sha256=knSaQbCNkWi7bZjwwEr_hTKj44_q67eHif6HI3W9i1M,4558
75
75
  pycityagent/cityagent/initial.py,sha256=0DSOWnVVknMw6xoJWfdZUFBH3yti8y800wnkXXCocxY,6194
76
- pycityagent/cityagent/societyagent.py,sha256=dY8coUMtrTrcATCYDdI0MvVt42YXSyP-ZWi24H9xg7o,20090
76
+ pycityagent/cityagent/societyagent.py,sha256=1c6k3RgxQ7AAYCiBXwiSZLDkCDMgCrBzNF6vi6lK2Yc,20069
77
77
  pycityagent/cityagent/message_intercept.py,sha256=dyT1G-nMxKb2prhgtyFFHFz593qBrkk5DnHsHvG1OIc,4418
78
78
  pycityagent/cityagent/governmentagent.py,sha256=XIyggG83FWUTZdOuoqc6ClCP3hhfkxNmtYRu9TFo0dU,3063
79
79
  pycityagent/cityagent/blocks/dispatcher.py,sha256=U5BPeUrjrTyDaznYfT6YUJIW8vfKVRDF4EO0oOn6Td4,2886
@@ -81,17 +81,17 @@ pycityagent/cityagent/blocks/needs_block.py,sha256=NYKrGDoYCuXoupMNMuSNhx4Ci1paC
81
81
  pycityagent/cityagent/blocks/cognition_block.py,sha256=yzjB0D_95vytpa5xiVdmTSpGp8H9HXcjWzzFN0OpP0k,15398
82
82
  pycityagent/cityagent/blocks/social_block.py,sha256=eedOlwRTGI47QFELYmfe2a_aj0GuHJweSyDxA6AYXcU,15493
83
83
  pycityagent/cityagent/blocks/__init__.py,sha256=h6si6WBcVVuglIskKQKA8Cxtf_VKen1sNPqOFKI311Q,420
84
- pycityagent/cityagent/blocks/economy_block.py,sha256=1yHUdCSAzvvhdGFzMfSM_wtbW_3D6YeYSNlVV3yQqsA,19083
85
- pycityagent/cityagent/blocks/utils.py,sha256=BVOTtZC8dJIc0eGGNmL0LQ_WnMfXr54q1gyrrDwRn-Y,2079
84
+ pycityagent/cityagent/blocks/economy_block.py,sha256=SSqb2qX5cVQ1zM8hyxvhnyTwgGwUrV2YViKtGRXmJhQ,20079
85
+ pycityagent/cityagent/blocks/utils.py,sha256=K--6odjUDUu9YrwrHPaiPIHryo7m_MBmcBqDAy3cV5M,1816
86
86
  pycityagent/cityagent/blocks/other_block.py,sha256=LdtL6248xvMvvRQx6NvdlJrWWZFu8Xusjxb9yEh1M0k,4365
87
87
  pycityagent/cityagent/blocks/plan_block.py,sha256=A5DvtXIy98MZkRGUQmp26grNI5i0BVbl3aEM_Ebd6Z4,11271
88
88
  pycityagent/cityagent/blocks/mobility_block.py,sha256=qkRiV0nkGOUUoo9lGIjAFE_Hl0kiyMev12-Zm7JyV7o,15089
89
89
  pycityagent/survey/models.py,sha256=g3xni4GcA1Py3vlGt6z4ltutjgQ4G0uINYAM8vKRJAw,5225
90
90
  pycityagent/survey/__init__.py,sha256=rxwou8U9KeFSP7rMzXtmtp2fVFZxK4Trzi-psx9LPIs,153
91
91
  pycityagent/survey/manager.py,sha256=tHkdeq4lTfAHwvgf4-udsXri0z2l6E00rEbvwl7SqRs,3439
92
- pycityagent-2.0.0a82.dist-info/RECORD,,
93
- pycityagent-2.0.0a82.dist-info/LICENSE,sha256=n2HPXiupinpyHMnIkbCf3OTYd3KMqbmldu1e7av0CAU,1084
94
- pycityagent-2.0.0a82.dist-info/WHEEL,sha256=ezfKMaDztqf77C8lvQ0NCnZxkTaOaKLprqJ8q932MhU,109
95
- pycityagent-2.0.0a82.dist-info/entry_points.txt,sha256=BZcne49AAIFv-hawxGnPbblea7X3MtAtoPyDX8L4OC4,132
96
- pycityagent-2.0.0a82.dist-info/top_level.txt,sha256=yOmeu6cSXmiUtScu53a3s0p7BGtLMaV0aff83EHCTic,43
97
- pycityagent-2.0.0a82.dist-info/METADATA,sha256=a48d_5hO9dLaPc6fmDJ4N-T83VWIwdmEJQFGMk1rlxw,9110
92
+ pycityagent-2.0.0a84.dist-info/RECORD,,
93
+ pycityagent-2.0.0a84.dist-info/LICENSE,sha256=n2HPXiupinpyHMnIkbCf3OTYd3KMqbmldu1e7av0CAU,1084
94
+ pycityagent-2.0.0a84.dist-info/WHEEL,sha256=ezfKMaDztqf77C8lvQ0NCnZxkTaOaKLprqJ8q932MhU,109
95
+ pycityagent-2.0.0a84.dist-info/entry_points.txt,sha256=BZcne49AAIFv-hawxGnPbblea7X3MtAtoPyDX8L4OC4,132
96
+ pycityagent-2.0.0a84.dist-info/top_level.txt,sha256=yOmeu6cSXmiUtScu53a3s0p7BGtLMaV0aff83EHCTic,43
97
+ pycityagent-2.0.0a84.dist-info/METADATA,sha256=wK7JDsxgO5pTlH_YLtftS9-nmD9T97_6-YZp8zru9dA,9110