Skip to content

feat: per-request request_id/token_range pipeline (generate -> native -> host -> ClickHouse) - #19

Merged
Samfisheryu merged 9 commits into
HF_Prometheusfrom
feat/per-request-id-stage1-split
Feb 24, 2026
Merged

Samfisheryu merged 9 commits into
HF_Prometheusfrom
feat/per-request-id-stage1-split

Conversation

@Samfisheryu

Copy link
Copy Markdown
Collaborator

Background

This PR finalizes per-request tracking in the monitoring pipeline:
HF generate() -> monitoring engine -> native backend -> host engine -> ClickHouse.

Main objective:

  • track per-request IDs and token ranges correctly in batched generation
  • keep host-engine route aligned with v0_host_side
  • add focused validation for request/range correctness (including EOS-finished behavior)

What changed

1) Python-side per-request tracking (monitoring engine)

Files:

  • monitoring/engine.py
  • monitoring/hook_points.py
  • monitoring/generate.py

Changes:

  • _register_db_step(...) now uses:
    • request_ids per active batch
    • start/end token range per request
    • attention_mask to compute prefill lengths
  • decode path now handles finished requests using EOS/PAD:
    • finished request uses empty range (start, start) and stops growth
  • prefill detection hardened:
    • not only past_key_values is None
    • also fallback to input_ids.shape[1] > 1 (for cache-mode edge cases)
  • host submit payload updated to new per-request contract:
    • (model_id, shard_rank, request_ids, token_ranges, cache_dict)

2) Native interface alignment

Files:

  • monitoring/csrc/native_engine.h
  • monitoring/csrc/native_engine_internal.h
  • monitoring/csrc/native_engine.cpp
  • monitoring/csrc/hooks.cpp
  • monitoring/csrc/bindings.cpp

Changes:

  • BackendFuture now carries task_size
  • native step map stores (token, task_size) for host queue budgeting
  • pybind exposes BackendFuture.size()

3) Host-engine side (delta vs origin/v0_host_side) — for focused review

Please review this section in detail: @XbzOnGit

Files:

  • monitoring/csrc/dmx_host_engine.h
  • monitoring/csrc/dmx_host_utils.h
  • monitoring/csrc/dmx_host_utils.cpp
  • monitoring/csrc/future_process.cpp
  • monitoring/csrc/clickhouse_client.h
  • monitoring/csrc/clickhouse_client.cpp
  • monitoring/csrc/bindings.cpp

Post-merge fixes/hardening (no architecture redesign):

  1. Fix metadata move bug
    • removed std::move(request_ids[i]) / std::move(token_range_per_request[i])
    • avoids empty metadata for later hooks in same step
  2. Add consistency checks before stage1 split
    • request_ids.size == token_ranges.size
    • tensor.size(0) == request_ids.size
    • skip invalid/empty ranges (start >= end, negative)
  3. Fix token-range correctness in stage1 split path
    • use correct start_token_idx/end_token_idx variables for effective range slicing
  4. Keep queue budgeting by future size
    • continue using t_future.size() in host enqueue budget
    • ensure BackendFuture.size() is available from bindings
  5. Keep v0 host contract/schema
    • submit contract and 8-column row format remain consistent with v0 host-side design
    • doc/signature cleanup for consistency

Tests added

Files:

  • tests/test_monitoring_engine_request_id.py
  • tests/validate_request_id_pipeline.py
  • benchmark/data/prompts_varlen_validation.txt

Coverage:

  • unit tests:
    • reset on new prefill / batch-size change
    • EOS-finished request stops decode token range growth
  • E2E validation:
    • request_id set consistency
    • prefill length vs attention_mask
    • decode range continuity
    • optional forced EOS path (--exercise-eos-path)
    • optional attention hook path (--with-attn-hook)
    • shape-rank checks in DB rows

Compatibility / notes

  • host submit path expects per-request payload format
  • shard_rank is preserved in host->DB schema path
  • current Python path sets shard_rank=0 as placeholder (TP/distributed to follow)

Review request

  • Host engine implementation & safety checks: @XbzOnGit
  • Python/native integration correctness: monitoring maintainers
  • Test strategy and E2E validator quality: benchmark/test owners

XbzOnGit and others added 8 commits February 23, 2026 12:05
- Add task size support on BackendFuture and submit as budget in submit
  to host engine.
padded tokens.
- DMX host engine shard_rank support for TP.
- DMX host engine batch to request breaking.
- DMX host engine support for dropping padded tokens.
- NOTE: Still require changes from monitoring engine for submit API
  change. Need to track per request id, track effective start_token_idx
and end_token_idx.
…update

- dmx_host_utils: fix std::move bug in hook loop (use const ref params)
- dmx_host_utils: add inner/outer length validation
- dmx_host_engine: clean up submit() signature to use const refs
- future_process: fix variable name error (token_end/start_idx)
- future_process: add tensor.size(0) vs request_ids.size() validation
- future_process: per-request select+narrow+clone, skip empty ranges
- future_process: special handling for attn hook token/key dim narrowing
- future_process: remove unsqueeze(0) to preserve correct tensor shape
- clickhouse_client: update schema comment to 8-column with shard_rank
- bindings: expose BackendFuture.size()
- native_engine/hooks: fix BackendFuture task size type to pair<int64_t,int64_t>
- engine.py: replace single request_id with per-batch request_id list
- engine.py: add _db_state_lock, _auto_batch_group_id, per-request
  start_idx and finished state
- engine.py: shape-based prefill detection (input_ids.shape[1] > 1)
  as fallback for HF cache modes that pass non-None past_key_values
