Skip to content

[KVConnector] Support worker -> scheduler metadata#31964

Merged
NickLucche merged 7 commits intovllm-project:mainfrom
orozery:connector-worker-metadata
Mar 11, 2026
Merged

[KVConnector] Support worker -> scheduler metadata#31964
NickLucche merged 7 commits intovllm-project:mainfrom
orozery:connector-worker-metadata

Conversation

@orozery
Copy link
Collaborator

@orozery orozery commented Jan 8, 2026

This PR introduces a new build_worker_connector_meta KV connector API,
allowing workers to send back arbitrary metadata back to the scheduler-side connector.
This aligns with the already existing API build_connector_metadata which allows for the same on the opposite direction (scheduler -> worker).

In particular, this API is needed for the OffloadingConnector to be able to notify the scheduler-side on offloaded blocks, even before a request is finished.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new API for workers to send metadata to the scheduler, which is a valuable addition for features like the OffloadingConnector. The implementation is well-structured and includes comprehensive tests. However, I've identified a critical correctness issue in MultiConnector.update_connector_output where state mutation is not handled safely, potentially leaving objects in an inconsistent state if an error occurs. My feedback includes a code suggestion to make this part of the implementation more robust.

@orozery orozery force-pushed the connector-worker-metadata branch from 50468f2 to bc8ade9 Compare January 8, 2026 11:11
@mergify
Copy link

mergify bot commented Jan 8, 2026

Hi @orozery, the pre-commit checks have failed. Please run:

uv pip install pre-commit
pre-commit install
pre-commit run --all-files

Then, commit the changes and push to your branch.

For future commits, pre-commit will run automatically on changed files before each commit.

Tip

Is mypy or markdownlint failing?
mypy and markdownlint are run differently in CI. If the failure is related to either of these checks, please use the following commands to run them locally:
# For mypy (substitute "3.10" with the failing version if needed)
pre-commit run --hook-stage manual mypy-3.10
# For markdownlint
pre-commit run --hook-stage manual markdownlint

@LucasWilkinson
Copy link
Collaborator

cc @NickLucche

Copy link
Collaborator

@NickLucche NickLucche left a comment

Choose a reason for hiding this comment

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

Agreed with @orozery offline to override this new pipe to coalesce worker->scheduler data propagation for a future Connector v2 interface.
I also believe we're already in partial agreement with @njhill (cc to check out PR if I missed something here).
=>For the time being, I think this is a generic channel that unlocks some development and the impl looks good on my side.

c.update_connector_output(connector_output)
finally:
# restore kv_connector_worker_meta
connector_output.kv_connector_worker_meta = multi_connector_worker_meta
Copy link
Collaborator

Choose a reason for hiding this comment

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

neat

Comment on lines +300 to +303
if metadata_list is None and kv_connector_worker_meta is not None:
metadata_list = [None] * i
if metadata_list is not None:
metadata_list.append(kv_connector_worker_meta)
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think this is not immediate but I don't have a cleaner solution other than doing an if any() check at the end.

Copy link
Contributor

Choose a reason for hiding this comment

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

This is very nice code - pythonic and terse but makes great use of indices of connectors with the tuple.

Copy link
Contributor

@hickeyma hickeyma left a comment

Choose a reason for hiding this comment

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

I like this in the main, thanks @orozery.

Overall is the aim to include all worker data to be returned through KVConnectorWorkerMetadata. Hence, stats and kv events and part of the class?

