Розробка AI-системи генерації коду
AI-система генерації коду автономно створює production-готовий код за текстовим описом або специфікацією. Включає розуміння вимог, генерацію з урахуванням існуючої кодової бази, запуск тестів та ітеративне вдосконалення. Архітектурно складніша, ніж одиничний виклик LLM — потребує керування контекстом коду, верифікації результату та інтеграції в CI/CD.
Архітектура системи
Context Manager — збір релевантного контексту: схема БД, API-інтерфейси, існуючі моделі, guide стилю коду.
Generation Engine — LLM-агент з інструментами для читання файлів, виконання тестів, пошуку по кодовій базі.
Verification Layer — перевірка синтаксису, запуск тестів, лінтер.
Feedback Loop — ітерації на основі помилок тестів.
Агент генерації коду
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from typing import TypedDict, Annotated, Optional
import subprocess
import ast
import operator
llm = ChatOpenAI(model="claude-opus-4-5", temperature=0.1)
class CodeGenState(TypedDict):
task_description: str
existing_code_context: str
generated_code: Optional[str]
test_results: Annotated[list, operator.add]
iteration: int
max_iterations: int
errors: Annotated[list, operator.add]
final_code: Optional[str]
@tool
def read_file(file_path: str) -> str:
"""Прочитати файл з кодової бази для отримання контексту."""
try:
with open(file_path) as f:
return f.read()
except FileNotFoundError:
return f"Файл {file_path} не знайдено"
@tool
def search_codebase(query: str, directory: str = "./src") -> str:
"""Пошук по кодовій базі за допомогою grep для знаходження подібного коду."""
result = subprocess.run(
["grep", "-r", "--include=*.py", "-n", query, directory],
capture_output=True, text=True
)
return result.stdout[:3000] if result.stdout else "Нічого не знайдено"
@tool
def run_python_syntax_check(code: str) -> str:
"""Перевірити синтаксис Python-коду."""
try:
ast.parse(code)
return "Синтаксис коректен"
except SyntaxError as e:
return f"Синтаксична помилка: {e}"
@tool
def run_tests(test_file_path: str) -> str:
"""Запустити pytest тести та повернути результати."""
result = subprocess.run(
["python", "-m", "pytest", test_file_path, "-v", "--tb=short"],
capture_output=True, text=True, timeout=60
)
output = result.stdout + result.stderr
return output[-3000:] # Останніх 3000 символів
@tool
def write_file(file_path: str, content: str) -> str:
"""Записати код у файл."""
with open(file_path, "w", encoding="utf-8") as f:
f.write(content)
return f"Файл {file_path} записано ({len(content)} символів)"
CODE_GEN_SYSTEM = """Ти — Senior Software Engineer. Генеруй production-якісний код.
Принципи:
- Дотримуйся існуючих паттернів кодової бази
- Пиши типізований код (type hints)
- Кожна функція — один рівень абстракції
- Обробляй помилки явно
- Мінімальні залежності від зовнішніх бібліотек, якщо є стандартні аналоги
Процес:
1. Читай існуючий код для контексту
2. Генеруй код відповідного стилю
3. Перевірь синтаксис
4. Запусти тести
5. Ітеративно виправляй помилки"""
from langgraph.prebuilt import create_react_agent
code_gen_agent = create_react_agent(
llm.bind_tools([read_file, search_codebase, run_python_syntax_check, run_tests, write_file]),
tools=[read_file, search_codebase, run_python_syntax_check, run_tests, write_file],
state_modifier=CODE_GEN_SYSTEM,
)
Генерація з контекстом кодової бази
class ContextAwareCodeGenerator:
def __init__(self, project_root: str):
self.project_root = project_root
self.context_cache = {}
async def gather_context(self, task: str) -> str:
"""Збирає релевантний контекст для задачі"""
# Пошук подібних файлів через LLM
relevant_files = await self.identify_relevant_files(task)
context_parts = []
# Читаємо схему БД
if await self.file_exists("models.py"):
models = await read_file_async(f"{self.project_root}/models.py")
context_parts.append(f"## Моделі даних\n{models[:2000]}")
# Читаємо базові класи та інтерфейси
for file_path in relevant_files[:3]:
content = await read_file_async(file_path)
context_parts.append(f"## {file_path}\n{content[:1500]}")
# Додаємо code style guide
if await self.file_exists(".codestyle.md"):
style = await read_file_async(f"{self.project_root}/.codestyle.md")
context_parts.append(f"## Code Style\n{style[:1000]}")
return "\n\n".join(context_parts)
async def generate(self, task: str, output_file: str) -> dict:
context = await self.gather_context(task)
result = await code_gen_agent.ainvoke({
"messages": [{
"role": "user",
"content": f"""Задача: {task}
Контекст кодової бази:
{context}
Вихідний файл: {output_file}
Згенеруй код, перевір його та запиши у файл."""
}]
})
return {
"task": task,
"output_file": output_file,
"iterations": result.get("iteration", 1),
"tests_passed": self.extract_test_status(result),
}
Генерація на основі шаблонів з LLM-заповненням
class CRUDGenerator:
"""Генерує CRUD-модулі по схемі сутності"""
CRUD_TEMPLATE = """
# Модуль для роботи з сутністю {entity_name}
from sqlalchemy import Column, Integer, String, DateTime, func
from sqlalchemy.orm import Session
from pydantic import BaseModel
from typing import Optional, List
from datetime import datetime
# ЗАГЛУШКИ ДЛЯ ЗАМЕНИ LLM:
# COLUMNS - список колонок SQLAlchemy
# PYDANTIC_FIELDS - поля Pydantic схем
# BUSINESS_LOGIC - специфічна бізнес-логіка
"""
async def generate_crud_module(self, entity_spec: dict) -> str:
"""entity_spec: {name, fields, business_rules, relationships}"""
# LLM заповнює специфічні частини
columns = await self.generate_sqlalchemy_columns(entity_spec["fields"])
schemas = await self.generate_pydantic_schemas(entity_spec["fields"])
business_logic = await self.generate_business_logic(entity_spec.get("business_rules", []))
# Збираємо итоговий модуль
result = await llm.ainvoke(f"""Створи повний CRUD-модуль для сутності {entity_spec['name']}.
Специфікація: {json.dumps(entity_spec, ensure_ascii=False)}
Стек: FastAPI + SQLAlchemy 2.0 + Pydantic v2
Включи: модель, pydantic схеми, CRUD-функції, FastAPI роутер з dependency injection
Стандарти коду: async/await, type hints, docstrings""")
return result.content
Практичний кейс: автоматизація у фінтех-стартапі
Задача: команда з 4 розробників створювала 3–5 нових API-ендпоінтів на тиждень. Кожен CRUD-ендпоінт з тестами займав 4–6 годин.
AI Code Generation:
- Генерація CRUD-модулів з OpenAPI-специфікації
- Автоматична генерація pytest-тестів для ендпоінтів
- Генерація міграцій Alembic при змінах моделей
- Suggestions для код-ревью через AI Code Review агент
Результати:
- Час створення стандартного CRUD-ендпоінту: 5ч → 50 хв (15 хв генерація + 35 хв ревью)
- Test coverage нових ендпоінтів: 45% → 82%
- Одноманітність коду: значно виросла (всі дотримуються одного паттерну)
- Виклики у системи: 14% PR потребували суттєвої доробки бізнес-логіки
Терміни
- Базовий генератор з контекстом: 2–3 тижні
- Агентний цикл з тестами та ітераціями: 2–3 тижні
- Інтеграція в CI/CD та IDE: 2–3 тижні
- Всього: 6–9 тижнів







