Переделываю систему под агента-планировщика

This commit is contained in:
ki.sagidullin
2026-04-12 09:27:07 +05:00
parent ee6d12c5fb
commit 8f16a6d669
7 changed files with 255 additions and 35 deletions

View File

@@ -1,5 +1,5 @@
# orchestrator.py
from typing import Dict, Any, Literal
from typing import Dict, Any, Literal, TypedDict, List
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.memory import MemorySaver
import uuid
@@ -8,6 +8,14 @@ from models import Task, TaskStatus, CodeSolution, ReviewResult, IterationRecord
from agent import DeveloperAgent, ReviewerAgent
from config import MAX_REVIEW_RETRIES
class AgentState(TypedDict):
task: str
plan: List[Dict]
execution_results: List[Dict]
review: Dict
iteration: int
max_iterations: int
class Orchestrator:
"""Оркестратор - управляет процессом разработки"""
@@ -19,7 +27,6 @@ class Orchestrator:
# Создаем граф состояний
self.workflow = self._build_workflow()
self.checkpointer = MemorySaver()
self.app = self.workflow.compile()
def _add_history(self, task: Task, agent: str, action: str,
input_summary: str = None, output_summary: str = None,
@@ -37,36 +44,72 @@ class Orchestrator:
)
task.history.append(record)
def _build_workflow(self) -> StateGraph:
def _build_workflow(self):
"""Строит граф процесса разработки"""
# Определяем состояния
workflow = StateGraph(Dict)
workflow = StateGraph(AgentState)
# Добавляем узлы
workflow.add_node("developer", self._developer_node)
workflow.add_node("reviewer", self._reviewer_node)
workflow.add_node("finalize", self._finalize_node)
workflow.add_node("planner", self._plan_node)
workflow.add_node("executor", self._exec_node)
workflow.add_node("reviewer", self._review_node)
# Определяем переходы
workflow.set_entry_point("developer")
workflow.add_edge("developer", "reviewer")
workflow.set_entry_point("planner")
workflow.add_edge("planner", "executor")
workflow.add_edge("executor", "reviewer")
# Условные переходы после ревью
workflow.add_conditional_edges(
"reviewer",
self._decide_next_step,
{
"approved": "finalize",
"rework": "developer",
"rejected": "finalize",
"failed": "finalize"
}
)
workflow.add_conditional_edges("reviewer", self._after_review, {
"approved": END,
"rework": "executor", # повторить выполнение с тем же планом? или перепланировать?
"replan": "planner",
"reject": END
})
workflow.add_edge("finalize", END)
return workflow.compile()
def _plan_node(self, state: AgentState):
print(f"\n🔧 [Iteration {state.get('iteration', 0)}] Планировщик начал работу...")
# Сначала получим описания инструментов для планировщика
tools_desc = [{"name": t.name, "description": t.description, "args": t.args} for t in self.tools]
plan = self.planner.create_plan(state["task"], tools_desc)
state["plan"] = plan
return state
def _exec_node(self, state: AgentState):
"""Узел разработчика"""
print(f"\n🔧 [Iteration {state.get('iteration', 0)}] Исполнитель начал работу...")
return workflow
# Логируем начало работы разработчика
results = self.executor.execute_plan(state["plan"])
state["execution_results"] = results
return state
def _review_node(self, state: AgentState):
print(f"\n🔧 [Iteration {state.get('iteration', 0)}] Ревьювер начал работу...")
review = self.reviewer.review(state["task"], state["plan"], state["execution_results"])
state["review"] = review
state["iteration"] = state.get("iteration", 0) + 1
return state
def _after_review(self, state: AgentState):
status = state["review"].get("status")
if status == "approved":
return "approved"
elif status == "changes_requested":
if state["iteration"] >= state.get("max_iterations", 3):
return "reject"
# пробуем перевыполнить те же шаги (может, ошибка временная)
return "rework"
elif status == "rejected":
if state["iteration"] >= state.get("max_iterations", 3):
return "reject"
# нужен новый план
return "replan"
else:
return "reject"
def _developer_node(self, state: Dict) -> Dict:
"""Узел разработчика"""
@@ -244,26 +287,26 @@ class Orchestrator:
f.write(test_content)
print(f" 💾 Сохранен тест: {testpath}")
def run(self, requirement: str, task_id: str = None) -> Dict:
def run(self, task: str, max_iterations:int = None) -> Dict:
"""Запускает процесс разработки"""
if not task_id:
task_id = str(uuid.uuid4())
task_id = str(uuid.uuid4())
initial_task = Task(
id=task_id,
requirement=requirement,
status=TaskStatus.PENDING,
iteration=0
)
initial_state = {
"task": task,
"plan": [],
"execution_results": [],
"review": {},
"iteration": 0,
"max_iterations": max_iterations
}
print(f"\n🚀 Запуск мультиагентной системы")
print(f"📝 Задача: {requirement}")
print(f"📝 Задача: {task}")
print(f"🆔 ID: {task_id}")
# Запускаем граф
initial_state = {"task": initial_task}
final_state = self.app.invoke(initial_state)
final_state = self.workflow.invoke(initial_state)
return final_state