Skip to content

Add tests and agent docs for kwargs_type input/output#14157

Open
yiyixuxu wants to merge 1 commit into
mainfrom
kwargs-type-tests-and-docs
Open

Add tests and agent docs for kwargs_type input/output#14157
yiyixuxu wants to merge 1 commit into
mainfrom
kwargs-type-tests-and-docs

Conversation

@yiyixuxu

Copy link
Copy Markdown
Collaborator

add tests and docs for kwargs_type, which comes very handy for cosmos3

…pelines

Document how kwargs_type-tagged values flow from block outputs and user
inputs to consumer blocks (the mechanism behind denoiser_input_fields),
pin the behavior down with tests, and add a key-pattern section to
.ai/modular.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added size/M PR with diff < 200 LOC tests and removed size/M PR with diff < 200 LOC labels Jul 10, 2026
@yiyixuxu yiyixuxu requested review from dg845 and sayakpaul July 13, 2026 21:05

@sayakpaul sayakpaul left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the work and I left some comments.

I found it a bit confusing as a user as to when one should use, for example, pipe(a="testa", ...) and when one should use pipe(typea={"a": "testa"}). Maybe we could simplify that a bit (can be in a different PR and doesn't have to block this one).

Comment thread .ai/modular.md

## Key pattern: `kwargs_type` bags (`denoiser_input_fields`)

The conditioning inputs a denoiser needs often vary by workflow — especially for omni models like Cosmos3, where the action workflow requires additional action conditioning, and a workflow that generates sound along with video requires additional sound inputs. Tag these outputs with `kwargs_type="denoiser_input_fields"` when they are written, and have the denoiser declare the bag once and receive everything tagged — this avoids creating a new denoiser block for each workflow just to list its specific inputs:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What is a bag here?


def __call__(self, components, state: PipelineState) -> PipelineState:
block_state = self.get_block_state(state)
assert block_state.typea == block_state.expected_typea

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I am a bit confused here.

I'd imagine that the block_state.typea and block_state.expected_typea are different state-level components. But seems like they are the same. In what circumstance, a user would want to define input params like that?

blocks = SequentialPipelineBlocks.from_blocks_dict(
{"producer": DummyKwargsProducerStep(), "consumer": DummyKwargsConsumerStep()}
)
pipe = blocks.init_pipeline()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

When pipe is constructed, should we also assert against the params accepted by the call method of pipe?

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.

2 participants