Справочник по API
ollaya serve предоставляет два API на http://localhost:11435:
- нативный API по пути
/api/*, смоделированный по образцу Ollama, для решений и управления моделями; - API, совместимый с TypeSafe, по пути
/v1/*, побитово идентичный TypeSafe, поэтому существующие SDK TypeSafe работают без изменений. См. Совместимость с TypeSafe.
| Метод | Путь | Назначение |
|---|---|---|
GET, HEAD |
/ |
Проверка доступности (liveness): Ollaya is running |
GET |
/api/version |
Версия сервера |
POST |
/api/decide |
Отвечает на типизированные вопросы о состоянии; также загружает и выгружает модель |
GET |
/api/tags |
Модели на этой машине |
POST |
/api/show |
Сведения об одной модели |
GET |
/api/ps |
Модели, загруженные в память |
POST |
/api/pull |
Загрузка модели (потоково передаёт прогресс) |
DELETE |
/api/delete |
Удаление модели |
POST |
/api/copy |
Копирование модели под новым именем |
POST |
/api/create |
Создание модели из другой (потоково передаёт прогресс) |
POST |
/v1/systemone |
TypeSafe System One |
POST |
/v1/decisions |
Псевдоним /v1/systemone |
GET |
/v1/models |
Список моделей TypeSafe |
/api/push и /api/blobs/:digest зарезервированы и отвечают 501 NOT_IMPLEMENTED. Текстовые эндпоинты Ollama (/api/generate, /api/chat, /api/embed) отвечают 404: модели принятия решений никогда не генерируют текст.
Соглашения
- JSON. Тела запросов и ответов — объекты JSON. Тело разбирается как JSON независимо от
Content-Type, поэтомуcurl -dработает как есть. Запросы — не более 8 MiB. - Имена полей —
snake_case. Неизвестные поля запроса игнорируются;nullозначает отсутствие. - Имена моделей —
[host/][namespace/]model[:tag], без учёта регистра. Отсутствующий тег означаетlatest. В ответах всегда используется каноническая форма, напримерlaya:latest. - Числа. Вероятности, уверенности,
scoreиnoulокругляются до 4 знаков после запятой. Длительности — целые числа в наносекундах; отметки времени — RFC 3339 в UTC. - Потоковая передача.
/api/pullи/api/createпередают JSON, разделённый переводами строк, по одному объекту на строку, заканчивая ровно одним{"status":"success"}или строкой ошибки. Отправьте"stream": falseдля единственного ответа. - Идентификаторы запросов. Каждый ответ несёт
X-Request-Id, а ответы/v1/*— ещё иx-typesafe-request-id. ДопустимыйX-Request-Id, отправленный клиентом, возвращается обратно. - Конкурентность. Загруженная модель выполняет по одному запросу за раз, и каждый запрос отвечает на все свои вопросы за один проход. Запросы к одной и той же модели встают в очередь, поэтому отправка большего числа сразу не завершается раньше; время кругового пути каждого тогда включает ожидание. Задавайте все вопросы о состоянии в одном запросе. Разные загруженные модели работают параллельно.
- Никаких неявных загрузок. Ни один эндпоинт не загружает модель как побочный эффект.
ollaya runсначала выполняет загрузку; приложения вызывают/api/pull.
Ошибки
Каждая ошибка на каждом эндпоинте имеет такое тело:
{
"error": "model \"laya:xl\" not found, try pulling it first",
"code": "MODEL_NOT_FOUND"
}
| Поле | Значение |
|---|---|
error |
Сообщение для человека. Не разбирайте его; единственное зафиксированное сообщение — model "<name>" not found, try pulling it first, как в Ollama. |
code |
Машиночитаемый код. Ветвитесь по нему. |
detail |
Только для INVALID_REQUEST, TOO_MANY_OPTIONS, INPUT_TOO_LONG и STATE_TRUNCATED: каждая проблема проверки в форме ValidationError из TypeSafe (FastAPI): loc, msg, type и иногда ctx. |
| Код | HTTP | Когда | Повтор |
|---|---|---|---|
INVALID_JSON |
400 | Тело отсутствует, не JSON или не объект | нет |
INVALID_REQUEST |
422 | Тело не проходит проверку; detail перечисляет все проблемы |
нет |
TOO_MANY_OPTIONS |
422 | Варианты вопроса не укладываются в бюджет вариантов модели | нет |
INPUT_TOO_LONG |
422 | state длиннее 65,536 токенов |
нет |
STATE_TRUNCATED |
422 | /v1/systemone или /v1/decisions отбросил бы часть state, чтобы уложиться в контекст модели |
нет |
UNAUTHORIZED |
401 | Задан OLLAYA_API_KEY, а в запросе нет ключа |
нет |
FORBIDDEN |
403 | Заголовок браузера Origin или Host не разрешён |
нет |
MODEL_NOT_FOUND |
404 | Модель (или цель роутера) отсутствует на этой машине; для загрузки — нет в реестре | нет |
NOT_FOUND |
404 | Такого эндпоинта нет | нет |
METHOD_NOT_ALLOWED |
405 | Эндпоинт есть, метода нет | нет |
OPERATION_IN_PROGRESS |
409 | Загрузка или создание записывает то же имя модели | после её завершения |
REQUEST_TOO_LARGE |
413 | Тело больше 8 MiB | нет |
QUEUE_FULL |
503 | Уже ожидают OLLAYA_MAX_QUEUE запросов; отправляется с Retry-After: 1 |
да |
MODEL_LOAD_FAILED |
500 | Не удалось загрузить модель (повреждённые файлы, память, OLLAYA_LOAD_TIMEOUT) |
редко |
INFERENCE_FAILED |
500 | Исполнитель дал сбой во время решения | да |
STORAGE_ERROR |
500 | Диск заполнен, проблемы с правами или вводом-выводом | нет |
INTERNAL |
500 | Ошибка в коде; подробности — в журнале сервера по идентификатору запроса | да |
UNSUPPORTED_MODEL |
501 | Эта сборка не может запустить формат модели | нет |
NOT_IMPLEMENTED |
501 | Зарезервированный эндпоинт | нет |
REGISTRY_ERROR |
502 | Реестр недоступен или недействителен | да |
DIGEST_MISMATCH |
502 | Загрузка не совпала со своим sha256 и была отброшена | да |
Набор кодов открыт: обрабатывайте неизвестный по его статусу HTTP. Ошибка проверки перечисляет все проблемы сразу:
{
"error": "state: Field required; questions.urgency.score.criteria: List should have at least 2 items after validation, not 1",
"code": "INVALID_REQUEST",
"detail": [
{"loc": ["body", "state"], "msg": "Field required", "type": "missing"},
{
"loc": ["body", "questions", "urgency", "score", "criteria"],
"msg": "List should have at least 2 items after validation, not 1",
"type": "too_short",
"ctx": {"field_type": "List", "min_length": 2, "actual_length": 1}
}
]
}
После начала потока сбой приходит последней строкой той же формы, например {"error": "…", "code": "DIGEST_MISMATCH"}. Проверяйте в каждой строке наличие error, прежде чем читать её как прогресс.
Вопросы
/api/decide, /v1/systemone и /api/create используют одну схему вопросов — схему TypeSafe. Запрос содержит от 1 до 256 вопросов с любыми идентификаторами в качестве ключей; ответы возвращаются в том же порядке.
type |
instructions |
criteria |
Ответ |
|---|---|---|---|
choice |
необязательно | обязательно: объект «метка → описание» или массив меток; от 2 до 255 вариантов | choice, confidence, probabilities |
score |
необязательно | обязательно: массив описаний уровней, уровень 0 первым; от 2 до 10 уровней | score, confidence, legend, probabilities |
noul |
необязательно | необязательно: {"true": "…", "false": "…"} |
noul |
instructionsможет быть строкой, объектом, массивом илиnull. Когда оно отсутствует или равноnull, модель вместо него читает идентификатор вопроса, поэтому описательный идентификатор вродеis_spamработает сам по себе.state— строка, объект или массив, до 65,536 токенов. Если он превышает доступный контекст модели,/api/decideусекает его и сообщаетstate_truncated: true./v1/systemoneи/v1/decisionsвозвращают422 STATE_TRUNCATEDс ответившей моделью вdetail[0].ctx.model.- Ограничения модели. Каждому варианту нужно место в контексте модели: около 125 вариантов для
laya:en(512 токенов) и 250 дляlaya:multilingual(1,024). Больше — это422 TOO_MANY_OPTIONS. Для роутера применяются ограничения цели.
Ответы имеют формы TypeSafe, в таком порядке полей:
type |
Поля |
|---|---|
choice |
choice: наиболее вероятная метка. confidence. probabilities: метка → вероятность, в порядке criteria. |
score |
score: ожидаемый уровень Σ i·pᵢ, который может попасть между уровнями. confidence. legend: "0"… → описание уровня. probabilities: "0"… → вероятность. |
noul |
noul: вероятность того, что утверждение верно. Без confidence, как в TypeSafe. |
confidence — это нормированная верхняя вероятность TypeSafe, (K · pmax − 1) / (K − 1) для K вариантов: 0, когда все варианты равновероятны, и 1, когда один вариант несёт всю вероятность. Формула одинакова для всех моделей, но значение конкретной уверенности — нет: модели откалиброваны по-разному, поэтому подбирайте порог для каждой модели на своих данных. Вероятности калибруются температурами каждой модели. На GPU CUDA работает граф fp16, чьи ответы могут отличаться от fp32 при почти равных вариантах.
keep_alive
Как долго модель остаётся загруженной после завершения запроса, с семантикой Ollama:
| Значение | Смысл |
|---|---|
"5m", "1h30m", "300ms", 300, "300" |
Остаётся загруженной столько времени после запроса |
0, "0", "0s" |
Выгружается сразу после завершения запроса |
-1, "-5m", любое отрицательное значение |
Остаётся загруженной, пока сервер не остановится или не будет явной выгрузки |
отсутствует или null |
OLLAYA_KEEP_ALIVE, по умолчанию 5m |
Таймер запускается при завершении запроса, и побеждает значение последнего запроса. Для роутера он применяется к цели, которая ответила. /v1/* игнорирует keep_alive.
Решение
POST /api/decide
Отвечает на типизированные вопросы о состоянии за один прямой проход. Тело — это тело /v1/systemone плюс нативные параметры; ответ — это ответ TypeSafe плюс нативные поля, поэтому клиент TypeSafe тоже может его разобрать.
| Поле | Тип | Обязательно | Примечания |
|---|---|---|---|
model |
string | да | Имя модели |
state |
string, object or array | да для решения | Без него запрос загружает или выгружает модель (ниже) |
questions |
object | да, если у модели нет встроенных вопросов | Полностью заменяет собственные вопросы модели |
preset |
string | нет | Имя пресета, встроенного или пользовательского, вместо questions |
images |
array of strings | нет | Для модели зрения: изображения PNG, base64 или base64-URL data:. Decider берёт одно; winnow:e4b-vision берёт до 16. См. Изображения |
keep_alive |
string or number | нет | См. keep_alive |
extras |
array of strings | нет | ["laya"] добавляет к каждому ответу собственную уверенность и вероятность действия laya |
stream |
boolean | нет | Зарезервировано; true отклоняется |
curl http://localhost:11435/api/decide -d '{
"model": "laya",
"state": "I was charged twice for my subscription this month. Please refund the second charge.",
"questions": {
"department": {
"type": "choice",
"instructions": "Which team should handle this ticket?",
"criteria": {
"billing": "Payments, invoices and refunds",
"technical": "Bugs, errors and outages",
"account": "Login, profile and settings"
}
},
"urgency": {
"type": "score",
"instructions": "How urgent is this ticket?",
"criteria": ["Can wait", "Needs attention this week", "Needs attention today"]
},
"refund": {
"type": "noul",
"instructions": "The customer asks for money back.",
"criteria": {"true": "Asks for a refund", "false": "Does not ask for a refund"}
}
},
"keep_alive": "10m"
}'
{
"model": "laya:en",
"answers": {
"department": {
"type": "choice",
"choice": "billing",
"confidence": 0.7781,
"probabilities": {"billing": 0.8521, "technical": 0.0611, "account": 0.0868}
},
"urgency": {
"type": "score",
"score": 1.1982,
"confidence": 0.3418,
"legend": {"0": "Can wait", "1": "Needs attention this week", "2": "Needs attention today"},
"probabilities": {"0": 0.1203, "1": 0.5612, "2": 0.3185}
},
"refund": {"type": "noul", "noul": 0.9127}
},
"usage": {"input_tokens": 118, "output_tokens": 0},
"routing": {
"router": "laya:latest",
"model": "laya:en",
"route": "english",
"reason": "English Latin text"
},
"state_truncated": false,
"done_reason": "decide",
"created_at": "2026-09-24T09:30:12.418Z",
"total_duration": 18734512,
"load_duration": 0,
"eval_duration": 16302117
}
| Поле | Значение |
|---|---|
model |
Модель, которая ответила: для роутера — его цель (laya:en для запроса laya) |
answers |
Идентификатор вопроса → ответ, в порядке вопросов |
usage |
Прочитанные input_tokens; output_tokens всегда 0 |
routing |
Для роутера: router, выбранная model, стабильный ключ route и информативный reason. Иначе null. |
state_truncated |
true, если часть состояния отброшена, чтобы уложиться в контекст модели |
done_reason |
"decide", "load" или "unload" |
created_at |
Когда был сформирован ответ |
total_duration |
Наносекунды от получения запроса до ответа, включая ожидание в очереди |
load_duration |
Наносекунды, потраченные на ожидание загрузки модели; 0, когда она была уже загружена |
eval_duration |
Наносекунды в исполнителе: токенизация, прямой проход, калибровка |
С "extras": ["laya"] каждый ответ также содержит объект laya: confidence (основанная на энтропии уверенность laya) и act_probability (из головы действий модели или null).
Изображения
Модель зрения (decider:2b-vision или winnow:e4b-vision) отвечает на вопросы об изображении так же, как о состоянии. Отправьте изображение в images в кодировке base64 — так, как работает images у Ollama:
curl http://localhost:11435/api/decide -d '{
"model": "decider:2b-vision",
"state": "A photo from the warehouse camera.",
"images": ["'"$(base64 -w0 shelf.png)"'"],
"questions": {
"blocked": {"type": "noul", "instructions": "Is the aisle blocked?"},
"fill": {"type": "score", "instructions": "How full is the shelf?", "criteria": ["empty", "half full", "full"]}
}
}'
- Decider: Одно изображение на запрос, только PNG. Предобработка модели воспроизводится значение за значением, поэтому пиксели должны совпадать с тем, что декодируют авторы модели. Декодеры JPEG в Rust отличаются от libjpeg-turbo до 4 уровней на некоторых пикселях, поэтому JPEG пока не принимается: сначала преобразуйте его в PNG.
- Decider: Изображение масштабируется до кратных 32 пикселям размеров, как ожидает модель, и после этого может содержать не более 4,096 патчей по 16x16 пикселей, что составляет примерно один мегапиксель (1024x1024). Слишком большое изображение получает 422 с указанием на это; сначала уменьшите его.
- Decider: Вопросы принимают не более 10 вариантов. Та же модель отвечает и на запросы только с текстом.
- Winnow E4B vision: до 16 упорядоченных PNG, 2–64 варианта на вопрос, в пределах объединённого контекста изображения/состояния/вопроса. Соответствующий проектор загружается отдельно из той же ревизии автора. Существующие текстовые теги Winnow его не загружают.
- Модель, которая не читает изображения, отвечает на запрос с
imagesкодом 422.
/v1/systemone и /v1/decisions остаются идентичными API TypeSafe, в котором нет поля изображения.
Загрузка и выгрузка. Запрос без state и questions никогда не принимает решение. Без keep_alive или с положительным либо отрицательным значением он загружает модель (для роутера — каждую цель) и возвращает done_reason: "load". С keep_alive: 0 он выгружает её ("unload"). ollaya run предзагружает этим способом, а ollaya stop выгружает.
curl http://localhost:11435/api/decide -d '{"model": "laya:en", "keep_alive": -1}'
curl http://localhost:11435/api/decide -d '{"model": "laya:en", "keep_alive": 0}'
Решение не оказывает побочного эффекта на сохранённые данные, поэтому повтор безопасен.
Пресеты
Пресет — это именованный набор вопросов. Шесть встроены (triage, email, guard, moderation, router, agent), и вы можете сохранить свои. Отправьте "preset": "NAME" в /api/decide вместо questions.
curl http://localhost:11435/api/presets/create -d '{
"name": "billing-check",
"description": "Billing, and how upset the customer is",
"questions": {
"billing": {"type": "noul", "instructions": "The message is about a charge, an invoice or a refund."},
"tone": {"type": "choice", "instructions": "How does the customer sound?", "criteria": {"calm": null, "annoyed": null, "angry": null}}
}
}'
curl http://localhost:11435/api/decide -d '{"model": "winnow:e4b", "state": "I was charged twice this month.", "preset": "billing-check"}'
| Эндпоинт | Тело | Действие |
|---|---|---|
GET /api/presets |
– | Сначала встроенные пресеты, затем пользовательские: name, builtin, description, идентификаторы вопросов, modified_at |
POST /api/presets/create |
name, questions, description (необязательно) |
Сохраняет пользовательский пресет, заменяя пресет с тем же именем |
POST /api/presets/show |
name |
Один пресет с его вопросами |
DELETE /api/presets/delete |
name |
Удаляет пользовательский пресет |
Имена — от 1 до 64 символов из строчных букв, цифр, - и _. Встроенное имя нельзя переиспользовать (422) или удалить (403), а неизвестное имя — это 404. Пользовательские пресеты хранятся рядом с моделями, поэтому все клиенты сервера видят одни и те же.
Роутеры
Роутер вроде laya (laya:latest) не имеет весов: для каждого запроса он выбирает одну из своих целей, которая затем отвечает. laya читает только state:
| Состояние | route |
Кто отвечает |
|---|---|---|
| Английский | english |
laya:en |
| Преимущественно нелатинская письменность (арабская, кириллица, CJK, …) | multilingual |
laya:multilingual |
| Латинская письменность, но не английский (турецкий, немецкий, …) | multilingual |
laya:multilingual |
| Совсем нет букв | english (по умолчанию) |
laya:en |
Короткий текст заглавными буквами без диакритики, например названия торговцев в выписке по карте (MIGROS KADIKOY ISTANBUL TR), артикулы или имена пользователей, обычно не поддаётся определению и отправляется в laya:en. Если вы знаете язык, запрашивайте laya:multilingual или laya:en напрямую; поле model в ответе говорит, какой чекпойнт ответил.
Маршрутизация занимает микросекунды. Ветвитесь по route, но никогда по reason, формулировка которого может измениться. laya:typed-decisions никогда не выбирается роутером; запрашивайте его напрямую.
Список локальных моделей
GET /api/tags
Модели на этой машине, сначала самые новые. Каждая запись содержит name, model (то же самое), modified_at, size в байтах, digest (sha256 манифеста, в виде простого hex) и details: parent_model, format (onnx, gguf или router), family, families, parameter_size и quantization_level (точности, которые она несёт, например F16/F32, или квантование модели GGUF, например Q8_0).
{
"models": [
{
"name": "laya:en",
"model": "laya:en",
"modified_at": "2026-09-24T08:11:02.117Z",
"size": 853634822,
"digest": "bf30e4654e9483ff1e6a4fe6fb21b8a71baff6c8a01013046e7d13339020efd7",
"details": {
"parent_model": "",
"format": "onnx",
"family": "laya",
"families": ["laya"],
"parameter_size": "421M",
"quantization_level": "F16/F32"
}
}
]
}
Сведения о модели
POST /api/show
curl http://localhost:11435/api/show -d '{"model": "laya:en"}'
| Поле | Значение |
|---|---|
license |
Текст лицензии |
modelfile |
Modelfile, который воссоздаёт модель |
parameters |
Параметры, заданные для модели, по одному name value в строке, например precision fp32 |
questions |
Встроенные вопросы или null |
router |
Для роутера: strategy, default и routes (route → model). Иначе null. |
details |
Как в /api/tags |
model_info |
general.architecture, general.languages, general.source (закреплённый репозиторий Hugging Face) и специфичные для семейства ключи, например laya.context_length. general.languages перечисляет языки, для которых модель обучалась и оценивалась (multilingual для многих); модель, построенная на многоязычной основе, всё же может читать другие языки, поэтому измеряйте на своих данных. |
capabilities |
Типы вопросов, на которые она отвечает (choice, score, noul), а также act, если у неё есть голова действий |
modified_at |
Как в /api/tags |
Роутер показывается сам по себе, а не разрешается в одну из целей.
Список работающих моделей
GET /api/ps
Загруженные модели, отсортированные по имени. Роутеры никогда не появляются; появляются их загруженные цели. Каждая запись содержит name, model, size (память, RAM плюс VRAM), digest, details (с фактически загруженной точностью: F16 или F32, либо квантование модели GGUF), expires_at (когда она выгрузится, или null, когда остаётся загруженной), size_vram, context_length и device (cpu, cuda:0, metal, …).
Загрузка модели
POST /api/pull
{"model": "laya:en"}
Загружает модель в локальное хранилище и проверяет каждый блоб по его sha256. Загрузка роутера также загружает каждую модель, на которую он маршрутизирует. Загружаются только нужные этой машине слои, блобы, общие для нескольких моделей, загружаются один раз, а прерванные загрузки возобновляются.
Ответ потоково передаёт прогресс со строками статуса Ollama:
{"status":"pulling manifest"}
{"status":"pulling 891102d37268","digest":"sha256:891102d372688fc2a094dac56a384bc537b87c63f21f9f3dac0be2b7cbc8d86c","total":842609210,"completed":420557117}
{"status":"pulling 891102d37268","digest":"sha256:891102d372688fc2a094dac56a384bc537b87c63f21f9f3dac0be2b7cbc8d86c","total":842609210,"completed":842609210}
{"status":"verifying sha256 digest"}
{"status":"writing manifest"}
{"status":"success"}
Модель появляется в /api/tags только после writing manifest. Для роутера есть один success в самом конце. Имя, которое не разбирается, модель, которой нет в реестре, и недоступный реестр — это обычные ошибки HTTP (422, 404, 502) до начала потока, поэтому curl --fail работает. С "stream": false ответ — {"status": "success"} по завершении. Вторая загрузка с тем же именем присоединяется к уже идущей. Повтор безопасен.
Удаление модели
DELETE /api/delete
{"model": "triage"}
Удаляет имя и блобы, которые не использует ни одна другая модель. Загруженная модель выгружается после завершения её запросов; удаление роутера сохраняет его цели. Ответ — 200 с пустым телом и 404 MODEL_NOT_FOUND, когда имени не существует; после тайм-аута считайте это успехом.
Копирование модели
POST /api/copy
{"source": "laya:en", "destination": "my-guardrail"}
Копирует модель под новым именем, перезаписывая существующее назначение. Ответ — 200 с пустым телом.
Создание модели
POST /api/create
API, стоящий за ollaya create -f Modelfile: CLI читает Modelfile и названные в нём файлы и отправляет их содержимое как JSON.
| Поле | Тип | Обязательно | Примечания |
|---|---|---|---|
model |
string | да | Имя для создания |
from |
string | да | Локальная модель, возможно роутер. Она никогда не загружается. |
questions |
object | нет | Встроенные вопросы, проверяемые как запрос решения |
calibration |
object | нет | temperature: до 3 чисел (choice, score, noul). temperature_by_options: "<type>:<2|3-5|6-10|11+>" → число. |
parameters |
object | нет | precision: "fp16" или "fp32", чтобы закрепить один граф |
license |
string or array | нет | Текст(ы) лицензии |
description |
string | нет | Одна строка, показываемая в /v1/models и ollaya show |
stream |
boolean | нет | По умолчанию true |
curl http://localhost:11435/api/create -d '{
"model": "triage",
"from": "laya:en",
"questions": {
"department": {
"type": "choice",
"instructions": "Which team should handle this ticket?",
"criteria": ["billing", "technical", "account"]
}
},
"parameters": {"precision": "fp32"},
"description": "Support ticket triage"
}'
Поток сообщает using existing layer sha256:… для каждого унаследованного слоя, creating new layer sha256:… для каждого нового, затем writing manifest и success. Слои адресуются по содержимому, поэтому повторное создание даёт ту же модель.
Версия
GET /api/version
{"version": "0.1.0"}
Эндпоинты, совместимые с TypeSafe
| Эндпоинт | Описание |
|---|---|
POST /v1/systemone |
Запрос: model, state (обязательно) и questions. Ответ: ровно model, answers и usage. |
POST /v1/decisions |
Псевдоним /v1/systemone |
GET /v1/models |
Локальные модели в виде {"models": [{"name", "description", "release_date"}]} |
/v1/* игнорирует нативные поля вроде keep_alive и extras и никогда не добавляет нативные поля в свои ответы. Ошибки используют то же тело, что и /api/*, которое SDK TypeSafe читает корректно. См. Совместимость с TypeSafe.
Безопасность
Сервер привязывается к 127.0.0.1:11435 и, как Ollama, доверяет локальным вызывающим. Привязка к другому адресу (OLLAYA_HOST=0.0.0.0) позволяет всем, кто может достучаться до порта, запускать решения и загружать, удалять и создавать модели, поэтому:
OLLAYA_API_KEYзаставляет каждый запрос, кромеGET /,HEAD /и предполётного запроса CORS, требоватьAuthorization: Bearer <key>; иначе ответ —401 UNAUTHORIZED. SDK TypeSafe отправляет свой ключ именно так, а CLIollayaотправляет$OLLAYA_API_KEY. Сервер записывает предупреждение, когда слушает за пределами loopback без ключа.- TLS не терминируется сервером; для удалённого доступа поставьте перед ним обратный прокси.
- Браузеры. Запросы с заголовком
Originразрешены только изlocalhost,127.0.0.1,0.0.0.0и[::1](любой порт), веб-представлений приложений и редакторов и источников изOLLAYA_ORIGINS(через запятую, подстановочные знаки*). Сервер на loopback также отклоняет неожиданные заголовкиHost, что блокирует DNS rebinding. - Ваши данные. Состояния и вопросы никогда не журналируются и не отражаются в ошибках.
| Переменная | По умолчанию | Действие |
|---|---|---|
OLLAYA_HOST |
127.0.0.1:11435 |
Адрес привязки; цель клиента. Адрес loopback также слушает [::1], поэтому программы Windows достигают сервера в WSL по localhost без задержки |
OLLAYA_API_KEY |
не задано | Требует Authorization: Bearer <key> |
OLLAYA_ORIGINS |
не задано | Дополнительные разрешённые источники браузера |
OLLAYA_KEEP_ALIVE |
5m |
Значение keep_alive по умолчанию |
OLLAYA_MAX_LOADED_MODELS |
3 |
Ограничение числа загруженных моделей |
OLLAYA_MAX_QUEUE |
512 |
Запросов в обработке до 503 QUEUE_FULL |
OLLAYA_LOAD_TIMEOUT |
5m |
Предельный срок загрузки до 500 MODEL_LOAD_FAILED |
OLLAYA_DEVICE |
auto |
auto, cpu, cuda или cuda:<n> |
OLLAYA_MODELS |
~/.ollaya/models |
Хранилище моделей |
OLLAYA_REGISTRY |
ollaya.dev |
Хост реестра по умолчанию в именах |