文件導航

API 參考

ollaya serve 在 http://localhost:11435 上暴露兩個 API:

  • 原生 API,位於 /api/* 下,仿照 Ollama 的設計,用於決策和模型管理;
  • TypeSafe 相容 API,位於 /v1/* 下,與 TypeSafe 的線上格式完全一致,所以現有的 TypeSafe SDK 無需改動即可使用。見 TypeSafe 相容性。
方法 路徑 用途
GET、HEAD / 存活檢查: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 物件。無論 Content-Type 是什麼,請求體都按 JSON 解析,所以 curl -d 直接可用。請求最大 8 MiB。
  • 欄位名是 snake_case。未知的請求欄位會被忽略;null 表示預設。
  • 模型名是 [host/][namespace/]model[:tag],不區分大小寫。省略 tag 表示 latest。響應始終使用規範形式,如 laya:latest。
  • 數字。 機率、置信度、score 和 noul 四捨五入到 4 位小數。時長是以納秒計的整數;時間戳是 UTC 的 RFC 3339。
  • 流式傳輸。 /api/pull 和 /api/create 流式傳輸以換行分隔的 JSON,每行一個物件,最後恰好以一個 {"status":"success"} 或一行錯誤結束。要單個響應就傳送 "stream": false。
  • 請求 ID。 每個響應都帶 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 出現:每個校驗問題,採用 TypeSafe(FastAPI)的 ValidationError 形狀:loc、msg、type,有時還有 ctx。
程式碼 HTTP 出現時機 重試
INVALID_JSON 400 請求體缺失、不是 JSON,或不是物件 否
INVALID_REQUEST 422 請求體未通過校驗;detail 列出每個問題 否
TOO_MANY_OPTIONS 422 一個問題的選項超出了模型的選項預算 否
INPUT_TOO_LONG 422 state 超過 65,536 個 token 否
STATE_TRUNCATED 422 /v1/systemone 或 /v1/decisions 為了塞進模型的上下文會丟掉 state 的一部分 否
UNAUTHORIZED 401 設定了 OLLAYA_API_KEY 而請求沒帶金鑰 否
FORBIDDEN 403 瀏覽器的 Origin 或 Host 頭不被允許 否
MODEL_NOT_FOUND 404 模型(或路由器的目標)不在這臺機器上;對拉取而言,是不在 registry 裡 否
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 磁碟已滿、許可權或 I/O 否
INTERNAL 500 程式缺陷;伺服器日誌在請求 ID 下有詳情 是
UNSUPPORTED_MODEL 501 這個構建無法執行該模型的格式 否
NOT_IMPLEMENTED 501 保留端點 否
REGISTRY_ERROR 502 registry 無法訪問或無效 是
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 共用同一套問題 schema,即 TypeSafe 的。一個請求有 1–256 個問題,以任意 id 為鍵;答案按相同順序返回。

type instructions criteria 答案
choice 可選 必填:物件 標籤 → 描述,或一組標籤的陣列;2–255 個選項 choice、confidence、probabilities
score 可選 必填:檔位描述的陣列,從檔位 0 開始;2–10 個檔位 score、confidence、legend、probabilities
noul 可選 可選:{"true": "…", "false": "…"} noul
  • instructions 可以是字串、物件、陣列或 null。當它預設或為 null 時,模型改為讀取問題 id,所以像 is_spam 這樣有描述性的 id 本身就能用。
  • state 是字串、物件或陣列,最多 65,536 個 token。如果它超出模型可用的上下文,/api/decide 會截斷它並報告 state_truncated: true。/v1/systemone 和 /v1/decisions 返回 422 STATE_TRUNCATED,並在 detail[0].ctx.model 裡給出作答的模型。
  • 模型限制。 每個選項都需要在模型的上下文裡佔空間:laya:en 約 125 個選項(512 token),laya:multilingual 約 250 個(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 個選項即 (K · pmax − 1) / (K − 1):當每個選項等可能時為 0,當一個選項佔盡全部機率時為 1。公式對每個模型都一樣,但一個給定的置信度意味著什麼卻不一樣:各模型的校準不同,所以要在你自己的資料上為每個模型調一個閾值。機率用各模型的溫度來校準。在 CUDA GPU 上跑的是 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 或 array 決策時必填 沒有它,請求會載入或解除安裝模型(見下)
questions object 必填,除非模型有內建問題 完全替換模型自帶的問題
preset string 否 一個 預設 的名字,內建或自定義,用來代替 questions
images 字串陣列 否 對視覺模型:多張 PNG 圖片,base64 或 base64 的 data: URL。Decider 接受一張;winnow:e4b-vision 最多接受 16 張。見 影像
keep_alive string 或 number 否 見 keep_alive
extras 字串陣列 否 ["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 請求對應 laya:en)
answers 問題 id → 答案,按問題順序
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 在執行器裡花掉的納秒數:tokenization、前向傳播、校準

帶上 "extras": ["laya"] 時,每條答案還會有一個 laya 物件:confidence(laya 基於熵的置信度)和 act_probability(來自模型的動作頭,或 null)。

影像

視覺模型(decider:2b-vision 或 winnow:e4b-vision)既能就狀態、也能就一張圖片回答問題。把圖片以 base64 編碼放在 images 裡傳送,就像 Ollama 的 images 那樣:

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。模型的預處理是逐值復現的,所以畫素必須與模型作者解碼出的一致。Rust 的 JPEG 解碼器與 libjpeg-turbo 在某些畫素上最多差 4 個色階,所以目前還不接受 JPEG:先把它轉成 PNG。
  • Decider: 圖片會按模型期望的方式縮放到 32 畫素的整數倍,之後最多可以有 4,096 個 16x16 畫素的 patch,約一百萬畫素(1024x1024)。更大的圖片會得到一個說明這一點的 422;先把它縮小。
  • Decider: 問題最多 10 個選項。同一個模型也能回答純文本請求。
  • Winnow E4B vision: 最多 16 張有序 PNG,每個問題 2–64 個選項,都在圖片、狀態與問題合併後的上下文之內。對應的投影器從同一作者修訂版單獨下載。現有的 Winnow 文本標籤不會載入它。
  • 一個不讀圖片的模型,遇到帶 images 的請求會返回 422。

/v1/systemone 和 /v1/decisions 與 TypeSafe 的 API 保持完全一致,後者沒有 image 欄位。

載入與解除安裝。 不帶 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、問題 id、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)、SKU 或使用者名稱,通常無法識別,會走 laya:en。如果你知道語言,直接請求 laya:multilingual 或 laya:en;響應裡的 model 會說明是哪個 checkpoint 作答的。

路由只花微秒級的時間。要按 route 分支,絕不要按 reason,它的措辭可能會變。路由器永遠不會挑 laya:typed-decisions;直接請求它。

列出本機模型

GET /api/tags

本機上的模型,最新的在前。每個條目有 name、model(與之相同)、modified_at、以位元組計的 size、digest(manifest 的 sha256,裸十六進位制)和 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 校驗每個 blob。拉取一個路由器也會拉取它路由到的每個模型。只下載本機需要的那幾層,模型之間共享的 blob 只下載一次,中斷的下載會續傳。

響應流式傳輸進度,用 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"}

模型只有在 writing manifest 之後才出現在 /api/tags 裡。對路由器來說,最後只有一個 success。無法解析的名字、registry 裡沒有的模型、以及無法訪問的 registry,都是流開始之前的普通 HTTP 錯誤(422、404、502),所以 curl --fail 能生效。用 "stream": false 時,完成後響應是 {"status": "success"}。對同一個名字的第二次拉取會併入正在進行的那個。可以安全重試。

刪除模型

DELETE /api/delete
{"model": "triage"}

刪除該名字,以及沒有其他模型使用的 blob。已載入的模型在其請求結束後解除安裝;刪除一個路由器會保留它的目標。響應是 200 和空響應體,名字不存在時是 404 MODEL_NOT_FOUND;超時之後,把它當作成功。

複製模型

POST /api/copy
{"source": "laya:en", "destination": "my-guardrail"}

把模型複製成一個新名字,覆蓋已存在的目標。響應是 200 和空響應體。

建立模型

POST /api/create

ollaya create -f Modelfile 背後的 API: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+>" → number。
parameters object 否 precision:"fp16" 或 "fp32",用來固定一個計算圖
license string 或 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/* 相同的響應體,TypeSafe SDK 能正確讀取。見 TypeSafe 相容性。

安全

伺服器繫結到 127.0.0.1:11435,並且像 Ollama 一樣信任本地呼叫方。把它繫結到另一個地址(OLLAYA_HOST=0.0.0.0)會讓所有能連到這個埠的人都能夠跑決策,以及拉取、刪除和建立模型,所以:

  • OLLAYA_API_KEY 會讓除 GET /、HEAD / 和 CORS 預檢之外的每個請求都要求 Authorization: Bearer <key>;否則答案是 401 UNAUTHORIZED。TypeSafe SDK 就是這樣傳送它的金鑰的,ollaya CLI 傳送的是 $OLLAYA_API_KEY。當伺服器在 loopback 之外監聽卻沒設金鑰時,它會記錄一條警告。
  • TLS 不由伺服器終結;要遠端訪問就在前面放一個反向代理。
  • 瀏覽器。 帶 Origin 頭的請求只允許來自 localhost、127.0.0.1、0.0.0.0 和 [::1](任意埠)、應用和編輯器的 webview,以及 OLLAYA_ORIGINS 裡的來源(逗號分隔,* 通配)。loopback 伺服器還會拒絕意外的 Host 頭,這能擋住 DNS 重繫結。
  • 你的資料。 狀態和問題永遠不會被記錄,也永遠不會在錯誤裡回顯。
變數 預設值 作用
OLLAYA_HOST 127.0.0.1:11435 繫結地址;客戶端的目標。loopback 地址還會在 [::1] 上監聽,所以 Windows 程式能無延遲地通過 localhost 訪問 WSL 裡的伺服器
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 名字裡的預設 registry 主機