diff --git a/docs/proxy-request-priority.md b/docs/proxy-request-priority.md new file mode 100644 index 0000000..5ada8d2 --- /dev/null +++ b/docs/proxy-request-priority.md @@ -0,0 +1,26 @@ +# Request priority on the AI proxy + +One local model instance (llama.cpp on the single R9700) serves every workload through the LiteLLM proxy ([issue #9](https://git.arthurerlich.de/haylan/LLM-Server/issues/9)). Interactive usage shouldn't get stuck behind a batch job. + +## Tiers + +Two tiers, assigned per workload's virtual key (per `docs/proxy-key-onboarding.md`): + +- **High priority** (interactive — someone's waiting): Open WebUI chat, coding CLIs (Claude Code / Kimi / OpenCode), Gitea code review. +- **Low priority** (batch — nobody's watching a spinner): Paperless OCR/tagging, Nextcloud Memories face-recognition, AI watermark removal. + +## Mechanism + +Use LiteLLM's built-in request-prioritization scheduler ([docs](https://docs.litellm.ai/docs/scheduler)) — callers pass a `priority` value, LiteLLM's router queues and dispatches by priority. Per `docs/research/proxy-tool-choice.md`, this feature is real but **beta**: there's a known, closed-as-not-planned bug where the `priority` field can leak into the provider request. Treat it as unproven, not settled: + +- **#14 (compose authoring) must smoke-test the scheduler against llama.cpp specifically** before this is relied on — confirm the `priority` field doesn't leak into llama.cpp's request and actually reorders dispatch under load. +- **If it's broken in practice**, fall back to a lightweight queuing shim in front of the proxy (a small sidecar) rather than reworking the gateway tool choice. Don't build this shim speculatively — only if the smoke test fails. +- Single-instance deployment (this stack) doesn't need Redis for virtual keys/spend, but LiteLLM's scheduler does use Redis for cross-instance state — if the scheduler needs it even single-instance, add a `redis` service to docker-compose.yml at that point, not before. + +## Timeout behavior + +A request queued too long (burst of batch jobs, or the model just being slow) times out and returns an error to the caller — no indefinite waiting. Use LiteLLM's default request timeout unless testing shows it needs tuning. + +## Lazytainer interaction + +No new risk: queueing happens inside LiteLLM *before* it dispatches to llama.cpp. Lazytainer watches actual traffic reaching the llama.cpp container, so it still sees the first dispatched request and wakes the container normally — priority ordering only changes which queued request gets dispatched first, not whether Lazytainer sees traffic.