Я регулярно выкладываю посты в блог НормЦРМ. На двух языках: русском и английском.Написал пост, придумал заголовок. Тут всё просто. А дальше неприятный процесс.Я регулярно выкладываю посты в блог НормЦРМ. На двух языках: русском и английском.Написал пост, придумал заголовок. Тут всё просто. А дальше неприятный процесс.

Как я сделал автоматический перевод постов у себя в блоге с помощью ChatGPT

2026/02/23 15:09
10м. чтение

Я регулярно выкладываю посты в блог НормЦРМ. На двух языках: русском и английском.

Написал пост, придумал заголовок. Тут всё просто. А дальше неприятный процесс. С помощью ИИ перевести пост на английский — и перенести перевод в блог. А ещё сгенерировать мета-данные и og-данные (это для поисковиков и мессенджеров), тоже перевести их на английский и руками поставить в нужные поля.

Всё это занимает минуты, но такая работа раздражает. А пишу я довольно часто (публикация раз в пару дней). И решил сделать в интерфейсе одну кнопку, которая возьмёт на себя всю эту рутину. Решил — и сделал. Теперь в один клик переводится пост и генерируются все мета-данные.

Сейчас расскажу во всех деталях, как именно это реализовано. Вдруг вы тоже так захотите?

Для начала немного контекста. Меня зовут Егор Камелев. Я проектировщик интерфейсов, но благодаря нейронкам, потихоньку погружаюсь в разработку. У меня есть свой проект — НормЦРМ (повышалка производительности для «взрослых» одиночек), написан на Python, Django, PostgreSQL. И в нём есть блог.

Первая версия блога была очень простой, из коробки. Затем я решил, что пора начинать активно писать и немного её улучшил. Добавил теги на нескольких языках, визуальный редактор, возможность подгружать картинки, вот это всё.

В каждой публикации можно добавлять разные языковые версии со своими адресами. Я пока поддерживаю только русский и английский. И вот настал момент, когда мне надоело заниматься рутинной работой по переносам переводов и мета-данных из соседнего окна с ChatGPT — и я решил сделать кнопку, которая возьмёт эту работу на себя.

В теории я представлял, что нужно делать, но на практике ни разу до этого не работал с API нейросетей.

Первое, с чего начал, — пошёл в ChatGPT и попросил помочь составить план действий. Сформулировал задачу примерно так:

Дальше я попытался понять, сколько это будет стоить, и пошёл регистрировать себе аккаунт в OpenAI Platform. Да, чтобы воспользоваться API, уже не подойдёт мой простой пользовательский аккаунт.

Прокси-сервер

Зарегистрировался — и вдруг понял, что ChatGPT недоступен пользователям из России. Я же всё это через VPN делаю. А на сервере моего проекта никакого VPN нет. И что ничего у меня не получится.

Выбирать какую-то другую нейронку мне не хотелось. Я неплохо освоился с ChatGPT и разобрался с его достоинствами и недостатками — не хотелось повторять весь этот путь с каким-то другим ИИ.

Так что я решил поднять прокси-сервер где-нибудь в Европе. Это такой промежуточный сервер, который делает вот что:

  1. Принимает HTTP-запрос от НормЦРМ

  2. Добавляет API-ключ

  3. Отправляет запрос в OpenAI

  4. Возвращает ответ обратно.

Я выбрал одного из провайдеров в Дубае и арендовал выделенный сервер, территориально находящийся в Амстердаме.

Вот всё, что понадобилось на сервере:

  • Ubuntu

  • Python venv

  • FastAPI

  • Uvicorn

  • Nginx

  • systemd

Дальше я попросил ИИ помочь мне с кодом, который будет управлять проксированием. Вот что получилось.

import os from fastapi import FastAPI, Header, HTTPException from pydantic import BaseModel from openai import OpenAI from dotenv import load_dotenv load_dotenv() app = FastAPI() AI_PROXY_TOKEN = os.getenv("AI_PROXY_TOKEN") AI_MODEL = os.getenv("AI_MODEL", "gpt-5-mini") client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) class GenerateRequest(BaseModel): prompt: str @app.post("/generate") async def generate( request: GenerateRequest, x_proxy_token: str | None = Header(default=None) ): if not AI_PROXY_TOKEN or x_proxy_token != AI_PROXY_TOKEN: raise HTTPException(status_code=401, detail="Unauthorized") response = client.responses.create( model=AI_MODEL, input=request.prompt, ) return { "output": response.output_text }

Как видите, всё умещается в 34 строки. По коду вы можете понять, что настройки токена, ключа и модели ChatGPT я вынес в .env файл. Ключ получил в OpenAI Platform, модель выбрал самую дешёвую на момент создания (любая справится с переводами), а токен уже добавил чуть позже, когда проверил, что всё работает. Токен нужен для того, чтобы никто не мог прийти ко мне на сервер и использовать его в качестве бесплатного входа в API (и потратить мои драгоценные пять баксов).

Я не стал делать полноценную async-архитектуру, потому что прокси используется только мной и нагрузка минимальна.

Дальше, чтобы это всё работало, необходим systemd-сервис. Потому что когда я запускаю Python-скрипт в терминале, он работает только пока открыт терминал. Но в продакшене сервер должен:

  • Стартовать автоматически при загрузке системы;

  • Перезапускаться при падении;

  • Работать в фоне.

Настройки (файл INI) выглядят так:

[Unit] Description=AI Proxy (FastAPI) After=network.target [Service] User=root WorkingDirectory=/opt/ai-proxy ExecStart=/opt/ai-proxy/venv/bin/uvicorn app:app --host 127.0.0.1 --port 8000 Restart=always [Install] WantedBy=multi-user.target

Что это значит?

  • ExecStart — какую команду запускать

  • Restart=always — если приложение упало, запустить снова

  • WorkingDirectory — из какой папки запускать

Как итог: прокси работает как полноценная серверная служба, а не как «скрипт в терминале».

После этого я настроил Nginx.

