Гайд · TNWS AI

Как запретить обрезку текста в Ollama Embed API через truncate:false

6 мин

Отправляем длинный input в /api/embed, отключаем скрытое усечение и требуем ошибку вместо embedding для неполного документа.

Задача и критерий готовности

Практическая задача — не допустить незаметной потери конца документа при построении embedding, заставив API отклонить вход, который не помещается в контекст. Готовность подтверждается программным тестом, а не впечатлением от текста. Для каждого сценария ниже заданы вход, ожидаемый наблюдаемый признак и негативная проверка.

Контракт сверён 12 сентября 2026 года по официальной документации Ollama API. Цены, тарифы, региональная доступность и неподтверждённые лимиты не используются: они не нужны для выполнения задачи.

Подтверждённые факты

  • POST /api/embed принимает boolean-параметр truncate.
  • По умолчанию truncate равен true и конец слишком длинного input обрезается.
  • При truncate:false API возвращает ошибку, если input превышает context length.
  • Параметр применяется к тексту или списку текстов в поле input.
  • Правильное исправление длинного документа — явное разбиение на chunks, а не повтор с молчаливой обрезкой.

Эти пункты задают границу решения. Не расширяйте их предположениями: наличие поля не гарантирует истинность содержимого, HTTP 200 не подтверждает бизнес-состояние, а комментарий в коде не заменяет assert.

Подготовка стенда

  • Зафиксируйте версию SDK, Ollama и точное имя тестовой модели.
  • Используйте fake tool или provider stub для сценариев с побочными эффектами.
  • Удалите токены, персональные данные, реальные счета и внутренние пути.
  • Добавьте счётчики model calls и tool executions.
  • Настройте завершение процесса с ошибкой при несовпадении контракта.

Тестовый ввод должен быть небольшим, но реалистичным. Идентификаторы T-781 и INV-781 в статье вымышлены. Для длинного текста создавайте синтетическую строку без копирования пользовательских документов.

Пошаговые действия

  1. Для индексатора задайте truncate:false во всех embed-запросах.
  2. Проверяйте HTTP status до чтения embeddings.
  3. При ошибке длины разбейте документ по смысловым границам и сохраните chunk id плюс позицию.
  4. Негативный тест отправляет заведомо длинную тестовую строку; точный предел берётся из вашей модели, а не выдумывается в статье.

После каждого действия сохраняйте минимальное доказательство: класс объекта, длину списка, status code, обязательное поле JSON или порядок событий. Полный prompt и raw payload в журнал не нужны.

Копируемый пример

Сохраните пример как отдельный файл языка javascript. Значения в угловых скобках — заполнители; их нельзя выдавать за реальные digest или идентификаторы.

const payload = {
  model: "all-minilm",
  input: documentText,
  truncate: false
};
const res = await fetch("http://localhost:11434/api/embed", {
  method: "POST",
  headers: {"content-type": "application/json"},
  body: JSON.stringify(payload)
});
if (!res.ok) {
  const detail = await res.text();
  throw new Error("embed rejected: " + res.status + " " + detail);
}
const data = await res.json();
if (!Array.isArray(data.embeddings) || data.embeddings.length !== 1)
  throw new Error("unexpected embeddings shape");

Python запускайте в virtualenv проекта, JavaScript — как .mjs в Node.js с fetch. Не смешивайте глобальную и проектную версии. Если импорт отсутствует, сначала проверьте установленную версию, а не подбирайте похожий API.

Реалистичный вход

Вход A — один короткий абзац. Вход B — синтетический текст, который гарантированно превышает context length установленной embedding-модели.

Ожидаемый результат

A возвращает один vector. B при truncate:false завершается ошибкой и не попадает в индекс как будто документ обработан полностью.

Ожидание перенесите в assert или throw. Если текст модели недетерминирован, сравнивайте структурный инвариант. Если API возвращает массив, проверяйте число элементов и форму каждого.

Негативная проверка

Уберите truncate:false. Запрос B может вернуть embedding усечённого текста; тест должен показать, почему успешный status без контроля параметра опасен.

