feat(litellm): embedder primary/failover split — qwen3-embedding on esh-ml1, new qwen3-embedding-bulk on nh3-ml1

Prime's ruling 2026-10-05 (relayed by albok-dev, confirmed directly) replaces
the 2026-09-26 simple-shuffle load-share for embeddings only; the reranker
groups are unchanged. Routing uses LiteLLM per-deployment `order` (semantics
read at source in v1.97.0): lowest order among healthy deployments, and a
failed request retries at the next order.

Verified after the restart (43 s gateway outage): 6/6 calls per alias landed
on its primary. With nh3-ml1 tei-embed stopped, qwen3-embedding-bulk served 6/6
from esh-ml1 with 200s; once nh3-ml1 was back, bulk returned 6/6 to nh3-ml1.
The albok-service key now covers qwen3-embedding-bulk (200); the Nemi key does
not (403).
This commit is contained in:
vh
2026-10-05 00:32:42 -07:00
parent a7a068f56f
commit c0d3384c68
5 changed files with 65 additions and 19 deletions
+3 -2
View File
@@ -177,8 +177,8 @@ _As of 2026-10-04 ~2300 PT. The newest subsection is first; older subsections ca
`10.100.250.61` on nh3-mgmt (UDM port 6), KVM on, Opt-in None, password in the `10.100.250.61` on nh3-mgmt (UDM port 6), KVM on, Opt-in None, password in the
vault as `nh3-pve/amt-admin`. → `servers/nh3-pve/README.md` vault as `nh3-pve/amt-admin`. → `servers/nh3-pve/README.md`
- **nh3-ml1** (CT 109 @ `10.100.50.80`): - **nh3-ml1** (CT 109 @ `10.100.50.80`):
- TEI embed/rerank is **load-shared with esh-ml1** through the gateway, with - TEI rerank is **load-shared with esh-ml1** through the gateway (`enable_weighted_failover`). Embeddings are
`router_settings.enable_weighted_failover`. **primary/failover since 2026-10-05**: `qwen3-embedding` esh-ml1 first, `qwen3-embedding-bulk` (albok writes) nh3-ml1 first.
- brokkr's foundry seats: - brokkr's foundry seats:
- `lfm-vl` `:8030` (gateway `lfm25-vl-3b`); - `lfm-vl` `:8030` (gateway `lfm25-vl-3b`);
- `lfm-vl-uncensored` `:8032` (direct; passed brokkr's eval); - `lfm-vl-uncensored` `:8032` (direct; passed brokkr's eval);
@@ -299,6 +299,7 @@ _As of 2026-10-04 ~2300 PT. The newest subsection is first; older subsections ca
## Recent decisions ## Recent decisions
- `[2026-10-05]` **Embedder routing split (Prime 0030, via albok-dev, confirmed directly): `qwen3-embedding` = esh-ml1 primary / nh3-ml1 failover; new `qwen3-embedding-bulk` = nh3-ml1 primary / esh-ml1 failover, for albok writes** — LiteLLM `order` (read at source, v1.97.0); failover proved by stopping nh3-ml1 tei-embed (bulk 6/6 → esh-ml1, 200s). Gateway restart = 43 s outage. albok-service key granted the bulk alias; Nemi key not. TEI weights revision unpinned on both (model_sha null). → `stacks/litellm/conf/config.yaml`
- `[2026-10-04]` **albok-service moved to nh3-albok, a VM that runs only albok (albok-dev relaying Prime)** — nh3-docker's socket containers and plaintext tcp/2375 were root over the restricted wings; nh3-pve-2 vmbr0 VLAN-aware by reboot; PBS ns `nh3-pve-2`; copy verified by digest (dir st_size differs on ext4, not data). → `persistent-memory.d/2026-10-04-albok-service-moved-to-nh3-albok.md` - `[2026-10-04]` **albok-service moved to nh3-albok, a VM that runs only albok (albok-dev relaying Prime)** — nh3-docker's socket containers and plaintext tcp/2375 were root over the restricted wings; nh3-pve-2 vmbr0 VLAN-aware by reboot; PBS ns `nh3-pve-2`; copy verified by digest (dir st_size differs on ext4, not data). → `persistent-memory.d/2026-10-04-albok-service-moved-to-nh3-albok.md`
- `[2026-10-04]` **The whole fleet is on PVE 9.2.21 and PBS 4.2.7** — per-host traps (pfi-pve's grub-pc on UEFI, esh-pve's dead bridge port, nh3-pve's missing 7.0 headers, PBS via guest agent) and what a pfi-pve reboot costs. → `persistent-memory.d/2026-10-04-fleet-on-pve-9-and-pbs-4.md` - `[2026-10-04]` **The whole fleet is on PVE 9.2.21 and PBS 4.2.7** — per-host traps (pfi-pve's grub-pc on UEFI, esh-pve's dead bridge port, nh3-pve's missing 7.0 headers, PBS via guest agent) and what a pfi-pve reboot costs. → `persistent-memory.d/2026-10-04-fleet-on-pve-9-and-pbs-4.md`
- `[2026-10-04]` **pfi-ana-webhost destroyed; phasefinal.com on Cloudflare Pages; token-creator + `infra-ops-pages` tokens** — the dragonfire sites were never ours to serve; 38.120.12.45 now unmapped. → `persistent-memory.d/2026-10-04-webhost-destroyed-phasefinal-on-pages.md` - `[2026-10-04]` **pfi-ana-webhost destroyed; phasefinal.com on Cloudflare Pages; token-creator + `infra-ops-pages` tokens** — the dragonfire sites were never ours to serve; 38.120.12.45 now unmapped. → `persistent-memory.d/2026-10-04-webhost-destroyed-phasefinal-on-pages.md`
+7 -1
View File
@@ -5,7 +5,13 @@ GPU LXC for the ESH home lab: **CT 110 on esh-pve**, holding the **NVIDIA RTX
reranking service** — the only backend behind the gateway's `qwen3-embedding`, reranking service** — the only backend behind the gateway's `qwen3-embedding`,
`reranker` and `reranker-a3-bge-v2-m3` since 2026-09-25. Built 2026-09-24. `reranker` and `reranker-a3-bge-v2-m3` since 2026-09-25. Built 2026-09-24.
**Load-shared with [nh3-ml1](../nh3-ml1/README.md) since 2026-09-26 (Prime).** The **Embedding routing since 2026-10-05 0030 (Prime): primary + failover, no longer shuffled.** `qwen3-embedding`
(fleet default) = esh-ml1 order 1, nh3-ml1 order 2; `qwen3-embedding-bulk` (albok-service's write path) = nh3-ml1 order 1,
esh-ml1 order 2. Measured 0730: 6/6 of each alias on its primary; with nh3-ml1's `tei-embed` stopped, bulk went 6/6 to esh-ml1
with 200s and fleet stayed on esh-ml1, then bulk returned 6/6 to nh3-ml1 once it was back. (esh-ml1-down → fleet failover is
the same code path, not separately tested.) The reranker groups are still load-shared as below.
**Load-shared with [nh3-ml1](../nh3-ml1/README.md) since 2026-09-26 (Prime), rerank only since 2026-10-05.** The
gateway splits `qwen3-embedding`, `reranker` and `reranker-a3-bge-v2-m3` across both gateway splits `qwen3-embedding`, `reranker` and `reranker-a3-bge-v2-m3` across both
TEI hosts, which are parity-verified as indistinguishable. Losing either host no TEI hosts, which are parity-verified as indistinguishable. Losing either host no
longer takes fleet embeddings down; the failover test results are in the nh3-ml1 longer takes fleet embeddings down; the failover test results are in the nh3-ml1
+7 -1
View File
@@ -6,7 +6,13 @@ reranking backend**, the twin of [esh-ml1](../esh-ml1/README.md): same card, sam
driver, same TEI image and models. Built 2026-09-25, after the NH3 site visit driver, same TEI image and models. Built 2026-09-25, after the NH3 site visit
turned Secure Boot off on nh3-pve. turned Secure Boot off on nh3-pve.
**Load-shared with esh-ml1 since 2026-09-26 (Prime).** The gateway splits **Embedding routing since 2026-10-05 0030 (Prime): primary + failover, no longer shuffled.** `qwen3-embedding`
(fleet default) = esh-ml1 order 1, nh3-ml1 order 2; `qwen3-embedding-bulk` (albok-service's write path) = nh3-ml1 order 1,
esh-ml1 order 2. Measured 0730: 6/6 of each alias on its primary; with nh3-ml1's `tei-embed` stopped, bulk went 6/6 to esh-ml1
with 200s and fleet stayed on esh-ml1, then bulk returned 6/6 to nh3-ml1 once it was back. (esh-ml1-down → fleet failover is
the same code path, not separately tested.) The reranker groups are still load-shared as below.
**Load-shared with esh-ml1 since 2026-09-26 (Prime); embeddings moved to primary/failover 2026-10-05, above.** The gateway split
`qwen3-embedding`, `reranker` and `reranker-a3-bge-v2-m3` across both hosts at `qwen3-embedding`, `reranker` and `reranker-a3-bge-v2-m3` across both hosts at
random, one `simple-shuffle` deployment each. Measured with 40 + 40 requests: embed random, one `simple-shuffle` deployment each. Measured with 40 + 40 requests: embed
12 esh / 28 nh3, rerank 22 / 18. 12 esh / 28 nh3, rerank 22 / 18.
+4 -3
View File
@@ -4,9 +4,10 @@
RTX 2000E Ada), served by **Hugging Face Text Embeddings Inference (TEI)**. RTX 2000E Ada), served by **Hugging Face Text Embeddings Inference (TEI)**.
It runs on **two hosts**, esh-ml1 and **nh3-ml1** (CT 109 on nh3-pve, the same It runs on **two hosts**, esh-ml1 and **nh3-ml1** (CT 109 on nh3-pve, the same
card). The two are parity-verified as indistinguishable, and since 2026-09-26 card). The two are parity-verified as indistinguishable, and since 2026-09-26
(Prime) they are **load-shared** behind the gateway names `qwen3-embedding`, (Prime) they are **load-shared** behind `reranker` and `reranker-a3-bge-v2-m3`, with intra-group failover
`reranker` and `reranker-a3-bge-v2-m3`, with intra-group failover (`servers/nh3-ml1/README.md` has the measurements). **Embeddings are primary + failover since 2026-10-05
(`servers/nh3-ml1/README.md` has the measurements). (Prime):** `qwen3-embedding` esh-ml1 first, `qwen3-embedding-bulk` (albok writes) nh3-ml1 first, set with LiteLLM
`order` in `stacks/litellm/conf/config.yaml`.
**TEI is the fleet's embed/rerank engine** (Prime, 2026-09-25). New embedding or **TEI is the fleet's embed/rerank engine** (Prime, 2026-09-25). New embedding or
reranking seats go on TEI, not vLLM. Why, and the measurements behind it: reranking seats go on TEI, not vLLM. Why, and the measurements behind it:
+44 -12
View File
@@ -7,7 +7,8 @@
# #
# Model-name → upstream mapping: # Model-name → upstream mapping:
# phi4-mini → vLLM :8004 (generative chat) # phi4-mini → vLLM :8004 (generative chat)
# qwen3-embedding → TEI on esh-ml1 :8001 (/v1/embeddings) # qwen3-embedding → TEI on esh-ml1 :8001, nh3-ml1 failover (/v1/embeddings)
# qwen3-embedding-bulk → TEI on nh3-ml1 :8001, esh-ml1 failover (albok writes)
# reranker → TEI on esh-ml1 :8013 (/rerank, huggingface/ provider) # reranker → TEI on esh-ml1 :8013 (/rerank, huggingface/ provider)
# * (wildcard) → llama-swap :9292 (the swappable generative zoo) # * (wildcard) → llama-swap :9292 (the swappable generative zoo)
# #
@@ -443,20 +444,34 @@ model_list:
# explicitly. Operator ruling 2026-08-23. --- # explicitly. Operator ruling 2026-08-23. ---
# --- Qwen3 embeddings --- # --- Qwen3 embeddings ---
# TWO backends, load-shared (simple-shuffle), since 2026-09-26 (Prime): esh-ml1 # TWO backends, esh-ml1 (ESH) and nh3-ml1 (NH3). Both are an RTX 2000E Ada running Hugging Face TEI
# (ESH) and nh3-ml1 (NH3). Both are an RTX 2000E Ada running Hugging Face TEI # 89-1.9.4 with the same model. Parity measured 2026-09-25: cosine esh vs nh3 min 0.999993 = each
# 89-1.9.4 with the same model. Parity measured 2026-09-25: cosine esh vs nh3 # host's own floor; overlap@10 1.000 (servers/nh3-ml1/README.md). Re-measured 2026-10-05 by albok-dev
# min 0.999993 = each host's own floor; overlap@10 1.000 # (20 texts x 3 runs, direct to each TEI): min cosine 0.999996, the same as each backend against
# (servers/nh3-ml1/README.md). TEI's /v1/embeddings is OpenAI-compatible, so the # itself; cross-backend query/document ranking identical 5/5. TEI's /v1/embeddings is
# provider is `hosted_vllm/`. TEI vectors match the retired vLLM seats (cosine # OpenAI-compatible, so the provider is `hosted_vllm/`.
# median 0.999925), so no index needed re-embedding. #
# ⚠ Never point this name at a DIFFERENT embedding model: vectors are # ROUTING (Prime 2026-10-05, replaces the 2026-09-26 simple-shuffle load-share for embeddings only;
# model-specific. Engine bake-off: docs/pfi/embed-rerank-tei-vs-vllm-bakeoff.md. # the reranker groups below are unchanged): PRIMARY + FAILOVER via `order`, never a split.
# qwen3-embedding fleet default esh-ml1 order 1, nh3-ml1 order 2
# qwen3-embedding-bulk albok writes nh3-ml1 order 1, esh-ml1 order 2
# so bulk ingest (an albok reindex is ~15k chunks) lands on nh3-ml1 and cannot starve the fleet's
# query path on esh-ml1, and either host going down slows its traffic rather than failing it.
# `order` semantics, read at source in this image (v1.97.0, litellm/utils.py
# _get_order_filtered_deployments + router.py "ORDER-BASED FALLBACKS"): the router picks the lowest
# `order` among HEALTHY (not cooled-down) deployments; when a request fails there, it retries the
# same group at the next `order` level before any external fallback.
# ⚠ Never point either name at a DIFFERENT embedding model: vectors are model-specific, and both
# aliases feed the same indexes. Engine bake-off: docs/pfi/embed-rerank-tei-vs-vllm-bakeoff.md.
# ⚠ TEI /info reports model_sha null on both hosts, so the weights revision is not pinned. A
# re-pull on one host could drift the pair apart silently; re-run the parity check after any
# re-pull (albok-dev, 2026-10-05).
- model_name: qwen3-embedding - model_name: qwen3-embedding
litellm_params: litellm_params:
model: hosted_vllm/Qwen/Qwen3-Embedding-0.6B model: hosted_vllm/Qwen/Qwen3-Embedding-0.6B
api_base: http://10.0.50.80:8001/v1 api_base: http://10.0.50.80:8001/v1
api_key: os.environ/VLLM_API_KEY api_key: os.environ/VLLM_API_KEY
order: 1
model_info: model_info:
mode: embedding mode: embedding
- model_name: qwen3-embedding - model_name: qwen3-embedding
@@ -464,6 +479,23 @@ model_list:
model: hosted_vllm/Qwen/Qwen3-Embedding-0.6B model: hosted_vllm/Qwen/Qwen3-Embedding-0.6B
api_base: http://10.100.50.80:8001/v1 api_base: http://10.100.50.80:8001/v1
api_key: os.environ/VLLM_API_KEY api_key: os.environ/VLLM_API_KEY
order: 2
model_info:
mode: embedding
- model_name: qwen3-embedding-bulk
litellm_params:
model: hosted_vllm/Qwen/Qwen3-Embedding-0.6B
api_base: http://10.100.50.80:8001/v1
api_key: os.environ/VLLM_API_KEY
order: 1
model_info:
mode: embedding
- model_name: qwen3-embedding-bulk
litellm_params:
model: hosted_vllm/Qwen/Qwen3-Embedding-0.6B
api_base: http://10.0.50.80:8001/v1
api_key: os.environ/VLLM_API_KEY
order: 2
model_info: model_info:
mode: embedding mode: embedding
@@ -1107,8 +1139,8 @@ router_settings:
# a share of requests: the router's default 2 retries re-picked at random and # a share of requests: the router's default 2 retries re-picked at random and
# hit the dead one again. Measured 2026-09-26 with nh3-ml1 TEI stopped: 7/40 # hit the dead one again. Measured 2026-09-26 with nh3-ml1 TEI stopped: 7/40
# embeds returned 500. # embeds returned 500.
# Affects ONLY multi-deployment groups (qwen3-embedding, reranker, # Affects ONLY multi-deployment groups (reranker and reranker-a3-bge-v2-m3; the two
# reranker-a3-bge-v2-m3 as of 2026-09-26). A single-deployment group has no # embedding groups route by `order` since 2026-10-05, see the Qwen3 embeddings block). A single-deployment group has no
# other deployment to re-pick, so its behaviour is unchanged. # other deployment to re-pick, so its behaviour is unchanged.
enable_weighted_failover: true enable_weighted_failover: true