- engine.py: EOS/PAD detection checks last_ids before advancing range
  (not after), fixing off-by-one row count for finished requests
- engine.py: update submit() call to new C++ signature
- hook_points.py: pass attention_mask to _register_db_step
- generate.py: sync shape-based prefill detection in monitored_forward
- validate_request_id_pipeline.py: E2E test via full DB pipeline
  - validates per-request token ranges are contiguous and correct
  - validates prefill length matches attention_mask effective length
  - validates row count matches effective generated length (EOS-aware)
  - validates tensor shape rank for final_logits and attn hooks
  - --with-attn-hook: exercises is_attn narrowing path in future_process
  - --exercise-eos-path: forces early EOS via LogitsProcessor to validate
    finished-request row count
- prompts_varlen_validation.txt: variable-length prompts for padding test
- test_monitoring_engine_request_id.py: unit tests for engine state logic
@Samfisheryu

Copy link
Copy Markdown
Collaborator Author

(proj-dmx) nengneng@FROOT-Lab:~/AIPrometheus/HF_Prometheus$ ./tests/run_request_id_tests.sh

========================================
Unit tests (test_monitoring_engine_request_id)

============================================================================== test session starts ==============================================================================
platform linux -- Python 3.10.19, pytest-9.0.2, pluggy-1.6.0 -- /home/nengneng/miniconda3/envs/proj-dmx/bin/python
cachedir: .pytest_cache
rootdir: /home/nengneng/AIPrometheus/HF_Prometheus
configfile: pyproject.toml
plugins: typeguard-4.4.4, jaxtyping-0.3.5, anyio-4.12.1
collected 2 items

tests/test_monitoring_engine_request_id.py::test_request_id_reset_on_prefill_and_batch_change PASSED [ 50%]
tests/test_monitoring_engine_request_id.py::test_request_id_eos_finished_stops_decode_growth PASSED [100%]

=============================================================================== 2 passed in 0.87s ===============================================================================
[PASS] Unit tests (test_monitoring_engine_request_id)

========================================
E2E: basic (final_logits, no attn hook)

torch_dtype is deprecated! Use dtype instead!
worker 0 in future_process introduced 0 tensor copies due to non-contiguous
[PASS] validated 10 request_ids, 60 rows, batch_size=4, max_new_tokens=6, with_attn_hook=False, exercise_eos_path=False
[PASS] E2E: basic (final_logits, no attn hook)

========================================
E2E: with attn hook (is_attn narrowing path)

torch_dtype is deprecated! Use dtype instead!
worker 0 in future_process introduced 42 tensor copies due to non-contiguous
[PASS] validated 10 request_ids, 60 rows, batch_size=4, max_new_tokens=6, with_attn_hook=True, exercise_eos_path=False
[PASS] E2E: with attn hook (is_attn narrowing path)

========================================
E2E: EOS early termination (finished-request row count)

torch_dtype is deprecated! Use dtype instead!
worker 0 in future_process introduced 0 tensor copies due to non-contiguous
[PASS] validated 10 request_ids, 48 rows, batch_size=4, max_new_tokens=6, with_attn_hook=False, exercise_eos_path=True
[PASS] E2E: EOS early termination (finished-request row count)

========================================
Results: 4 passed, 0 failed

(proj-dmx) nengneng@FROOT-Lab:~/AIPrometheus/HF_Prometheus$

@Samfisheryu
Samfisheryu requested a review from XbzOnGit February 24, 2026 20:54
@Samfisheryu

Copy link
Copy Markdown
Collaborator Author

Follow-up update: removed db_state_lock in MonitoringEngine (commit 04ae3f069).

Reason: in the current runtime model, we do not have multiple workers concurrently mutating the same Python engine instance (single inference owner per engine / per-rank engine separation), so this lock is non-essential for current behavior and only adds complexity.

The previously lock-protected fields were:

  • _pending_db_step
  • _active_batch_request_ids
  • _active_batch_start_idx_per_request
  • _active_batch_finished_per_request

@Samfisheryu Samfisheryu self-assigned this Feb 24, 2026

@XbzOnGit XbzOnGit left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

@Samfisheryu
Samfisheryu merged commit 6acf7e3 into HF_Prometheus Feb 24, 2026
@Samfisheryu
Samfisheryu deleted the feat/per-request-id-stage1-split branch February 24, 2026 21:44
zaoxing added a commit that referenced this pull request Sep 6, 2026
DMI-vLLM-Integration PR #21 merged (squash 23717cb): attach_model
accepts layers=LayerSelection(...), applies it to the local specs and
the model-wide candidate-rank sets, and stays importable on DMI builds
without the layer-range facade. The pin moves old-main 29f26c3 ->
23717cb, picking up both the V2-runner promotion (#19) and the layer
range (#21).
zaoxing added a commit that referenced this pull request Sep 7, 2026
DMI-vLLM-Integration PR #21 merged (squash 23717cb): attach_model
accepts layers=LayerSelection(...), applies it to the local specs and
the model-wide candidate-rank sets, and stays importable on DMI builds
without the layer-range facade. The pin moves old-main 29f26c3 ->
23717cb, picking up both the V2-runner promotion (#19) and the layer
range (#21).
zaoxing added a commit that referenced this pull request Sep 7, 2026
DMI-vLLM-Integration PR #21 merged (squash 23717cb): attach_model
accepts layers=LayerSelection(...), applies it to the local specs and
the model-wide candidate-rank sets, and stays importable on DMI builds
without the layer-range facade. The pin moves old-main 29f26c3 ->
23717cb, picking up both the V2-runner promotion (#19) and the layer
range (#21).
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.

2 participants