Spaces:
Sleeping
Sleeping
Trying something new - an agent builder...
Browse files- agent_builder.py +321 -0
- agent_builder_template/design_puml.txt +15 -0
- agent_builder_template/design_yaml.txt +11 -0
- agent_builder_template/graph.txt +21 -0
- agent_builder_template/graph_builder.txt +24 -0
- agent_builder_template/test.txt +2 -0
- agents/universal_solver/design.puml +32 -0
- agents/universal_solver/design.yaml +21 -0
- agents/universal_solver/graph.py +74 -0
- agents/universal_solver/test.py +20 -0
agent_builder.py
ADDED
@@ -0,0 +1,321 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from pathlib import Path
|
2 |
+
import yaml
|
3 |
+
from typing import Dict, List, Any
|
4 |
+
|
5 |
+
|
6 |
+
class AgentBuilder:
|
7 |
+
@staticmethod
|
8 |
+
def initialize(agent_name: str):
|
9 |
+
"""Create agent folder and an empty 'yaml' file
|
10 |
+
|
11 |
+
Args:
|
12 |
+
agent_name: Name of the agent to create
|
13 |
+
"""
|
14 |
+
# Create base agents directory if it doesn't exist
|
15 |
+
agents_base_dir = Path("agents")
|
16 |
+
agents_base_dir.mkdir(exist_ok=True)
|
17 |
+
|
18 |
+
# Create agent-specific directory
|
19 |
+
agent_dir = agents_base_dir / agent_name
|
20 |
+
agent_dir.mkdir(exist_ok=True)
|
21 |
+
|
22 |
+
# Create YAML file with initial content
|
23 |
+
yaml_file = agent_dir / f"design.yaml"
|
24 |
+
|
25 |
+
# Initial YAML content with nodes list and example node
|
26 |
+
initial_content = {
|
27 |
+
"nodes": [
|
28 |
+
{
|
29 |
+
"name": "START",
|
30 |
+
"connections": ["example_node"],
|
31 |
+
"description": "This is the mandatory initial node `START` !"
|
32 |
+
},
|
33 |
+
{
|
34 |
+
"name": "example_node",
|
35 |
+
"connections": [],
|
36 |
+
"description": "This is an example node"
|
37 |
+
}
|
38 |
+
]
|
39 |
+
}
|
40 |
+
|
41 |
+
# Write the YAML content to the file
|
42 |
+
with open(yaml_file, "w") as f:
|
43 |
+
yaml.dump(initial_content, f, default_flow_style=False, sort_keys=False)
|
44 |
+
|
45 |
+
@classmethod
|
46 |
+
def setup(cls, agent_name: str):
|
47 |
+
"""Create the graph and the test python files as well as a 'puml' diagram
|
48 |
+
|
49 |
+
Args:
|
50 |
+
agent_name: Name of the agent to set up
|
51 |
+
"""
|
52 |
+
design_data = cls._validate_design(agent_name)
|
53 |
+
|
54 |
+
cls._create_graph_file(agent_name, design_data)
|
55 |
+
cls._create_test_file(agent_name)
|
56 |
+
cls._create_puml_file(agent_name, design_data)
|
57 |
+
|
58 |
+
@classmethod
|
59 |
+
def _validate_design(cls, agent_name: str) -> Dict[str, List[Dict[str, Any]]]:
|
60 |
+
"""Validate the design.yaml file structure
|
61 |
+
|
62 |
+
Args:
|
63 |
+
agent_name: Name of the agent to validate
|
64 |
+
|
65 |
+
Returns:
|
66 |
+
The parsed design data if valid
|
67 |
+
|
68 |
+
Raises:
|
69 |
+
ValueError: If design file is invalid or missing required elements
|
70 |
+
"""
|
71 |
+
yaml_path = Path(f"agents/{agent_name}/design.yaml")
|
72 |
+
|
73 |
+
if not yaml_path.exists():
|
74 |
+
raise ValueError(f"Design file not found at {yaml_path}")
|
75 |
+
|
76 |
+
with open(yaml_path, 'r') as f:
|
77 |
+
design_data = yaml.safe_load(f)
|
78 |
+
|
79 |
+
# Check if nodes list exists
|
80 |
+
if not design_data or 'nodes' not in design_data or not isinstance(design_data['nodes'], list):
|
81 |
+
raise ValueError("Design file must contain a 'nodes' list")
|
82 |
+
|
83 |
+
# Check if START node is defined
|
84 |
+
start_node_exists = any(node.get('name') == "START" for node in design_data['nodes'])
|
85 |
+
if not start_node_exists:
|
86 |
+
raise ValueError("Design file must contain a 'START' node")
|
87 |
+
|
88 |
+
# Validate each node
|
89 |
+
for i, node in enumerate(design_data['nodes']):
|
90 |
+
if not isinstance(node, dict):
|
91 |
+
raise ValueError(f"Node at index {i} must be a dictionary")
|
92 |
+
|
93 |
+
if 'name' not in node:
|
94 |
+
raise ValueError(f"Node at index {i} is missing a 'name' field")
|
95 |
+
|
96 |
+
if 'description' not in node:
|
97 |
+
raise ValueError(f"Node '{node.get('name', f'at index {i}')}' is missing a 'description' field")
|
98 |
+
|
99 |
+
if 'connections' not in node or not isinstance(node['connections'], list):
|
100 |
+
raise ValueError(f"Node '{node.get('name')}' must have a 'connections' list")
|
101 |
+
|
102 |
+
return design_data
|
103 |
+
|
104 |
+
@classmethod
|
105 |
+
def _create_graph_file(cls, agent_name: str, design_data: Dict[str, List[Dict[str, Any]]]):
|
106 |
+
"""Create the graph.py file with the necessary classes
|
107 |
+
|
108 |
+
Args:
|
109 |
+
agent_name: Name of the agent
|
110 |
+
design_data: The validated design data
|
111 |
+
"""
|
112 |
+
nodes = design_data['nodes']
|
113 |
+
|
114 |
+
# Prepare node methods and conditional edge methods
|
115 |
+
node_methods = []
|
116 |
+
edge_methods = []
|
117 |
+
|
118 |
+
# Generate node method for each node
|
119 |
+
for node in nodes:
|
120 |
+
node_name = node['name']
|
121 |
+
node_desc = node['description']
|
122 |
+
|
123 |
+
node_method = f'''
|
124 |
+
def {node_name}_node(self, state):
|
125 |
+
"""
|
126 |
+
{node_desc}
|
127 |
+
"""
|
128 |
+
# TODO: To implement...
|
129 |
+
pass
|
130 |
+
'''
|
131 |
+
if node_name != "START":
|
132 |
+
node_methods.append(node_method)
|
133 |
+
|
134 |
+
# Check if this node has more than one connection (needs conditional edge)
|
135 |
+
if len(node['connections']) > 1:
|
136 |
+
connections_str = ", ".join([f'"{conn}"' for conn in node['connections']])
|
137 |
+
edge_method = f'''
|
138 |
+
def {node_name}_edge(self, state):
|
139 |
+
"""
|
140 |
+
Conditional edge for {node_name} node.
|
141 |
+
Returns one of: {connections_str}
|
142 |
+
"""
|
143 |
+
# TODO: To implement...
|
144 |
+
pass
|
145 |
+
'''
|
146 |
+
edge_methods.append(edge_method)
|
147 |
+
|
148 |
+
# Build the file content
|
149 |
+
file_content = f'''from typing import Dict, Any
|
150 |
+
from langgraph.graph import StateGraph, END, START
|
151 |
+
from langgraph.graph.state import CompiledStateGraph
|
152 |
+
|
153 |
+
|
154 |
+
class State:
|
155 |
+
"""
|
156 |
+
State class for the agent graph.
|
157 |
+
"""
|
158 |
+
# TODO: Define state structure
|
159 |
+
pass
|
160 |
+
|
161 |
+
|
162 |
+
class Nodes:
|
163 |
+
"""
|
164 |
+
Collection of node functions for the agent graph.
|
165 |
+
"""
|
166 |
+
{"".join(node_methods)}
|
167 |
+
|
168 |
+
|
169 |
+
class Edges:
|
170 |
+
"""
|
171 |
+
Collection of conditional edge functions for the agent graph.
|
172 |
+
"""
|
173 |
+
{"".join(edge_methods)}
|
174 |
+
|
175 |
+
|
176 |
+
class GraphBuilder:
|
177 |
+
def __init__(self):
|
178 |
+
"""
|
179 |
+
Initializes the GraphBuilder.
|
180 |
+
"""
|
181 |
+
self.nodes = Nodes()
|
182 |
+
self.edges = Edges()
|
183 |
+
# TODO: Implement the desired constructor.
|
184 |
+
pass
|
185 |
+
|
186 |
+
def build_agent_graph(self) -> CompiledStateGraph:
|
187 |
+
"""Build and return the agent graph."""
|
188 |
+
graph = StateGraph(State)
|
189 |
+
|
190 |
+
# Add all nodes
|
191 |
+
{cls._generate_add_nodes_code(nodes)}
|
192 |
+
|
193 |
+
# Add edges
|
194 |
+
{cls._generate_regular_edges_code(nodes)}
|
195 |
+
{cls._generate_conditional_edges_code(nodes)}
|
196 |
+
return graph.compile()
|
197 |
+
'''
|
198 |
+
# Write to file
|
199 |
+
graph_file_path = Path(f"agents/{agent_name}/graph.py")
|
200 |
+
with open(graph_file_path, 'w') as f:
|
201 |
+
f.write(file_content)
|
202 |
+
|
203 |
+
@staticmethod
|
204 |
+
def _generate_add_nodes_code(nodes):
|
205 |
+
"""Generate code for adding nodes to the graph"""
|
206 |
+
code_lines = []
|
207 |
+
for node in nodes:
|
208 |
+
if node["name"] != "START":
|
209 |
+
code_lines.append(f' graph.add_node("{node["name"]}", self.nodes.{node["name"]}_node)')
|
210 |
+
return "\n".join(code_lines)
|
211 |
+
|
212 |
+
@staticmethod
|
213 |
+
def _generate_conditional_edges_code(nodes):
|
214 |
+
"""Generate code for adding conditional edges to the graph"""
|
215 |
+
code_lines = []
|
216 |
+
for node in nodes:
|
217 |
+
if len(node['connections']) > 1:
|
218 |
+
destinations = ", ".join([f'{conn}: {conn}' if conn in ["START", "END"] else f'"{conn}": "{conn}"' for conn in node['connections']])
|
219 |
+
code_lines.append(f''' graph.add_conditional_edges(
|
220 |
+
"{node["name"]}",
|
221 |
+
self.edges.{node["name"]}_edge,
|
222 |
+
{{
|
223 |
+
{destinations}
|
224 |
+
}}
|
225 |
+
)''')
|
226 |
+
return "\n".join(code_lines) if code_lines else ""
|
227 |
+
|
228 |
+
@staticmethod
|
229 |
+
def _generate_regular_edges_code(nodes):
|
230 |
+
"""Generate code for adding regular edges to the graph"""
|
231 |
+
code_lines = []
|
232 |
+
for node in nodes:
|
233 |
+
if len(node['connections']) == 1:
|
234 |
+
start_key = node["name"] if node["name"] in ["START", "END"] else f'"{node["name"]}"'
|
235 |
+
end_key = node["connections"][0] if node["connections"][0] in ["START", "END"] else f'"{node["connections"][0]}"'
|
236 |
+
code_lines.append(f' graph.add_edge({start_key}, {end_key})')
|
237 |
+
return "\n".join(code_lines) if code_lines else ""
|
238 |
+
|
239 |
+
@staticmethod
|
240 |
+
def _create_test_file(agent_name: str):
|
241 |
+
"""Create the test.py file
|
242 |
+
|
243 |
+
Args:
|
244 |
+
agent_name: Name of the agent
|
245 |
+
"""
|
246 |
+
test_file_content = f'''# Test file for {agent_name} agent
|
247 |
+
from graph import GraphBuilder
|
248 |
+
|
249 |
+
def test_agent():
|
250 |
+
"""
|
251 |
+
Test the {agent_name} agent functionality.
|
252 |
+
"""
|
253 |
+
# Create the graph
|
254 |
+
builder = GraphBuilder()
|
255 |
+
graph = builder.build_agent_graph()
|
256 |
+
|
257 |
+
# TODO: Add test code here
|
258 |
+
print("Testing {agent_name} agent...")
|
259 |
+
|
260 |
+
# Example test
|
261 |
+
# result = graph.invoke({{"input": "Test input"}})
|
262 |
+
# print(f"Result: {{result}}")
|
263 |
+
|
264 |
+
if __name__ == "__main__":
|
265 |
+
test_agent()
|
266 |
+
'''
|
267 |
+
|
268 |
+
# Write to file
|
269 |
+
test_file_path = Path(f"agents/{agent_name}/test.py")
|
270 |
+
with open(test_file_path, 'w') as f:
|
271 |
+
f.write(test_file_content)
|
272 |
+
|
273 |
+
@staticmethod
|
274 |
+
def _create_puml_file(agent_name: str, design_data: Dict[str, List[Dict[str, Any]]]):
|
275 |
+
"""Create the design.puml file for diagram visualization
|
276 |
+
|
277 |
+
Args:
|
278 |
+
agent_name: Name of the agent
|
279 |
+
design_data: The validated design data
|
280 |
+
"""
|
281 |
+
nodes = design_data['nodes']
|
282 |
+
|
283 |
+
# Start the PlantUML content
|
284 |
+
puml_content = f'''@startuml {agent_name}
|
285 |
+
!define NOT_IMPLEMENTED_NODE_COLOR #IndianRed
|
286 |
+
!define IMPLEMENTED_NODE_COLOR #Gold
|
287 |
+
!define TESTED_NODE_COLOR #LawnGreen
|
288 |
+
!define TERMINAL_NODE_COLOR #DodgerBlue
|
289 |
+
|
290 |
+
'''
|
291 |
+
|
292 |
+
# Add node descriptions
|
293 |
+
for node in nodes:
|
294 |
+
puml_content += f'node {node["name"]} {node["status"]}_NODE_COLOR[\n {node["description"]}\n]\n\n'
|
295 |
+
puml_content += f'node END TERMINAL_NODE_COLOR[\n This is the final Node !\n]\n\n'
|
296 |
+
|
297 |
+
# Add connections
|
298 |
+
for node in nodes:
|
299 |
+
node_name = node["name"]
|
300 |
+
for connection in node["connections"]:
|
301 |
+
if connection == "END":
|
302 |
+
puml_content += f'{node_name} --> END\n'
|
303 |
+
else:
|
304 |
+
puml_content += f'{node_name} --> {connection}\n'
|
305 |
+
|
306 |
+
# End the PlantUML content
|
307 |
+
puml_content += '\n@enduml'
|
308 |
+
|
309 |
+
# Write to file
|
310 |
+
puml_file_path = Path(f"agents/{agent_name}/design.puml")
|
311 |
+
with open(puml_file_path, 'w') as f:
|
312 |
+
f.write(puml_content)
|
313 |
+
|
314 |
+
@staticmethod
|
315 |
+
def validate(agent_name: str):
|
316 |
+
pass
|
317 |
+
|
318 |
+
|
319 |
+
if __name__ == "__main__":
|
320 |
+
# AgentBuilder.initialize("universal_solver")
|
321 |
+
AgentBuilder.setup("universal_solver")
|
agent_builder_template/design_puml.txt
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@startuml universal_solver
|
2 |
+
!define NOT_IMPLEMENTED_NODE_COLOR #IndianRed
|
3 |
+
!define IMPLEMENTED_NODE_COLOR #Gold
|
4 |
+
!define TESTED_NODE_COLOR #LawnGreen
|
5 |
+
!define TERMINAL_NODE_COLOR #DodgerBlue
|
6 |
+
|
7 |
+
>>>>>NODES<<<<<
|
8 |
+
|
9 |
+
node END TERMINAL_NODE_COLOR[
|
10 |
+
This is the final Node !
|
11 |
+
]
|
12 |
+
|
13 |
+
>>>>>EDGES<<<<<
|
14 |
+
|
15 |
+
@enduml
|
agent_builder_template/design_yaml.txt
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
nodes:
|
2 |
+
- name: START
|
3 |
+
connections:
|
4 |
+
- example_node
|
5 |
+
description: This is the mandatory initial node `START` !
|
6 |
+
status: TERMINAL
|
7 |
+
|
8 |
+
- name: example_node
|
9 |
+
connections: [END]
|
10 |
+
description: This is an example node
|
11 |
+
status: NOT_IMPLEMENTED
|
agent_builder_template/graph.txt
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
class State:
|
2 |
+
"""
|
3 |
+
State class for the agent graph.
|
4 |
+
"""
|
5 |
+
# TODO: Define state structure
|
6 |
+
pass
|
7 |
+
|
8 |
+
|
9 |
+
class Nodes:
|
10 |
+
"""
|
11 |
+
Collection of node functions for the agent graph.
|
12 |
+
"""
|
13 |
+
>>>>>NODE_METHODS<<<<<
|
14 |
+
|
15 |
+
|
16 |
+
|
17 |
+
class Edges:
|
18 |
+
"""
|
19 |
+
Collection of conditional edge functions for the agent graph.
|
20 |
+
"""
|
21 |
+
>>>>>CONDITIONAL_EDGE_METHODS<<<<<
|
agent_builder_template/graph_builder.txt
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Dict, Any
|
2 |
+
from langgraph.graph import StateGraph, END, START
|
3 |
+
from langgraph.graph.state import CompiledStateGraph
|
4 |
+
|
5 |
+
|
6 |
+
class GraphBuilder:
|
7 |
+
def __init__(self):
|
8 |
+
"""
|
9 |
+
Initializes the GraphBuilder.
|
10 |
+
"""
|
11 |
+
self.nodes = Nodes()
|
12 |
+
self.edges = Edges()
|
13 |
+
# TODO: Implement the desired constructor.
|
14 |
+
pass
|
15 |
+
|
16 |
+
def build_agent_graph(self) -> CompiledStateGraph:
|
17 |
+
"""Build and return the agent graph."""
|
18 |
+
graph = StateGraph(State)
|
19 |
+
|
20 |
+
>>>>>NODES<<<<<
|
21 |
+
|
22 |
+
>>>>>EDGES<<<<<
|
23 |
+
|
24 |
+
return graph.compile()
|
agent_builder_template/test.txt
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
from graph import State, Nodes, Edges
|
2 |
+
from graph_builder import GraphBuilder
|
agents/universal_solver/design.puml
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@startuml universal_solver
|
2 |
+
!define NOT_IMPLEMENTED_NODE_COLOR #IndianRed
|
3 |
+
!define IMPLEMENTED_NODE_COLOR #Gold
|
4 |
+
!define TESTED_NODE_COLOR #LawnGreen
|
5 |
+
!define TERMINAL_NODE_COLOR #DodgerBlue
|
6 |
+
|
7 |
+
node START TERMINAL_NODE_COLOR[
|
8 |
+
This is the mandatory initial node `START` !
|
9 |
+
]
|
10 |
+
|
11 |
+
node example_node_1 NOT_IMPLEMENTED_NODE_COLOR[
|
12 |
+
This is an example node
|
13 |
+
]
|
14 |
+
|
15 |
+
node example_node_2 IMPLEMENTED_NODE_COLOR[
|
16 |
+
This is another example node
|
17 |
+
]
|
18 |
+
|
19 |
+
node example_node_3 TESTED_NODE_COLOR[
|
20 |
+
This is yet another example node
|
21 |
+
]
|
22 |
+
|
23 |
+
node END TERMINAL_NODE_COLOR[
|
24 |
+
This is the final Node !
|
25 |
+
]
|
26 |
+
|
27 |
+
START --> example_node_1
|
28 |
+
example_node_1 --> example_node_2
|
29 |
+
example_node_2 --> example_node_3
|
30 |
+
example_node_3 --> END
|
31 |
+
|
32 |
+
@enduml
|
agents/universal_solver/design.yaml
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
nodes:
|
2 |
+
- name: START
|
3 |
+
connections:
|
4 |
+
- example_node_1
|
5 |
+
description: This is the mandatory initial node `START` !
|
6 |
+
status: TERMINAL
|
7 |
+
|
8 |
+
- name: example_node_1
|
9 |
+
connections: [example_node_2]
|
10 |
+
description: This is an example node
|
11 |
+
status: NOT_IMPLEMENTED
|
12 |
+
|
13 |
+
- name: example_node_2
|
14 |
+
connections: [example_node_3]
|
15 |
+
description: This is another example node
|
16 |
+
status: IMPLEMENTED
|
17 |
+
|
18 |
+
- name: example_node_3
|
19 |
+
connections: [END]
|
20 |
+
description: This is yet another example node
|
21 |
+
status: TESTED
|
agents/universal_solver/graph.py
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Dict, Any
|
2 |
+
from langgraph.graph import StateGraph, END, START
|
3 |
+
from langgraph.graph.state import CompiledStateGraph
|
4 |
+
|
5 |
+
|
6 |
+
class State:
|
7 |
+
"""
|
8 |
+
State class for the agent graph.
|
9 |
+
"""
|
10 |
+
# TODO: Define state structure
|
11 |
+
pass
|
12 |
+
|
13 |
+
|
14 |
+
class Nodes:
|
15 |
+
"""
|
16 |
+
Collection of node functions for the agent graph.
|
17 |
+
"""
|
18 |
+
|
19 |
+
def example_node_1_node(self, state):
|
20 |
+
"""
|
21 |
+
This is an example node
|
22 |
+
"""
|
23 |
+
# TODO: To implement...
|
24 |
+
pass
|
25 |
+
|
26 |
+
def example_node_2_node(self, state):
|
27 |
+
"""
|
28 |
+
This is another example node
|
29 |
+
"""
|
30 |
+
# TODO: To implement...
|
31 |
+
pass
|
32 |
+
|
33 |
+
def example_node_3_node(self, state):
|
34 |
+
"""
|
35 |
+
This is yet another example node
|
36 |
+
"""
|
37 |
+
# TODO: To implement...
|
38 |
+
pass
|
39 |
+
|
40 |
+
|
41 |
+
|
42 |
+
class Edges:
|
43 |
+
"""
|
44 |
+
Collection of conditional edge functions for the agent graph.
|
45 |
+
"""
|
46 |
+
|
47 |
+
|
48 |
+
|
49 |
+
class GraphBuilder:
|
50 |
+
def __init__(self):
|
51 |
+
"""
|
52 |
+
Initializes the GraphBuilder.
|
53 |
+
"""
|
54 |
+
self.nodes = Nodes()
|
55 |
+
self.edges = Edges()
|
56 |
+
# TODO: Implement the desired constructor.
|
57 |
+
pass
|
58 |
+
|
59 |
+
def build_agent_graph(self) -> CompiledStateGraph:
|
60 |
+
"""Build and return the agent graph."""
|
61 |
+
graph = StateGraph(State)
|
62 |
+
|
63 |
+
# Add all nodes
|
64 |
+
graph.add_node("example_node_1", self.nodes.example_node_1_node)
|
65 |
+
graph.add_node("example_node_2", self.nodes.example_node_2_node)
|
66 |
+
graph.add_node("example_node_3", self.nodes.example_node_3_node)
|
67 |
+
|
68 |
+
# Add edges
|
69 |
+
graph.add_edge(START, "example_node_1")
|
70 |
+
graph.add_edge("example_node_1", "example_node_2")
|
71 |
+
graph.add_edge("example_node_2", "example_node_3")
|
72 |
+
graph.add_edge("example_node_3", END)
|
73 |
+
|
74 |
+
return graph.compile()
|
agents/universal_solver/test.py
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Test file for universal_solver agent
|
2 |
+
from graph import GraphBuilder
|
3 |
+
|
4 |
+
def test_agent():
|
5 |
+
"""
|
6 |
+
Test the universal_solver agent functionality.
|
7 |
+
"""
|
8 |
+
# Create the graph
|
9 |
+
builder = GraphBuilder()
|
10 |
+
graph = builder.build_agent_graph()
|
11 |
+
|
12 |
+
# TODO: Add test code here
|
13 |
+
print("Testing universal_solver agent...")
|
14 |
+
|
15 |
+
# Example test
|
16 |
+
# result = graph.invoke({"input": "Test input"})
|
17 |
+
# print(f"Result: {result}")
|
18 |
+
|
19 |
+
if __name__ == "__main__":
|
20 |
+
test_agent()
|