Skip to content

[mm] Accept per-item embedding lists from DataEmbeddingFunc - #31826

Merged
merrymercy merged 2 commits into
sgl-project:mainfrom
houseroad:mm-per-item-embedding-list
Jul 24, 2026
Merged

merrymercy merged 2 commits into
sgl-project:mainfrom
houseroad:mm-per-item-embedding-list

Conversation

@houseroad

@houseroad houseroad commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Motivation

DataEmbeddingFunc currently must return a single combined [tokens, hidden] tensor (or an EVSEmbeddingResult). Some encoders naturally produce per-item outputs — for example, an audio AutoEncoder that loops over clips. To satisfy the current contract they have to torch.cat their per-item results, which the per-item consumer (_get_chunked_embedding_by_item) then immediately splits back apart via torch.split. Those split views also pin the whole concatenated buffer for as long as any single item stays cached.

Modifications

  • DataEmbeddingFunc may now also return List[torch.Tensor] (one tensor per input item).
  • _get_chunked_embedding_by_item keeps the per-item tensors as separate cache entries — no concat, no split, and each cache entry owns its storage.
  • _get_chunked_embedding_full flattens the per-item form back to one tensor (it caches the combined per-request embedding) via a new _flatten_embedding_result helper.
  • The combined-tensor path is unchanged.

The per-item form is opt-in; existing encoders returning a single tensor or EVSEmbeddingResult are unaffected.

Tests

Adds CPU-only unit tests (test/registered/chunked_prefill/test_mm_chunked_embedding_unit.py) that exercise mm_utils internals directly (no engine/GPU) and assert:

  • the per-item and combined forms produce bitwise-identical chunked-prefill embeddings for both _get_chunked_embedding_by_item and _get_chunked_embedding_full;
  • per-item cache entries own their storage, while combined-tensor split views share the concatenated buffer.

These tests could not be executed in the porting environment (no torch/pytest available); they run identically in the source environment.

Original commits

  • d4fd0560e

CI States

Latest PR Test (Base): ✅ Run #30053812808
Latest PR Test (Extra): ❌ Run #30053812690

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@houseroad

Copy link
Copy Markdown
Collaborator Author

/tag-and-rerun-ci

@houseroad
houseroad force-pushed the mm-per-item-embedding-list branch 2 times, most recently from 97eaaf3 to c2900e6 Compare July 22, 2026 02:14
@houseroad

Copy link
Copy Markdown
Collaborator Author

/rerun-failed-ci

@houseroad
houseroad force-pushed the mm-per-item-embedding-list branch 2 times, most recently from de12d75 to 4779ff5 Compare July 22, 2026 17:03
@houseroad

Copy link
Copy Markdown
Collaborator Author

/rerun-failed-ci

1 similar comment
@houseroad

Copy link
Copy Markdown
Collaborator Author

/rerun-failed-ci

@houseroad

Copy link
Copy Markdown
Collaborator Author

CI recovery needed for the required pr-test.yml run: https://github.com/sgl-project/sglang/actions/runs/29940709888

The run was cancelled while jobs were queued/running; no executed test job failed. The PR-author /rerun-failed-ci command cannot recover it because the slash handler currently processes only workflow conclusions failure and skipped, not cancelled, and the PR author does not have Actions write permission.

Could a maintainer please use Re-run failed jobs on that run? This will retain the successful jobs and rerun only the cancelled/failed dependency chain.

DataEmbeddingFunc may now return one tensor per input item, in addition to
the existing combined [tokens, hidden] tensor or EVSEmbeddingResult. Encoders
that naturally produce per-item outputs (e.g. looping over clips) can return
the list directly and skip an encoder-side torch.cat that the per-item
consumer (_get_chunked_embedding_by_item) would immediately split back apart.
Each cached entry then owns its storage instead of being a torch.split view
that pins the whole concatenated buffer for as long as any single item stays
cached.

_get_chunked_embedding_full flattens the per-item form (it caches the
combined per-request embedding); _get_chunked_embedding_by_item keeps the
per-item tensors as separate cache entries.

Adds CPU-only unit tests asserting the per-item and combined forms produce
bitwise-identical chunked-prefill embeddings, and that per-item cache entries
own their storage while combined-tensor split views share it.

Co-authored-by: Lu Fang <30275821+houseroad@users.noreply.github.com>
@houseroad
houseroad force-pushed the mm-per-item-embedding-list branch from 4779ff5 to b36e7c0 Compare July 23, 2026 23:34
The CI registry validator (collect_tests) rejects registered test files
without an executable `if __name__ == "__main__":` block, since
run_unittest_files invokes them as `python3 file.py -f`. This failed every
base-a job at suite-collection time.
@houseroad
houseroad force-pushed the mm-per-item-embedding-list branch from b36e7c0 to 518dce1 Compare July 23, 2026 23:38
@merrymercy

Copy link
Copy Markdown
Contributor

/rerun-test test/registered/vlm/test_vision_chunked_prefill.py test/registered/vlm/test_vlm_input_format.py

@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Results for /rerun-test test/registered/vlm/test_vision_chunked_prefill.py test/registered/vlm/test_vlm_input_format.py:

🚀 1-gpu-h100 (2 tests): ✅ View workflow run

cd test/ && python3 registered/vlm/test_vision_chunked_prefill.py
cd test/ && python3 registered/vlm/test_vlm_input_format.py

@merrymercy
merrymercy merged commit 448662e into sgl-project:main Jul 24, 2026
221 of 253 checks passed
@mingfeima

Copy link
Copy Markdown
Collaborator

@houseroad this pr failed xeon ci: as you can see here: https://github.com/sgl-project/sglang/actions/runs/30229696257/job/89886278479?pr=24959 and every pr-test-xeon workflow.

Could you please fix this?

Two things need to be updated:

  • change register_cpu_ci(est_time=10, suite="base-b-test-cpu") to register_cpu_ci(est_time=10, suite="base-a-test-cpu"). base-a right now is generic cpu test and base-b is intel xeon cpu test (test/registered/cpu/test_xxx.py)
  • probably need to update _acknowledge_deferred_cuda_ipc_cache_hits, make an early-return when no item has a CudaIpcTensorTransportProxy feature, before touching attn_tp_rank. that depends on whether tp rank has been set on base-a-test-cpu host machine. (this ci machine is not managed by intel, base-b-test-cpu is and tp rank not set on the intel machine, that's the root cause of the fail)

CC @1pikachu @ZailiWang

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants