Skip to content

Conversation

cowanwalls
Copy link
Member

@cowanwalls cowanwalls commented Oct 2, 2025

Description

Adds ensemble definition support.

Changes

  • nextmv/nextmv/cloud/ensemble.py
    • Ensemble definition types added
  • nextmv/nextmv/cloud/__init__.py
    • Ensemble definition types exported to cloud
      • Should we consolidate ToleranceType in acceptance tests and Ensemble runs to a single type? Maybe via the addition of a statatics.py file in nextmv/nextmv/cloud?
  • nextmv/nextmv/cloud/application.py
    • Adds ensemble management functions
    • new_version now defaults the name field to the value of id if name is None (fixes unexpected 404)

Testing

Manually tested these changes.

Copy link
Member

@sebastian-quintero sebastian-quintero left a comment

Choose a reason for hiding this comment

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

This is looking really good, congratulations! Aside from the specific comments, please add the new ensemble.py to the docs reference. For that there are two changes you need to make:

  1. In the mkdocs.yml file in the root of the repo, add this reference in the appropriate location, which should be under - client.py: nextmv/reference/cloud/client.md, to keep the alphabetical order. You can simply copy that line and change client for ensemble.
  2. Because you are referencing a non-existent ensemble.md file, you need to create it. Add it to docs/nextmv/reference/cloud. You can copy any of the existing files there, rename it, and modify the content to point to the correct reference ::: nextmv.nextmv.cloud.ensemble.

Basically, whenever we add new files to the SDK, we need to add them to the technical reference of docs as well.

endpoint=f"{self.endpoint}/secrets/{secrets_collection_id}",
)

def delete_ensemble_definition(self, ensemble_definition_id: str) -> None:
Copy link
Member

Choose a reason for hiding this comment

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

Nit: we try to organize the methods in this class alphabetically, so this one should be above delete_scenario_test.


def delete_ensemble_definition(self, ensemble_definition_id: str) -> None:
"""
Delete a secrets collection.
Copy link
Member

Choose a reason for hiding this comment

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

This is not accurate.

return False
raise e

def ensemble_definition(self, ensemble_definition_id: str) -> EnsembleDefinition:
Copy link
Member

Choose a reason for hiding this comment

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

Nit: same comment about ordering methods alphabetically inside the class.


return [Instance.from_dict(instance) for instance in response.json()]

def list_ensemble_definitions(self) -> list[EnsembleDefinition]:
Copy link
Member

Choose a reason for hiding this comment

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

Nit: same comment here about ordering alphabetically.

Returns
-------
list['EnsembleDefinition']
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
list['EnsembleDefinition']
list[EnsembleDefinition]

I think in this case backticks are not needed.

Comment on lines 1387 to 1398
----------
id: str
ID of the ensemble defintion.
name: Optional[str]
Name of the ensemble definition.
description: Optional[str]
Description of the ensemble definition.
run_groups: Optional[list[RunGroup]]
Information to facilitate the execution of child runs.
rules: Optional[list[EvaluationRule]]
Information to facilitate the selection of
a result for the ensemble run from child runs.
Copy link
Member

Choose a reason for hiding this comment

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

Parameters should be in the same order they are expected in the function arguments.


response = self.client.request(
method="POST",
endpoint=f"{self.endpoint}/ensembles",
Copy link
Member

Choose a reason for hiding this comment

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

Nit: consider defining ensembles as an attribute of the class, similar to experiments_endpoint:

experiments_endpoint: str = "{base}/experiments"

That way, you can use {self.ensembles_endpoint} as opposed to {self.endpoint}/ensembles here and in other places.


return Instance.from_dict(response.json())

def update_ensemble_definition(
Copy link
Member

Choose a reason for hiding this comment

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

Nit: same comment about alphabetical order.

from .batch_experiment import ExperimentStatus as ExperimentStatus
from .client import Client as Client
from .client import get_size as get_size
from .ensemble import EnsembleDefinition as EnsembleDefinition
Copy link
Member

Choose a reason for hiding this comment

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

Strange, this should be ok.

@sebastian-quintero
Copy link
Member

@cowanwalls You should pip install ruff locally and run ruff check . to make sure that the linting passes locally....

Copy link
Member

@sebastian-quintero sebastian-quintero left a comment

Choose a reason for hiding this comment

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

My only leftover request is for this new file to be exposed as reference. Look at the cloud section in the mkdocs.yml index, you should see how to add the file as .md as well. This for docs to be up to date. Would really be awesome to have a dedicated page of a tutorial to handle ensemble definitions and runs in general.

@cowanwalls cowanwalls merged commit 7bdf266 into develop Oct 6, 2025
88 checks passed
@cowanwalls cowanwalls deleted the feature/eng-5549-support-ensemble-runs-via-python-sdk branch October 6, 2025 15:03
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