Skip to content

Align NAT functionals with FunctionSpec#1615

Open
loliverhennigh wants to merge 10 commits intoNVIDIA:mainfrom
loliverhennigh:functional-api-cleanup
Open

Align NAT functionals with FunctionSpec#1615
loliverhennigh wants to merge 10 commits intoNVIDIA:mainfrom
loliverhennigh:functional-api-cleanup

Conversation

@loliverhennigh
Copy link
Copy Markdown
Collaborator

PhysicsNeMo Pull Request

Description

Cleans up some of the NAT functional stuff and others that made it past my radar.

@copy-pr-bot
Copy link
Copy Markdown

copy-pr-bot Bot commented May 4, 2026

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 4, 2026

Greptile Summary

This PR wraps the existing na1d/na2d/na3d NATTEN functions in FunctionSpec-derived classes (NeighborhoodAttention1D/2D/3D), adds them to the benchmark registry alongside two geometry specs, ships a new doc page, and updates FNC-000 to officially allow lightweight pure-PyTorch helpers to stay as plain functions.

  • P1 – test will fail when natten is installed: test_natten_version_mismatch_error_message monkeypatches get_installed_version but available is frozen at class-definition time; with natten >= 0.21.5 present, dispatch succeeds and pytest.raises(ImportError) raises Failed: DID NOT RAISE.
  • P2 – unreachable raise in _NeighborhoodAttention.dispatch: the final bare re-raise is only reachable if get_installed_version returns None yet _natten.functional does not raise, a combination that cannot occur with OptionalImport; worth a clarifying comment or a more descriptive fallback error.

Important Files Changed

Filename Overview
physicsnemo/nn/functional/natten.py Wraps na1d/na2d/na3d in FunctionSpec subclasses with a custom dispatch that enriches ImportError messages; the dispatch error-handling has an unreachable code path and an associated test that breaks in environments with a conforming natten install.
test/nn/functional/test_natten.py Adds FunctionSpec contract tests and error-message tests; test_natten_version_mismatch_error_message is unreliable when natten >= 0.21.5 is installed because available=True is fixed at class-definition time.
benchmarks/physicsnemo/nn/functional/registry.py Adds NeighborhoodAttention1D/2D/3D and geometry specs to FUNCTIONAL_SPECS; straightforward and correct.
CODING_STANDARDS/FUNCTIONAL_APIS.md Clarifies FNC-000 to allow lightweight pure-PyTorch helpers to stay as plain functions; well-reasoned criteria and rationale.
docs/api/nn/functionals/neighborhood_attention.rst New RST page auto-documenting na1d/na2d/na3d from the correct public path; no issues.
docs/api/physicsnemo.nn.functionals.rst Adds the new neighborhood_attention page to the functionals TOC; no issues.

Reviews (1): Last reviewed commit: "Align NAT functionals with FunctionSpec" | Re-trigger Greptile

Comment thread test/nn/functional/test_natten.py Outdated
Comment on lines +49 to +64
@classmethod
def dispatch(cls, *args, **kwargs):
try:
return super().dispatch(*args, **kwargs)
except ImportError as exc:
installed_version = get_installed_version("natten")
if installed_version is not None:
raise ImportError(
f"{cls._NATTEN_REQUIREMENT} is required for {cls.__name__}, "
f"but found natten {installed_version}"
) from exc
try:
_natten.functional
except ImportError as missing_exc:
raise missing_exc from exc
raise
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.

P2 Unreachable raise at the end of the dispatch override

The final bare raise is only reached when installed_version is None and _natten.functional does not raise ImportError. Because installed_version is None means the package metadata is absent and the OptionalImport proxy always raises ImportError on attribute access when the underlying module cannot be imported, this branch is currently unreachable in practice. If _natten.functional somehow succeeds (e.g., metadata is absent but the package is importable), re-raising exc produces the cryptic "No available implementations found" message rather than any natten-specific hint. The code path should either be documented with a comment explaining the invariant, or the final raise should emit a more descriptive error.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done.

Comment thread physicsnemo/nn/functional/attention/neighborhood_attention.py
@pzharrington
Copy link
Copy Markdown
Collaborator

@loliverhennigh my main question is have you tested that this still works with ShardTensor and domain parallelism? Want to make sure the dispatch path in that case does the right thing. Otherwise looks good