"""
return None

def build_connector_worker_meta(self) -> KVConnectorWorkerMetadata | None:
Copy link
Contributor

Choose a reason for hiding this comment

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

Would this read better as get_connector_worker_meta(self)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I thought to follow the convention being used for the other direction (build_connector_meta).

Comment on lines 138 to +140
output.kv_connector_stats = kv_connector.get_kv_connector_stats()
output.kv_cache_events = kv_connector.get_kv_connector_kv_cache_events()
output.kv_connector_worker_meta = kv_connector.build_connector_worker_meta()
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this mean that output.kv_connector_stats and output.kv_cache_events will be integrated into output.kv_connector_worker_meta at some stage? Hence all future data from workers will be returned in output.kv_connector_worker_meta?

Comment on lines +300 to +303
if metadata_list is None and kv_connector_worker_meta is not None:
metadata_list = [None] * i
if metadata_list is not None:
metadata_list.append(kv_connector_worker_meta)
Copy link
Contributor

Choose a reason for hiding this comment

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

This is very nice code - pythonic and terse but makes great use of indices of connectors with the tuple.

@orozery
Copy link
Collaborator Author

orozery commented Feb 11, 2026

Overall is the aim to include all worker data to be returned through KVConnectorWorkerMetadata. Hence, stats and kv events and part of the class?

My thinking:
KVConnectorWorkerMetadata will remain abstract (just like the respective KVConnectorMetadata), and will basically replace KVConnectorOutput.
The consumer of KVConnectorOutput is the scheduler (an exception to that is KVConnectorKVEvents which is not consumed by the scheduler, but only by the LMCache scheduler-side connector)
Instead of consuming of ModelRunnerOutput.kv_connector_output, the scheduler will consume its required output (stats, finished requests, block errors) via a single new scheduler-side API.

To ease the common use-case of aggregating across all workers (as in the case of finished_sending, finished_recving, etc), we can create a utility class inhering from KVConnectorWorkerMetadata that will include a generic aggregation logic (sort of a generalization of today's KVOutputAggregator.

Copy link
Contributor

@hickeyma hickeyma left a comment

Choose a reason for hiding this comment

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

My thinking:
KVConnectorWorkerMetadata will remain abstract (just like the respective KVConnectorMetadata), and will basically replace KVConnectorOutput.
The consumer of KVConnectorOutput is the scheduler (an exception to that is KVConnectorKVEvents which is not consumed by the scheduler, but only by the LMCache scheduler-side connector)
Instead of consuming of ModelRunnerOutput.kv_connector_output, the scheduler will consume its required output (stats, finished requests, block errors) via a single new scheduler-side API.
To ease the common use-case of aggregating across all workers (as in the case of finished_sending, finished_recving, etc), we can create a utility class inhering from KVConnectorWorkerMetadata that will include a generic aggregation logic (sort of a generalization of today's KVOutputAggregator.

Sounds good but would like to get a better picture of the overall direction. Do you have a RFC or design doc that I could look at?

@orozery
Copy link
Collaborator Author

orozery commented Feb 12, 2026

Sounds good but would like to get a better picture of the overall direction. Do you have a RFC or design doc that I could look at?

I'm working on an RFC for connector API refactoring. It will include other proposed changes as well.
Note that even just with this current API, KVConnectorKVEvents can be eliminated. I don't think there's a need to wait for the RFC.

@hickeyma
Copy link
Contributor

Note that even just with this current API, KVConnectorKVEvents can be eliminated. I don't think there's a need to wait for the RFC.

Can you explain what you mean by removed? How will events from connector be processed by vLLM then?

@orozery
Copy link
Collaborator Author

orozery commented Feb 12, 2026

Can you explain what you mean by removed? How will events from connector be processed by vLLM then?

The same way they are processed today, using the take_events function.

@hickeyma
Copy link
Contributor

The same way they are processed today, using the take_events function.

How do they get from workers to scheduler process?

@orozery
Copy link
Collaborator Author

orozery commented Feb 12, 2026

How do they get from workers to scheduler process?

KVConnectorWorkerMetadata

Copy link
Collaborator

@NickLucche NickLucche left a comment

Choose a reason for hiding this comment

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

LGTM thanks for the work @orozery , only left one nit on the test, double check to make sure I haven't overlooked that case.


# ----------------------------- test aggregate ----------------------------

# aggregate ({"0a"}, None) and (None, {"1a"}) -> ({"0a"}, {"1a"})
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit missing cae

aggregate (None, {"1a"}) and (None, {"1b"}) -> (None, {. . .} )

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks! I've now added:

# aggregate ({"0a"}, None) and ({"0b"}, None) -> ({"0a", "0b"}, None)

Copy link
Contributor

@hickeyma hickeyma left a comment

Choose a reason for hiding this comment

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

LGTM, thanks @orozery for improving metadata handling.

@orozery orozery force-pushed the connector-worker-metadata branch from d1de052 to 4068559 Compare February 13, 2026 10:07
@orozery orozery added the ready ONLY add when PR is ready to merge/full CI is needed label Feb 13, 2026
hickeyma added a commit to hickeyma/vllm that referenced this pull request Feb 13, 2026
This change removes kv_cache_events as a top-level field on KVConnectorOutput
and instead carries KV cache events inside a connector-specific
KVConnectorWorkerMetadata subclass (LMCacheWorkerMetadata).
This aligns KV event transport with the generic worker-to-scheduler
metadata mechanism introduced in PR vllm-project#31964, eliminating redundant aggregation code paths.

Signed-off-by: Martin Hickey <martin.hickey@ie.ibm.com>
@hickeyma
Copy link
Contributor

Note that even just with this current API, KVConnectorKVEvents can be eliminated.

@orozery I pushed an initial draft #34522 for this. Will iterate on it a bit more for now.

This commit introduces a new build_worker_connector_meta KV connector API
allowing workers to send back arbitrary metadata back to the scheduler-side connector.
This aligns with the already existing API build_connector_metadata which allows
for the same on the opposite direction (scheduler -> worker).

Signed-off-by: Or Ozeri <oro@il.ibm.com>
@orozery orozery force-pushed the connector-worker-metadata branch from 7db7632 to 263ba3f Compare March 5, 2026 09:09
@NickLucche NickLucche enabled auto-merge (squash) March 5, 2026 09:18
@NickLucche NickLucche merged commit a1a3523 into vllm-project:main Mar 11, 2026
49 checks passed
hickeyma added a commit to hickeyma/vllm that referenced this pull request Mar 12, 2026
This change removes kv_cache_events as a top-level field on KVConnectorOutput
and instead carries KV cache events inside a connector-specific
KVConnectorWorkerMetadata subclass (LMCacheWorkerMetadata).
This aligns KV event transport with the generic worker-to-scheduler
metadata mechanism introduced in PR vllm-project#31964, eliminating redundant aggregation code paths.

Signed-off-by: Martin Hickey <martin.hickey@ie.ibm.com>
wendyliu235 pushed a commit to wendyliu235/vllm-public that referenced this pull request Mar 18, 2026
Signed-off-by: Or Ozeri <oro@il.ibm.com>
Co-authored-by: Nicolò Lucchesi <nlucches@redhat.com>
fxdawnn pushed a commit to fxdawnn/vllm that referenced this pull request Mar 19, 2026
Signed-off-by: Or Ozeri <oro@il.ibm.com>
Co-authored-by: Nicolò Lucchesi <nlucches@redhat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kv-connector ready ONLY add when PR is ready to merge/full CI is needed v1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants