Гайд · TNWS AI
Как создать модель Ollama из каталога Safetensors через API
Загружаем каждый файл каталога как blob, собираем отображение files, вызываем /api/create и проверяем финальный status:"success".
Задача и практический результат
Цель этого гайда — создать локальную модель из полного Safetensors-каталога, передав Ollama проверенное отображение имён файлов в SHA-256 blobs. Результат считается готовым только при наличии машинно проверяемого доказательства: конкретного типа, HTTP-статуса, поля JSON, элемента истории или счётчика вызовов. Красивый ответ модели и отсутствие исключения сами по себе успех не подтверждают.
Названия методов и полей сверены 12 сентября 2026 года по официальной документации Ollama API. В материал не включены неподтверждённые цены, лимиты, региональная доступность и результаты производительности: они не нужны для выполнения описанного контракта. При обновлении пакета или сервера запустите тесты повторно.
Подтверждённый контракт
POST /api/createпринимаетfilesкак словарь имя файла → SHA-256 digest.- Перед create каждый файл Safetensors-каталога нужно загрузить через blob endpoint.
- В официальном примере присутствуют config, tokenizer-related JSON и model.safetensors.
- Blob-файлы Safetensors остаются в cache до перезапуска Ollama server.
- Успешное завершение create подтверждается финальным
status:"success".
Каждый пункт выше превращается в отдельную проверку. Не объединяйте их в одну расплывчатую проверку вроде «запрос прошёл». Например, HTTP 200 не заменяет проверку status в теле, а подсказка type checker не заменяет runtime-валидацию. Такой подход особенно важен в агентных системах, где модельный ответ, tool call и локальная бизнес-логика имеют разные жизненные циклы.
Что подготовить
- отдельное тестовое окружение и зафиксированную версию зависимости или сервера;
- обезличенный вход без API-ключей, cookie, реальных реквизитов и персональных данных;
- fake tool или model stub, если сценарий способен вызвать внешний side effect;
- лог событий с точными полями, но без полного пользовательского диалога;
- автоматическую проверку, завершающую процесс ошибкой при несовпадении контракта.
До запуска определите, какой эффект допустим. Проверка чтения может обращаться к тестовому endpoint, но публикацию, оплату, удаление и отправку сообщений следует заменить счётчиком или sandbox-реализацией. Retry и resume нельзя тестировать на реальной операции, которую опасно выполнить дважды.
Пошаговая настройка
- Сформируйте allowlist обязательных файлов каталога; не отправляйте случайные README, секреты или скрытые файлы.
- Для каждого файла вычислите SHA-256, загрузите blob и подтвердите HEAD 200.
- Соберите объект
files, где ключи совпадают с исходными именами, а значения содержат полный digest. - Вызовите
/api/createсstream:false, проверьтеstatus:"success", затем найдите новое имя через/api/tags.
После каждого шага фиксируйте наблюдаемый результат. Если проверяется порядок, храните массив событий. Если тип — используйте isinstance или строгий runtime-флаг. Если HTTP API — проверяйте и status code, и обязательные поля тела. Если состояние сервера — подтверждайте его отдельным read-only endpoint.
Готовый минимальный пример
Сохраните код в отдельный файл. Заполнители в угловых скобках нельзя отправлять как реальные digest или идентификаторы. Пример намеренно останавливается при несовпадении: тихое продолжение превратило бы ошибку в ложный успех.
const files = {
"config.json": "sha256:<digest-config>",
"generation_config.json": "sha256:<digest-generation>",
"special_tokens_map.json": "sha256:<digest-special>",
"tokenizer.json": "sha256:<digest-tokenizer>",
"tokenizer_config.json": "sha256:<digest-tokenizer-config>",
"model.safetensors": "sha256:<digest-model>"
};
// Значения выше заменяются только digest, подтверждёнными HEAD 200.
const res = await fetch("http://localhost:11434/api/create", {
method: "POST",
headers: {"content-type": "application/json"},
body: JSON.stringify({model: "support-local", files, stream: false}),
});
if (!res.ok) throw new Error("create HTTP " + res.status);
const data = await res.json();
if (data.status !== "success") throw new Error(JSON.stringify(data));
const tags = await (await fetch("http://localhost:11434/api/tags")).json();
if (!tags.models.some(x => x.name === "support-local:latest" || x.name === "support-local"))
throw new Error("model not listed");
Для Python запускайте файл в virtualenv проекта. JavaScript-пример сохраните как .mjs и используйте Node.js с глобальным fetch. Не смешивайте глобальную и проектную версии SDK. Перед первым интеграционным запросом выведите только безопасные параметры: endpoint, имя тестовой модели и версию, но никогда токен.
Реалистичный вход
Вход: локальный каталог совместимой модели с шестью перечисленными файлами; каждому соответствует digest уже загруженного blob.
Ожидаемый результат
Create возвращает единичный JSON status:"success" при stream:false, а /api/tags содержит новое точное имя. Это подтверждает регистрацию, но не качество ответов модели.
Запишите это ожидание в assert или явный throw. Естественно-языковой текст может меняться, поэтому тестируйте стабильный инвариант. Для типов это класс объекта, для approval — число interruptions и executions, для blob — точный status, для create — финальное поле success и независимое присутствие новой записи.
Обязательный негативный тест
Удалите из files tokenizer.json либо подмените один digest. Create должен завершиться ошибкой, и проверка tags не должна объявить старую одноимённую запись доказательством новой сборки.
Негативный сценарий запускайте в том же окружении. Он должен сломать ровно проверяемое условие, а не весь стенд. Сетевая недоступность не равна 404, TypeError не равен отказу модели, новый Runner не равен resume, а старое имя в каталоге не доказывает успешную пересборку. Эти различия следует выразить кодом.
Копируемый prompt для ревью
Проверь манифест Safetensors для Ollama: каждый файл имеет подтверждённый blob, имена не изменены, stream:false, status success проверяется, а финальная запись сверяется через /api/tags.
Ответ верни таблицей: проверяемое условие, доказательство из кода или лога, PASS/FAIL, минимальное исправление. Не додумывай версии, статусы и результаты. Если доказательства нет, ставь FAIL.
Прикладывайте к prompt минимальный код и очищенный лог. После ответа вручную откройте указанные строки: языковая модель может принять комментарий за работающую проверку. Prompt помогает организовать ревью, но не заменяет запуск тестов.
Как проверить результат независимо
Сделайте таблицу минимум из трёх строк: штатный ввод, намеренно ошибочный ввод и пограничное значение. Для каждой укажите ожидаемую ветку, наблюдаемый признак и фактический результат. Если используется provider stub, считайте модельные обращения. Если tool fake — считайте исполнения. Если API — сохраните status и минимальный JSON без чувствительных данных.
Повторите тест дважды. Второй запуск не должен неожиданно удваивать side effect, использовать старый объект или принимать кешированный результат за новый. Для операций создания выбирайте уникальное тестовое имя и после проверки сверяйте именно его. Для content-addressed blobs сравнивайте полный SHA-256, а не начало строки.
В CI фиксируйте версии и exit code. Не сохраняйте сырой prompt, полный raw response или пути пользователя, если они содержат данные. Для диагностики достаточно response id, типа события, статуса и контрольного digest — при условии, что каждый из них получен из реального ответа, а не создан локально для красоты.
Типичные ошибки
Проверяется только счастливый путь
Такой тест может никогда не войти в нужную ветку. Добавьте управляемое несовпадение типа, отсутствующий digest, отказ approval или изменённую историю. Убедитесь, что тест падает именно по ожидаемой причине.
Разные идентификаторы смешиваются
Response ID, trace ID, tool call ID, SHA-256 digest и имя модели служат разным задачам. Не подменяйте один другим и не генерируйте локальное значение там, где нужен идентификатор сервера.
Успех объявляется слишком рано
Ответ transport-уровня ещё не подтверждает бизнес-состояние. После POST проверьте обязательное поле, после create — каталог моделей, после approval — счётчик tool, после преобразования — runtime-тип.
Ошибка версии маскируется fallback-кодом
Если метода или параметра нет, зафиксируйте несовместимость. Универсальный except, возвращающий «готово», делает документацию недостоверной и скрывает регрессию.
Чек-лист финальной проверки
- Title, slug и тема не повторяют существующую публикацию.
- Точные имена API сверены по официальному источнику 12 сентября 2026 года.
- В коде нет секретов и реальных пользовательских данных.
- Успешная ветка проверяет точный тип, status, поле или состояние.
- Негативная ветка действительно активирует противоположный исход.
- Fake tool или stub считает обращения, если возможен side effect.
- Не смешиваются response ID, trace ID, call ID и digest.
- Повторный запуск не создаёт ложный или двойной результат.
- Ограничения не заменены выдуманными метриками.
- После обновления версии тест можно запустить повторно.
Ограничения
Руководство проверяет один технический контракт, а не безопасность всей системы, качество модели или экономическую эффективность. Конкретные задержки, расход памяти, размер файла и точность зависят от модели и инфраструктуры; без воспроизводимого измерения их нельзя превращать в обещание.
Учитывайте доверительную границу. Локальный Ollama endpoint при публикации в сеть требует собственной защиты. Approval в SDK не заменяет серверную авторизацию. Освобождение ссылок Python не гарантирует мгновенное уменьшение RSS. Типизированный output не гарантирует истинность извлечённых данных. Эти риски проверяются отдельными слоями.
FAQ
Почему в статье нет цен и универсальных лимитов?
Они не участвуют в данном контракте и меняются независимо. Если стоимость нужна вашему проекту, сверяйте официальный pricing в день расчёта с валютой и единицей тарификации.
Можно ли считать HTTP 200 достаточной проверкой?
Нет. Используйте точный статус из официального контракта и проверяйте обязательные поля или состояние через независимый endpoint.
Зачем сохранять версию?
Имена методов и поведение меняются. Версия позволяет воспроизвести результат и отличить ошибку интеграции от изменения SDK или сервера.
Можно ли доверить финальную проверку нейросети?
Нет. Она может провести ревью структуры, но фактический PASS должен выставлять исполняемый тест или проверенный ответ API.
Первоисточник
- Официальная документация Ollama API — проверено 12 сентября 2026 года.
Материал написан самостоятельно по контракту первоисточника. Примеры используют тестовые идентификаторы и не являются результатами скрытого бенчмарка.
Читайте также
Как использовать raw mode в Ollama /api/generate без двойного шаблона
Передаём готовый шаблон prompt с raw:true, отключаем автоматическое форматирование и проверяем отсутствие context в ответе raw mode.
Как квантовать FP16-модель через Ollama API /api/create
Создаём отдельный q4_K_M-вариант из FP16-модели, проверяем progress, финальный success и не перезаписываем исходное имя.
Как подключить LoRA adapter при создании модели через Ollama API
Загружаем adapter как blob, передаём словарь adapters в /api/create, проверяем success и сохраняем базовую модель без изменений.
Комментарии
Пока тихо. Скажите первое слово