Skip to content
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

New kernels REST API #900

Open
davidbrochart opened this issue Jul 3, 2022 · 24 comments
Open

New kernels REST API #900

davidbrochart opened this issue Jul 3, 2022 · 24 comments

Comments

@davidbrochart
Copy link
Contributor

Problem

Currently, the kernel protocol over ZMQ in the back-end is "forwarded" to the front-end over a WebSocket. This brings a lot of complexity to the front-end, which has to speak this protocol.
With JupyterLab moving to RTC, the (notebook) UI becomes merely a shared document editor: the user enters some text in a cell, asks for execution, sees outputs being populated, clears outputs... There is no need for the front-end to e.g. interpret IOPub messages in order to display results, all this could be done in the back-end and directly modify the shared document, which would automatically update in the front-end.

Proposed Solution

We could create a much more simple REST API for kernels, which would consist of e.g. "POST execute request", etc.
All kernel state information (idle, busy, dead, restarting...) could go to the new event system.

@davidbrochart
Copy link
Contributor Author

For the back-end to be able to make changes to a shared document based on some code execution, the back-end has to know which (part of a) document the code is linked to. For instance in a notebook, a cell input contains code that will produce outputs in the same cell.
This means that this REST API must provide information about the document to modify, as well as the kernel to use. A notebook cell "POST execute request" should consist of the following body:

{
  "document_id": "path/to/notebook.ipynb",
  "cell_id": "b4d4a3fe-bc05-4965-b5eb-94732e4329ae",
  "kernel_id": "c71c23dd-38ba-4967-aa46-415ba7317012"
}

@Zsailer
Copy link
Member

Zsailer commented Jul 5, 2022

I would be in favor of extending the current kernels API in core to include a new REST endpoint for executing code. Something like

POST /api/kernels/<kernel_id>/execute

Body: 
{
  "document_id": "path/to/notebook.ipynb",
  "cell_id": "b4d4a3fe-bc05-4965-b5eb-94732e4329ae",
  "kernel_id": "c71c23dd-38ba-4967-aa46-415ba7317012",
  "code": ...
}

Response:
{
  "document_id": "path/to/notebook.ipynb",
  "cell_id": "b4d4a3fe-bc05-4965-b5eb-94732e4329ae",
  "kernel_id": "c71c23dd-38ba-4967-aa46-415ba7317012"

}

This wouldn't require a websocket to the kernel for two-way comms. It simply sends an execute_request to the kernel. On the server, this request would be handled by the KernelManager and formulated into a proper ZMQ message to be sent across kernels shell channel.

I don't think we should replace any of the the current kernel's REST/Websocket API, though. The kernel websocket APIs are still heavily used by projects other than JupyterLab. We don't want those endpoints to degrade or deprecate anytime soon.

As for checking kernel status, I think it also makes sense to add a GET /api/kernels/<kernel_id>/status endpoint that sends a message to IOPub for kernel status and wait for a response. The event bus websocket is also a good way to shuttle these messages.

@davidbrochart
Copy link
Contributor Author

This work is happening in jupyter-server/jupyverse#191.

@echarles
Copy link
Member

echarles commented Jul 6, 2022

There is no need for the front-end to e.g. interpret IOPub messages in order to display results,

What would the impact for the Comm messages used by IPyWidgets?

@davidbrochart
Copy link
Contributor Author

That's a good point, currently ipywidgets won't work with this, but there are discussions about using y-py in ipywidgets, which would be very aligned with this REST API in my opinion.

@echarles
Copy link
Member

echarles commented Jul 6, 2022

but there are discussions about using y-py in ipywidgets

Any pointers? Any backwards compatibly requirement taken in that discussion?

@davidbrochart
Copy link
Contributor Author

davidbrochart commented Jul 6, 2022

I think it has been discussed in some meetings, but it's probably not going to happen anytime soon.
Regardless of ipywidgets, this kernels REST API could make it easier for new collaborative front-ends which don't want to bother about low-level kernel protocols. I think it can lower the bar quite a lot in that regard.

@vidartf
Copy link
Member

vidartf commented Jul 7, 2022

