Test whether code is running inside livebook?

I’ve written a wrapper around stan to allow me to sample from bayesian models built in Elixir (and analyse the results with Explorer and other elixir utilities). Because stan models may take a long time to sample, I like to provide some feedback to the user.

When the models are sampled in the command line, I can use the excelent Owl package to show some progress bars on how many iterations out of the total have finished already. However, I have also written some Kino progress bars that work inside livebook.

Is there any way (not using private APIs or inspecting the supervision tree) my code can tell whether it is running inside a livebook so that I can setup the Kino widgets instead of the console-based progress bars?

I can’t simply implement Kino.Render for a custom type, because the goal here is to statefully display the number of iterations before the function returns.

There is currently no public API. One thing that you could do is have Kino as optional dependency and then do Code.ensure_loaded?(Kino). We could add an API to Kino, but on the other hand I don’t think libraries should special case Livebook on such internal level.

If you are only rendering a progress bar, then an alternative could be the progress_bar package, which works fine in Livebook.

2 Likes

Ji
I need to render n progress bars (one per each montecarlo chain) and update them in parallel as results come in from each chain that runs in parallel. I believe I’ve tried progress_bar in the past and it didn’t support this.

The API would have to answer not whether Kino is available (kino may be available but we may be calling the sampler from the command line, in which case we shouldn’t try to use kino widgets). The API would need to tell use whether the live book/kino/whatever is being used at the moment.

Regarding “special casing” livebook: ideally, the “environment” (speaking very loosely) would make certain APIs available for things like logging and showing feedback. I think that the library should be able to choose how to render feedback to the user based on what’s available. If livebook is available, it should use rich HTML progress bars.

The way it works in my library right now is to have a ProgressMonitor behaviour which can be implemented for various backends: console, libreview, others. So I have a KinoProgressMonitor and a ConsoleProgressMonitor (the default). I just wanted to be able to automatically pick the KinoProgressMonitor if livebook is running.

The main point is that we don’t want general-purpose libraries to include dependencies such as Kino for altering behaviour in Livebook.

One thing you could do is have the generic ProgressMonitor with default console implementation and then have a separate package such as kino_ex_stan, which would provide a kino-based implementation and registers it in KinoExStan.Application.start/2. The package could also provide other visualizations and render implementations appropriate for the library structs. Then, people using the library in Livebook could add kino_ex_stan as a dependency for richer experience.

All that said, I think the main issue here is actually that owl doesn’t render in Livebook (it does in the terminal where Livebook is running). That’s because IO happens from processes started under owl supervision tree, not in Livebook. Other than that it also uses ANSI codes to move cursor up, which Livebook doesn’t support either.

Ok, this seems like and acceptable compromise.