Skip to content

WIP Add new channel and allow instance selection with new platform #2239

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 30 commits into
base: main
Choose a base branch
from

Conversation

kt474
Copy link
Member

@kt474 kt474 commented Apr 25, 2025

Summary

Documented changes in 2239.feat.rst

TODO:

  • Backends are tied to their instances so api calls won't work unless an instance with the backend available is being passed in to the api_client. This makes the logic a bit hacky/tricky - is there a way around this? Even just fetching the
    backend configuration requires an instance.
  • Prioritization by plan type
  • Cleanup & Tests
  • Should service.backends() return all backends available through all instances?
  • Fetching all instances then fetching backends for every instance is very slow (ntc 5779 would help)

Details and comments

Fixes #2236
Mostly fixes #2237

@ElePT ElePT added this to the 0.39.0 milestone May 6, 2025
Copy link
Collaborator

@ElePT ElePT left a comment

Choose a reason for hiding this comment

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

Thanks @kt474, I took an initial look at the PR and I see that some details need to be ironed out and in general is a tricky feature to develop. I left a few comments here and there (some really minor), but I think that my main points are:

  1. The documentation of the "ibm_cloud" channel should stay while the option is supported, even if it's not the recommended one. We should extend the documentation with the new "ibm_quantum_platform" channel, make sure the new name is used in the examples and deprecation message, and mention that it's the new default and follows the same configuration path as "ibm_cloud". After the alternative is in place, we can deprecate "ibm_cloud" explicitly. The new name is too close to "ibm_quantum" and many users will naively assume that it is replacing it making the migration even more complex.

  2. Regarding your 2 questions from the PR description:

  • Should service.backends() return all backends available through all instances?
  • Fetching all instances then fetching backends for every instance is very slow (ntc 5779 would help)

My take is that with any change that we make that adds API calls, we should make sure users are not hit with a performance regression if they aren't getting anything out of it (so if you really need this functionality, sure, you might be willing to sacrifice speed, but some users won't need it). So I would only really fetch all instances if no instance or default_instance is set, and would only iterate over all instances and backends in that case. Also brainstorming here, this might be a good opportunity to try async API calls, which might mitigate the performance hit a bit?

Comment on lines 148 to 151
# def list_instances(self) -> None:
# """"""
# pass

Copy link
Collaborator

Choose a reason for hiding this comment

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

The method is defined later:

Suggested change
# def list_instances(self) -> None:
# """"""
# pass

@@ -371,7 +371,7 @@ def usage_estimation(self) -> Dict[str, Any]:
@property
def instance(self) -> Optional[str]:
"""For ibm_quantum channel jobs, return the instance where the job was run.
For ibm_cloud, `None` is returned.
For ibm_quantum_platform, `None` is returned.
Copy link
Collaborator

Choose a reason for hiding this comment

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

The behavior for ibm_cloud should still be documented until the option is removed.

instance: This is only supported for ``ibm_quantum`` runtime and is in the
hub/group/project format.
instance: In hub/group/project format if on the ``ibm_quantum`` channel.
IBM Cloud account crn if on the ``ibm_quantum_platform`` channel.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same comment on still documenting "ibm_cloud" if it is still a valid channel, which it is until deprecation (then during the deprecation PR we can mark it as deprecated in the docstrings, but not remove the info until the feature is removed).

Comment on lines 616 to 621
if instance_with_backend:
# TODO how do we handle this logic here?
# fetching a backend not in the current account instance requires a
# different api client - this api client is tied to everything
self._client_params.instance = instance_with_backend
self._api_client = RuntimeClient(self._client_params)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This code seems to be overwriting the api client. How would it behave if a user let's say instantiates the service, asks for backend 1 in instance A, asks for a backend 2 in instance B and decides to start a session with backend 1? Would this work?

Copy link
Member Author

Choose a reason for hiding this comment

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

That's a good point, I'l have to test that edge case - I don't think that would work. I can't think of any other way to handle this since the backend is ultimately always tied to its instance.

Copy link
Collaborator

@ElePT ElePT left a comment

Choose a reason for hiding this comment

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

Sharing some conclusions from our internal discussion on how to advance with this PR:

  1. We will not add default_instance, and use instance instead. We will document the parameter in save_account as: “This is an optional parameter. If set, it will define a default instance for service instantiation, if not set, the service will fetch all instances related to a specific token” (or something along these lines). We will add this change in behavior to the reno, mentioning that it’s now optional and that not setting it gives access to all instances. We will also let the docs team know about the change.
  2. We will add the following new optional parameters to both save_account and __init__ : account , region , plans_preference. Where if the value is set in init it will overwrite the default from save_account.
  3. If no instance is set during init, to do authentication, we can call IBM Cloud platform APIs to get all the service instances the user has access to

@@ -1183,7 +1330,7 @@ def instances(self) -> List[str]:
"""
if self._channel == "ibm_quantum":
return list(self._hgps.keys())
return []
return [t["crn"] for t in self._all_instances]
Copy link
Collaborator

Choose a reason for hiding this comment

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

This line returns an empty list for the case where no instance is given, but I would expect it to list all available instances, as when calling list_instances()

Comment on lines 219 to 221
self._client_params.instance = instance
self._api_client = RuntimeClient(self._client_params)
return self._api_client.list_backends()
Copy link
Collaborator

Choose a reason for hiding this comment

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

You may have come up with a better solution to avoid overwriting the client, but in case it helps: I think that you could refactor the client_params object and/or the RuntimeClient object (I would have to look into the specifics) to be able to store more than 1 instance in the cloud case. This would allow to keep handles to all instances a user might need instead of imposing one instance at a time. They could be stored together with the backend name, so the client knows which instance to use to access a specific backend.

@mtreinish
Copy link
Member

So I'm playing with this locally and some observations, right now if you do:

QiskitRuntimeService.save_account(channel="ibm_quantum_platform", token="...")

it saves an ibm_cloud channel account in the json file. Then when you instantiate the service from the saved credentials it loads up as a ibm_cloud channel account and not ibm_quantum_platform. This causes a warning to be printed when you load the account because there is no instance set QiskitRuntimeService(). I kind of expected this to just all work by default and show all the instances I have since I didn't set a specific one.

@kt474 kt474 modified the milestones: 0.39.0, 0.40.0 May 15, 2025
@kt474
Copy link
Member Author

kt474 commented May 15, 2025

it saves an ibm_cloud channel account in the json file. Then when you instantiate the service from the saved credentials it loads up as a ibm_cloud channel account and not ibm_quantum_platform. This causes a warning to be printed when you load the account because there is no instance set QiskitRuntimeService(). I kind of expected this to just all work by default and show all the instances I have since I didn't set a specific one.

Fixed the issue where ibm_cloud was being saved instead of ibm_quantum_platform . Currently we raise a warning at service initialization because one api can token can have access to multiple accounts. The instances aren't needed until the first backends() call.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants