Telegram-бот, который подбирает 10-значный код ТН ВЭД ЕАЭС по текстовому описанию товара или
по фотографии. Работает локально на Windows, обращается к ИИ через CLI claude -p.
Ключевая гарантия: ИИ не изобретает коды. Кандидаты берутся из локального справочника, модель выбирает только из них, и каждый код перед отправкой пользователю сверяется с базой. Код, которого нет в активной версии справочника, физически не может попасть в ответ.
⚠️ Бот носит справочный характер. Окончательное решение о классификации принимает декларант; для официальной позиции — предварительное решение ФТС.
- Техническое задание: docs/TZ.md
- Тикеты и отчёты: docs/tasklist/tickets.md
- Правила разработки: CLAUDE.md, conventions.md
| Возможность | Как работает |
|---|---|
| Код по описанию | Два обращения к ИИ: перевод запроса на язык справочника, затем выбор из кандидатов |
| Код по фотографии | Модель описывает товар, вы подтверждаете описание, дальше обычный пайплайн |
| Уточняющие вопросы | Кнопками, до 3 раундов; при неуверенности бот спрашивает, а не гадает |
| Пошлина и НДС | У основного кода и у каждой альтернативы; ставка — из локального справочника |
| Разрешительные документы | Перечень и техрегламенты по коду, с разделением обязательных и условных |
| Маркировка «Честный знак» | Локальная таблица товарных групп; ответ даётся всегда, в том числе отрицательный |
| Ставка ниже рядом | Соседние коды той же позиции с меньшей пошлиной — как повод перепроверить классификацию |
| Обучение на ошибках | 👎 → присылаете верный код → бот учитывает его при похожих запросах |
| Управление доступом | Whitelist в БД + приглашения ссылкой в один клик |
| Рассылка | /broadcast с предпросмотром и подтверждением |
| Автозапуск | Задача планировщика при входе в систему, без консольного окна |
| Автоудаление фото | 48 часов, включая догоняющую очистку после простоя компьютера |
Ставка пошлины — из загруженного справочника ТН ВЭД. НДС, перечень разрешительных
документов, техрегламенты и обезличенные примеры деклараций — со страницы кода на
ifcg.ru; ответ кешируется в БД на 30 дней, поэтому за одним
и тем же кодом бот ходит в сеть не чаще раза в месяц. Это единственный выход бота в интернет
помимо Telegram, и он отключается одной переменной REFERENCE_ENABLED=false — без него бот
работает как раньше, только без справки.
alta.ru отдаёт в HTML лишь пошлину и НДС, остальное подгружает скриптами, поэтому используется как ссылка «проверить код», а не как источник данных.
Перечни маркировки правятся в src/tnved_bot/customs/marking.csv — обычным текстом, без
изменения кода. Они утверждаются постановлениями и меняются несколько раз в год, поэтому бот
говорит «вероятно, проверьте по перечню», а не «маркировка нужна».
- Windows 10/11, Python 3.12 (проверено на 3.12.10)
- Claude Code CLI в PATH и авторизованный (
claude --version) - Токен бота от @BotFather
- Файл справочника ТН ВЭД ЕАЭС (XLSX или CSV) — см. ниже
cd c:\Claude\TNVED_BOT
py -3.12 -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
pip install -e .
Copy-Item .env.example .env
# заполнить BOT_TOKEN и ADMIN_USER_IDSADMIN_USER_IDS — числовые Telegram ID администраторов через запятую, без пробелов. Свой ID
можно узнать, написав боту: он вернёт его в сообщении об отказе в доступе.
Скачайте актуальную выгрузку и импортируйте:
Invoke-WebRequest -Uri 'https://www.tws.by/tws/tnved/download/excel' `
-OutFile "data\nomenclature\tnved_$(Get-Date -Format 'yyyy-MM-dd').xlsx"
python scripts\import_nomenclature.py "data\nomenclature\tnved_$(Get-Date -Format 'yyyy-MM-dd').xlsx"Импорт атомарен: пока новая версия не записана целиком, активной остаётся прежняя.
Откат — --rollback, список версий — --list. Разбор источника и его ограничения:
docs/research/nomenclature-sources.md.
До загрузки справочника бот стартует, но на запросы отвечает «справочник не загружен».
python -m tnved_bot # вручную, Ctrl+C для остановкиpowershell -ExecutionPolicy Bypass -File scripts\install_autostart.ps1Создаёт задачу TNVED_BOT: запуск при входе в систему, без ограничения времени работы.
Окно не появляется вовсе: задача вызывает wscript.exe с scripts\run_hidden.vbs, а тот
запускает надзорный скрипт с невидимым окном. Через powershell -WindowStyle Hidden консоль
всё равно создавалась и мелькала при входе в систему.
Перезапуск после падения делает надзорный цикл в scripts\run_bot.ps1 — проверено, что
встроенный механизм планировщика в этом сценарии не срабатывает.
Start-ScheduledTask -TaskName TNVED_BOT # запустить сейчас
powershell -File scripts\stop_bot.ps1 # остановить
powershell -File scripts\uninstall_autostart.ps1 # убрать автозапуск
python scripts\smoke_check.py # проверить состояние| Команда | Что делает |
|---|---|
/start |
Приветствие и краткая инструкция |
/start <код> |
Активировать приглашение |
/help |
Как описывать товар, чтобы код был точным |
/code <10 цифр> |
Официальное наименование кода из справочника |
/cancel |
Прервать текущие уточнения |
/forget |
Немедленно удалить свои фото и диалоги |
/version |
Версия бота и справочника |
Под ответом — кнопки 👍 / 👎. «Неверно» не уходит в пустоту: бот спросит верный код и учтёт его при похожих запросах.
Команды видны в меню Telegram (кнопка слева от поля ввода) — бот публикует их при старте. Администраторам показывается расширенный набор, обычным пользователям — только их шесть команд.
/admin открывает панель на кнопках:
🛠 Панель администратора
Пользователей с доступом: 3
Невостребованных приглашений: 1
Запросов за сутки: 12
[ 👥 Пользователи ] [ 🎟 Приглашения ]
[ ➕ Новое приглашение ]
[ 📊 Статистика ] [ 🩺 Состояние ]
[ 📝 Исправления ] [ 📣 Рассылка ]
- Пользователи — список с заметками и датой последнего визита; кнопка напротив каждого
отзывает доступ (с подтверждением). Администратора из
.envотозвать нельзя — это аварийный вход. - Приглашения — невостребованные коды с сроком действия; лишние отзываются кнопкой. Выданный и забытый код остаётся открытой дверью до истечения суток.
- Новое приглашение — код в один клик и готовое сообщение со ссылкой для пересылки.
- Исправления — что пользователи поправили после 👎 и какие коды бот запомнил.
- Рассылка — сообщение всем пользователям: предпросмотр, подтверждение, отчёт о доставке. Есть готовый текст об обновлении.
Те же действия доступны командами, когда ID уже известен:
| Команда | Что делает |
|---|---|
/admin |
Панель на кнопках |
/users |
Список пользователей с заметками |
/adduser <id> [заметка] |
Выдать доступ без перезапуска |
/deluser <id> |
Отозвать доступ, закрыть активные диалоги |
/invite [заметка] |
Приглашение ссылкой на 24 часа |
/broadcast |
Рассылка всем пользователям |
/corrections |
Исправления, присланные пользователями |
/health |
Справочник, claude, диск, очередь |
/stats |
Статистика за сутки |
/reload_db |
Сведения об активной версии справочника |
Спрашивать у него Telegram ID неудобно — он обычно не знает, где его взять. Нажмите
➕ Новое приглашение в панели (или /invite Петров). Бот пришлёт два сообщения: код
со сроком действия — вам, и готовое приглашение — для пересылки:
Приглашение в бота подбора кодов ТН ВЭД ЕАЭС.
👉 Открыть бота и войти
Нажмите ссылку, затем кнопку «Запустить» — код подставится сам.
Ссылка вида https://t.me/<бот>?start=TNVED-7K2M-9XQP подставляет код за человека: вводить
его руками больше не нужно. Приглашение одноразовое, живёт 24 часа, после активации человек
появляется в списке пользователей.
Нажмите 👎 под ответом — бот попросит прислать верный код. Пара «запрос → код» сохраняется и при похожем запросе попадает и в подсказку модели, и в список кандидатов. Код проверяется по справочнику до сохранения: исправление с несуществующим кодом бот не примет. Не знаете верный код — просто напишите новый запрос, ничего делать не нужно.
- Доступ только по whitelist: администраторы из
.env, остальные — в таблицеallowed_users. - Наружу уходит только код ТН ВЭД — за справкой о пошлине и документах. Текст запроса, описание товара и фотографии не покидают компьютер.
- Фотографии хранятся локально не более 48 часов, затем файлы удаляются с диска.
- При сохранении фото пересохраняется в JPEG — это уничтожает EXIF, включая геолокацию съёмки.
- Фото не передаются никуда, кроме локального процесса
claude. - Полные тексты запросов в журнал не пишутся — только SHA-256.
/forgetудаляет данные пользователя немедленно, не дожидаясь TTL.
pytest -q # все тесты
pytest tests\test_sanitize.py -v # защита от инъекций
ruff check src tests scripts
ruff format src tests scripts
mypy src
pytest -q --cov --cov-report=term-missing # покрытие: 87 %, порог CI — 70 %Те же четыре проверки на каждый push и pull request гоняет
GitHub Actions на windows-latest — на той платформе, для которой
бот написан. Секреты CI не нужны: тесты не ходят в сеть и не читают .env.
| Симптом | Причина и решение |
|---|---|
| Бот не отвечает | python scripts\smoke_check.py; смотреть logs\bot.log |
| «Справочник не загружен» | Выполнить scripts\import_nomenclature.py |
| «ИИ временно недоступен» | Проверить claude --version и авторизацию Claude Code |
| Ответ идёт 15–20 секунд | Нормально: два обращения к ИИ. Норматив ТЗ — до 60 с |
| Бот отвечает дважды | Запущено два экземпляра: scripts\stop_bot.ps1, затем один запуск |
| Не стартует после перезагрузки | Get-ScheduledTask -TaskName TNVED_BOT; смотреть logs\stdout.log |
| «Диалог уже закрыт» | Сессия истекла (30 мин) — отправьте запрос заново |
Скрипт .ps1 падает на разборе |
Файл сохранён без BOM: PowerShell 5.1 читает .ps1 как ANSI |
| «Справка недоступна» в ответе | Нет сети или изменилась вёрстка источника; код и ставка из справочника показываются всё равно |
| Ставки устарели | REFERENCE_TTL_DAYS или сброс кеша: DELETE FROM code_reference |
MIT — © 2026 Alex Korytchenko (@AlexKorWeb).
Справочник ТН ВЭД ЕАЭС в репозиторий не входит: он загружается отдельно, из официального
источника, скриптом scripts/import_nomenclature.py. Перечни маркировки в
src/tnved_bot/customs/marking.csv носят справочный характер и не заменяют действующие
постановления.
