Гайд · TNWS AI

Как получить embeddings через llama.cpp /v1/embeddings и проверить pooling

4 мин—

Запускаем специализированную embedding-модель, кодируем две строки и проверяем размерность и числовой формат.

Задача и применимость

Поисковый вопрос: «как получить embeddings llama.cpp server pooling v1 embeddings». Получить два сопоставимых вектора для прототипа смыслового поиска без подмены модели обычным чат-LLM. llama.cpp server с подходящей embedding GGUF-моделью и pooling, отличным от none; GET /v1/models и POST /v1/embeddings документированы в README на 20 сентября 2026 года. Точный checkpoint и разрешение его использования выбирает читатель.

Пример рассчитан на уже имеющийся файл модели, полученный законным способом по условиям его лицензии. Здесь не утверждается, что любая GGUF-модель одинаково понимает русский язык или имеет один и тот же чат-шаблон. Фактический номер сборки узнавайте локально через llama-server --version и повторяйте контрольный опыт после обновления бинарника.

Что подтверждено документацией

README предупреждает: /v1/embeddings требует pooling, отличный от none, и выдаёт embeddings, нормализованные по евклидовой норме. --embedding предназначен для выделенной embedding-модели. input может быть строкой или массивом строк. Native /embeddings имеет иной формат и допускает pooling none, поэтому разбор ответов нельзя смешивать.

Порядок действий

  1. Выберите подходящий embedding GGUF по документации автора модели и запустите сервер с --embedding.
  2. Получите фактический идентификатор через /v1/models, чтобы не придумывать поле model.
  3. Передайте массив из двух фраз в /v1/embeddings с encoding_format=float.
  4. Проверьте соответствие индексов строкам, длину и конечность чисел.
  5. Сохраните model id и стратегию pooling рядом с векторами для будущего переиндексирования.

Локальный запуск для описанного сценария (замените путь к файлу на ваш):

./build/bin/llama-server -m /models/your-embedding-model.gguf --embedding --pooling mean --host 127.0.0.1 --port 8080

Готовый шаблон запроса и проверки

import json, math, urllib.request
base = "http://127.0.0.1:8080"
model = json.load(urllib.request.urlopen(base + "/v1/models"))["data"][0]["id"]
texts = ["Возврат заказа за 14 дней", "Доставка по будням"]
body = {"model": model, "input": texts, "encoding_format": "float"}
req = urllib.request.Request(base + "/v1/embeddings",
    data=json.dumps(body, ensure_ascii=False).encode("utf-8"),
    headers={"Content-Type": "application/json"}, method="POST")
with urllib.request.urlopen(req, timeout=90) as reply:
    data = json.load(reply)["data"]
data.sort(key=lambda item: item["index"])
assert len(data) == len(texts)
assert all(len(item["embedding"]) == len(data[0]["embedding"])
           for item in data)
assert all(math.isfinite(v) for item in data for v in item["embedding"])
print("Размерность:", len(data[0]["embedding"]))

Входные данные и ожидаемый результат

Вход: два текста — о возврате и доставке. Ожидаемый выход: две записи data, у каждой числовой embedding одинаковой положительной длины и индекс, соответствующий входной строке. Число координат и сами значения не задаём наперёд: они зависят от выбранного файла GGUF.

Почему важна именно эта проверка

Embedding — числовое представление, а не готовый ответ. Даже удачная генерация массива ещё не показывает, что выбранная модель хорошо ищет русский текст. Попросите эксперта разметить несколько десятков пар запрос–подходящий документ и затем оцените долю правильных попаданий. Если checkpoint обучен преимущественно на другом языке, контрольный тест на русском обязателен. Размерность векторов у разных GGUF может отличаться, но даже при одинаковой размерности смешивать модели в одном индексе нельзя: пространство признаков изменится.

Работа с реальными данными

Отдельная ловушка — pooling none. Native маршрут /embeddings может возвращать вектора отдельных токенов, что полезно для других исследований, но это не одно представление документа, ожидаемое большинством векторных баз. /v1/embeddings требует pooling и выдаёт нормализованный результат. При чтении ответа сначала восстановите порядок через index, потом привяжите каждый вектор к ID документа и метаданным доступа. Если порядок массива был изменён при асинхронной загрузке, поиск может вернуть чужой текст, хотя косинусное сходство выглядит правдоподобно.

Проверка после изменения модели или нагрузки

В примере отправлены искусственные фразы, а не клиентские данные. Для реального RAG заранее определите границы фрагмента: короткий абзац, статья или заголовок, и проверяйте усечение больших текстов по спецификации конкретной модели. Не полагайтесь на прямое сравнение одного значения координаты с порогом качества: оценивают целый вектор и релевантность выдачи на тестовом наборе. После смены стратегии pooling или GGUF пересоздавайте все embeddings корпуса и вопросов. Храните путь к модели, её контрольную сумму и параметры запуска.

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

Критерии приёмки

  1. Получено ровно два вектора и восстановлен порядок по index.
  2. Размерность положительна и одинакова, значения конечны.
  3. Релевантность на русских данных проверена отдельно от синтаксиса API.

Частые ошибки и чего не делать

  • Не запускать обычную чат-модель как embedding-модель без проверки её назначения.
  • Не смешивать /embeddings и /v1/embeddings при разборе.
  • Не объединять в одном индексе векторы разных моделей.

Краткие ответы на вопросы

Нужен ли --embedding?

README описывает его для специализированных embedding-моделей.

Можно ли pooling none?

Не для /v1/embeddings.

Гарантирует ли вектор качество поиска?

Нет, качество измеряют на размеченных примерах.

Официальные источники

Частые вопросы

Нужен ли --embedding?

README описывает его для специализированных embedding-моделей.

Можно ли pooling none?

Не для /v1/embeddings.

Гарантирует ли вектор качество поиска?

Нет, качество измеряют на размеченных примерах.

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

Комментарии

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