Агент на коленке: 10 локальных моделей, два harness и домен, купленный посреди эксперимента
Мы захотели понять, годятся ли локальные LLM как веб-агенты: дают ли им интернет, поручают ли им настоящие задачи — проверить домен, сравнить цены регистраторов, разобраться с хостингом. Железо самое обычное: RTX 5060 на 8 ГБ, Ollama, Python. За два дня прогнали 10 моделей через две версии обвязки, два эталонных задания, пачку микробенчмарков и два медиа-конвейера. Ниже — что получилось, что сломалось и почему результат зависит от обвязки сильнее, чем от модели.
Спойлер: домен из эталонной задачи мы купили прямо посреди эксперимента — и модели это заметили.
Эксперимент
Две эталонные задачи. Первая — проверить, свободен ли домен wchats.ru, и сравнить цены регистрации и продления .RU минимум у четырёх регистраторов. Вторая, ключевая: сколько стоит продление .RU у хостера Hostland. Хостер цену продления нигде публично не пишет — только правило на сайте («продление равно обычной цене регистрации»), так что задача не гуглится в лоб и честно решается только навигацией по сайту. Эталон: 299 ₽/год, 2540 ₽ для доменов с чужих регистраторов, регистрация 299 ₽ (по акции 169 ₽).
Модели: шесть «ветеранов» (qwen3.5-4b, qwen3-8b, granite4.1-8b, glm4-9b, qwen3-30b-a3b, glm4.7-flash) и четыре новичка (qwen3.5:9b, gemma4:12b, qwen3.5:27b, Nanonets-OCR2-3B для OCR). Плюс безцензурная qwythos-9b — в микробенчмарках.
Тур 1: текстовый протокол сыпется
Первая обвязка была наивной: ReAct-цикл, модель отвечает строками «SEARCH: … / FETCH: … / DONE: …», скрипт исполняет. Результат: эталонную задачу решили 2 из 6 моделей. Причины видны по ходам: модели выдумывают URL (panel.php?login=guest, /price, /pricing), сжигают ходы на 404-е, а при неудачных загрузках — дорисовывают цены («SpaceWeb 189 ₽», которых никто не называл). Одна glm4.7-flash вообще сгенерировала несуществующий whois-адрес и десять ходов прометалась по 404-м.
Первый рефлекс — «сменить рантайм». Правильный ответ: рантайм не виноват. Ollama — это просто движок; качество теряется в протоколе, в том, что модель видит, и в том, что ей разрешено.
Тур 2: v2 — что изменилось
Вторая обвязка собрана за день и умеет принципиально другое:
Нативный function calling вместо текстового протокола — модели отдают структурированные JSON-вызовы инструментов. Сбои формата: из нескольких за тур — до нуля. Для моделей без поддержки tools остаётся текстовый фолбэк.
Allowlist URL. Загрузка разрешена только на ссылки, реально пришедшие из наблюдений, или на главную известного домена. Выдуманный адрес блокируется с подсказкой живых ссылок со страницы. Это убрало главный убийцу ходов.
Авто-починка 404 (скрипт сам поднимается к родителю и отдаёт ссылки), кэш страниц, анти-луп предупреждения при повторных вызовах, проверка релевантности поисковой выдачи. И плагины: поиск, загрузка с извлечением ссылок, настоящий браузер (Playwright с фолбэком на системный Edge), пассивный recon для багбаунти, OCR, описание картинок, кадры из видео.
Результат: эталонную задачу решили 7 из 8 моделей.
Цифры: задача Hostland в v2
| Модель | Верно? | Время | Примечание |
|---|---|---|---|
| qwen3.5:27b | 10/10 | 350 с | Единственная нашла всё: 299 ₽ + 2540 ₽ для чужих + акцию 169 ₽ |
| gemma4:12b | 8.5/10 | 157 с | Всё верно, лучший формат отчёта |
| qwen3.5:9b | 8/10 | 59 с | Верно; честно отметила «для других регистраторов отличается» |
| qwen3-8b | 8/10 | 36 с | Самая быстрая из верных |
| qwen3.5-4b | 8/10 | 57 с | Верно, анти-луп спас ходы |
| granite4.1-8b | 8/10 | 132 с | Процитировала правило дословно |
| qwen3-30b-a3b | 8/10 | 58 с | Сама вызвала браузер |
| glm4.7-flash | ~ | 96 с | Дошла за 3 хода, финал обрезал лимит токенов (починено) |
Маленькая glm4-9b — чемпион первого тура — во втором рухнула: она не умеет нативный tools-API, а в смешанном режиме путала протоколы. Живое подтверждение тезиса «гибридность протокола — часть контракта».
Микробенчмарки: дисциплина и честность
Чтобы не гонять часовые агентные прогоны ради каждой цифры, собрали стандартизированный сьют: 10 моделей × 8 испытаний (скорость, четыре сценария tool-дисциплины, две ловушки на честность, разбор подсаженных уязвимостей).
| Модель | tok/s | GPU | Tools/4 | Честность/2 | Сек-разбор/4 |
|---|---|---|---|---|---|
| qwen3.5-4b | 70 | 100% | 4 | 2 | 3 |
| qwen3-8b | 64 | 100% | 4 | 1 | 1 |
| granite4.1-8b | 64 | 100% | 4 | 2 | 2 |
| glm4-9b | 64 | 100% | 2 | 1 | 3 |
| qwen3.5:9b | 41 | 100% | 4 | 2 | 2 |
| gemma4:12b | 21 | 100% | 3 | 2 | 3 |
| qwen3.5:27b | 3.2 | гибрид | 4 | 2 | 2 |
| qwen3-30b-a3b | 27 | гибрид | 4 | 2 | 3 |
| glm4.7-flash | 26 | гибрид | 4 | 1 | 1 |
| qwythos-9b-abliterated | 60 | 100% | 4 | 2 | 2 |
Три находки. Микротесты предсказывают живое поведение: провалившие ловушку «данных нет — признайся» (qwen3-8b, glm4-9b, glm4.7-flash) — это ровно те, кто выдумывал цены в реальных задачах. Безцензурные модели — полноценные агенты: qwythos-9b-abliterated дала 4/4 и 2/2 — abliteration не ломает агентное поведение. Слепая зона у всех десяти: CORS со звёздочкой и отсутствие HSTS замечают почти все, но cookie без Secure/HttpOnly не увидел никто — аргумент, что LLM не заменяет сканер.
Картинки и обучающие видео
Заодно собрали конвейеры контента. Картинки: torch cu128 (для Blackwell нужен именно он) + diffusers, Dreamshaper-8 — 2,2–3 секунды на обложку при 2,6 ГБ VRAM, это 1200–1600 картинок в час. Реле «LLM пишет SD-промпт → рендер → VLM-судья»: все пять текстовых моделей, включая крошечную 4b, пишут промпты уровня 8–9/10. Видеоролики «как работает кнопка»: сториборд от LLM → скриншоты Playwright → аннотации → русская озвучка Silero → ffmpeg. Двадцатисекундный ролик собирается сам; LLM-сценарий требует одной человеческой правки (4 из 5 моделей сдают валидный JSON, но нарратив тоньше человеческого).
Сага об инфраструктуре
О чём не пишут в туториалах. За два дня — четыре инцидента. Бан поисковиков: после ~50 запросов DuckDuckGo отдал капчу, Bing — кешированный мусор (на запрос про хостинг — Roblox). Лечится пулом движков и детектором нерелевантности; запасной путь — навигация по ссылкам. Блокировка registry.ollama.ai по IPv4 (при живом IPv6): модели качались напрямую из registry API через curl с резюмом и sha256-проверкой — 34 ГБ, все живые. CDN Playwright недоступен — фолбэк на системный Edge. Убийство процессов OOM при соседстве двух тяжёлых моделей — правило «один тяжёлый резидент за раз».
Домен, купленный посреди эксперимента
Утром модели проверяли wchats.ru — домен был свободен, мы рекомендовали, где покупать. Днём домен купили через Hostland (регистратор-партнёр REGTIME, NS hostland.ru). Вечером модели в тестах уже отвечали «занят» — и формально были правы, хотя двое пришли к этому по кешу поисковика, а трое продолжали уверять, что домен свободен. Урок: ground truth живёт своей жизнью, а агенту нужны прямые инструменты проверки (whois/DNS), иначе он транслирует чужой кеш.
Шесть выводов
1. Обвязка > рантайм. Смена движка не дала бы ничего; переход v1→v2 поднял решение с 2/6 до 7/8. 2. Нативный tool-calling решает формат, не интеллект — ошибки сместились в стратегию, и именно их лечит allowlist и честные ошибки. 3. Размер ≠ агентность: qwen3.5:9b (6,6 ГБ) обходит модели вдвое крупнее; 27b даёт максимум полноты ценой 3 tok/s. 4. Честность — отдельная ось, и она коррелирует между микротестами и живыми задачами. 5. Специалисты бьют универсалов в своей нише: Nanonets-OCR2-3B (4,1 ГБ) всухую обыграла qwen3-vl-8b в распознавании документов. 6. Инфраструктура — часть результата: агент должен уметь деградировать красиво.
Файлы
Весь код исследования — agent.py (v1), agent2.py (v2), pull_v2.py (обход блокировки реестра), bench_suite.py (микробенчмарки), video_make.py и img_bench.py (медиа) — выложим отдельно; вопросы и запросы исходников — в комментариях Дзена или в ВК.