server { listen 80; server_name _; location /generate { proxy_pass http://127.0.0.1:8000/generate; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }

Что тут происходит? FastAPI запущен на локальном адресе внутри сервера (127.0.0.1:8000). Но пользователи (и мой НормЦРМ в их числе) обращаются к серверу по обычному HTTP-порту 80. И вот для таких случаев, когда приходят запросы на адрес /generate, Nginx берёт и перенаправляет их внутреннему приложению. Так что Nginx — это reverse proxy

И всё. Прокси-сервер настроен, автономен и базово защищён от злоумышленников.

Доработки в НормЦРМ

Дальше я сформулировал задачу уже для Codex. Это нейронка от ChatGPT, в которой я вайб-кодю НормЦРМ. В результате получилось всего три правки в код НормЦРМ.

Первая отвечает за то, чтобы по API отправлялся запрос к ИИ, а ответ обрабатывался и встраивался в публикацию в блоге.

Вторая — добавление в файл с настройками всего проекта пары переменных: адреса прокси-сервера, а также токена, который используется для обращения к нему.

Наконец, третья — это небольшая правка в шаблон страницы создания/редактирования поста в админке.

Внешний вид меня вообще не волновал — это инструмент сугубо для меня. Поэтому я просто попросил сделать мне кнопку под полем с текстом публикации. Получилось вот что:

Это скриншот из админки. Видите синюю страшную кнопку по-середине экрана? Вот это оно.
Это скриншот из админки. Видите синюю страшную кнопку по-середине экрана? Вот это оно.

Промпт

Как отправляется запрос к ИИ? Да таким же промптом, какие мы отправляем, общаясь с чат-ботами. Вот промпт, который сейчас используется в моём коде:

AI_PROMPT_TEMPLATE = """You are a professional bilingual editor and SEO specialist. Your task is to: 1) Generate Russian SEO metadata for the original Russian blog post. 2) Generate a full English version of the blog post. 3) Preserve HTML formatting. 4) Return STRICT JSON only. No explanations. No markdown. No extra text. -------------------------------------------------- ORIGINAL RUSSIAN DATA: Title (RU): {{RU_TITLE}} Body (RU, HTML): {{RU_BODY_HTML}} -------------------------------------------------- REQUIREMENTS: === RUSSIAN SEO === Generate: - ru_meta_title (50–60 characters preferred) - ru_meta_description (140–160 characters preferred) - ru_og_title (can match meta_title) - ru_og_description (can match meta_description) Meta fields must: - Be natural Russian - Not repeat the full title verbatim unless appropriate - Be concise and clickable - Not contain quotation marks unless necessary === ENGLISH VERSION === Generate: - en_title - en_slug (lowercase, hyphen-separated, latin only) - en_body_html (valid HTML) - en_meta_title (50–60 characters preferred) - en_meta_description (140–160 characters preferred) - en_og_title - en_og_description EN rules: - Translate naturally, not word-for-word. - Preserve ALL HTML structure. - DO NOT modify: - <a href=""> - <img src=""> - Preserve paragraphs, lists, strong, em, headings. - Translate image alt attributes into English. - Do not invent new links. - Do not add scripts or styles. - Do not wrap result in markdown. - Do not add explanations. - Ensure en_body_html is a JSON string (escape quotes and newlines). Return ONLY a single JSON object (not an array). Output must be valid JSON that can be parsed by json.loads(). Critical JSON rules: - Use double quotes for all keys and string values. - Escape any double quotes inside strings as \" - Escape newlines as \n - Do not include trailing commas. - Do not wrap the JSON in markdown fences. - Do not include any text before or after the JSON. If you are unsure about any field, return an empty string for it. Never add explanations. JSON FORMAT: { "ru_meta_title": "", "ru_meta_description": "", "ru_og_title": "", "ru_og_description": "", "en_title": "", "en_slug": "", "en_body_html": "", "en_meta_title": "", "en_meta_description": "", "en_og_title": "", "en_og_description": "" } """

Как видите, в промпте указан и контекст, и задача, и формат, в котором должен приходить ответ. Обратите внимание на то, что отдельно формируется просьба не ломать ничего в html-разметке, не присылать ничего, помимо JSON (не сопровождать ответы дополнительными объяснениями) и так далее.

Я бы и рад поделиться с вами историями о том, как ИИ прислал мне ответ в неверном формате — и ничего не сработало, но у меня их нет. Пока что всё работает, как задумано, и без сбоев.

В коде также предусмотрены сценарии которые описывают, что делать с уже заполненными полями, а также подробное логирование. Это уже результат моей работы в роли обычного проектировщика интерфейсов (хотя здесь интерфейсов и нет, как таковых, но как по мне UX-дизайнеры должны разбираться в движении и обработке данных не хуже аналитиков).

В общем, я это всё задеплоил, протестировал — и оно не заработало :)

Единственная неполадка

На уровне интерфейса всё выглядело хаотично: то 500, то 502, то сообщение о том, что сервер вернул не JSON. Причём ошибка возникала не всегда, что сбивало с толку.

Логи показали, что прокси отрабатывает корректно: запрос до OpenAI уходит, ответ генерируется и возвращается. Проблема оказалась в Gunicorn. По умолчанию его timeout — 30 секунд. Если воркер не вернул ответ за это время, он считается зависшим и перезапускается.

Мой промпт довольно объёмный: перевод статьи, генерация slug, SEO-метаданных и OG-данных, плюс строгий JSON и сохранение HTML. В среднем модель отвечала за 40–50 секунд. То есть OpenAI честно формировал результат, но Gunicorn уже успевал «похоронить» воркер. Ответ приходил — а принимать его было уже некому.

В продакшене такую задачу правильнее выносить в очередь и обрабатывать асинхронно. Но в моём случае кнопкой пользуюсь только я, нагрузка минимальная, а ожидание в 40 секунд некритично. Поэтому я просто увеличил timeout до 120 секунд. Для соло-проекта это оказалось самым рациональным решением.

Итоги

Что по деньгам? Сервер в Амстердаме — пять евро в месяц. На баланс OpenAI Platform я закинул пять долларов. Генерация одного поста обходится примерно в один цент. Даже если публиковать по 30 постов в месяц, денег хватит надолго.

Что по времени? От идеи до работающего решения прошло около трёх часов (это включая регистрацию в OpenAI Platform и закидывание денег в неё и на хостинг). Ещё пара часов ушла на разбор с тайм-аутами и закрытие прямого доступа к прокси.

И да, всё работает. Подготовил текст на русском, нажал кнопку — через 40 секунд появляются перевод, slug, SEO- и OG-метаданные. Экономия — около пяти минут на пост. При 10–15 публикациях в месяц это уже час времени. Стоимость моего часа перекрывает все расходы на сервер и токены, а затраченные на разработку пять часов окупятся довольно быстро.

Интеграция OpenAI в блог оказалась не столько задачей про «ИИ», сколько задачей про инфраструктуру. Основные сложности возникли не на уровне модели, а на уровне сетевой архитектуры и тайм-аутов. Сам вызов API занял несколько строк кода. Всё остальное — продакшен.

Пару лет назад я вряд ли поверил бы, что буду поднимать прокси, настраивать systemd и разбираться с Gunicorn ради кнопки в админке. А сейчас это просто ещё один инструмент в арсенале.

ИИ оказался не магией, а обычным внешним сервисом — просто очень мощным. И если относиться к нему как к любому другому API, он начинает решать вполне приземлённые задачи.

И, честно говоря, это самое интересное в происходящем.

Полезные ссылки

  • Статья: 20 лет объяснял программистам, что делать. А теперь попробовал сам

  • Статья: 20 лет объяснял программистам, что делать. А теперь попробовал сам. Часть вторая

  • Мой канал в Телеграме

Источник

Возможности рынка
Логотип OG
OG Курс (OG)
$3.053
$3.053$3.053
-6.94%
USD
График цены OG (OG) в реальном времени
Отказ от ответственности: Статьи, размещенные на этом веб-сайте, взяты из общедоступных источников и предоставляются исключительно в информационных целях. Они не обязательно отражают точку зрения MEXC. Все права принадлежат первоисточникам. Если вы считаете, что какой-либо контент нарушает права третьих лиц, пожалуйста, обратитесь по адресу service@support.mexc.com для его удаления. MEXC не дает никаких гарантий в отношении точности, полноты или своевременности контента и не несет ответственности за любые действия, предпринятые на основе предоставленной информации. Контент не является финансовой, юридической или иной профессиональной консультацией и не должен рассматриваться как рекомендация или одобрение со стороны MEXC.

Быстрое чтение

Еще

Цена Conway Research (CONWAY) в сравнении с ценой Bitcoin (BTC) дает инвесторам четкое представление о том, как этот развивающийся мемкоин соотносится с крупнейшей криптовалютой. Поскольку BTC остается эталоном крипторынка, анализ динамики цен CONWAY vs BTC выявляет относительную силу, волатильность и возможности для трейдеров, ищущих прогнозы цены Conway Research и данные для сравнения цен Bitcoin.

Сравнение цены Conway Research (CONWAY) с ценой Ethereum (ETH) предлагает ценную перспективу для трейдеров и инвесторов. Поскольку ETH является второй по величине криптовалютой по рыночной капитализации и краеугольным камнем децентрализованных финансов, анализ его производительности по сравнению с CONWAY помогает выявить как конкурентные преимущества, так и потенциальные возможности роста.