Итерация 3, финальная
This commit is contained in:
141
orchestrator.py
141
orchestrator.py
@@ -7,13 +7,16 @@ from datetime import datetime
|
||||
from models import Task, TaskStatus, CodeSolution, ReviewResult, IterationRecord
|
||||
from agent.developer import DeveloperAgent
|
||||
from agent.reviewer import ReviewerAgent
|
||||
from config import MAX_REVIEW_RETRIES
|
||||
from agent.planner import PlannerAgent
|
||||
from agent.executor import ExecutorAgent
|
||||
from agent.plan_reviewer import PlanReviewerAgent
|
||||
from tool.filesystem import read_file, write_file, delete_lines, replace_text_in_file, search_in_files
|
||||
|
||||
class AgentState(TypedDict):
|
||||
task: Task
|
||||
plan: Dict
|
||||
plan: List[Dict]
|
||||
execution_results: List[Dict]
|
||||
review: Optional[ReviewResult]
|
||||
review: Dict
|
||||
iteration: int
|
||||
max_iterations: int
|
||||
|
||||
@@ -23,7 +26,14 @@ class Orchestrator:
|
||||
def __init__(self):
|
||||
self.developer = DeveloperAgent()
|
||||
self.reviewer = ReviewerAgent()
|
||||
self.max_retries = MAX_REVIEW_RETRIES
|
||||
self.planner = PlannerAgent()
|
||||
self.plan_reviewer = PlanReviewerAgent()
|
||||
|
||||
# Инструменты для ExecutorAgent
|
||||
self.tools = [read_file, write_file, delete_lines, replace_text_in_file, search_in_files]
|
||||
self.executor = ExecutorAgent(self.tools)
|
||||
|
||||
self.max_retries = 3
|
||||
|
||||
# Создаем граф состояний
|
||||
self.workflow = self._build_workflow()
|
||||
@@ -84,46 +94,40 @@ class Orchestrator:
|
||||
details={}
|
||||
))
|
||||
|
||||
# План просто содержит задачу - разработчик выполнит её напрямую
|
||||
plan = {"task": task.requirement, "iteration": task.iteration}
|
||||
# Описываем доступные инструменты для планировщика
|
||||
tools_desc = [
|
||||
{"name": "read_file", "description": "Прочитать файл", "args": ["path", "start_line", "end_line"]},
|
||||
{"name": "write_file", "description": "Записать файл", "args": ["path", "content"]},
|
||||
{"name": "delete_lines", "description": "Удалить строки", "args": ["path", "start_line", "end_line"]},
|
||||
{"name": "replace_text_in_file", "description": "Заменить текст", "args": ["path", "old", "new"]},
|
||||
{"name": "search_in_files", "description": "Поиск в файлах", "args": ["directory", "pattern", "file_pattern"]}
|
||||
]
|
||||
|
||||
# Создаем план
|
||||
plan = self.planner.create_plan(task.requirement, tools_desc)
|
||||
state["plan"] = plan
|
||||
|
||||
print(f"📋 План создан: {len(plan)} шагов")
|
||||
return state
|
||||
|
||||
def _exec_node(self, state: AgentState):
|
||||
"""Узел разработчика"""
|
||||
"""Узел исполнителя"""
|
||||
task = state["task"]
|
||||
print(f"\n🔧 [Iteration {task.iteration}] Исполнитель начал работу...")
|
||||
print(f"\n🔨 [Iteration {task.iteration}] Исполнитель начал работу...")
|
||||
|
||||
# Обновляем статус
|
||||
task.status = TaskStatus.DEVELOPMENT
|
||||
|
||||
# Разработчик выполняет задачу напрямую
|
||||
solution = self.developer.develop(task, [])
|
||||
task.solution = solution
|
||||
task.status = TaskStatus.REVIEW
|
||||
# Выполняем план через ExecutorAgent
|
||||
results = self.executor.execute_plan(state["plan"])
|
||||
state["execution_results"] = results
|
||||
|
||||
# Записываем результат выполнения
|
||||
state["execution_results"] = [{"status": "success", "solution": solution}]
|
||||
success_count = sum(1 for r in results if r.get("success", False))
|
||||
print(f"✅ Выполнено шагов: {success_count}/{len(results)}")
|
||||
|
||||
# Добавляем запись в историю
|
||||
task.history.append(IterationRecord(
|
||||
iteration=task.iteration,
|
||||
timestamp=datetime.now().isoformat(),
|
||||
agent="developer",
|
||||
action="complete",
|
||||
output_summary=f"Generated {len(solution.files)} file(s), {len(solution.tests)} test(s)",
|
||||
details={
|
||||
"files": list(solution.files.keys()),
|
||||
"tests": list(solution.tests.keys())
|
||||
}
|
||||
))
|
||||
|
||||
print(f"✅ Разработчик создал решение: {len(solution.files)} файлов")
|
||||
return state
|
||||
|
||||
def _review_node(self, state: AgentState):
|
||||
task = state["task"]
|
||||
print(f"\n🔍 [Iteration {task.iteration}] Ревьювер начал работу...")
|
||||
print(f"\n🔍 [Iteration {task.iteration}] План-ревьювер начал работу...")
|
||||
|
||||
# Добавляем запись о начале ревью
|
||||
task.history.append(IterationRecord(
|
||||
@@ -131,47 +135,41 @@ class Orchestrator:
|
||||
timestamp=datetime.now().isoformat(),
|
||||
agent="reviewer",
|
||||
action="start",
|
||||
input_summary=f"Reviewing {len(task.solution.files) if task.solution else 0} file(s)",
|
||||
input_summary=f"Reviewing plan with {len(state['plan'])} steps",
|
||||
details={}
|
||||
))
|
||||
|
||||
if not task.solution:
|
||||
task.status = TaskStatus.FAILED
|
||||
error_msg = "No solution to review"
|
||||
task.error_log.append(error_msg)
|
||||
task.history.append(IterationRecord(
|
||||
iteration=task.iteration,
|
||||
timestamp=datetime.now().isoformat(),
|
||||
agent="reviewer",
|
||||
action="error",
|
||||
error=error_msg
|
||||
))
|
||||
return state
|
||||
# Проводим ревью плана через PlanReviewerAgent
|
||||
review = self.plan_reviewer.review(task.requirement, state["plan"], state["execution_results"])
|
||||
state["review"] = review
|
||||
|
||||
# Проводим ревью
|
||||
review = self.reviewer.review(task, task.solution)
|
||||
task.last_review = review
|
||||
task.iteration += 1
|
||||
# Обновляем статус задачи
|
||||
if review.get("status") == "approved":
|
||||
task.status = TaskStatus.APPROVED
|
||||
elif review.get("status") == "changes_requested":
|
||||
task.status = TaskStatus.REWORK
|
||||
else:
|
||||
task.status = TaskStatus.FAILED
|
||||
|
||||
# Увеличиваем счётчик итераций
|
||||
state["iteration"] = state.get("iteration", 0) + 1
|
||||
|
||||
# Добавляем запись в историю
|
||||
task.history.append(IterationRecord(
|
||||
iteration=task.iteration - 1, # предыдущая итерация
|
||||
iteration=task.iteration,
|
||||
timestamp=datetime.now().isoformat(),
|
||||
agent="reviewer",
|
||||
action="complete",
|
||||
output_summary=f"Verdict: {review.status}, Comments: {len(review.comments)}",
|
||||
output_summary=f"Verdict: {review.get('status')}",
|
||||
details={
|
||||
"verdict": review.status,
|
||||
"comments_count": len(review.comments)
|
||||
"verdict": review.get("status"),
|
||||
"feedback": review.get("feedback", "")[:200]
|
||||
}
|
||||
))
|
||||
|
||||
# Сохраняем результат ревью
|
||||
state["review"] = review
|
||||
|
||||
print(f"📊 Вердикт: {review.status}")
|
||||
if review.comments:
|
||||
print(f" Найдено замечаний: {len(review.comments)}")
|
||||
print(f"📊 Вердикт: {review.get('status')}")
|
||||
if review.get("feedback"):
|
||||
print(f" Feedback: {review['feedback'][:100]}...")
|
||||
|
||||
return state
|
||||
|
||||
@@ -180,24 +178,18 @@ class Orchestrator:
|
||||
review = state["review"]
|
||||
|
||||
# Определяем статус
|
||||
if isinstance(review, ReviewResult):
|
||||
status = review.status
|
||||
elif isinstance(review, dict):
|
||||
status = review.get("status")
|
||||
else:
|
||||
status = None
|
||||
status = review.get("status") if isinstance(review, dict) else None
|
||||
|
||||
if status == "approved":
|
||||
task.status = TaskStatus.APPROVED
|
||||
return "approved"
|
||||
elif status == "changes_requested":
|
||||
if task.iteration >= state.get("max_iterations", 3):
|
||||
if state.get("iteration", 0) >= state.get("max_iterations", 3):
|
||||
task.status = TaskStatus.FAILED
|
||||
return "reject"
|
||||
task.status = TaskStatus.REWORK
|
||||
return "rework"
|
||||
elif status == "rejected":
|
||||
if task.iteration >= state.get("max_iterations", 3):
|
||||
if state.get("iteration", 0) >= state.get("max_iterations", 3):
|
||||
task.status = TaskStatus.FAILED
|
||||
return "reject"
|
||||
task.status = TaskStatus.REWORK
|
||||
@@ -243,9 +235,9 @@ class Orchestrator:
|
||||
|
||||
initial_state = {
|
||||
"task": task,
|
||||
"plan": {},
|
||||
"plan": [],
|
||||
"execution_results": [],
|
||||
"review": None,
|
||||
"review": {},
|
||||
"iteration": 0,
|
||||
"max_iterations": max_iterations
|
||||
}
|
||||
@@ -257,10 +249,8 @@ class Orchestrator:
|
||||
# Запускаем граф
|
||||
final_state = self.workflow.invoke(initial_state)
|
||||
|
||||
# Сохраняем решение если успешно
|
||||
# Обновляем итоговый статус в задаче
|
||||
final_task = final_state["task"]
|
||||
if final_task.status == TaskStatus.APPROVED and final_task.solution:
|
||||
self._save_solution(final_task.solution)
|
||||
|
||||
print("\n" + "="*50)
|
||||
print("📋 ИТОГИ РАБОТЫ")
|
||||
@@ -268,13 +258,6 @@ class Orchestrator:
|
||||
print(f"Статус: {final_task.status.value}")
|
||||
print(f"Итераций: {final_task.iteration}")
|
||||
|
||||
if final_task.status == TaskStatus.APPROVED:
|
||||
print(f"\n✅ Решение принято!")
|
||||
print(f" Файлов: {len(final_task.solution.files)}")
|
||||
print(f" Тестов: {len(final_task.solution.tests)}")
|
||||
elif final_task.last_review:
|
||||
print(f"\n📝 Финальный вердикт: {final_task.last_review.summary}")
|
||||
|
||||
if final_task.error_log:
|
||||
print(f"\n❌ Ошибки: {len(final_task.error_log)}")
|
||||
for error in final_task.error_log:
|
||||
|
||||
Reference in New Issue
Block a user