Как писать код на Python с помощью нейросети

Нейросеть полезнее всего там, где задачу можно описать входными данными, ожидаемым результатом и ограничениями.
Я использую языковые модели как ускоритель черновиков: прошу набросать функцию, тест, SQL-запрос, хук для интерфейса или README, а затем проверяю результат как обычный код от коллеги. Такой подход хорошо работает для повторяемых задач: преобразовать CSV в JSON, написать валидатор, собрать класс с понятным контрактом, разложить сырую функцию на несколько маленьких, подготовить unit-тесты для крайних случаев.
В SoftChat удобно вести такие задачи в отдельных разговорах: история переписки сохраняется, модель можно переключать для конкретного диалога, а ответы с кодом отображаются в Markdown с блоками кода и таблицами. Для повторяемых сценариев я держу шаблоны промптов, например «сгенерируй функцию по контракту» или «проведи ревью с акцентом на безопасность». Если черновик запроса получился рыхлым, перед отправкой можно использовать «Улучшить запрос» и принять или отклонить предложенную редакцию. Это не заменяет ревью. Это снижает трение на старте.
Что хорошо отдавать нейросети в разработке
Хороший кандидат для генерации кода имеет 4 признака: входные данные можно описать формально, результат проверяется тестом, зависимостей немного, а бизнес-правила не спрятаны в голове одного разработчика. Например, «прочитать CSV с колонками order_id, created_at, amount, status и посчитать выручку по дням» подходит. Запрос «сделай красиво весь модуль аналитики» не подходит, потому что модель не знает контекст проекта.
Я обычно делю работу на 5 шагов. Сначала формулирую контракт: что приходит на вход, что выходит, какие ошибки ожидаемы. Затем прошу код. После этого отдельно прошу тесты. Третьим проходом даю модели свой же код и прошу найти дефекты. Финальный шаг делаю руками: запускаю линтер, тесты, профилирование при необходимости. Если нужна более строгая формулировка промптов, полезно заранее разобрать как формулировать запросы для нейросетей, потому что в кодогенерации разница между «сделай скрипт» и «сделай чистую функцию с тестами и обработкой пустого файла» видна сразу.
Ниже все примеры связаны одной темой: поток заказов, ежедневная выручка и витрина данных для интерфейса. Это ближе к реальной работе, чем набор несвязанных задач.
Сценарий Python: скрипт, функция, класс и файл по описанию
Начнём с Python. Задача: есть CSV-файл с заказами, надо отфильтровать оплаченные заказы, сгруппировать выручку по дате и сохранить JSON. Для нейросети это нормальная задача, если дать схему входа и формат выхода.
Промпт:
Напиши код на Python 3.11.
Вход: CSV-файл orders.csv с колонками order_id, created_at, amount, status.
created_at в формате ISO 8601, amount может быть строкой с десятичной точкой.
Нужно оставить только status = paid, посчитать сумму amount по дате created_at и сохранить daily_revenue.json.
Сделай функцию load_daily_revenue(path: str) -> list[dict], класс OrderRow для валидации строки и короткий main.
Без внешних библиотек. Добавь комментарии на русском.
Ответ нейросети:
from __future__ import annotations
import csv
import json
from dataclasses import dataclass
from datetime import datetime
from decimal import Decimal, InvalidOperation
from pathlib import Path
@dataclass(frozen=True)
class OrderRow:
order_id: str
created_at: datetime
amount: Decimal
status: str
@classmethod
def from_csv(cls, row: dict[str, str]) -> 'OrderRow':
# Проверяем обязательные поля до преобразований
for field in ('order_id', 'created_at', 'amount', 'status'):
if not row.get(field):
raise ValueError(f'Пустое поле: {field}')
try:
created_at = datetime.fromisoformat(row['created_at'])
amount = Decimal(row['amount'])
except (ValueError, InvalidOperation) as exc:
raise ValueError(f'Некорректная строка заказа: {row}') from exc
return cls(
order_id=row['order_id'],
created_at=created_at,
amount=amount,
status=row['status'].strip().lower(),
)
def load_daily_revenue(path: str) -> list[dict]:
revenue_by_day: dict[str, Decimal] = {}
with Path(path).open(newline='', encoding='utf-8') as csv_file:
reader = csv.DictReader(csv_file)
for raw_row in reader:
order = OrderRow.from_csv(raw_row)
if order.status != 'paid':
continue
day = order.created_at.date().isoformat()
revenue_by_day[day] = revenue_by_day.get(day, Decimal('0')) + order.amount
return [
{'date': day, 'revenue': str(amount)}
for day, amount in sorted(revenue_by_day.items())
]
def main() -> None:
result = load_daily_revenue('orders.csv')
Path('daily_revenue.json').write_text(
json.dumps(result, ensure_ascii=False, indent=2),
encoding='utf-8',
)
if __name__ == '__main__':
main()
Черновик полезный, но я не вставляю его в проект сразу. Минимальный чек-лист: пустой файл, отсутствующая колонка, отрицательная сумма, статус с пробелами, часовой пояс в created_at, точность Decimal при сериализации. В этом примере модель выбрала Decimal, а не float, и это правильно для денег. Но она не проверила заголовки CSV до чтения строк. Я бы добавил явную проверку reader.fieldnames и тест на файл без нужных колонок.
Для генерации функций работает короткая формула: «контракт, ограничения, пример входа, пример выхода, стиль ошибок». Если нужен файл целиком, добавляйте структуру: «один модуль», «отдельный класс», «без внешних библиотек», «совместимо с Python 3.11». Такой формат заметно лучше, чем просьба «напиши скрипт для отчёта». Про общий подход к черновикам и проверке результата я отдельно писал в статье про нейросеть для генерации текста и проверку результата, и для кода логика та же: сначала черновик, затем критерии качества.
Сценарий JavaScript и TypeScript: хук для витрины данных
Теперь фронтенд. Пусть Python-скрипт кладёт агрегаты в API, а интерфейсу нужен хук, который грузит данные, показывает состояние загрузки и отдаёт ошибку. Здесь нейросеть часто помогает быстрее собрать каркас, но типы и контракты ответа надо задавать явно.
Промпт:
Напиши React-хук на TypeScript для загрузки дневной выручки.
Эндпоинт: /api/revenue/daily.
Ответ: массив объектов { date: string, revenue: string }.
Нужны состояния data, loading, error и отмена запроса при размонтировании.
Без сторонних библиотек. Добавь короткий пример использования в компоненте.
Ответ нейросети:
import { useEffect, useState } from 'react';
type DailyRevenue = {
date: string;
revenue: string;
};
type UseDailyRevenueResult = {
data: DailyRevenue[];
loading: boolean;
error: string | null;
};
export function useDailyRevenue(): UseDailyRevenueResult {
const [data, setData] = useState<DailyRevenue[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const controller = new AbortController();
async function loadRevenue() {
try {
setLoading(true);
setError(null);
const response = await fetch('/api/revenue/daily', {
signal: controller.signal,
headers: { Accept: 'application/json' },
});
if (!response.ok) {
throw new Error(`Ошибка загрузки: ${response.status}`);
}
const payload = (await response.json()) as DailyRevenue[];
setData(payload);
} catch (err) {
// AbortError не считаем пользовательской ошибкой
if (err instanceof DOMException && err.name === 'AbortError') {
return;
}
setError(err instanceof Error ? err.message : 'Неизвестная ошибка');
} finally {
setLoading(false);
}
}
loadRevenue();
return () => controller.abort();
}, []);
return { data, loading, error };
}
function RevenueTable() {
const { data, loading, error } = useDailyRevenue();
if (loading) return <p>Загрузка...</p>;
if (error) return <p>Ошибка: {error}</p>;
return (
<table>
<tbody>
{data.map((row) => (
<tr key={row.date}>
<td>{row.date}</td>
<td>{row.revenue}</td>
</tr>
))}
</tbody>
</table>
);
}
Что я проверяю в таком коде: не обновляется ли состояние после отмены запроса, есть ли валидация формы ответа, как ведёт себя повторный запрос, нужен ли кеш, не потеряна ли локализация ошибок. Модель дала минимальный каркас. Для production-кода я бы добавил runtime-проверку массива и полей, потому что приведение as DailyRevenue[] ничего не гарантирует во время выполнения.
Сценарий SQL: агрегация и оконная функция
SQL хорошо генерируется, когда схема таблиц короткая и задача звучит как аналитический запрос. Если в базе есть специфичный диалект, его надо назвать. В примере возьмём таблицу orders и посчитаем дневную выручку вместе со скользящим средним за 7 дней.
Промпт:
Напиши SQL-запрос для PostgreSQL.
Таблица orders: id, created_at timestamptz, amount numeric, status text.
Нужно получить date, revenue, avg_revenue_7d.
Учитывать только status = paid.
Сначала агрегировать по дням, затем посчитать скользящее среднее за текущий день и 6 предыдущих.
Ответ нейросети:
WITH daily AS (
SELECT
created_at::date AS date,
SUM(amount) AS revenue
FROM orders
WHERE status = 'paid'
GROUP BY created_at::date
)
SELECT
date,
revenue,
AVG(revenue) OVER (
ORDER BY date
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
) AS avg_revenue_7d
FROM daily
ORDER BY date;
Запрос читаемый, но есть нюанс: если в данных нет заказов в какой-то день, строка за этот день не появится. Для отчёта с непрерывной шкалой дат понадобится календарная сетка через generate_series и LEFT JOIN. Ещё один практический пункт: индекс по status, created_at может помочь, если таблица большая и запрос часто фильтрует оплаченные заказы. Нейросеть обычно не знает распределение данных, поэтому план выполнения всё равно смотрим руками через EXPLAIN.
Ревью и рефакторинг: как просить модель проверять код
Генерация кода даёт первый слой пользы. Второй слой часто ценнее: ревью чужого или собственного кода. Я предпочитаю давать модели узкую роль, иначе она начинает комментировать стиль вместо дефектов.
Хороший промпт для ревью:
Проведи code review этого Python-кода.
Ищи только 5 типов проблем: ошибки валидации, потерю точности Decimal, проблемы с кодировкой, непокрытые крайние случаи, небезопасную обработку файлов.
Верни таблицу: проблема, строка или фрагмент, риск, исправление.
Не переписывай весь файл, пока я не попрошу.
Такой формат удобен: модель не расползается на общие советы, а выдаёт проверяемый список. В SoftChat ответы с таблицами отображаются прямо в чате, поэтому ревью можно читать без копирования в отдельный редактор. Если выбранная модель не вернула пригодный ответ, SoftChat может получить ответ от резервной модели и показать строку «Ответ получен на резервной модели». Если неудачна и повторная попытка на стороне сервиса, этот ход не списывает кредиты, и пользователь может повторить запрос бесплатно. Я воспринимаю это как страховку от пустых ответов, а не как гарантию качества кода.
Для рефакторинга лучше просить маленькие изменения: «раздели функцию на чтение, валидацию и агрегацию», «сохрани внешний контракт», «не меняй формат JSON», «покажи diff словами». Если дать команду «улучши код», модель может переименовать половину сущностей, поменять сигнатуры и сломать совместимость.
Документирование кода: README, докстринги и API-описания
Документация хорошо ложится на нейросеть, потому что код уже содержит факты. Для небольшого модуля можно вставить файл и попросить README по шаблону: назначение, входные данные, запуск, пример CSV, пример JSON, ошибки, тесты. Для функции полезнее просить докстринг с контрактом, а не пересказ тела.
Промпт:
Составь README для скрипта агрегации заказов.
Структура: назначение, формат orders.csv, команда запуска, пример результата daily_revenue.json, ограничения, как проверить вручную.
Не придумывай флаги командной строки, которых нет в коде.
Последняя строка в промпте важна. Модель может добавить параметры --input и --output, если привыкла к типовым CLI-утилитам. Если этих флагов нет в коде, документация станет вредной. То же касается API-описаний: просите опираться только на переданный код, схему или контракт. Для повседневных рабочих задач с нейросетями помогает навык дробить крупный запрос на несколько маленьких шагов, об этом есть отдельный разбор про нейросети и чат-боты для повседневных задач.
Где нейросеть ошибается чаще всего
Первый риск, устаревшие API. Модель может использовать метод, который был нормален в старой версии библиотеки, но уже помечен как нежелательный. Проверка простая: фиксируйте версии в промпте и сверяйте с документацией проекта.
Второй риск, скрытые бизнес-правила. В примере с заказами модель не знает, что возвраты могут приходить отдельными строками, что тестовые заказы надо исключать по source = internal, а день отчёта считается в часовом поясе магазина. Если этого нет в запросе, этого почти наверняка не будет в коде.
Третий риск, безопасность. Никогда не вставляйте секреты, токены, приватные ключи и персональные данные в промпт. Для кода проверяйте работу с файлами, SQL-инъекции, небезопасную десериализацию, права доступа и логирование. Запрос «найди возможные проблемы безопасности» полезен, но не заменяет SAST, ревью и тесты.
Четвёртый риск, производительность. Модель может предложить алгоритм O(n²) для задачи, где вход уже сейчас измеряется сотнями тысяч строк. Просите оценку сложности и альтернативу для больших данных. Для SQL просите вариант с индексами и объяснение, какие строки фильтруются до агрегации.
Пятый риск, уверенный тон при ошибке. Ответ может выглядеть гладко, компилироваться и всё равно неверно считать деньги на краевых случаях. Поэтому рабочее правило простое: любой сгенерированный код проходит тесты. Минимум: нормальный случай, пустой вход, некорректная строка, край даты, дубликат, ошибка внешнего сервиса.
Финальный вывод
Нейросеть хорошо пишет код, когда вы даёте ей не мечту о готовой системе, а инженерную задачу: вход, выход, ограничения, версию языка, стиль ошибок и критерии проверки. Для Python она быстро собирает функции, классы и файловые скрипты. Для TypeScript даёт каркас хуков и компонентов. Для SQL помогает с агрегациями и оконными функциями. Но ответственность остаётся у разработчика: прочитать код, запустить тесты, проверить безопасность, сверить API и понять, не потерялись ли бизнес-правила.
Мой практический шаблон короткий: сгенерировать черновик, запросить тесты, провести ревью через отдельный промпт, поправить руками, затем документировать. Если держать этот цикл, нейросеть экономит время на рутине и не превращается в источник случайных багов.