Skip to content

fix: Preserve global embedding order across bounded batches - #811

Draft
buildingjoshbetter wants to merge 3 commits into
fix/daemon-tier-identity-795from
fix/model-global-order-publish-735
Draft

buildingjoshbetter wants to merge 3 commits into
fix/daemon-tier-identity-795from
fix/model-global-order-publish-735

Conversation

@buildingjoshbetter

@buildingjoshbetter buildingjoshbetter commented Oct 8, 2026 •

Copy link
Copy Markdown
Owner

Scope

Narrow Qwen embedding-order correction for #735, stacked on #804. The earlier native diagnostic established default embedding parity and exposed additional explicit-eight regressions. The current follow-up limits global ordering to an effective bound of 32; its native reconfirmation is pending. This draft does not close the numerical/performance release gates.

Reproduced problem

SentenceTransformers orders a complete request by input length before making its own batches. The earlier bounded wrapper split caller order first, then each encode call sorted only its slice. Default mixed requests of 33 and 100 rows therefore changed native batch membership and padding. All six large-request default comparisons failed the frozen numerical tolerance in the prior native diagnostic; the mixed 100 default median was 1000.544282 ms versus 390.950397 ms for the full-list native reference, a ratio of 2.559261. Those failed receipts remain evidence, not acceptance.

Correction

  • For the known cached Qwen encoder, plain strings, modern input-length API, non-flattened mode and effective limit exactly 32, calculate the complete request's length order once after output-allocation preflight.
  • Slice that order at the existing fixed effective request bound. Invert each slice's inner tie permutation before encode, so the library's own sort restores the intended native order. Reversing ties alone cannot test inverse direction; cyclic-tie cases now cover it.
  • Scatter each returned row into the existing bounded output buffer using its original occurrence index. Duplicate and empty strings retain their positions.
  • Keep the cursor unchanged until successful storage. OOM retry uses the same bounded slice and indices under existing inference ownership. Check deadlines around planning, each slice and retries.
  • Preserve single-input, single-batch and unsupported encoder/mode behavior. Models, model revisions, precision, prompts, dimensions, output limits, rerankers and retrieval caps are unchanged. No extra full-request output buffer or tokenization pass is introduced.

Compatibility follow-up

Current head a01579868c36df9c2ba93f603dfe248d14c0cd7d retains the earlier contiguous slice membership whenever the resolved bound is below 32, including explicit-eight and adaptive reductions. Omitted or oversized requests use global order only when their effective bound is 32. This avoids adding the measured global-eight regression while preserving all actual request caps. It does not resolve or waive the earlier contiguous-eight numerical failure.

Root independently ran 15 focused production-AST tests with no native imports. Removing the effective-limit guard makes the lower-bound membership and adaptive tests fail. Cyclic inverse, occurrence coverage, output preflight, expiry and OOM ownership remain tested at the applicable bounds. The exact updated publication branch passed 2,197 tests and 513 subtests, with 22 skips, 3 deselections and actual sqlite-vec enabled. Log SHA256: 0217353d4bafefb23ea9d12f7c83e50f1e832763549d6ff3afc6af9bafb61f37. Configured Ruff, Python3.10 syntax and scoped privacy/commit-identity checks passed. Hosted checks for this new head are pending.

Earlier validation

  • 14 focused stdlib tests passed. Cases cover counts 31/33/63/64/65, duplicate/empty/Unicode inputs, prompts, output bounds, deadlines, request limits and OOM retry ownership.
  • Self-challenge exercised 60 order/coverage cases. Removing global planning, compensation or scatter, or duplicating an occurrence, failed all 54 applicable cases per mutation. Non-involutive cyclic ties rejected the wrong inverse in 36/36 checks. This is author self-review, not an independent authorship claim.
  • The initial integration-based full run had one scheduler threshold failure. Its actual in-memory reproduction identified a fixture-global model-lock interference mechanism; fix: Coalesce engine maintenance behind owned workers #808 now contains a test-only isolation correction and retains the original 24/25 assertions. The historical log cannot identify its specific interloping worker; no production scheduling fix is claimed for that test change.
  • Corrected integration-based candidate: 2,759 passed, 22 skipped, 3 deselected; 1,946 subtests passed, with actual sqlite-vec. Log SHA256: 6d49be4e1f7dc4925f00451277c967401640a4c2f7a78a0b54675ff5418b5975.
  • Exact isolated publication branch: 2,196 passed, 22 skipped, 3 deselected; 503 subtests passed, with actual sqlite-vec. Log SHA256: a62cabdfba1480ffe8f819548b59b24bcd1c50117fbd12abd74a55b8a77874e0. This branch excludes the unrelated scheduler fixture follow-up.
  • Combined accumulator, health and embedding branch: 2,814 passed and 1,993 subtests passed, with 22 skips and 3 deselections. Log SHA256: 301089dab0102f2608cb91ba6e831d88bac148ec557cacf5dee5e06dc02c00bb.
  • Configured Ruff, Python 3.10 syntax, whitespace, new-content privacy and commit-identity checks passed. All 34 hosted checks pass at e4371cc1d581a19d784aea2e7dc46fa92d198e37.

