Разработка AI-системы генерации кода
AI-система генерации кода автономно создаёт production-готовый код по текстовому описанию или спецификации. Включает понимание требований, генерацию с учётом существующей кодовой базы, запуск тестов и итеративное улучшение. Архитектурно сложнее, чем однократный вызов LLM — требует управления контекстом кода, верификации результата и интеграции в CI/CD.
Архитектура системы
Context Manager — сбор релевантного контекста: схема БД, API-интерфейсы, существующие модели, code style guide.
Generation Engine — LLM-агент с инструментами для чтения файлов, выполнения тестов, поиска по кодовой базе.
Verification Layer — синтаксическая проверка, запуск тестов, линтер.
Feedback Loop — итерации на основе ошибок тестов.
Code Generation агент
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-quality код.
Принципы:
- Следуй существующим паттернам кодовой базы
- Пиши типизированный код (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),
}
Template-based генерация с 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 недель







