Skip to content

Add per-site recipe config helper#4792

Open
IsaacYangSLA wants to merge 1 commit into
NVIDIA:mainfrom
IsaacYangSLA:codex/set-per-site-config-helper
Open

Add per-site recipe config helper#4792
IsaacYangSLA wants to merge 1 commit into
NVIDIA:mainfrom
IsaacYangSLA:codex/set-per-site-config-helper

Conversation

@IsaacYangSLA

Copy link
Copy Markdown
Collaborator

Summary

  • add set_per_site_config(recipe, config) and export it from nvflare.recipe
  • add base Recipe.configured_sites() with helper-config precedence and legacy per_site_config fallback
  • document that per-site config values are recipe-specific and must use fields the selected recipe understands

Tests

  • python3 -m pytest tests/unit_test/recipe/spec_test.py tests/unit_test/recipe/utils_test.py -q
  • ./runtest.sh -s

Copilot AI review requested due to automatic review settings June 10, 2026 16:55
@IsaacYangSLA IsaacYangSLA force-pushed the codex/set-per-site-config-helper branch from 263e6df to 407f75b Compare June 10, 2026 16:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a public helper for attaching site-keyed (per-site) configuration to a Recipe, adds a base Recipe.configured_sites() API with helper-precedence and legacy fallback, and documents the intended usage/limitations.

Changes:

  • Added set_per_site_config(recipe, config) helper and exported it from nvflare.recipe.
  • Added Recipe.set_per_site_config(), _apply_per_site_config() hook, and Recipe.configured_sites() with helper-over-legacy precedence.
  • Added unit tests and user-guide documentation for the new per-site configuration helper.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
nvflare/recipe/utils.py Adds helper + shape validation for per-site config before applying to a recipe.
nvflare/recipe/spec.py Adds base recipe APIs for storing helper config, applying it via hook, and reporting configured sites.
nvflare/recipe/__init__.py Exposes set_per_site_config from the top-level nvflare.recipe package.
tests/unit_test/recipe/utils_test.py Verifies the new helper is importable from nvflare.recipe.
tests/unit_test/recipe/spec_test.py Adds behavioral tests for helper storage, hook invocation, precedence, and validation.
docs/user_guide/data_scientist_guide/job_recipe.rst Documents per-site configuration, configured_sites(), and recipe-specific semantics.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread nvflare/recipe/utils.py Outdated
Comment thread docs/user_guide/data_scientist_guide/job_recipe.rst
Comment thread docs/user_guide/data_scientist_guide/job_recipe.rst Outdated
@greptile-apps

greptile-apps Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a set_per_site_config(recipe, config) helper to the nvflare.recipe package and a corresponding configured_sites() method on the Recipe base class, providing a recipe-agnostic way to attach per-site configuration with explicit precedence over the legacy per_site_config constructor path.

  • utils.set_per_site_config validates the generic shape (top-level keys are strings, values are dicts) and delegates to Recipe.set_per_site_config, which stores a shallow copy and dispatches to the _apply_per_site_config hook — mutation isolation is correctly handled with a second shallow copy, confirmed by a dedicated regression test.
  • Recipe.configured_sites() returns helper-provided site names when set, falls back to the legacy per_site_config attribute otherwise, and explicitly does not infer sites from job metadata.
  • Tests cover shape validation, hook mutation isolation, legacy fallback precedence, empty-config override, and job-meta non-inference; documentation clearly scopes the contract to configured-name reporting only.

Confidence Score: 5/5

Safe to merge. The change is purely additive and touches only the recipe helper layer with no impact on existing job generation or execution paths.

All new code is strictly additive. Mutation isolation is correctly handled with a second shallow copy passed to the hook, and a regression test confirms hook key-deletions cannot corrupt stored state. The validation covers all three bad-shape cases and is tested for each. The legacy fallback uses getattr with a None default, making it safe for existing subclasses.

No files require special attention.

Important Files Changed

Filename Overview
nvflare/recipe/spec.py Adds set_per_site_config, _apply_per_site_config hook, and configured_sites() to Recipe base class; shallow copy correctly isolates top-level hook mutations from stored state.
nvflare/recipe/utils.py Adds _validate_per_site_config_shape (validates top-level key/value types) and the public set_per_site_config helper that validates then delegates to the recipe method.
nvflare/recipe/init.py Exports set_per_site_config from utils and adds it to all; straightforward.
tests/unit_test/recipe/spec_test.py Adds 7 well-scoped tests covering hook mutation isolation, legacy fallback precedence, empty-config override, job-meta non-inference, and shape validation error cases.
tests/unit_test/recipe/utils_test.py Adds a single importability smoke test verifying set_per_site_config is callable from the top-level nvflare.recipe package.
docs/user_guide/data_scientist_guide/job_recipe.rst Documents the per-site config contract, helper-validation scope, and FedAvg legacy path; clearly scopes what configured_sites() does and does not imply.

Sequence Diagram

sequenceDiagram
    participant User
    participant set_per_site_config as set_per_site_config (utils)
    participant Recipe
    participant Hook as _apply_per_site_config (subclass)

    User->>set_per_site_config: set_per_site_config(recipe, config)
    set_per_site_config->>set_per_site_config: _validate_per_site_config_shape(config)
    Note right of set_per_site_config: Checks top-level keys are str,<br/>values are dict -- raises TypeError otherwise
    set_per_site_config->>Recipe: recipe.set_per_site_config(validated_config)
    Recipe->>Recipe: "_helper_per_site_config = dict(config)"
    Recipe->>Hook: _apply_per_site_config(dict(_helper_per_site_config))
    Hook-->>Recipe: may mutate its own copy safely
    User->>Recipe: recipe.configured_sites()
    alt helper config set
        Recipe-->>User: list(_helper_per_site_config.keys())
    else legacy per_site_config exists
        Recipe-->>User: list(per_site_config.keys())
    else
        Recipe-->>User: []
    end
Loading

Reviews (3): Last reviewed commit: "Add per-site recipe config helper" | Re-trigger Greptile

Comment thread nvflare/recipe/spec.py Outdated
@IsaacYangSLA IsaacYangSLA force-pushed the codex/set-per-site-config-helper branch from 407f75b to 55a3274 Compare June 10, 2026 17:10
@IsaacYangSLA IsaacYangSLA force-pushed the codex/set-per-site-config-helper branch from 55a3274 to 110c546 Compare June 11, 2026 16:12
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