Генерация REST API из текстового описания: как это работает
Разработка API с нуля — процесс, где каждая ошибка в дизайне или моделях данных выливается в часы переписывания кода. Мы сталкивались с проектами, где команды тратили недели на создание CRUD и документации, а бизнес-логика оставалась незакрытой. Text-to-API решает это: вы описываете систему словами — мы генерируем готовый код на FastAPI или Express с тестами, Docker и документацией. Наш опыт показывает, что time-to-market сокращается в 3–5 раз, а затраты на шаблонный код — до 80%.
"Text-to-API экономит до 80% времени на CRUD-операциях" — из опыта наших проектов.
Проблемы, которые решает Text-to-API
Почему AI-генерация быстрее?
Ручное написание эндпоинтов, моделей данных, схем валидации и тестов занимает до 70% времени бэкенд-разработчика. AI берет на себя шаблонную работу: парсит описание, строит спецификацию OpenAPI, генерирует модели Pydantic, роутеры и тесты. Остается только бизнес-логика, которая действительно требует внимания.
Какие проблемы решаем?
- Дизайн API. Неверные URL, методы HTTP, статусы ответа — частая боль. AI следует REST-конвенциям: существительные во множественном числе, правильные коды (201 для POST, 204 для DELETE).
- Модели и схемы. Согласование типов полей, обязательности, вложенности. Генератор создает SQLAlchemy модели и Pydantic схемы с валидаторами.
- Тестирование. Автоматически генерируются pytest-тесты для каждого эндпоинта, покрывающие happy path, 404, валидацию входных данных. Тестовое покрытие достигает 70%.
Архитектура генератора и стек
В основе — языковые модели (Claude, GPT-4) с тонкой настройкой промптов через LangChain. Спецификация API парсится в Pydantic-модели, затем генерируется код. Используем структурный вывод: модель возвращает валидный JSON, который преобразуется в APISpec.
from anthropic import Anthropic
from pathlib import Path
import json
from pydantic import BaseModel
from typing import Literal, Optional
client = Anthropic()
class APIEndpoint(BaseModel):
method: Literal["GET", "POST", "PUT", "PATCH", "DELETE"]
path: str
summary: str
request_body: Optional[dict] = None
response_schema: dict
auth_required: bool = True
query_params: list[dict] = []
class APISpec(BaseModel):
title: str
description: str
version: str
base_path: str
endpoints: list[APIEndpoint]
entities: list[dict]
class TextToAPIGenerator:
def parse_description(self, description: str) -> APISpec:
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=4096,
system="""Ты — API-архитектор. Парсишь описание системы в структуру REST API.
Правила REST:
- Существительные в URL (не глаголы): /users, /orders
- Правильные HTTP методы: GET=чтение, POST=создание, PUT=полная замена, PATCH=частичное обновление, DELETE=удаление
- Вложенность максимум 2 уровня: /users/{id}/orders
- Plural для коллекций: /products, /categories
- Пагинация: ?page=1&limit=20
- Фильтрация: ?status=active&created_after=2024-01-01""",
messages=[{
"role": "user",
"content": f"""Разбери описание и верни JSON спецификацию API:
{{
"title": "...",
"description": "...",
"version": "1.0.0",
"base_path": "/api/v1",
"entities": [
{{"name": "...", "fields": [{{"name": "...", "type": "...", "required": true}}]}}
],
"endpoints": [
{{
"method": "GET|POST|PUT|PATCH|DELETE",
"path": "/resource/{{id}}",
"summary": "...",
"auth_required": true,
"request_body": {{"field": "type"}},
"response_schema": {{"id": "int", "name": "str"}},
"query_params": [{{"name": "...", "type": "...", "required": false}}]
}}
]
}}
Описание системы:
{description}"""
}]
)
text = response.content[0].text
start = text.find("{")
end = text.rfind("}") + 1
data = json.loads(text[start:end])
return APISpec(**data)
def generate_fastapi_code(self, spec: APISpec) -> dict[str, str]:
files = {}
files["models.py"] = self._generate_models(spec)
files["schemas.py"] = self._generate_schemas(spec)
for entity in spec.entities:
router_code = self._generate_router(entity, spec)
files[f"routers/{entity['name'].lower()}.py"] = router_code
files["main.py"] = self._generate_main(spec)
for entity in spec.entities:
test_code = self._generate_tests(entity, spec)
files[f"tests/test_{entity['name'].lower()}.py"] = test_code
return files
def _generate_models(self, spec: APISpec) -> str:
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=4096,
messages=[{
"role": "user",
"content": f"""Создай SQLAlchemy 2.0 модели для сущностей:
Сущности:
{json.dumps(spec.entities, ensure_ascii=False, indent=2)}
Требования:
- Используй DeclarativeBase
- Добавь id (Integer PK autoincrement), created_at, updated_at для всех моделей
- Используй правильные типы: String(256), Text, Integer, Float, Boolean, DateTime
- Добавь __tablename__
- Добавь relationship() для связей между моделями
- Добавь __repr__ для дебага
Верни только Python код."""
}]
)
return response.content[0].text.strip()
def _generate_schemas(self, spec: APISpec) -> str:
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=4096,
messages=[{
"role": "user",
"content": f"""Создай Pydantic v2 схемы для валидации:
Сущности: {json.dumps(spec.entities, ensure_ascii=False)}
Endpoints: {json.dumps([e.dict() for e in spec.endpoints], ensure_ascii=False)}
Для каждой сущности создай:
- <Entity>Create — для POST (все обязательные поля)
- <Entity>Update — для PATCH (все поля Optional)
- <Entity>Response — для ответов (включая id, created_at)
- <Entity>ListResponse — с пагинацией
Добавь field validators где нужно (email формат, позитивные числа, длина строк).
Верни только Python код."""
}]
)
return response.content[0].text.strip()
def _generate_router(self, entity: dict, spec: APISpec) -> str:
entity_endpoints = [
e for e in spec.endpoints
if entity["name"].lower() in e.path.lower()
]
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=4096,
messages=[{
"role": "user",
"content": f"""Создай FastAPI роутер для сущности {entity['name']}.
Endpoints для реализации:
{json.dumps([e.dict() for e in entity_endpoints], ensure_ascii=False, indent=2)}
Требования:
- Используй APIRouter с prefix и tags
- Dependency injection для DB session (AsyncSession)
- Dependency injection для авторизации (get_current_user)
- Async/await для всех операций
- Правильные HTTP статусы: 201 для POST, 204 для DELETE, 404 если не найдено
- Пагинация через query params page/limit
- Логирование через structlog
Верни только Python код."""
}]
)
return response.content[0].text.strip()
def _generate_main(self, spec: APISpec) -> str:
return f"""from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager
{chr(10).join(f"from routers.{e['name'].lower()} import router as {e['name'].lower()}_router" for e in spec.entities)}
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
yield
# Shutdown
app = FastAPI(
title="{spec.title}",
description="{spec.description}",
version="{spec.version}",
lifespan=lifespan,
)
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])
{chr(10).join(f'app.include_router({e["name"].lower()}_router, prefix="{spec.base_path}")' for e in spec.entities)}
"""
def _generate_tests(self, entity: dict, spec: APISpec) -> str:
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=2048,
messages=[{
"role": "user",
"content": f"""Создай pytest тесты для CRUD endpoints сущности {entity['name']}.
Используй:
- pytest-asyncio для async тестов
- httpx.AsyncClient для HTTP запросов
- pytest fixtures для setup/teardown
- TestDatabase (SQLite in-memory) для изоляции
Покрой: создание, чтение списка, чтение одного, обновление, удаление, 404 случаи, валидацию входных данных.
Верни только Python код."""
}]
)
return response.content[0].text.strip()
CLI-интерфейс для быстрого старта
import click
import yaml
@click.command()
@click.argument("description_file", type=click.Path(exists=True))
@click.option("--output-dir", "-o", default="./generated_api")
@click.option("--framework", default="fastapi", type=click.Choice(["fastapi", "express"]))
def generate_api(description_file: str, output_dir: str, framework: str):
description = Path(description_file).read_text()
generator = TextToAPIGenerator()
click.echo("Parsing description...")
spec = generator.parse_description(description)
click.echo(f"Found {len(spec.endpoints)} endpoints, {len(spec.entities)} entities")
click.echo("Generating code...")
files = generator.generate_fastapi_code(spec)
output_path = Path(output_dir)
output_path.mkdir(parents=True, exist_ok=True)
for filename, content in files.items():
file_path = output_path / filename
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.write_text(content)
click.echo(f" Created: {filename}")
_generate_project_files(output_path, spec)
click.echo(f"\nAPI generated in {output_dir}")
click.echo("Run: cd generated_api && docker-compose up")
if __name__ == "__main__":
generate_api()
Пример описания для генерации
# Система управления задачами
Многопользовательская система для команд.
Сущности:
- User: email (уникальный), name, role (admin/member), avatar_url
- Team: name, description, owner_id
- Project: name, description, team_id, status (active/archived)
- Task: title, description, project_id, assignee_id, status (todo/in_progress/done), priority (low/medium/high), due_date
Функциональность:
- Регистрация и авторизация (JWT)
- CRUD для команд, проектов, задач
- Назначение задач участникам команды
- Фильтрация задач по статусу, исполнителю, приоритету
- Пагинация всех списков
- Soft delete для задач
Практический кейс
Клиент — B2B-стартап, которому требовалось получить MVP backend для marketplace услуг за 2 недели. 8 сущностей, 45+ эндпоинтов.
Генерация:
- Описание продукта (2 страницы) → APISpec за несколько секунд
- Генерация кода FastAPI (7 файлов + тесты) — несколько минут
- Ручная доработка авторизации — 3 дня
- Интеграция платежного шлюза — 2 дня
Результат: работающий MVP через 5 дней вместо 14. Тестовое покрытие — 67% (сгенерировано автоматически). Сократили бюджет на разработку в 3 раза.
AI отлично справляется с CRUD, пагинацией, валидацией, структурой проекта и тестами happy path. Ручного вмешательства требуют сложные бизнес-правила, алгоритмы ценообразования и нетривиальные SQL-запросы.
Процесс работы, сроки и результаты
Этапы
- Анализ требований — изучаем описание, уточняем детали, фиксируем спецификацию.
- Генерация спецификации — AI парсит описание в APISpec (сущности, эндпоинты, типы).
- Генерация кода — создаем полный проект: модели, схемы, роутеры, тесты, Docker.
- Тестирование — запускаем тесты, исправляем ошибки, добавляем недостающие кейсы.
- Деплой и документация — готовим инструкцию, CI/CD (опционально).
Сроки и стоимость
Сроки зависят от сложности проекта:
- Прототип (один файл) — от 2 дней
- Полный проект с тестами — от 1 до 2 недель
- Добавление поддержки нового фреймворка — +1 неделя
- Интеграция в CI/CD — 1 неделя
Стоимость рассчитывается индивидуально. Свяжитесь с нами для оценки вашего проекта.
Что вы получаете в результате
| Компонент | Детали |
|---|---|
| Спецификация | OpenAPI 3.0 (YAML/JSON) |
| Бэкенд-код | FastAPI/Express с моделями, схемами, роутерами |
| Тесты | pytest с покрытием до 70% |
| Документация | README, инструкция по запуску |
| Инфраструктура | Docker Compose, requirements.txt |
Сравнение ручной разработки и AI-генерации
| Критерий | Ручная разработка | AI-генерация |
|---|---|---|
| Время на CRUD | 3-5 дней | 2-10 минут |
| Тестовое покрытие | 40-60% | до 70% |
| Риск ошибок в моделях | высокий | низкий (следует конвенциям) |
| Документация | пишется отдельно | генерируется автоматически |
Типичные ошибки при AI-генерации API
- Отсутствие авторизации. AI не знает вашу систему ролей — требует ручной настройки.
- Неправильные HTTP статусы. Иногда модель генерирует 200 вместо 201 для POST — важно проверить.
- Пропущенная валидация. Для специфичных бизнес-правил (уникальность email) нужно добавлять кастомные проверки.
- Недостаточное тестирование. Тесты покрывают happy path, но граничные случаи остаются за кадром.
Наши инженеры имеют сертификаты AWS и опыт в AI-генерации кода более 5 лет. Гарантируем соответствие лучшим практикам REST и полную документацию. Закажите демо-генерацию API по вашему описанию — убедитесь сами.







