Короткий ответ: harness - это обвязка, а не модель
Harness - это весь код и логика вокруг модели: поиск в вебе, вызов инструментов, сборка и обрезка контекста, память, маршрутизация запросов, разбор ответа и проверки. Модель генерирует токены. Harness решает, что ей показать, какие инструменты разрешить и что сделать с результатом.
Метафора из обсуждения на r/LocalLLaMA точная: модель - двигатель, harness - весь автомобиль (тред). Двигатель без трансмиссии, руля и маршрута никуда не едет. Обратное тоже верно: кузов без мотора не поедет. Это два разных слоя, и путать их дорого.
Универсального ответа «берите готовое» или «стройте своё» нет. Unsloth и MLX Serve в строгом смысле не harness: первый связан с подготовкой и адаптацией модели, второй даёт доступ к модели по API. Набор функций у обоих зависит от версии, поэтому проверять его нужно в документации на конкретную дату. Дальше - как разграничить слои и по каким критериям выбрать.
Что такое harness в LLM и из чего он состоит
Рабочее определение: harness - слой между пользователем или приложением и моделью. Он превращает текстовый генератор в систему, которая умеет что-то делать. Типовые блоки:
- Оркестрация запросов: системный промпт, история диалога, обрезка и переупаковка контекста при переполнении.
- Вызов инструментов (tool calling): схемы инструментов, парсинг вызовов, валидация аргументов, повтор при ошибке.
- Веб-поиск и RAG: запрос, загрузка страниц, извлечение фрагментов, ранжирование, вставка в контекст с цитатами.
- Память: что сохранить между сессиями, что подгрузить, что выбросить.
- Маршрутизация: какая модель обрабатывает запрос, когда включается маленькая локальная, когда большая.
- Логирование и наблюдаемость: трассы вызовов, расход токенов, время ответа, причины падений.
- Ограничения: белый список инструментов, лимиты на файлы и команды, подтверждение опасных действий.
Пример. Запрос «найди актуальные цены на две модели и сравни» требует минимум четырёх шагов: сформировать поисковые запросы, получить страницы, вырезать из них нужные фрагменты, собрать ответ с указанием источников. Модель участвует в каждом шаге, но последовательность задаёт harness.
Термин используют по-разному: в одних обсуждениях harness называют CLI-обёртку для кодинга, в других - весь агентный фреймворк. Договоритесь о значении до спора о выборе, иначе сравниваете разные вещи.
Чем harness отличается от модели и от fine-tuning
Три слоя, которые часто смешивают в один:
- Веса модели. Файлы с параметрами, часто в квантованном виде.
- Инференс-движок. Считает токены: llama.cpp, MLX, vLLM и их аналоги. От движка зависят скорость, поддержка квантований и формат API. Различия между движками разобраны в материале про overfit-рантаймы.
- Harness. Решает, что спросить у модели, с какими инструментами и что делать с ответом.
Fine-tuning меняет веса, harness их не трогает. Правка промптов и обвязки меняет поведение системы без переобучения, поэтому занимает минуты вместо часов на GPU. Аналогия: двигатель, трансмиссия и водитель с маршрутом. Мощность мотора не поможет, если маршрут проложен в стену.
Путаница возникает из-за упаковки. Готовые приложения совмещают движок, клиент и часть обвязки в одном интерфейсе. Пользователь видит один установочный файл и решает, что «всё уже есть».
Unsloth и MLX Serve: это harness или нет
Коротко: скорее нет. Это разные слои стека, и оба полезны, но задачу оркестрации поведения агента целиком они не закрывают.
Что реально умеет Unsloth, а что нет
Unsloth известен как библиотека для ускоренного fine-tuning, в первую очередь LoRA/QLoRA-адаптеров, с экономией памяти по сравнению со стандартными реализациями. Это работа с весами: вы готовите адаптер под свою задачу, а не описываете, как модель должна искать в вебе и вызывать инструменты.
В исходном обсуждении Unsloth упомянут как решение, у которого уже есть веб-поиск и tool calling. Воспринимайте это как формулировку автора вопроса, а не как проверенный факт: состав функций у быстро развивающихся проектов меняется от версии к версии, и сверять его нужно в документации. Даже если часть обвязки там появилась, fine-tuning и агентная оркестрация - разные задачи с разными издержками.
MLX Serve как слой запуска модели
Название отсылает к MLX, фреймворку Apple для вычислений на Apple Silicon. Серверная часть в этом стеке поднимает локальную модель и отдаёт к ней доступ по HTTP, чтобы с ней работали сторонние клиенты. Насколько API совместим с форматом OpenAI и какие эндпоинты доступны, зависит от конкретной реализации: сверяйтесь с документацией сборки, которую ставите.
Практический вывод: MLX Serve - двигатель с коробкой передач. Модель работает и отвечает на запросы, а поиск, инструменты, маршрутизацию и память к нему добавляют отдельно: готовым клиентом, готовым фреймворком или своим кодом. Сам по себе сервер не решает, что модели делать с найденной страницей.
Зачем строить кастомный harness: реальные причины
Совет «попроси Claude или ChatGPT собрать тебе harness» появляется в тредах, где у людей не получается результат с локальными моделями. Причины строить своё существуют, и они конкретные.
Контроль над логикой и интеграция в свои процессы
Готовый инструмент навязывает свой сценарий: свой поиск, свои промпты, свой формат ответа, свои лимиты на инструменты. Как только задача отклоняется от шаблона, начинаются обходные пути.
- Свои источники данных. Внутренняя база знаний, тикеты, документация, локальные файлы. Нужен контроль над тем, что попадает в контекст и в каком порядке.
- Внутренние API. Заказ в биллинге, запрос в CRM, запуск задачи в CI. Готовый клиент такие вызовы не поддержит, а MCP-сервер или собственный инструмент - да.
- Жёсткий формат ответа. JSON по схеме, обязательные поля, цитата на каждый факт. Проверку схемы проще встроить в свой слой, чем надеяться на инструкции в промпте.
- Аудит и воспроизводимость. Требование показать, какие инструменты вызывались и какие данные ушли в модель, часто решает выбор в пользу своего кода.
- Метрики. Свои трассы вызовов, расход токенов, доля успешно закрытых задач.
Пример: пайплайн, который раз в сутки собирает изменения в документации, вытаскивает различия, прогоняет их через локальную модель и складывает отчёт в корпоративный мессенджер. Универсальный чат-клиент такое не сделает без вашего кода.
Эксперименты и обучение как отдельная цель
Автор обсуждения сам предполагает, что часть мотивации - тюнинг и эксперименты как хобби. Это честная причина. Если цель разобраться, как работает tool calling, что происходит с контекстом при длинных ответах и почему агент зацикливается, свой harness даёт ответ быстрее любого гайда.
Разница только в честности с собой: обучение и производственная необходимость - разные бюджеты. В первом случае нормально потратить выходные на код, который не пойдёт в работу. Во втором считайте стоимость поддержки и риск.
Издержки кастомной обвязки: что придётся заплатить
Самодельный harness - проект со своим жизненным циклом. Основные статьи расходов:
- Поддержка кода. Обновления моделей, форматов квантования и API ломают совместимость. Свой веб-поиск - это запрос, парсинг, дедупликация, ранжирование, обрезка контекста и цитаты. Каждый пункт ломается по-своему.
- Отладка промптов. Изменение одной инструкции меняет поведение на всех сценариях сразу. Нужен набор тестовых задач, иначе регрессии находят пользователи.
- Обработка ошибок. Таймауты, повторы, частичные ответы, невалидный JSON от модели, пустой результат инструмента. На каждую ситуацию нужно решение.
- Безопасность. Инъекции промптов через найденные страницы и прочитанные файлы, доступ инструментов к файловой системе и сети, подтверждение опасных действий. Готовые инструменты берут часть этого на себя.
- Токены и время. Агентный цикл читает контекст многократно. Длинная история плюс результаты поиска быстро упираются в лимит окна, начинается обрезка, и качество падает.
- Галлюцинации на стыках. Модель уверенно вызывает несуществующий инструмент или подставляет выдуманный аргумент. Валидация и повторные попытки - обязательная часть, а не улучшение.
Похожая логика работает и в других слоях стека: специализированный форк движка под одну модель обещает ускорение, но требует постоянного сопровождения. Разбор этой цены есть в материале про кастомную сборку llama.cpp. С harness то же самое, только ставки выше: ошибка в обвязке выглядит как «модель тупая», хотя модель может быть в порядке.
Практические критерии выбора: готовое или своё
Решайте по задаче, а не по принципу. Четыре вопроса отсекают лишнее:
- Задача типовая (чат, поиск, чтение документов) или в ней есть уникальная логика?
- Нужны свои данные, внутренние API или специфический формат ответа?
- Есть требования к аудиту и воспроизводимости?
- Кто будет поддерживать код через три месяца?
Когда достаточно готового инструмента
Признаки, что строить своё рано:
- Сценарий стандартный: вопросы по документам, поиск в вебе, черновики текста, разбор файлов.
- Своих источников и API нет.
- Результат нужен сегодня, а не через две недели.
- Нет ресурса на поддержку и тесты.
- Вы ещё не поняли, чего именно не хватает: жалоба «плохо отвечает» чаще лечится моделью, квантованием и промптом, а не обвязкой.
Когда кастомный harness оправдан
- Логика уникальна и повторяется: сбор данных из нескольких источников, вызовы внутренних сервисов, проверки по правилам.
- Нужен контроль над тем, какие инструменты доступны и что логируется.
- Требуется воспроизводимость: одинаковый вход даёт одинаковый маршрут обработки.
- Идут эксперименты с агентными пайплайнами, нужна свобода менять каждый шаг.
- Обучение - самостоятельная цель.
Между двумя крайностями есть рабочий вариант: готовый сервер локальной модели плюс лёгкая надстройка своим кодом на 200-500 строк. Сервер отвечает за инференс и API, скрипт - за поиск, инструменты и формат ответа. Такой гибрид закрывает большинство личных задач и не превращается во второй проект.
| Критерий | Готовый инструмент | Кастомный harness |
|---|---|---|
| Сценарий | Типовой чат, поиск, документы | Уникальная логика и интеграции |
| Свои данные и API | Не нужны или хватает загрузки файлов | Обязательны |
| Время до результата | Часы | Дни и недели |
| Поддержка | На разработчике инструмента | На вас |
| Гибкость | Ограничена функциями инструмента | Полная |
| Основной риск | Упёрлись в потолок функций | Утонули в отладке и поддержке |
Автор обсуждения прямо оговаривает, что ждёт разбора различий, а не универсального рецепта (тред). Это правильная рамка: выбор зависит от задачи, бюджета времени и готовности поддерживать код.
Как это выглядит на M5 Max и 64 ГБ RAM
Apple Silicon использует unified memory: CPU и GPU работают с одним пулом оперативной памяти. Для локальных LLM это удобно, потому что модель не нужно делить между дискретной видеопамятью и системной RAM. Практический потолок задаёт объём пула и скорость его чтения.
Прикидка по объёму: 4-битное квантование даёт примерно 0,5 ГБ на миллиард параметров плюс запас. Модель на 8B - около 5 ГБ весов, на 30B - около 18 ГБ, на 70B - около 40 ГБ. Это арифметика, а не замеры: к весам добавятся KV-кэш под длину контекста, буферы и сама система. 64 ГБ позволяют работать с моделями среднего размера с запасом на контекст, а на 70B остаётся мало места под длинные диалоги.
Скорость зависит от квантования, размера модели и длины контекста. Гоняться за большими числами токенов в секунду на такой машине смысла мало: агентный цикл с поиском и инструментами упирается в количество шагов, а не в один ответ.
Что это значит для выбора. На M5 Max реалистичны оба пути: готовый сервер с клиентом и лёгкий кастомный harness поверх того же API. MLX-стек ориентирован на Apple Silicon, поэтому он естественный кандидат в слой запуска. Многошаговые агенты с десятком инструментов на 30B-модели будут заметно медленнее облачных, и это стоит учитывать до того, как писать свой оркестратор.
С чего начать: последовательность шагов
- Освойте готовое. Поднимите локальный сервер с моделью и поработайте с ним неделю на своих реальных задачах. Записывайте, где именно не хватает функций.
- Добавьте тонкий слой. Скрипт, который вызывает локальный API, делает поиск и подставляет результаты в промпт, закрывает половину запросов «мне нужен свой harness». Для кодинга логика похожая: разбор того, как harness влияет на качество малых моделей, есть в материале little-coder против Pi.
- Стройте полноценную обвязку, когда появились требования. Логирование, валидация инструментов, обработка ошибок, тестовый набор задач. Связка модели и harness в локальном кодинге разобрана в статье про локальный coding: там видно, где заканчиваются возможности модели и начинается работа обвязки.
- Используйте Claude и ChatGPT как подрядчиков по коду. Они помогают написать парсер, схему инструментов или обработчик таймаутов. Архитектуру, отладку и ответственность за поведение системы они не берут.
Harness - инструмент под задачу, а не обязательный этап взросления в локальных LLM. Если готовая связка сервера и клиента даёт нужный результат, стройте своё только тогда, когда появилась причина, которую можно назвать одним предложением.