I think it would be important to make it possible for clients to (easily) combine RTC experience with Comms. Having an example of how to do this would be helpful (but I agree that it might not be needed in the first iteration).

@davidbrochart
Copy link
Contributor Author

I opened an issue in ipywidgets.

@Wh1isper
Copy link
Contributor

Wh1isper commented Dec 7, 2022

I implemented a simple generic client based on the websocket interface (I tried using jupyter_client's zmq interface, but it was hard to use), and then implemented a plugin with fileid support to implement this functionality.

client: https://github.com/Wh1isper/jupyter_kernel_client
extension: https://github.com/Wh1isper/jupyter_kernel_executor

Looking forward to your suggestions !
@davidbrochart @Zsailer

@kevin-bates
Copy link
Member

I would strongly suggest you use the AsyncMappingKernelManager. That way your kernels will be managed by the ServerKernelManager where you'll be able to leverage future functionality.

@fcollonval
Copy link
Member

We have started the work for an jupyter_server extension at https://github.com/datalayer/jupyter-server-nbmodel

@davidbrochart
Copy link
Contributor Author

This repo doesn't seem to be public?

@fcollonval
Copy link
Member

Thanks @davidbrochart for the ping - it should now be public

@davidbrochart
Copy link
Contributor Author

Confirmed, thanks!
@Zsailer might be interested too.

@echarles
Copy link
Member

echarles commented May 7, 2024

Looks like the current implementations target two goals:

  1. Run some code via a HTTP POST endpoint (loosing the "streaming" feature of the output).
  2. Have an endpoint to move the complete model to the server.

Do we want to serve those 2 goals via the same endpoint or should we separate them.
(PS: This may have impact on the existing jupyterlab implementation).

@davidbrochart
Copy link
Contributor Author

  1. Run some code via a HTTP POST endpoint (loosing the "streaming" feature of the output).

Why would output streams be lost?

@fcollonval
Copy link
Member

fcollonval commented May 7, 2024

Demo for https://github.com/datalayer/jupyter-server-nbmodel using RTC model to update the notebook model on the server side from the kernel outputs (with jupyterlab/jupyter-collaboration#307)

demo_server_side_execution_rtc

@echarles
Copy link
Member

echarles commented May 7, 2024

Why would output streams be lost?

I was meaning that in the case 1 (Run some code via a HTTP POST without RTC), the server needs to wait the end of the execution before sending back the result. In that case, the client receives the complete outputs at once, so can not show the user the progress in streaming. Does it make sense?

@davidbrochart
Copy link
Contributor Author

Run some code via a HTTP POST without RTC

I don't see a lot of value in that.

@Wh1isper
Copy link
Contributor

Wh1isper commented May 8, 2024

Run some code via a HTTP POST without RTC

In this mode, websocket (the current JupyterLab implementation) seems the only option

@Wh1isper
Copy link
Contributor

Wh1isper commented May 8, 2024

Demo for datalayer/jupyter-server-nbmodel using RTC model to update the notebook model on the server side from the kernel outputs (with jupyterlab/jupyter-collaboration#307)

Thanks for creating this awosome project!

I took a quick look at the code and left with two questions:

Feel free to discuss them with me anytime! :D

@fcollonval
Copy link
Member

Update on the jupyter server extension:

  • Support stdin
  • Workish with ipywidgets

Prerequisites:

Execution of a notebook only from the left user - the right view is a RTC collaborator only viewing in the demo:

demo_server_side_exec3b.mp4

Note

The input prompt only appears for the user starting the execution request
The fake output keeping track of the input value is added in the document by the left client (this is not ideal)
ipywidget may or may not render at first execution (it smells like a race condition) as can be seen with the button and slider that appears in one of the client but not in both
ipywidget are correctly instantiated when closing and reopening a document (small victory ✌️ )

I added some sequence diagrams to explain what is going on there.

@rishabh-dream11
Copy link

Hi, @fcollonval @davidbrochart , currently server-side state persistence is only supported by JupyVerse, will this ticket allow Jupyter-server based platforms to do the same?

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

No branches or pull requests

8 participants