Earlier native diagnostic results

These measurements apply to source 2844072af8857a903ac9750a0f54026f9a33a51c, before the effective-limit compatibility guard. Preserve the failed findings; do not attribute these native receipts to the current head. The next combined-source diagnostic will recheck defaults and prior explicit-eight compatibility.

Draft #811 preserves the native Qwen request order across bounded calls. Source 2844072af8857a903ac9750a0f54026f9a33a51c keeps models, model revisions, dtype, dimensions, defaults and result caps unchanged. Actual ModelServer handlers run in process; this is a direct serial CUDA diagnostic, without socket/RPC timing.

Three separately bounded cells completed 90 timed records, three warmups, 3,741 input rows and 267 native forwards. Each loaded one model. Controller durations were 12.087, 15.176 and 11.695 seconds. Cleanup was verified for every owned container, with no timeout or OOM. Root and an independent reviewer recomputed the raw comparisons, work counts, repeatability and timing summaries.

Workload Default numerical gate Explicit-eight numerical gate
Six embedding cases, 1/8/32 short and mixed inputs, three repeats 18/18 pass, exact 15/18 pass; mixed32 fails
Mixed embeddings, 33 and 100 inputs, three repeats 6/6 pass, exact 0/6 pass
Short and mixed reranking, 100 pairs, three repeats 6/6 pass 6/6 pass

Default passes 30/30 comparisons; explicit-eight still passes 21/30. All 24 default embedding comparisons are exact, and their ordered native feature records match the same-repeat reference: input IDs, attention masks, position IDs or explicit absence, shapes, dtypes and observed options. These recorded digests were compared; tokens were not independently regenerated. Every mode's outputs and feature records repeated exactly across its three repetitions. Reranker scores pass tolerance but are not exact; maximum difference is 4.172325134277344e-7. Its feature-parity gate is not applicable.

The unchanged reference-first tolerance is abs(candidate-reference) <= 0.0001 + 0.001 * abs(reference). Default improvement does not override explicit-eight failures.

Instrumented timings

Medians of three operations, including synchronized CUDA work and CPU feature-observation overhead:

Case Native reference ms Default handler ms Explicit-eight handler ms
Mixed embeddings, 33 338.979 340.590 125.893
Mixed embeddings, 100 397.146 403.472 251.991
Short reranking, 100 52.790 56.537 119.347
Mixed reranking, 100 424.322 631.853 342.452

For 100 mixed embeddings, default/reference is 403.471858 / 397.146104 = 1.015928027. Both now use native shapes [32x778,32x70,32x70,4x70]. The earlier wrapper measured 1000.544282 ms against its 390.950397 ms reference in a separate diagnostic. This is evidence of the corrected grouping and measured diagnostic timing, not a controlled production p95 comparison.

Mixed reranking still has default/reference 631.852592 / 424.322110 = 1.489087128. Its shapes remain [64x779,36x779] versus reference [64x779,36x72]; that performance gap remains open.

Explicit-eight regression detail

Old and new native reference arrays are exact. Each finding below repeats identically three times:

Case Maximum error, old to new Failed rows, old to new Failed components, old to new
Mixed32 0.34375 to 0.4375 8 to 32 1,817 to 7,335
Mixed33 0.34375 to 0.4375 10 to 32 2,263 to 7,340
Mixed100 0.4375 to 0.5 83 to 24 18,950 to 5,440

The correction worsens mixed32/33 under explicit-eight, and mixed100 has a larger worst error despite fewer failed rows. Faster failed cases are not accepted as improvements. Prior padded-eight evidence already showed differences with matching token IDs, masks and effective positions, so padding alone is not established as the remedy. The specific numerical mechanism remains unproven.

Evidence and limits

  • Driver SHA256: 9822e3503158b36043c8fa6f111d903c1f2e1b9746fbd49bedffc22d666a5d5e
  • Workload SHA256: 22451e02d3047ddd65aec9b6fbdee6021ba257415220a0cef5da5a17a4518842
  • Frozen-size raw report: f923d1c44f9267f216c39bd2b1618e56b20c32cd1bbd44c9da9df8bd97c78f90
  • Larger-input raw report: 9d9902987844797b2dfb4950081560499d6f041205865af3bebb9c7eea1bf773
  • Reranker raw report: a035139b3400af0e4dd18aaad4f2c1824dcfebb26a696f865c7cb82312e4af59
  • Root recomputation: 26ec9c8ec6554a59a9de759a60beb064c226b104e25476f99ecbdda0ac73fa85

Combined acceptance remains false. Retrieval rankings, concurrent traffic, production p95, whole-process memory drift, final soak, MPS and thermal behavior remain unvalidated by this diagnostic. Only public model artifacts and generated synthetic inputs were used. No personal memories, transcripts or credentials were included. No issue is closed, main merge performed or release approved.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant