iFirst!
This commit is contained in:
160
agents.py
Normal file
160
agents.py
Normal file
@@ -0,0 +1,160 @@
|
||||
# agents.py
|
||||
from typing import Dict, Any
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langchain_core.messages import HumanMessage, SystemMessage
|
||||
from langchain_community.chat_models import ChatOllama
|
||||
import json
|
||||
from config import MODEL_NAME, TEMPERATURE
|
||||
from models import CodeSolution, ReviewResult, ReviewComment, Task
|
||||
|
||||
class DeveloperAgent:
|
||||
"""Агент-разработчик: генерирует код по требованию"""
|
||||
|
||||
def __init__(self):
|
||||
self.llm = ChatOllama(
|
||||
model=MODEL_NAME,
|
||||
temperature=TEMPERATURE,
|
||||
base_url="http://localhost:11434"
|
||||
)
|
||||
|
||||
def develop(self, task: Task, previous_comments: list = None) -> CodeSolution:
|
||||
"""Генерирует код на основе требования и замечаний"""
|
||||
|
||||
system_prompt = """Ты - опытный разработчик. Твоя задача - написать качественный код.
|
||||
Ты должен:
|
||||
1. Писать чистый, читаемый код с комментариями
|
||||
2. Добавлять обработку ошибок
|
||||
3. Писать юнит-тесты (pytest/unittest)
|
||||
4. Следовать PEP8 (для Python) или стандартам языка
|
||||
5. Возвращать решение в строго определённом JSON формате
|
||||
|
||||
В ответе должен быть JSON с полями:
|
||||
- files: dict (имя_файла -> содержимое)
|
||||
- description: str (описание решения)
|
||||
- tests: dict (имя_теста -> содержимое теста)
|
||||
"""
|
||||
|
||||
user_prompt = f"""
|
||||
Требование: {task.requirement}
|
||||
|
||||
Текущая итерация: {task.iteration}
|
||||
"""
|
||||
|
||||
if previous_comments:
|
||||
user_prompt += f"""
|
||||
|
||||
Замечания с предыдущего ревью:
|
||||
{json.dumps(previous_comments, indent=2, ensure_ascii=False)}
|
||||
|
||||
Пожалуйста, исправь код согласно замечаниям.
|
||||
"""
|
||||
|
||||
messages = [
|
||||
SystemMessage(content=system_prompt),
|
||||
HumanMessage(content=user_prompt)
|
||||
]
|
||||
|
||||
response = self.llm.invoke(messages)
|
||||
|
||||
# Парсим JSON ответ
|
||||
try:
|
||||
# Извлекаем JSON из ответа
|
||||
content = response.content
|
||||
# Находим JSON в тексте (между ```json и ``` или просто сам JSON)
|
||||
if "```json" in content:
|
||||
content = content.split("```json")[1].split("```")[0]
|
||||
elif "```" in content:
|
||||
content = content.split("```")[1].split("```")[0]
|
||||
|
||||
data = json.loads(content.strip())
|
||||
return CodeSolution(
|
||||
files=data.get("files", {}),
|
||||
description=data.get("description", ""),
|
||||
tests=data.get("tests", {})
|
||||
)
|
||||
except Exception as e:
|
||||
raise ValueError(f"Failed to parse developer response: {e}\nResponse: {response.content}")
|
||||
|
||||
class ReviewerAgent:
|
||||
"""Агент-ревьювер: проверяет качество кода"""
|
||||
|
||||
def __init__(self):
|
||||
self.llm = ChatOllama(
|
||||
model=MODEL_NAME,
|
||||
temperature=0.1,
|
||||
base_url="http://localhost:11434"
|
||||
)
|
||||
|
||||
def review(self, task: Task, solution: CodeSolution) -> ReviewResult:
|
||||
"""Проверяет код и возвращает замечания"""
|
||||
|
||||
system_prompt = """Ты - строгий ревьювер кода. Твоя задача:
|
||||
1. Проверить соответствие требованиям
|
||||
2. Найти логические ошибки и баги
|
||||
3. Оценить читаемость и стиль кода
|
||||
4. Проверить покрытие тестами
|
||||
5. Найти проблемы безопасности
|
||||
6. Предложить улучшения
|
||||
|
||||
Оценивай код критически. Будь конкретен в замечаниях, указывай файлы и строки.
|
||||
|
||||
Верни JSON с полями:
|
||||
- status: "approved", "changes_requested", или "rejected"
|
||||
- comments: массив объектов с полями: file, line, severity, text
|
||||
- summary: краткое резюме ревью
|
||||
"""
|
||||
|
||||
# Формируем представление кода для ревью
|
||||
code_for_review = ""
|
||||
for filename, content in solution.files.items():
|
||||
code_for_review += f"\n--- {filename} ---\n{content}\n"
|
||||
|
||||
if solution.tests:
|
||||
code_for_review += "\n--- TESTS ---\n"
|
||||
for testname, test_content in solution.tests.items():
|
||||
code_for_review += f"\n--- {testname} ---\n{test_content}\n"
|
||||
|
||||
user_prompt = f"""
|
||||
Требование: {task.requirement}
|
||||
|
||||
Код на ревью:
|
||||
{code_for_review}
|
||||
|
||||
Описание решения разработчика: {solution.description}
|
||||
|
||||
Проведи ревью. Будь строг, но справедлив.
|
||||
"""
|
||||
|
||||
messages = [
|
||||
SystemMessage(content=system_prompt),
|
||||
HumanMessage(content=user_prompt)
|
||||
]
|
||||
|
||||
response = self.llm.invoke(messages)
|
||||
|
||||
# Парсим JSON ответ
|
||||
try:
|
||||
content = response.content
|
||||
if "```json" in content:
|
||||
content = content.split("```json")[1].split("```")[0]
|
||||
elif "```" in content:
|
||||
content = content.split("```")[1].split("```")[0]
|
||||
|
||||
data = json.loads(content.strip())
|
||||
|
||||
comments = []
|
||||
for comment_data in data.get("comments", []):
|
||||
comments.append(ReviewComment(
|
||||
line=comment_data.get("line"),
|
||||
file=comment_data.get("file"),
|
||||
severity=comment_data.get("severity", "major"),
|
||||
text=comment_data.get("text", "")
|
||||
))
|
||||
|
||||
return ReviewResult(
|
||||
status=data.get("status", "changes_requested"),
|
||||
comments=comments,
|
||||
summary=data.get("summary", "")
|
||||
)
|
||||
except Exception as e:
|
||||
raise ValueError(f"Failed to parse reviewer response: {e}\nResponse: {response.content}")
|
||||
Reference in New Issue
Block a user