beswarm 0.2.44__py3-none-any.whl → 0.2.46__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.
Potentially problematic release.
This version of beswarm might be problematic. Click here for more details.
- beswarm/agents/planact.py +37 -8
- beswarm/core.py +1 -1
- beswarm/knowledge_graph.py +16 -6
- beswarm/tools/graph.py +3 -1
- {beswarm-0.2.44.dist-info → beswarm-0.2.46.dist-info}/METADATA +1 -1
- {beswarm-0.2.44.dist-info → beswarm-0.2.46.dist-info}/RECORD +8 -8
- {beswarm-0.2.44.dist-info → beswarm-0.2.46.dist-info}/WHEEL +0 -0
- {beswarm-0.2.44.dist-info → beswarm-0.2.46.dist-info}/top_level.txt +0 -0
beswarm/agents/planact.py
CHANGED
|
@@ -17,7 +17,7 @@ from ..utils import extract_xml_content, get_current_screen_image_message, repla
|
|
|
17
17
|
|
|
18
18
|
class BaseAgent:
|
|
19
19
|
"""Base class for agents, handling common initialization and disposal."""
|
|
20
|
-
def __init__(self, goal: str, tools_json: List, agent_config: Dict, work_dir: str, cache_messages: Union[bool, List[Dict]], broker: MessageBroker, listen_topic: str, publish_topic: str, status_topic: str):
|
|
20
|
+
def __init__(self, goal: str, tools_json: List, agent_config: Dict, work_dir: str, cache_messages: Union[bool, List[Dict]], broker: MessageBroker, listen_topic: str, publish_topic: str, status_topic: str, graph_update_topic: str = None):
|
|
21
21
|
self.goal = goal
|
|
22
22
|
self.tools_json = tools_json
|
|
23
23
|
self.work_dir = work_dir
|
|
@@ -32,12 +32,20 @@ class BaseAgent:
|
|
|
32
32
|
self.error_topic = listen_topic + ".error"
|
|
33
33
|
self.publish_topic = publish_topic
|
|
34
34
|
self.status_topic = status_topic
|
|
35
|
+
self.graph_update_topic = graph_update_topic
|
|
36
|
+
if self.graph_update_topic:
|
|
37
|
+
self.graph_update_subscription = self.broker.subscribe(self.handle_graph_update, self.graph_update_topic)
|
|
38
|
+
|
|
35
39
|
self._subscription = self.broker.subscribe(self.handle_message, [self.listen_topic, self.error_topic])
|
|
36
40
|
|
|
37
41
|
async def handle_message(self, message: Dict):
|
|
38
42
|
"""Process incoming messages. Must be implemented by subclasses."""
|
|
39
43
|
raise NotImplementedError
|
|
40
44
|
|
|
45
|
+
def handle_graph_update(self, message: Dict):
|
|
46
|
+
"""Handle graph update messages."""
|
|
47
|
+
raise NotImplementedError
|
|
48
|
+
|
|
41
49
|
def dispose(self):
|
|
42
50
|
"""Cancels the subscription and cleans up resources."""
|
|
43
51
|
if self._subscription:
|
|
@@ -46,12 +54,13 @@ class BaseAgent:
|
|
|
46
54
|
|
|
47
55
|
class InstructionAgent(BaseAgent):
|
|
48
56
|
"""Generates instructions and publishes them to a message broker."""
|
|
49
|
-
def __init__(self, goal: str, tools_json: List, agent_config: Dict, work_dir: str, cache_messages: Union[bool, List[Dict]], broker: MessageBroker, listen_topic: str, publish_topic: str, status_topic: str):
|
|
50
|
-
super().__init__(goal, tools_json, agent_config, work_dir, cache_messages, broker, listen_topic, publish_topic, status_topic)
|
|
57
|
+
def __init__(self, goal: str, tools_json: List, agent_config: Dict, work_dir: str, cache_messages: Union[bool, List[Dict]], broker: MessageBroker, listen_topic: str, publish_topic: str, status_topic: str, graph_update_topic: str):
|
|
58
|
+
super().__init__(goal, tools_json, agent_config, work_dir, cache_messages, broker, listen_topic, publish_topic, status_topic, graph_update_topic)
|
|
51
59
|
|
|
52
60
|
self.last_instruction = None
|
|
53
61
|
self.agent = chatgpt(**self.config)
|
|
54
62
|
|
|
63
|
+
self.graph_tree = None
|
|
55
64
|
self.goal_diff = None
|
|
56
65
|
|
|
57
66
|
if self.cache_messages and isinstance(self.cache_messages, list) and len(self.cache_messages) > 1:
|
|
@@ -64,8 +73,13 @@ class InstructionAgent(BaseAgent):
|
|
|
64
73
|
changed_lines.append(line)
|
|
65
74
|
self.goal_diff = '\n'.join(changed_lines).strip()
|
|
66
75
|
|
|
67
|
-
def
|
|
68
|
-
|
|
76
|
+
def handle_graph_update(self, message: Dict):
|
|
77
|
+
"""Handle graph update messages."""
|
|
78
|
+
if message.get("message") == "graph_updated":
|
|
79
|
+
self.graph_tree = message.get("graph")
|
|
80
|
+
|
|
81
|
+
def get_conversation_history(self, raw_conversation_history: List[Dict]):
|
|
82
|
+
conversation_history = copy.deepcopy(raw_conversation_history)
|
|
69
83
|
|
|
70
84
|
self.cache_file.write_text(json.dumps(conversation_history, ensure_ascii=False, indent=4), encoding="utf-8")
|
|
71
85
|
|
|
@@ -83,6 +97,17 @@ class InstructionAgent(BaseAgent):
|
|
|
83
97
|
elif isinstance(conversation_history[0]["content"], list) and extracted_content:
|
|
84
98
|
conversation_history[0]["content"].append({"type": "text", "text": extracted_content})
|
|
85
99
|
|
|
100
|
+
for message in conversation_history:
|
|
101
|
+
if message.get("content") and isinstance(message["content"], str) \
|
|
102
|
+
and "<knowledge_graph_tree>" in message["content"] and self.graph_tree:
|
|
103
|
+
message["content"] = replace_xml_content(message["content"], "knowledge_graph_tree", self.graph_tree)
|
|
104
|
+
|
|
105
|
+
for index, message in enumerate(raw_conversation_history):
|
|
106
|
+
if message.get("content") and isinstance(message["content"], str) \
|
|
107
|
+
and "<knowledge_graph_tree>" in message["content"] and self.graph_tree:
|
|
108
|
+
message["content"] = replace_xml_content(message["content"], "knowledge_graph_tree", self.graph_tree)
|
|
109
|
+
raw_conversation_history[index] = message
|
|
110
|
+
|
|
86
111
|
return conversation_history
|
|
87
112
|
|
|
88
113
|
async def handle_message(self, message: Dict):
|
|
@@ -201,18 +226,21 @@ class BrokerWorker:
|
|
|
201
226
|
self.task_completion_event = asyncio.Event()
|
|
202
227
|
self.final_result = None
|
|
203
228
|
self._status_subscription = None
|
|
204
|
-
self.setup()
|
|
205
229
|
|
|
206
230
|
self.channel = self.broker.request_channel()
|
|
207
231
|
self.INSTRUCTION_TOPIC = self.channel + ".instructions"
|
|
208
232
|
self.WORKER_RESPONSE_TOPIC = self.channel + ".worker_responses"
|
|
209
233
|
self.TASK_STATUS_TOPIC =self.channel + ".task_status"
|
|
234
|
+
self.GRAPH_UPDATE_TOPIC = self.channel + ".knowledge_graph"
|
|
235
|
+
|
|
236
|
+
self.setup()
|
|
210
237
|
|
|
211
238
|
def setup(self):
|
|
212
239
|
cache_dir = self.work_dir / ".beswarm"
|
|
213
240
|
cache_dir.mkdir(parents=True, exist_ok=True)
|
|
214
241
|
self.task_manager.set_root_path(self.work_dir)
|
|
215
242
|
self.kgm.set_root_path(self.work_dir)
|
|
243
|
+
self.kgm.set_publish_topic(self.GRAPH_UPDATE_TOPIC)
|
|
216
244
|
self.cache_file = cache_dir / "work_agent_conversation_history.json"
|
|
217
245
|
if not self.cache_file.exists():
|
|
218
246
|
self.cache_file.write_text("[]", encoding="utf-8")
|
|
@@ -276,13 +304,14 @@ class BrokerWorker:
|
|
|
276
304
|
instruction_agent = InstructionAgent(
|
|
277
305
|
goal=self.goal, tools_json=self.tools_json, agent_config=instruction_agent_config, work_dir=self.work_dir, cache_messages=self.cache_messages,
|
|
278
306
|
broker=self.broker, listen_topic=self.WORKER_RESPONSE_TOPIC,
|
|
279
|
-
publish_topic=self.INSTRUCTION_TOPIC, status_topic=self.TASK_STATUS_TOPIC
|
|
307
|
+
publish_topic=self.INSTRUCTION_TOPIC, status_topic=self.TASK_STATUS_TOPIC,
|
|
308
|
+
graph_update_topic=self.GRAPH_UPDATE_TOPIC
|
|
280
309
|
)
|
|
281
310
|
|
|
282
311
|
worker_agent = WorkerAgent(
|
|
283
312
|
goal=self.goal, tools_json=self.tools_json, agent_config=worker_agent_config, work_dir=self.work_dir, cache_messages=self.cache_messages,
|
|
284
313
|
broker=self.broker, listen_topic=self.INSTRUCTION_TOPIC,
|
|
285
|
-
publish_topic=self.WORKER_RESPONSE_TOPIC, status_topic=self.TASK_STATUS_TOPIC
|
|
314
|
+
publish_topic=self.WORKER_RESPONSE_TOPIC, status_topic=self.TASK_STATUS_TOPIC,
|
|
286
315
|
)
|
|
287
316
|
return instruction_agent, worker_agent
|
|
288
317
|
|
beswarm/core.py
CHANGED
beswarm/knowledge_graph.py
CHANGED
|
@@ -9,7 +9,7 @@ class KnowledgeGraphManager:
|
|
|
9
9
|
- 数据持久化为 GraphML 文件。
|
|
10
10
|
- 提供添加、删除、重命名、移动节点和渲染树状图的功能。
|
|
11
11
|
"""
|
|
12
|
-
def __init__(self, storage_path="knowledge_graph.graphml"):
|
|
12
|
+
def __init__(self, storage_path="knowledge_graph.graphml", broker=None, publish_topic=None):
|
|
13
13
|
"""
|
|
14
14
|
初始化知识图谱管理器。
|
|
15
15
|
|
|
@@ -20,6 +20,8 @@ class KnowledgeGraphManager:
|
|
|
20
20
|
self.storage_path = Path(storage_path)
|
|
21
21
|
self.graph = nx.DiGraph()
|
|
22
22
|
self.root_path = None
|
|
23
|
+
self.broker = broker
|
|
24
|
+
self.publish_topic = publish_topic
|
|
23
25
|
# self._load_graph()
|
|
24
26
|
|
|
25
27
|
def set_root_path(self, root_path):
|
|
@@ -49,16 +51,24 @@ class KnowledgeGraphManager:
|
|
|
49
51
|
self.graph.add_node("root", name=".", description="知识图谱根节点")
|
|
50
52
|
self._save_graph()
|
|
51
53
|
|
|
54
|
+
def set_publish_topic(self, publish_topic):
|
|
55
|
+
if not publish_topic:
|
|
56
|
+
return
|
|
57
|
+
self.publish_topic = publish_topic
|
|
58
|
+
|
|
52
59
|
def _save_graph(self):
|
|
53
60
|
"""将当前图的状态保存到文件。"""
|
|
54
61
|
nx.write_graphml(self.graph, self.storage_path)
|
|
55
62
|
|
|
63
|
+
if self.publish_topic and self.broker:
|
|
64
|
+
self.broker.publish({"message": "graph_updated", "graph": self.render_tree()}, self.publish_topic)
|
|
65
|
+
|
|
56
66
|
def _get_node_id_by_path(self, path: str):
|
|
57
67
|
"""通过'/'分隔的路径查找节点的唯一ID,支持前缀匹配。"""
|
|
58
68
|
if path is None or not path.strip() or path.strip() in ['.', '/']:
|
|
59
69
|
return "root"
|
|
60
70
|
|
|
61
|
-
segments = path.strip('/').split('/')
|
|
71
|
+
segments = [s for s in path.strip('/').split('/') if s and s != '.']
|
|
62
72
|
current_node_id = "root"
|
|
63
73
|
|
|
64
74
|
for segment in segments:
|
|
@@ -69,17 +79,17 @@ class KnowledgeGraphManager:
|
|
|
69
79
|
current_node_id = child_id
|
|
70
80
|
found_child = True
|
|
71
81
|
break
|
|
72
|
-
|
|
82
|
+
|
|
73
83
|
if found_child:
|
|
74
84
|
continue
|
|
75
|
-
|
|
85
|
+
|
|
76
86
|
# 如果完全匹配失败,尝试前缀匹配
|
|
77
87
|
prefix_matches = []
|
|
78
88
|
for child_id in self.graph.successors(current_node_id):
|
|
79
89
|
child_name = self.graph.nodes[child_id].get('name', '')
|
|
80
90
|
if child_name.startswith(segment):
|
|
81
91
|
prefix_matches.append(child_id)
|
|
82
|
-
|
|
92
|
+
|
|
83
93
|
if len(prefix_matches) == 1:
|
|
84
94
|
# 只有一个前缀匹配,使用这个节点
|
|
85
95
|
current_node_id = prefix_matches[0]
|
|
@@ -89,7 +99,7 @@ class KnowledgeGraphManager:
|
|
|
89
99
|
else:
|
|
90
100
|
# 没有前缀匹配,节点不存在
|
|
91
101
|
return None
|
|
92
|
-
|
|
102
|
+
|
|
93
103
|
return current_node_id
|
|
94
104
|
|
|
95
105
|
def add_node(self, parent_path: str, node_name: str, description: str = "") -> str:
|
beswarm/tools/graph.py
CHANGED
|
@@ -65,7 +65,9 @@ def get_knowledge_graph_tree() -> str:
|
|
|
65
65
|
此工具不需要任何参数,它会读取当前的图状态并生成一个易于阅读的、
|
|
66
66
|
表示层级结构的字符串。
|
|
67
67
|
|
|
68
|
+
注意:此函数返回的知识图谱状态是实时更新的,永远是最新的。只需要调用一次,不必重复调用。
|
|
69
|
+
|
|
68
70
|
Returns:
|
|
69
71
|
str: 表示整个知识图谱的、格式化的树状结构字符串。
|
|
70
72
|
"""
|
|
71
|
-
return kgm.render_tree()
|
|
73
|
+
return "<knowledge_graph_tree>" + kgm.render_tree() + "</knowledge_graph_tree>"
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
beswarm/__init__.py,sha256=HZjUOJtZR5QhMuDbq-wukQQn1VrBusNWai_ysGo-VVI,20
|
|
2
2
|
beswarm/broker.py,sha256=RtnQZVbhf25acUHahNBiaS5FGxcrj0rhBhkon9gFY_M,9873
|
|
3
|
-
beswarm/core.py,sha256=
|
|
4
|
-
beswarm/knowledge_graph.py,sha256=
|
|
3
|
+
beswarm/core.py,sha256=htssaaeIBZ_yOqvX9VtANoVWaZHt_7oWcxyDI1z0paQ,310
|
|
4
|
+
beswarm/knowledge_graph.py,sha256=Q2hhXL2RXnAM8vvxstYetch5wX7ghTM5S7FnORSxCG0,9205
|
|
5
5
|
beswarm/prompt.py,sha256=n0a1a6NThIxAYSkisg1sEKjvz2w0tozpKL4BIplaAkI,32286
|
|
6
6
|
beswarm/taskmanager.py,sha256=xczsnehCaOAI3SRE8wUxhzmt6i6G7ynndSWS_bAZn3k,12192
|
|
7
7
|
beswarm/utils.py,sha256=S9jEtht0hTZbjZ2Hk24p4Ip41R69BogOkYS6fgPKY2Y,8219
|
|
8
8
|
beswarm/agents/chatgroup.py,sha256=YHofra9kE0x7UrhqZjlP7PbWvinEew1BkjJ0XilzudM,12020
|
|
9
|
-
beswarm/agents/planact.py,sha256=
|
|
9
|
+
beswarm/agents/planact.py,sha256=PGj69lhy6r3q07R8w16aMoWY1OjXVXothu7lDG-UC4Y,19140
|
|
10
10
|
beswarm/aient/main.py,sha256=SiYAIgQlLJqYusnTVEJOx1WNkSJKMImhgn5aWjfroxg,3814
|
|
11
11
|
beswarm/aient/setup.py,sha256=Mq1M05mT9_UYBK2jk5mP_sLxKQAolcuh8PYXexfj-XU,487
|
|
12
12
|
beswarm/aient/src/aient/__init__.py,sha256=SRfF7oDVlOOAi6nGKiJIUK6B_arqYLO9iSMp-2IZZps,21
|
|
@@ -135,7 +135,7 @@ beswarm/tools/__init__.py,sha256=fhJSEaYcfgMTW_nzUqQiyX5RLBhE-gxs8u4PpFquOdg,186
|
|
|
135
135
|
beswarm/tools/click.py,sha256=7g6x1X7ffTInGWp7112KS-MAQ5-8wa1Ze2sIipUIbjc,20884
|
|
136
136
|
beswarm/tools/completion.py,sha256=wHEJrdzjuTKQNQZhelSuPnK2YRsGbeUqZ0P6IgT3c10,605
|
|
137
137
|
beswarm/tools/edit_file.py,sha256=iwWl7a8sTVq4vj0e1ny3H6UGcHfYnxALRGcLuk5hZS8,9155
|
|
138
|
-
beswarm/tools/graph.py,sha256
|
|
138
|
+
beswarm/tools/graph.py,sha256=-Lyhi-AsJNKQ5p9BJk6mzARd1-IDhdLyKmNAVN5PdUE,2703
|
|
139
139
|
beswarm/tools/planner.py,sha256=lguBCS6kpwNPoXQvqH-WySabVubT82iyWOkJnjt6dXw,1265
|
|
140
140
|
beswarm/tools/repomap.py,sha256=YsTPq5MXfn_Ds5begcvHDnY_Xp2d4jH-xmWqNMHnNHY,45239
|
|
141
141
|
beswarm/tools/request_input.py,sha256=gXNAJPOJektMqxJVyzNTFOeMQ7xUkO-wWMYH-r2Rdwk,942
|
|
@@ -145,7 +145,7 @@ beswarm/tools/search_web.py,sha256=LhgXOSHL9fwxg5T2AAOV4TTJkcJVLogsfRJW2faPvDE,1
|
|
|
145
145
|
beswarm/tools/subtasks.py,sha256=zZmRCjDocbvrU8MvZvpDWpQCKNntDJ123ByBiS8pRko,9889
|
|
146
146
|
beswarm/tools/worker.py,sha256=-tcLGrdLPZYxc1z66iQIB1VH7RWcR-5CgVWuDIQJBCQ,2013
|
|
147
147
|
beswarm/tools/write_csv.py,sha256=-r5OghcvjCg00hY0YQbp6u31VIJLrgaqDIvczAFoqDE,1470
|
|
148
|
-
beswarm-0.2.
|
|
149
|
-
beswarm-0.2.
|
|
150
|
-
beswarm-0.2.
|
|
151
|
-
beswarm-0.2.
|
|
148
|
+
beswarm-0.2.46.dist-info/METADATA,sha256=xFDxpNffZqMEucZHFfh63mCH2YBq6UnKBz8gJF5kvtk,3878
|
|
149
|
+
beswarm-0.2.46.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
150
|
+
beswarm-0.2.46.dist-info/top_level.txt,sha256=pJw4O87wvt5882smuSO6DfByJz7FJ8SxxT8h9fHCmpo,8
|
|
151
|
+
beswarm-0.2.46.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|