Негативный тест должен ломать ровно одно условие. Сетевая ошибка не равна 404, пустой список не равен PASS, новый запуск не равен resume, а локально созданный UUID не равен response ID провайдера.

Готовый prompt для ревью

Проверь embed-клиент: truncate явно false, ошибка длины не проглатывается, документ режется на адресуемые chunks, число embeddings совпадает с числом входов.

Верни таблицу: условие, доказательство из кода или очищенного лога, PASS/FAIL, минимальное исправление. Если доказательства нет — FAIL. Не додумывай версии, статусы и результаты.

Prompt помогает найти пропуски, но не заменяет исполнение. Вручную проверьте каждую ссылку ревьюера на код: комментарий может быть ошибочно принят за работающую защиту.

Независимая проверка

Составьте матрицу из штатного, ошибочного и пограничного входа. Для каждой строки укажите ожидаемую ветку, наблюдаемый признак и фактический результат. Повторите тест дважды, чтобы обнаружить кеш, старое состояние или двойной side effect.

Для agent run отдельно считайте model responses, tools и RunItem: это разные сущности. Для Ollama проверяйте HTTP и тело. Если операция изменяет модель или индекс, после неё используйте read-only endpoint или схему хранилища как второе доказательство.

В CI сохраняйте exit code, версии и безопасные агрегаты. Не сохраняйте полный raw response, словарь tokenizer, пользовательский prompt или tool arguments без отдельной политики редактирования.

Типичные ошибки

Пустой список принимают за успех

Конструкции вроде all([]) истинны. Если ожидается конкретный guardrail или embedding, сначала проверьте количество элементов, затем их свойства.

Логируют всё для удобства

Raw responses, arguments и verbose model_info могут быть большими или чувствительными. Создайте allowlist полей и сохраняйте только агрегаты, нужные для расследования.

Смешивают идентификаторы

Response ID, trace ID, tool call ID, model tag и SHA-256 отвечают на разные вопросы. Храните их в отдельных колонках и не генерируйте подмену для отсутствующего значения.

Не проверяют версию

Поведение после обновления может измениться. Версия и точное имя модели должны быть частью воспроизводимого отчёта, особенно для snapshot-тестов и tokenizer-данных.

Чек-лист финальной проверки

  • Тема, title и slug уникальны.
  • API и поля сверены по первоисточнику 12 сентября 2026 года.
  • Есть точный вход и программируемый ожидаемый результат.
  • Негативный тест активирует нужную противоположную ветку.
  • Секреты, PII и реальные реквизиты исключены.
  • Счётчики разделяют model, tool и item events.
  • Проверяется форма массива и каждый элемент.
  • Полный raw или verbose payload не уходит в журнал.
  • Повторный запуск не создаёт ложный успех.
  • Ограничения не заменены выдуманными метриками.

Ограничения

Этот материал проверяет один технический контракт, но не точность модели, безопасность всей системы и не производительность вашего сервера. Конкретные пределы контекста, поддерживаемые dimensions, размеры и скорость зависят от модели и окружения; их измеряют на собственном стенде.

Approval не заменяет авторизацию, typed output не гарантирует истинность, release ссылок не обещает мгновенное падение RSS, а seed не гарантирует одинаковый ответ после смены модели. Такие границы должны оставаться явными в рабочей документации.

FAQ

Почему нет универсальных чисел?

Потому что они зависят от версии и модели. Используйте фактический ответ вашего стенда и фиксируйте дату измерения.

Достаточно ли HTTP 200?

Нет. Проверяйте контрактный status, обязательные поля и при необходимости независимое состояние.

Можно ли доверить проверку нейросети?

Она полезна для ревью, но PASS выставляет исполняемый тест или проверенный ответ API.

Что сохранять в отчёте?

Версии, безопасные идентификаторы, агрегаты, exit code и результат каждого assert — без секретов и полного пользовательского содержимого.

Первоисточник

Материал подготовлен самостоятельно; примеры не выдают синтетические данные за результаты реального бенчмарка.

Читайте также

Комментарии

Пока тихо. Скажите первое слово