Гайд · TNWS AI
Как получить embeddings через llama.cpp /v1/embeddings и проверить pooling
Запускаем специализированную 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, поэтому разбор ответов нельзя смешивать.
Порядок действий
- Выберите подходящий embedding GGUF по документации автора модели и запустите сервер с --embedding.
- Получите фактический идентификатор через /v1/models, чтобы не придумывать поле model.
- Передайте массив из двух фраз в /v1/embeddings с encoding_format=float.
- Проверьте соответствие индексов строкам, длину и конечность чисел.
- Сохраните 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 и измеряйте совпадение результатов с ним.
Критерии приёмки
- Получено ровно два вектора и восстановлен порядок по index.
- Размерность положительна и одинакова, значения конечны.
- Релевантность на русских данных проверена отдельно от синтаксиса API.
Частые ошибки и чего не делать
- Не запускать обычную чат-модель как embedding-модель без проверки её назначения.
- Не смешивать /embeddings и /v1/embeddings при разборе.
- Не объединять в одном индексе векторы разных моделей.
Краткие ответы на вопросы
Нужен ли --embedding?
README описывает его для специализированных embedding-моделей.
Можно ли pooling none?
Не для /v1/embeddings.
Гарантирует ли вектор качество поиска?
Нет, качество измеряют на размеченных примерах.
Официальные источники
Частые вопросы
Нужен ли --embedding?
README описывает его для специализированных embedding-моделей.
Можно ли pooling none?
Не для /v1/embeddings.
Гарантирует ли вектор качество поиска?
Нет, качество измеряют на размеченных примерах.
Читайте также
Как ограничить генерацию llama.cpp через n_predict и проверить причину остановки
Используем native /completion и поля остановки, чтобы отличить заданный лимит от нормального конца ответа.
Как переранжировать найденные документы через llama.cpp /v1/rerank
Запускаем reranker GGUF, подаём список кандидатов и проверяем порядок и связь результата с исходными документами.
Как получить JSON по схеме через response_format в llama.cpp server
Задаём объектную JSON Schema в chat endpoint, разбираем строку content и валидируем обязательные поля отдельно.
Комментарии
Пока тихо. Скажите первое слово