from physicsnemo.nn.functional.geometry import SignedDistanceField
from physicsnemo.nn.functional.geometry import (
MeshPoissonDiskSample,
MeshToVoxelFraction,
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Some of the functionals got left out so adding them back in

All functionals must be implemented with `FunctionSpec`, even if only a single
implementation exists. This ensures the operation participates in validation
and benchmarking through input generators and `compare_forward` (and
All functionals with backend dispatch, optional accelerated implementations, or
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Basically going to make some space for if we have very simple python functions and dont want to implement the whole FunctionSpec stuff

@loliverhennigh loliverhennigh force-pushed the functional-api-cleanup branch from 8da5e27 to 280d401 Compare May 5, 2026 18:53
@loliverhennigh loliverhennigh force-pushed the functional-api-cleanup branch 2 times, most recently from f0cb8a9 to e3847e8 Compare May 5, 2026 19:08
Copy link
Copy Markdown
Collaborator

@megnvidia megnvidia left a comment

Choose a reason for hiding this comment

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

tiny suggestion

Comment thread CODING_STANDARDS/FUNCTIONAL_APIS.md Outdated
@megnvidia
Copy link
Copy Markdown
Collaborator

rst files looked good to me, I had one very minor suggestion for Nvidia style guide rules. Looks like you still have other comments, but I am ready to approve of this when you need.

@loliverhennigh loliverhennigh force-pushed the functional-api-cleanup branch 2 times, most recently from 297f9cb to 62a0ef7 Compare May 5, 2026 22:41
@loliverhennigh
Copy link
Copy Markdown
Collaborator Author

/blossom-ci

@loliverhennigh
Copy link
Copy Markdown
Collaborator Author

/multi-gpu-ci

@loliverhennigh
Copy link
Copy Markdown
Collaborator Author

/blossom-ci

@coreyjadams
Copy link
Copy Markdown
Collaborator

/multi-gpu-ci

I have no idea if this still does anything. You might need to test manually on a cluster.

@loliverhennigh
Copy link
Copy Markdown
Collaborator Author

Hey @coreyjadams and @pzharrington , Just manually ran on two GB200s and it passed. I think we are all good to merge unless there is something else

DualInteractionPlan,
SourceAggregates,
)
from physicsnemo.experimental.models.globe.cluster_tree import ClusterTree
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.

Motivation for this edit? Seems unrelated

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done.

@loliverhennigh
Copy link
Copy Markdown
Collaborator Author

/blossom-ci

# See the License for the specific language governing permissions and
# limitations under the License.

from .ops import (
Copy link
Copy Markdown
Collaborator

@peterdsharpe peterdsharpe May 7, 2026

Choose a reason for hiding this comment

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

This change of equivariant_ops -> equivariant.ops is backwards-incompatible. We should at-bare-minimum have a CHANGELOG entry for this, but realistically this probably calls for a larger discussion about whether this is worth breaking back-compat for, given that there may be downstream users that are consumers of this API surface. In general, we shouldn't be breaking public (i.e., non-_-prefixed) API surface unless it's exceedingly important that we do so.

Also, tagging @laserkelvin for API thoughts on the equivariant module (not sure if you have any uses of this?)

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.

I don't think I have an issue with naming alignment itself (i.e. nn.functional.equivariant) - I'm just confused why this is happening now, and to your (@peterdsharpe's) point this is backwards incompatible. AFAIK there aren't public consumers of that API yet, but please make sure that the tests associated with this change pass

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.

Unless we introduced equivariant_ops within this current release cycle (in which case it's not part of the public API yet)? What does the git blame say?

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.

It's not in the 2.0.0 release, and I think you added it 2 months ago

Copy link
Copy Markdown
Collaborator

@peterdsharpe peterdsharpe May 8, 2026

Choose a reason for hiding this comment

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

Ah - if it wasn't ever released publicly in an official release cut, then I'm more ok with breaking this API.

That said, it's not obvious to me that either naming convention is better than the other. In the absence of motivation, defaulting to the existing API seems like the best path forward. That said, there may be motivation for this change that I'm not seeing - @loliverhennigh can you speak to the motivation for this change?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

External customers should only use functionals via physicsnemo.nn.functionals.xyz. This is how the coding standards and docs are laid out at least. This PR does not change that import so I think we are good. Only internal imports might change.

@loliverhennigh
Copy link
Copy Markdown
Collaborator Author

/blossom-ci

Copy link
Copy Markdown
Collaborator

@megnvidia megnvidia left a comment

Choose a reason for hiding this comment

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

lgtm

@@ -22,11 +22,15 @@


@overload
def smooth_log(x: Float[torch.Tensor, "..."]) -> Float[torch.Tensor, "..."]: ...
def smooth_log(x: Float[torch.Tensor, "..."]) -> Float[torch.Tensor, "..."]:
"""Apply smooth log elementwise to a tensor."""
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.

These are @overloads - are docstrings needed to satisfy interrogate? I would hope that they would not be needed, but I don't know if interrogate is smart enough to handle this.

Maybe interrogate has an option to ignore overloaded functions?

@peterdsharpe
Copy link
Copy Markdown
Collaborator

@loliverhennigh can we flesh out the discussion in unresolved comment threads before merging?

@loliverhennigh loliverhennigh force-pushed the functional-api-cleanup branch from 8519251 to 6885e86 Compare May 8, 2026 18:41
@loliverhennigh
Copy link
Copy Markdown
Collaborator Author

/blossom-ci

@peterdsharpe peterdsharpe self-requested a review May 8, 2026 19:33
@loliverhennigh loliverhennigh force-pushed the functional-api-cleanup branch from b8d31d3 to e638afc Compare May 8, 2026 22:04
@loliverhennigh
Copy link
Copy Markdown
Collaborator Author

/blossom-ci

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.

6 participants