pycityagent 2.0.0a13__py3-none-any.whl → 2.0.0a15__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 +14 -0
- pycityagent/agent.py +164 -63
- pycityagent/economy/econ_client.py +2 -0
- pycityagent/environment/simulator.py +5 -4
- pycityagent/memory/const.py +1 -0
- pycityagent/memory/memory.py +8 -7
- pycityagent/memory/memory_base.py +6 -4
- pycityagent/message/messager.py +8 -7
- pycityagent/simulation/agentgroup.py +136 -14
- pycityagent/simulation/simulation.py +212 -42
- pycityagent/survey/manager.py +58 -0
- pycityagent/survey/models.py +120 -0
- pycityagent/utils/__init__.py +7 -0
- pycityagent/utils/avro_schema.py +110 -0
- pycityagent/utils/survey_util.py +53 -0
- pycityagent/workflow/tool.py +0 -3
- {pycityagent-2.0.0a13.dist-info → pycityagent-2.0.0a15.dist-info}/METADATA +3 -1
- {pycityagent-2.0.0a13.dist-info → pycityagent-2.0.0a15.dist-info}/RECORD +20 -21
- pycityagent/simulation/interview.py +0 -40
- pycityagent/simulation/survey/manager.py +0 -68
- pycityagent/simulation/survey/models.py +0 -52
- pycityagent/simulation/ui/__init__.py +0 -3
- pycityagent/simulation/ui/interface.py +0 -602
- /pycityagent/{simulation/survey → survey}/__init__.py +0 -0
- {pycityagent-2.0.0a13.dist-info → pycityagent-2.0.0a15.dist-info}/WHEEL +0 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
def process_survey_for_llm(survey_dict: dict) -> str:
|
2
|
+
"""
|
3
|
+
将问卷字典转换为LLM可以逐题处理的格式,使用英文提示
|
4
|
+
"""
|
5
|
+
prompt = f"""Survey Title: {survey_dict['title']}
|
6
|
+
Survey Description: {survey_dict['description']}
|
7
|
+
|
8
|
+
Please answer each question in the following format:
|
9
|
+
|
10
|
+
"""
|
11
|
+
|
12
|
+
question_count = 1
|
13
|
+
for page in survey_dict['pages']:
|
14
|
+
for question in page['elements']:
|
15
|
+
prompt += f"Question {question_count}: {question['title']}\n"
|
16
|
+
|
17
|
+
# 根据不同类型的问题生成不同的提示
|
18
|
+
if question['type'] == 'radiogroup':
|
19
|
+
prompt += "Options: " + ", ".join(question['choices']) + "\n"
|
20
|
+
prompt += "Please select ONE option\n"
|
21
|
+
|
22
|
+
elif question['type'] == 'checkbox':
|
23
|
+
prompt += "Options: " + ", ".join(question['choices']) + "\n"
|
24
|
+
prompt += "You can select MULTIPLE options\n"
|
25
|
+
|
26
|
+
elif question['type'] == 'rating':
|
27
|
+
prompt += f"Rating range: {question.get('min_rating', 1)} - {question.get('max_rating', 5)}\n"
|
28
|
+
prompt += "Please provide a rating within the range\n"
|
29
|
+
|
30
|
+
elif question['type'] == 'matrix':
|
31
|
+
prompt += "Rows: " + ", ".join(question['rows']) + "\n"
|
32
|
+
prompt += "Columns: " + ", ".join(question['columns']) + "\n"
|
33
|
+
prompt += "Please select ONE column option for EACH row\n"
|
34
|
+
|
35
|
+
elif question['type'] == 'text':
|
36
|
+
prompt += "Please provide a text response\n"
|
37
|
+
|
38
|
+
elif question['type'] == 'boolean':
|
39
|
+
prompt += "Options: Yes, No\n"
|
40
|
+
prompt += "Please select either Yes or No\n"
|
41
|
+
|
42
|
+
prompt += "\nAnswer: [Your response here]\n\n---\n\n"
|
43
|
+
question_count += 1
|
44
|
+
|
45
|
+
# 添加总结提示
|
46
|
+
prompt += """Please ensure:
|
47
|
+
1. All required questions are answered
|
48
|
+
2. Responses match the question type requirements
|
49
|
+
3. Answers are clear and specific
|
50
|
+
|
51
|
+
Format your responses exactly as requested above."""
|
52
|
+
|
53
|
+
return prompt
|
pycityagent/workflow/tool.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: pycityagent
|
3
|
-
Version: 2.0.
|
3
|
+
Version: 2.0.0a15
|
4
4
|
Summary: LLM-based城市环境agent构建库
|
5
5
|
License: MIT
|
6
6
|
Author: Yuwei Yan
|
@@ -20,6 +20,7 @@ Requires-Dist: aiohttp (==3.10.10)
|
|
20
20
|
Requires-Dist: aiomqtt (>=2.3.0,<3.0.0)
|
21
21
|
Requires-Dist: citystreetview (==1.2.4)
|
22
22
|
Requires-Dist: dashscope (==1.14.1)
|
23
|
+
Requires-Dist: fastavro (>=1.10.0,<2.0.0)
|
23
24
|
Requires-Dist: geojson (==3.1.0)
|
24
25
|
Requires-Dist: gradio (>=5.7.1,<6.0.0)
|
25
26
|
Requires-Dist: grpcio (==1.67.1)
|
@@ -28,6 +29,7 @@ Requires-Dist: mosstool (==1.0.24)
|
|
28
29
|
Requires-Dist: networkx (==3.2.1)
|
29
30
|
Requires-Dist: numpy (>=1.20.0,<2.0.0)
|
30
31
|
Requires-Dist: openai (>=1.58.1,<2.0.0)
|
32
|
+
Requires-Dist: pandavro (>=1.8.0,<2.0.0)
|
31
33
|
Requires-Dist: poetry (>=1.2.2)
|
32
34
|
Requires-Dist: protobuf (<=4.24.0)
|
33
35
|
Requires-Dist: pycitydata (==1.0.0)
|
@@ -1,7 +1,7 @@
|
|
1
|
-
pycityagent/__init__.py,sha256=
|
2
|
-
pycityagent/agent.py,sha256=
|
1
|
+
pycityagent/__init__.py,sha256=EDxt3Su3lH1IMh9suNw7GeGL7UrXeWiZTw5KWNznDzc,637
|
2
|
+
pycityagent/agent.py,sha256=fcuKX6FtMzjNP8lVep9pG-9KHzHQwJ8IymJbmLKMfu0,23109
|
3
3
|
pycityagent/economy/__init__.py,sha256=aonY4WHnx-6EGJ4WKrx4S-2jAkYNLtqUA04jp6q8B7w,75
|
4
|
-
pycityagent/economy/econ_client.py,sha256=
|
4
|
+
pycityagent/economy/econ_client.py,sha256=wcuNtcpkSijJwNkt2mXw3SshYy4SBy6qbvJ0VQ7Aovo,10854
|
5
5
|
pycityagent/environment/__init__.py,sha256=awHxlOud-btWbk0FCS4RmGJ13W84oVCkbGfcrhKqihA,240
|
6
6
|
pycityagent/environment/interact/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
7
|
pycityagent/environment/interact/interact.py,sha256=ifxPPzuHeqLHIZ_6zvfXMoBOnBsXNIP4bYp7OJ7pnEQ,6588
|
@@ -21,7 +21,7 @@ pycityagent/environment/sim/person_service.py,sha256=nIvOsoBoqOTDYtsiThg07-4ZBgk
|
|
21
21
|
pycityagent/environment/sim/road_service.py,sha256=phKTwTyhc_6Ht2mddEXpdENfl-lRXIVY0CHAlw1yHjI,1264
|
22
22
|
pycityagent/environment/sim/sim_env.py,sha256=HI1LcS_FotDKQ6vBnx0e49prXSABOfA20aU9KM-ZkCY,4625
|
23
23
|
pycityagent/environment/sim/social_service.py,sha256=6Iqvq6dz8H2jhLLdtaITc6Js9QnQw-Ylsd5AZgUj3-E,1993
|
24
|
-
pycityagent/environment/simulator.py,sha256=
|
24
|
+
pycityagent/environment/simulator.py,sha256=K7IyhiGC9BxanW28bpML4M0YREdMp1h7yMoWBlbf3RY,12504
|
25
25
|
pycityagent/environment/utils/__init__.py,sha256=1m4Q1EfGvNpUsa1bgQzzCyWhfkpElnskNImjjFD3Znc,237
|
26
26
|
pycityagent/environment/utils/base64.py,sha256=hoREzQo3FXMN79pqQLO2jgsDEvudciomyKii7MWljAM,374
|
27
27
|
pycityagent/environment/utils/const.py,sha256=3RMNy7_bE7-23K90j9DFW_tWEzu8s7hSTgKbV-3BFl4,5327
|
@@ -36,35 +36,34 @@ pycityagent/llm/llm.py,sha256=BtxBvPK4tb8QlZIfxO5XJ73lKXwF8L31LqVbejWB8eo,15121
|
|
36
36
|
pycityagent/llm/llmconfig.py,sha256=4Ylf4OFSBEFy8jrOneeX0HvPhWEaF5jGvy1HkXK08Ro,436
|
37
37
|
pycityagent/llm/utils.py,sha256=hoNPhvomb1u6lhFX0GctFipw74hVKb7bvUBDqwBzBYw,160
|
38
38
|
pycityagent/memory/__init__.py,sha256=Hs2NhYpIG-lvpwPWwj4DydB1sxtjz7cuA4iDAzCXnjI,243
|
39
|
-
pycityagent/memory/const.py,sha256=
|
40
|
-
pycityagent/memory/memory.py,sha256=
|
41
|
-
pycityagent/memory/memory_base.py,sha256=
|
39
|
+
pycityagent/memory/const.py,sha256=6zpJPJXWoH9-yf4RARYYff586agCoud9BRn7sPERB1g,932
|
40
|
+
pycityagent/memory/memory.py,sha256=FjKVL_MgNBnSc0sox2tuxLqXg9_MQQr9vYdRDHMdDL4,18183
|
41
|
+
pycityagent/memory/memory_base.py,sha256=euKZRCs4dbcKxjlZzpLCTnH066DAtRjj5g1JFKD40qQ,5633
|
42
42
|
pycityagent/memory/profile.py,sha256=s4LnxSPGSjIGZXHXkkd8mMa6uYYZrytgyQdWjcaqGf4,5182
|
43
43
|
pycityagent/memory/self_define.py,sha256=poPiexNhOLq_iTgK8s4mK_xoL_DAAcB8kMvInj7iE5E,5179
|
44
44
|
pycityagent/memory/state.py,sha256=5W0c1yJ-aaPpE74B2LEcw3Ygpm77tyooHv8NylyrozE,5113
|
45
45
|
pycityagent/memory/utils.py,sha256=wLNlNlZ-AY9VB8kbUIy0UQSYh26FOQABbhmKQkit5o8,850
|
46
46
|
pycityagent/message/__init__.py,sha256=TCjazxqb5DVwbTu1fF0sNvaH_EPXVuj2XQ0p6W-QCLU,55
|
47
|
-
pycityagent/message/messager.py,sha256=
|
47
|
+
pycityagent/message/messager.py,sha256=W_OVlNGcreHSBf6v-DrEnfNCXExB78ySr0w26MSncfU,2541
|
48
48
|
pycityagent/simulation/__init__.py,sha256=jYaqaNpzM5M_e_ykISS_M-mIyYdzJXJWhgpfBpA6l5k,111
|
49
|
-
pycityagent/simulation/agentgroup.py,sha256=
|
50
|
-
pycityagent/simulation/
|
51
|
-
pycityagent/
|
52
|
-
pycityagent/
|
53
|
-
pycityagent/
|
54
|
-
pycityagent/
|
55
|
-
pycityagent/
|
56
|
-
pycityagent/simulation/ui/interface.py,sha256=cSQRQhuA5Gj-X7anuN9tmRpG6-I8QYOuswjIWUeSvio,21636
|
57
|
-
pycityagent/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
49
|
+
pycityagent/simulation/agentgroup.py,sha256=JwfssUtVrOgSnJCan4jcIcSHLjWBCwYxqOPT-AXA2sE,12514
|
50
|
+
pycityagent/simulation/simulation.py,sha256=G68P1EJ3JceA3zID2O6AGd_KdhhYy5XVZVUgkfJHypc,18897
|
51
|
+
pycityagent/survey/__init__.py,sha256=rxwou8U9KeFSP7rMzXtmtp2fVFZxK4Trzi-psx9LPIs,153
|
52
|
+
pycityagent/survey/manager.py,sha256=N4-Q8vve4L-PLaFikAgVB4Z8BNyFDEd6WjEk3AyMTgs,1764
|
53
|
+
pycityagent/survey/models.py,sha256=Z2gHEazQRj0TkTz5qbh4Uy_JrU_FZGWpOLwjN0RoUrY,3547
|
54
|
+
pycityagent/utils/__init__.py,sha256=xXEMhVfFeOJUXjczaHv9DJqYNp57rc6FibtS7CfrVbA,305
|
55
|
+
pycityagent/utils/avro_schema.py,sha256=DHM3bOo8m0dJf8oSwyOWzVeXrH6OERmzA_a5vS4So4M,4255
|
58
56
|
pycityagent/utils/decorators.py,sha256=Gk3r41hfk6awui40tbwpq3C7wC7jHaRmLRlcJFlLQCE,3160
|
59
57
|
pycityagent/utils/parsers/__init__.py,sha256=AN2xgiPxszWK4rpX7zrqRsqNwfGF3WnCA5-PFTvbaKk,281
|
60
58
|
pycityagent/utils/parsers/code_block_parser.py,sha256=Cs2Z_hm9VfNCpPPll1TwteaJF-HAQPs-3RApsOekFm4,1173
|
61
59
|
pycityagent/utils/parsers/json_parser.py,sha256=FZ3XN1g8z4Dr2TFraUOoah1oQcze4fPd2m01hHoX0Mo,2917
|
62
60
|
pycityagent/utils/parsers/parser_base.py,sha256=k6DVqwAMK3jJdOP4IeLE-aFPm3V2F-St5qRBuRdx4aU,1742
|
61
|
+
pycityagent/utils/survey_util.py,sha256=Be9nptmu2JtesFNemPgORh_2GsN7rcDYGQS9Zfvc5OI,2169
|
63
62
|
pycityagent/workflow/__init__.py,sha256=EyCcjB6LyBim-5iAOPe4m2qfvghEPqu1ZdGfy4KPeZ8,551
|
64
63
|
pycityagent/workflow/block.py,sha256=6EmiRMLdOZC1wMlmLMIjfrp9TuiI7Gw4s3nnXVMbrnw,6031
|
65
64
|
pycityagent/workflow/prompt.py,sha256=tY69nDO8fgYfF_dOA-iceR8pAhkYmCqoox8uRPqEuGY,2956
|
66
|
-
pycityagent/workflow/tool.py,sha256=
|
65
|
+
pycityagent/workflow/tool.py,sha256=zMvz3BV4QBs5TqyQ3ziJxj4pCfL2uqUI3A1FbT1gd3Q,6626
|
67
66
|
pycityagent/workflow/trigger.py,sha256=t5X_i0WtL32bipZSsq_E3UUyYYudYLxQUpvxbgClp2s,5683
|
68
|
-
pycityagent-2.0.
|
69
|
-
pycityagent-2.0.
|
70
|
-
pycityagent-2.0.
|
67
|
+
pycityagent-2.0.0a15.dist-info/METADATA,sha256=8ONKHaTIPOGja6FKJDE9tZ-pLZL2aeXQufB-LWkElR8,7705
|
68
|
+
pycityagent-2.0.0a15.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
69
|
+
pycityagent-2.0.0a15.dist-info/RECORD,,
|
@@ -1,40 +0,0 @@
|
|
1
|
-
from dataclasses import dataclass
|
2
|
-
from datetime import datetime
|
3
|
-
from typing import List, Optional
|
4
|
-
|
5
|
-
|
6
|
-
@dataclass
|
7
|
-
class InterviewRecord:
|
8
|
-
"""采访记录"""
|
9
|
-
|
10
|
-
timestamp: datetime
|
11
|
-
agent_name: str
|
12
|
-
question: str
|
13
|
-
response: str
|
14
|
-
blocking: bool
|
15
|
-
|
16
|
-
|
17
|
-
class InterviewManager:
|
18
|
-
"""采访管理器"""
|
19
|
-
|
20
|
-
def __init__(self):
|
21
|
-
self._history: List[InterviewRecord] = []
|
22
|
-
|
23
|
-
def add_record(self, agent_name: str, question: str, response: str, blocking: bool):
|
24
|
-
"""添加采访记录"""
|
25
|
-
record = InterviewRecord(
|
26
|
-
timestamp=datetime.now(),
|
27
|
-
agent_name=agent_name,
|
28
|
-
question=question,
|
29
|
-
response=response,
|
30
|
-
blocking=blocking,
|
31
|
-
)
|
32
|
-
self._history.append(record)
|
33
|
-
|
34
|
-
def get_agent_history(self, agent_name: str) -> List[InterviewRecord]:
|
35
|
-
"""获取指定智能体的采访历史"""
|
36
|
-
return [r for r in self._history if r.agent_name == agent_name]
|
37
|
-
|
38
|
-
def get_recent_history(self, limit: int = 10) -> List[InterviewRecord]:
|
39
|
-
"""获取最近的采访记录"""
|
40
|
-
return sorted(self._history, key=lambda x: x.timestamp, reverse=True)[:limit]
|
@@ -1,68 +0,0 @@
|
|
1
|
-
from typing import List, Dict, Optional
|
2
|
-
from datetime import datetime
|
3
|
-
import uuid
|
4
|
-
import json
|
5
|
-
from .models import Survey, Question, QuestionType
|
6
|
-
|
7
|
-
|
8
|
-
class SurveyManager:
|
9
|
-
def __init__(self):
|
10
|
-
self._surveys: Dict[str, Survey] = {}
|
11
|
-
|
12
|
-
def create_survey(
|
13
|
-
self, title: str, description: str, questions: List[dict]
|
14
|
-
) -> Survey:
|
15
|
-
"""创建新问卷"""
|
16
|
-
survey_id = str(uuid.uuid4())
|
17
|
-
|
18
|
-
# 转换问题数据
|
19
|
-
survey_questions = []
|
20
|
-
for q in questions:
|
21
|
-
question = Question(
|
22
|
-
content=q["content"],
|
23
|
-
type=QuestionType(q["type"]),
|
24
|
-
required=q.get("required", True),
|
25
|
-
options=q.get("options", []),
|
26
|
-
min_rating=q.get("min_rating", 1),
|
27
|
-
max_rating=q.get("max_rating", 5),
|
28
|
-
)
|
29
|
-
survey_questions.append(question)
|
30
|
-
|
31
|
-
survey = Survey(
|
32
|
-
id=survey_id,
|
33
|
-
title=title,
|
34
|
-
description=description,
|
35
|
-
questions=survey_questions,
|
36
|
-
)
|
37
|
-
|
38
|
-
self._surveys[survey_id] = survey
|
39
|
-
return survey
|
40
|
-
|
41
|
-
def get_survey(self, survey_id: str) -> Optional[Survey]:
|
42
|
-
"""获取指定问卷"""
|
43
|
-
return self._surveys.get(survey_id)
|
44
|
-
|
45
|
-
def get_all_surveys(self) -> List[Survey]:
|
46
|
-
"""获取所有问卷"""
|
47
|
-
return list(self._surveys.values())
|
48
|
-
|
49
|
-
def add_response(self, survey_id: str, agent_name: str, response: dict) -> bool:
|
50
|
-
"""添加问卷回答"""
|
51
|
-
survey = self.get_survey(survey_id)
|
52
|
-
if not survey:
|
53
|
-
return False
|
54
|
-
|
55
|
-
survey.responses[agent_name] = {"timestamp": datetime.now(), **response}
|
56
|
-
return True
|
57
|
-
|
58
|
-
def export_results(self, survey_id: str) -> str:
|
59
|
-
"""导出问卷结果"""
|
60
|
-
survey = self.get_survey(survey_id)
|
61
|
-
if not survey:
|
62
|
-
return json.dumps({"error": "问卷不存在"})
|
63
|
-
|
64
|
-
return json.dumps(
|
65
|
-
{"survey": survey.to_dict(), "responses": survey.responses},
|
66
|
-
ensure_ascii=False,
|
67
|
-
indent=2,
|
68
|
-
)
|
@@ -1,52 +0,0 @@
|
|
1
|
-
from dataclasses import dataclass, field
|
2
|
-
from typing import List, Dict, Optional
|
3
|
-
from datetime import datetime
|
4
|
-
from enum import Enum
|
5
|
-
import uuid
|
6
|
-
|
7
|
-
|
8
|
-
class QuestionType(Enum):
|
9
|
-
TEXT = "文本"
|
10
|
-
SINGLE_CHOICE = "单选"
|
11
|
-
MULTIPLE_CHOICE = "多选"
|
12
|
-
RATING = "评分"
|
13
|
-
LIKERT = "李克特量表"
|
14
|
-
|
15
|
-
|
16
|
-
@dataclass
|
17
|
-
class Question:
|
18
|
-
content: str
|
19
|
-
type: QuestionType
|
20
|
-
required: bool = True
|
21
|
-
options: List[str] = field(default_factory=list)
|
22
|
-
min_rating: int = 1
|
23
|
-
max_rating: int = 5
|
24
|
-
|
25
|
-
def to_dict(self) -> dict:
|
26
|
-
return {
|
27
|
-
"content": self.content,
|
28
|
-
"type": self.type.value,
|
29
|
-
"required": self.required,
|
30
|
-
"options": self.options,
|
31
|
-
"min_rating": self.min_rating,
|
32
|
-
"max_rating": self.max_rating,
|
33
|
-
}
|
34
|
-
|
35
|
-
|
36
|
-
@dataclass
|
37
|
-
class Survey:
|
38
|
-
id: str
|
39
|
-
title: str
|
40
|
-
description: str
|
41
|
-
questions: List[Question]
|
42
|
-
responses: Dict[str, dict] = field(default_factory=dict)
|
43
|
-
created_at: datetime = field(default_factory=datetime.now)
|
44
|
-
|
45
|
-
def to_dict(self) -> dict:
|
46
|
-
return {
|
47
|
-
"id": self.id,
|
48
|
-
"title": self.title,
|
49
|
-
"description": self.description,
|
50
|
-
"questions": [q.to_dict() for q in self.questions],
|
51
|
-
"response_count": len(self.responses),
|
52
|
-
}
|