WEBVTT

00:00:00.020 --> 00:00:08.320
Have you ever spent an afternoon wrestling with a Jupyter notebook, hoping that you ran all the cells in just the right order, only to realize your outputs were completely out of sync?

00:00:08.900 --> 00:00:11.800
Today's guest has a fresh take on solving that exact problem.

00:00:12.380 --> 00:00:20.040
Akshay Agrawal is here to introduce Marimo, a reactive Python notebook that ensures your code and outputs always stay in lockstep.

00:00:20.640 --> 00:00:21.840
And that's just the start.

00:00:21.900 --> 00:00:32.700
We'll also dig into Axie's background at Google Brain and Stanford, what it's like to work on cutting-edge AI, and how Marimo is uniting the best of data science exploration and real software engineering.

00:00:33.580 --> 00:00:39.780
This is Talk Python To Me, episode 501, recorded Thursday, February 27th, 2025.

00:00:41.040 --> 00:00:41.220
Are

00:00:41.220 --> 00:00:42.640
you ready for your host, please?

00:00:43.560 --> 00:00:46.400
You're listening to Michael Kennedy on Talk Python To Me.

00:00:46.940 --> 00:00:50.020
Live from Portland, Oregon, and this segment was made with Python.

00:00:53.300 --> 00:00:56.140
Welcome to Talk Python To Me, a weekly podcast on Python.

00:00:56.840 --> 00:00:58.300
This is your host, Michael Kennedy.

00:00:58.740 --> 00:01:11.640
Follow me on Mastodon, where I'm @mkennedy, and follow the podcast using @talkpython, both accounts over at fosstodon.org, and keep up with the show and listen to over nine years of episodes at talkpython.fm.

00:01:12.240 --> 00:01:16.100
If you want to be part of our live episodes, you can find the live streams over on YouTube.

00:01:16.540 --> 00:01:22.380
subscribe to our YouTube channel over at talkpython.fm/youtube and get notified about upcoming shows.

00:01:23.000 --> 00:01:25.520
This episode is sponsored by Worth Recruiting.

00:01:26.120 --> 00:01:30.500
Worth Recruiting specializes in placing senior level Python developers and data scientists.

00:01:31.140 --> 00:01:35.880
Let Worth help you find your next Python opportunity at talkpython.fm/Worth.

00:01:36.640 --> 00:01:39.100
Akshay, welcome to Talk Python To Me. Awesome to have you here.

00:01:39.400 --> 00:01:41.000
Thanks, Michael. Really happy to be here.

00:01:41.280 --> 00:01:43.500
Yeah, it's data science hour, isn't it?

00:01:44.640 --> 00:01:45.840
Yeah, I guess it is.

00:01:46.320 --> 00:01:54.380
In a sense, but also in a sense, kind of bringing data science a little closer to traditional, formal computer science or more.

00:01:55.080 --> 00:01:55.400
I don't know.

00:01:55.660 --> 00:01:56.920
I don't know what to think about computer science.

00:01:57.120 --> 00:01:57.660
Software engineering.

00:01:58.200 --> 00:01:58.780
Software engineering.

00:01:59.040 --> 00:01:59.920
Yeah, that's our goal.

00:02:00.100 --> 00:02:04.640
Blending data science with sort of the rigor reproducibility of software engineering.

00:02:05.120 --> 00:02:05.320
Yeah.

00:02:05.700 --> 00:02:07.840
And I think people are going to find it pretty interesting.

00:02:08.100 --> 00:02:10.300
It's definitely gained a lot of traction lately.

00:02:10.560 --> 00:02:13.420
So it's going to be really fun to dive into Marimo.

00:02:13.940 --> 00:02:15.780
Before we do, though, who are you?

00:02:15.840 --> 00:02:17.360
What are you doing here? Tell people about yourself.

00:02:18.100 --> 00:02:23.880
Sure. So I'm Akshay. I'm one of the co-founders and developers of Marimo.

00:02:24.960 --> 00:02:34.000
I started working on Marimo a few years ago, I guess, a little over two years ago, right after I finished a PhD at Stanford where I was working on machine learning research.

00:02:35.080 --> 00:02:38.040
And before that, I was at Google Brain where I worked on TensorFlow.

00:02:39.400 --> 00:02:51.300
And I guess for the past several years, I've been wearing different hats, It's either a computer systems hat where I build open source software and domain specific languages for people who do machine learning or I just do machine learning.

00:02:51.830 --> 00:02:52.120
And for the

00:02:52.120 --> 00:02:52.740
past few years,

00:02:52.820 --> 00:02:54.520
it's been the first hat.

00:02:54.610 --> 00:03:05.260
So working on the Marimo notebook, which is our attempt to blend the best parts of interactive computing with the reusability and reproducibility of regular Python software.

00:03:05.550 --> 00:03:06.180
Well, that's very cool.

00:03:06.680 --> 00:03:11.120
You've been right at the cutting edge of this whole machine learning thing, I guess, right?

00:03:11.220 --> 00:03:15.860
If you go back a handful of years, it's different today than it was five years ago.

00:03:16.240 --> 00:03:16.680
Oh, yeah.

00:03:16.900 --> 00:03:17.640
It's very different.

00:03:17.930 --> 00:03:20.700
I was at Google Brain 2017 to 2018.

00:03:21.680 --> 00:03:27.020
So I think we had Transformers, but we didn't really appreciate all that they could do.

00:03:27.720 --> 00:03:27.880
Yeah.

00:03:29.180 --> 00:03:37.680
But it was a really exciting time to be at Google Brain where it was pure research, just like one, that you could just work on anything that you wanted to work on.

00:03:37.800 --> 00:03:47.520
And I was an engineer there on a, actually on a small sub team inside of TensorFlow where we were working on TensorFlow too, which is sort of making TensorFlow more like PyTorch crudely.

00:03:47.920 --> 00:03:54.260
And that was a lot of fun, but yeah, got to go to like a bunch of talks by researchers and it was a special time for sure.

00:03:54.440 --> 00:03:55.360
Yeah, I bet it was.

00:03:55.700 --> 00:03:58.360
Well, you know, that's such an interesting background.

00:03:58.520 --> 00:04:04.680
I think maybe give people a sense of what is Google Brain and all that and maybe just Transformers, right?

00:04:04.780 --> 00:04:11.840
It's the foundation of so much surprising and unexpected tech these days.

00:04:12.260 --> 00:04:13.860
Yeah, yeah, I'm happy to.

00:04:14.600 --> 00:04:16.299
So Google Brain, what is Google Brain?

00:04:16.400 --> 00:04:20.200
So I guess technically Google Brain no longer exists as it did back then.

00:04:20.380 --> 00:04:22.800
Now it's just DeepMind with DeepMind and Google Brain merged.

00:04:23.300 --> 00:04:30.140
But back then Google Brain was, so there was, I guess, two researchers under the alphabet umbrella, Google Brain and DeepMind.

00:04:31.140 --> 00:04:33.900
And Google Brain was a place where it was really special.

00:04:34.020 --> 00:04:42.780
So there were folks working on all kinds of research projects from you, like using transformers for code generation, but also like systems research projects.

00:04:42.880 --> 00:04:43.980
Like I was there when

00:04:43.980 --> 00:04:45.460
the JAX

00:04:45.460 --> 00:04:51.600
machine learning library, which is an alternative to TensorFlow and PyTorch, was still being in the early days of development.

00:04:51.780 --> 00:04:56.140
And I was able to meet with like Roy Frostig, Matt Johnson.

00:04:56.800 --> 00:05:02.400
And that was really cool sort of coming up to speed on machine learning systems in that era.

00:05:03.460 --> 00:05:16.000
I was only there for a year because I decided I wanted to go back and do a PhD myself in machine learning research where I used actually TensorFlow and PyTorch to work on new sort of like machine learning modules.

00:05:16.960 --> 00:05:18.540
Did you feel bad when you used PyTorch?

00:05:18.640 --> 00:05:19.600
You're like, oh, I'm cheating.

00:05:20.340 --> 00:05:21.100
No, no.

00:05:21.330 --> 00:05:23.040
I mean, a little, I guess.

00:05:23.220 --> 00:05:26.780
But, you know, it's the thing like everyone else used PyTorch.

00:05:27.140 --> 00:05:28.680
And we had just started working

00:05:28.680 --> 00:05:29.220
on TensorFlow

00:05:29.220 --> 00:05:31.760
too when I joined, whereas PyTorch had already been mature.

00:05:31.940 --> 00:05:34.240
So it was the responsible thing to do.

00:05:36.780 --> 00:05:36.940
And

00:05:36.940 --> 00:05:37.500
Transformers,

00:05:38.140 --> 00:05:39.020
what are these Transformer things?

00:05:39.800 --> 00:05:40.800
They came out of Google, right?

00:05:41.320 --> 00:05:42.200
Yeah, yeah, they did.

00:05:42.420 --> 00:05:43.600
Attention is all you need.

00:05:45.280 --> 00:05:50.600
These Transformer things, I guess, are the backbone of all these large language models that we're seeing today.

00:05:51.120 --> 00:05:59.160
And they proved to have like an incredible capacity for modeling, I guess, in a generative way, all kinds of text.

00:05:59.260 --> 00:06:02.860
And in a way that, honestly, if I had to admit, surprised me.

00:06:03.160 --> 00:06:07.780
At the time in 27 to 18, we were doing good work in machine translation and stuff.

00:06:08.560 --> 00:06:18.680
But even back then, there was researchers who were working on, at Google Brain, code generation, writing a bunch of unit tests, stuff that people do regularly today, actually, with large language models.

00:06:20.280 --> 00:06:24.120
I put on my systems engineer hat back then, and I was a little skeptical, to be honest.

00:06:24.660 --> 00:06:27.400
And I've just totally proved wrong, and I'm happy to have been proved wrong.

00:06:28.220 --> 00:06:33.140
So it's been phenomenal seeing sort of that, the success of that particular model.

00:06:34.540 --> 00:06:35.320
And yeah, having

00:06:35.320 --> 00:06:36.240
quite a small

00:06:36.240 --> 00:06:36.960
part in it.

00:06:37.100 --> 00:06:43.300
Yeah, I was, I've been a long time skeptic of machine learning in the sense that for so long, it was, it's kind of like fusion.

00:06:43.860 --> 00:06:54.960
It's going to be amazing, but it's 10, 20, 30 years out and maybe, you know, and it was all almost like knowledge, knowledge-based type things.

00:06:55.140 --> 00:06:55.400
And just,

00:06:55.840 --> 00:06:56.460
I

00:06:56.460 --> 00:06:57.420
mean, it was interesting.

00:06:57.620 --> 00:07:01.880
it looked kind of relevant and possibly useful in some of the cases, but not like it is today.

00:07:02.260 --> 00:07:13.240
Like today, people who don't even care about technology are blown away by this stuff, and they use it all day long, and it's gone so much farther and so much faster than I expected it to.

00:07:13.900 --> 00:07:15.280
I'm all about it these days.

00:07:15.510 --> 00:07:26.060
I still write most of my code, but any time there's something tricky instead of going to Google and hunting through Stack Overflow, let's see what chat says about it or something like that.

00:07:27.160 --> 00:07:29.620
And then maybe we'll go to Google if we don't get a good answer, you

00:07:29.620 --> 00:07:29.700
know?

00:07:29.800 --> 00:07:29.920
Yeah.

00:07:30.340 --> 00:07:31.320
No, no, I'm the same way.

00:07:31.380 --> 00:07:37.340
I spent more time than I care to admit last night migrating from Vim to NeoVim.

00:07:37.360 --> 00:07:47.800
And I know I'm late to the party, but perplexity and other tools just made it a lot easier to start from scratch installation without bringing over my VimRC.

00:07:49.020 --> 00:07:49.240
And you

00:07:49.240 --> 00:07:50.980
can ask it detailed questions, right?

00:07:51.260 --> 00:07:52.540
For example, I

00:07:52.540 --> 00:07:56.780
needed some way to reset the initial offset in DaVinci Resolve timelines.

00:07:56.960 --> 00:08:00.820
It was, okay, well, here's your four options, and these are the way you can do it, and these are the tradeoffs.

00:08:00.960 --> 00:08:05.700
It's not just you might get an, you know, here is the switch, but you get an analysis.

00:08:05.800 --> 00:08:08.160
And I'm pretty impressive.

00:08:08.420 --> 00:08:19.800
So the reason I'm going into this is I want to ask you, having been on the inside at the early days, what is your perspective of seeing this trajectory or trajectory is the way I should point it.

00:08:20.560 --> 00:08:22.140
Upwards, not logarithmic.

00:08:22.160 --> 00:08:22.440
Yeah.

00:08:23.260 --> 00:08:39.000
I guess what I will say is I think one thing that's like really changed, like, so back when I was at Brain, even the models were advanced, like, I felt like in order to use machine learning well, you really did need to be somewhat trained in machine learning.

00:08:39.099 --> 00:08:42.979
You know, it was important to understand what a loss function, like basic things, like what a

00:08:42.979 --> 00:08:43.800
loss function was,

00:08:43.880 --> 00:08:45.620
what's training, what's validation.

00:08:46.480 --> 00:08:49.700
These days, like, you don't need to, like, at all, actually.

00:08:49.860 --> 00:08:52.040
I think especially to use LLMs, right?

00:08:52.120 --> 00:08:54.660
Like, you just need to know inputs and outputs.

00:08:54.820 --> 00:08:56.920
It's like a function call that sort of has fuzzy outputs.

00:08:57.600 --> 00:08:57.840
You know,

00:08:57.900 --> 00:08:58.840
it's a mathematical

00:08:58.840 --> 00:08:59.860
function in quotes.

00:09:00.760 --> 00:09:00.900
Yeah.

00:09:01.000 --> 00:09:01.320
So

00:09:01.320 --> 00:09:04.520
I think that's one thing that's totally...

00:09:04.740 --> 00:09:13.760
I guess it kind of shows that artificial intelligence is transitioning more from, I guess, like a science to a technology, and that tool that people can just readily use without

00:09:13.760 --> 00:09:14.260
really needing

00:09:14.260 --> 00:09:16.460
to understand how it works.

00:09:18.200 --> 00:09:22.540
As for the trajectory, I've been bad at making predictions in the past.

00:09:22.880 --> 00:09:25.580
I think I will be bad at predicting anything right now.

00:09:26.860 --> 00:09:30.400
Surely, these models are very good for coding.

00:09:31.040 --> 00:09:55.700
for massaging marketing copy and like you know i do like the random tasks where like i have a bio i wrote in for first person and someone asked for it in third person and i'm too lazy to change and i just give it to a chat model um yeah but if you ask for a trajectory of agi or asi which i don't even remember what the s stands for these days but i i'm not sure i can predict anything on those timelines.

00:09:56.260 --> 00:10:07.760
Yeah. I hear you. I'm, I'm, I'm with you on the projects prediction, but I would say that the adoption and effectiveness of it has far outpaced what I would have guessed five years ago.

00:10:08.200 --> 00:10:13.260
Yeah. I mean, even local models, like it's kind of exciting, like what you can just run on your Mac book.

00:10:13.540 --> 00:10:13.940
I also

00:10:13.940 --> 00:10:16.360
didn't really anticipate that. yeah.

00:10:16.840 --> 00:10:18.860
All right. I don't want to make this the AI show cause it's not about

00:10:18.860 --> 00:10:19.200
AI,

00:10:19.440 --> 00:10:50.840
but your background is so interesting. So when you were working initially on transformers did you perceive you as a group not you individually you guys perceive the need for the scale of the computation like you know to train gpt01 i don't know how much compute was involved but probably more than cities use in terms of energy sometimes you know what i mean it was a lot and how much compute were you all using back then versus now i guess is what i'm getting that so

00:10:50.840 --> 00:10:59.620
i guess yeah and i think you kind of said it but just just to clarify or to make it clear that i personally didn't work on transformers i was working on tensorflow so that yeah

00:10:59.620 --> 00:11:00.640
the yeah the

00:11:00.640 --> 00:11:20.140
i guess embedded dsl for for training machine learning models that was used within google and still used today um i can't give you specific numbers to be honest because i was pretty deep in the systems part of working on tensorflow and not paying too much attention for like standing up distributed clusters.

00:11:21.340 --> 00:11:26.540
I did things like adding support to TensorFlow for creating a function library.

00:11:27.280 --> 00:11:37.980
TensorFlow is like a Dataflow graph engine, and it didn't have functions, so I added support for functions, partitioning functions over devices, but other teams used that work to go and train the big models.

00:11:38.540 --> 00:11:43.360
I know it was a lot of compute, but a lot versus a lot, all

00:11:43.360 --> 00:11:45.540
caps versus just capital case.

00:11:46.760 --> 00:11:46.820
Yeah,

00:11:47.160 --> 00:11:47.420
I'm sure

00:11:47.420 --> 00:11:47.900
there's a delta.

00:11:48.090 --> 00:11:49.500
I just, I don't know how much.

00:11:49.720 --> 00:11:49.900
Yeah.

00:11:50.230 --> 00:11:55.280
Well, today they're all talking about restarting nuclear reactors and plugging them straight to the data center.

00:11:55.480 --> 00:11:56.560
So it's a weird time.

00:11:57.920 --> 00:11:58.560
Let's go back.

00:11:59.740 --> 00:12:05.240
Maybe a little bit before then, 2012 or so, I believe is maybe the right timeframe.

00:12:05.490 --> 00:12:06.760
And let's talk about notebooks.

00:12:07.660 --> 00:12:11.700
And, you know, around then, Jupyter notebooks burst on the scene.

00:12:12.100 --> 00:12:20.140
And I think they fundamentally changed the ecosystem of Python and basically scientific work in general, right?

00:12:22.140 --> 00:12:28.400
By changing Python, I mean, there are so many people in Python who are here because they got pulled into a notebook.

00:12:28.920 --> 00:12:30.080
They wrote a little bit of code.

00:12:30.410 --> 00:12:31.480
They got incredible results.

00:12:32.000 --> 00:12:36.600
They were never, ever a programmer, but now they're the maintainer of an open source project or something like that.

00:12:36.980 --> 00:12:37.600
You know what I mean?

00:12:38.200 --> 00:12:40.320
They're just like, oh, this is kind of neat.

00:12:40.620 --> 00:12:54.240
oh I'll create a biology library or whatever and then all the all of a sudden you know they're they're deep in it and so jupiter I think was really the start of that maybe there was some precursors that I'm not familiar with

00:12:54.240 --> 00:12:58.580
yeah jupiter was essentially the start of it especially for python like I think

00:12:58.580 --> 00:12:59.620
the idea of computational

00:12:59.620 --> 00:13:24.220
yeah notebooks has been around but uh yeah the ipython repl I guess the ipython project with the ipython repl I think was early 2000s and um And Jupyter, I think you're right, like 2012-ish, as he's burst onto the scene with putting the IPython REPL into a web browser with multiple REPL cells, and all of a sudden you could do more than what you could do in the console and also made it a lot more accessible.

00:13:25.150 --> 00:13:25.300
Yeah.

00:13:26.280 --> 00:13:34.200
Going back to that sixth cell you entered on your REPL and editing it, that is not a way to draw beginners in.

00:13:35.420 --> 00:13:36.520
No, definitely not.

00:13:37.040 --> 00:13:38.420
Up arrow key six times, no.

00:13:38.840 --> 00:13:44.340
Yeah, 2012, coincidentally, is when I started college as an undergrad.

00:13:44.980 --> 00:13:51.780
So I had been using, I kind of grew up, as long as I used Python, I think I probably was using Jupyter Notebooks.

00:13:52.460 --> 00:14:03.100
And I even started using Google CoLab before it was made public, because when I was interning at Google, and I think the year I started working at Google full-time is when they made it public to the world.

00:14:03.500 --> 00:14:08.940
So, yeah, notebooks have sort of shaped the way that I think and interact with code quite a bit.

00:14:09.440 --> 00:14:10.140
Yeah, absolutely.

00:14:11.300 --> 00:14:14.100
So maybe you could give us some perspective.

00:14:14.230 --> 00:14:16.540
It sounds like you were there, like, right at the right time.

00:14:16.810 --> 00:14:23.120
You know, what was the goal and sort of the job of Jupyter Notebooks and those kinds of things then?

00:14:23.780 --> 00:14:25.560
And how has that changed now?

00:14:25.700 --> 00:14:29.020
And maybe how does it still solve that problem or not solve it so much?

00:14:29.360 --> 00:14:32.780
Yeah, I think, so stepping back.

00:14:32.980 --> 00:14:41.300
So you mentioned like how many people who might not have traditionally, you know, worked with code sort of came into it because of Jupyter Notebooks.

00:14:41.300 --> 00:14:43.900
And I think that's like really, I think you're onto something there.

00:14:43.900 --> 00:14:44.520
I think that's correct.

00:14:44.710 --> 00:14:55.100
And I think the special thing about Notebooks is that they like mix code and visuals and like narrative text in like this interactive programming environment.

00:14:55.560 --> 00:15:00.520
And that interactivity in particular, I think is really important for anyone who works with data.

00:15:01.160 --> 00:15:13.780
It's where you got to like first like, you know, run some queries against your data to see the general shape of it, you know, run some transformations to see like, you know, basically like explore your data, like hold it in your hands.

00:15:14.030 --> 00:15:23.020
Right. And like, you know, REPLs before and then Jupyter Notebooks in particular lets you do that in a way that you just can't easily do in a script because it holds the variables in memory.

00:15:23.660 --> 00:15:33.640
And so I think the role that it played was that it enabled data scientists or computational scientists, biologists, astrophysicists, all these different types of people who work with data.

00:15:34.980 --> 00:15:45.120
It let them rapidly experiment with code and models and importantly, get some kind of like artifact out of it.

00:15:45.180 --> 00:15:52.940
And in particular, this was like a static HTML type artifact, right, where you have some text documenting what experiments you're running.

00:15:53.380 --> 00:15:58.300
you have Python code, and then you have like Matplotlib plots and other artifacts.

00:15:59.660 --> 00:16:06.860
And I think for the sciences in particular early on, that was super important and transformative.

00:16:07.380 --> 00:16:09.960
And we were talking about other computational notebook environments.

00:16:10.110 --> 00:16:17.000
And it's interesting to mention this because things like this existed sort of before, like Mathematica's workbooks, I think they

00:16:17.000 --> 00:16:17.380
called them.

00:16:17.410 --> 00:16:17.760
I might have

00:16:17.760 --> 00:16:18.420
done that wrong.

00:16:19.220 --> 00:16:25.760
But I think just like the open source nature of Python and the accessibility of it just like made it way easier to get started.

00:16:26.140 --> 00:16:36.760
And also the fact that it was like browser based, right, so that like you can easily share like these, the HTML artifacts that come out, I think was really transformative.

00:16:37.620 --> 00:16:40.880
And insofar as like what they're used for today, they're used for a lot.

00:16:41.080 --> 00:16:44.480
It's kind of remarkable how much they're used.

00:16:44.640 --> 00:16:53.080
Like I remember seeing a statistic for Google CoLab alone, which is just one particular hosted version of a Jupyter notebook.

00:16:53.840 --> 00:16:57.800
And it was two years ago, and they said something about like having 10 million monthly active users.

00:16:58.600 --> 00:17:03.660
And so the number of people who use Jupyter on a monthly basis is surely larger than that.

00:17:04.310 --> 00:17:04.680
Oh, yeah.

00:17:05.400 --> 00:17:14.420
And they're used for the sciences, but they're also used for like things where you want, like the traditional rigor and reproducibility of software engineering.

00:17:14.620 --> 00:17:19.819
So they're increasingly used for like data pipelines and like ETL jobs.

00:17:19.819 --> 00:17:28.360
And like, so anyone who's in Databricks, for example, runs like, they call them workflows, Databricks workflows, through essentially Jupyter Notebooks.

00:17:29.740 --> 00:17:31.480
They're used for training machine learning models.

00:17:31.820 --> 00:17:34.620
Like I've trained many models in a Jupyter Notebook.

00:17:35.020 --> 00:17:36.880
I've developed algorithms in Jupyter Notebooks.

00:17:37.160 --> 00:17:41.420
I've produced scientific figures that go straight into my paper from a Jupyter notebook.

00:17:42.880 --> 00:17:50.900
And the reason people do this is because, again, the interactivity and the visuals that come out is very liberating compared to using a script.

00:17:51.500 --> 00:17:56.400
I think there's also a developing understanding that happens from them.

00:17:56.600 --> 00:18:01.680
Because when you're writing just a straight program, you're like, okay, this step, this step, this step, this step, and then we get the answer.

00:18:02.180 --> 00:18:04.920
Whereas notebooks, it's like step one, step two.

00:18:05.180 --> 00:18:06.000
Let me look at it.

00:18:06.080 --> 00:18:07.100
oh, maybe that's different.

00:18:07.330 --> 00:18:08.140
Let me go back and change.

00:18:08.600 --> 00:18:11.780
It's more iterative from an exploratory perspective.

00:18:12.340 --> 00:18:13.800
Yeah, I think that's exactly right.

00:18:15.040 --> 00:18:20.280
Because you have that, when you're writing a software system, you kind of know the state of the system.

00:18:20.450 --> 00:18:22.300
You know what you want to change it to.

00:18:22.500 --> 00:18:26.140
But when you're working with data, there's that unknown, what will my algorithm do to my data?

00:18:26.460 --> 00:18:26.540
You

00:18:26.540 --> 00:18:26.840
just have

00:18:26.840 --> 00:18:27.100
to run

00:18:27.100 --> 00:18:27.680
it to find out.

00:18:27.960 --> 00:18:28.520
Yeah, absolutely.

00:18:28.810 --> 00:18:32.440
And graphs and tables and iterative stuff like that is really nice.

00:18:33.040 --> 00:18:37.040
So why create something instead of Jupyter?

00:18:37.900 --> 00:18:39.800
Why is Jupyter not enough for the world?

00:18:40.240 --> 00:18:40.580
Yeah.

00:18:41.750 --> 00:18:42.520
I think there's a...

00:18:42.780 --> 00:18:48.640
So just, you know, you're the creator of Marimo, along with the rest of the team and so on.

00:18:48.980 --> 00:18:52.720
But yeah, it's like, why create this thing when Jupyter exists?

00:18:53.320 --> 00:18:53.540
Yeah.

00:18:53.630 --> 00:18:57.000
So I think there's quite a few reasons.

00:18:58.179 --> 00:19:06.660
So Jupyter notebooks are like, I guess, It's more like Jupyter Notebooks powered by the IPython kernel, just to put a finger on it.

00:19:07.600 --> 00:19:08.520
Right, because it could be different.

00:19:08.520 --> 00:19:12.280
It could be like a C++ kernel or.NET kernel or whatever.

00:19:12.530 --> 00:19:13.400
Yeah, exactly.

00:19:13.770 --> 00:19:27.080
But this particular form of notebooks where you get a page and then in the front end shows you a bunch of cells that you execute one at a time imperatively, even though you have a sequence of cells, it still is essentially a REPL.

00:19:27.260 --> 00:19:38.020
And like it's the onus falls on the developer, the scientist, whoever's using it to like run each cell on their own and like maintain the state of their kernel.

00:19:38.260 --> 00:19:43.220
So like you run a cell, say you have three cells, you know, you decide to go rerun the second cell.

00:19:43.640 --> 00:19:47.100
You have to remember to rerun whatever cell depends on it.

00:19:47.220 --> 00:19:48.000
Maybe it's the third cell.

00:19:48.120 --> 00:19:50.020
Maybe it's the first cell because you wrote things out of order.

00:19:50.420 --> 00:19:57.040
And so you can easily get into a state with Jupyter Notebooks where your code on the page doesn't match the outputs that were

00:19:57.040 --> 00:19:57.640
created.

00:19:58.000 --> 00:20:03.240
Yeah. So if you were to like basically go to the menu option, say rerun all cells, you would get different answers.

00:20:03.820 --> 00:20:11.320
Exactly. And this is like it's actually been studied and like it happens a kind of a shockingly large amount of times that like.

00:20:11.440 --> 00:20:19.560
So there's one study in 2019 by Pimentel, I'm going to probably pronounce his name wrong, but by I think four professors.

00:20:20.260 --> 00:20:21.740
And they studied a bunch of notebooks on GitHub.

00:20:22.070 --> 00:20:27.980
And they found that only like a quarter of the notebooks that were on GitHub, they were able to run it all.

00:20:28.330 --> 00:20:38.060
And then like either 4% of those or 4% of all of them, only 4% of them like when they ran recreated the same results that were serialized in the notebook.

00:20:38.680 --> 00:20:44.720
Meaning like maybe people ran sales out of order when they originally created the notebook and then committed it.

00:20:45.260 --> 00:20:52.140
Or maybe they didn't like create a requirements.txt that faithfully captured the package environment they used.

00:20:53.040 --> 00:21:06.680
So there's like this recognition that Jupyter Notebooks suffer from a reproducibility crisis, which is rather unfortunate for a tool that is used for science and data science and data engineering, like things where reproducibility is paramount.

00:21:07.120 --> 00:21:08.100
And so that was one issue.

00:21:08.580 --> 00:21:13.220
Reproducibility was like one main thing that sort of we wanted to solve for with Marima notebooks.

00:21:13.960 --> 00:21:24.560
And the other thing I think that we alluded to earlier is that Jupyter notebooks are stored as like a JSON file where like the outputs, like the plots, et cetera, are serialized as these binary strings.

00:21:25.420 --> 00:21:33.700
And like the, you know, the one downside of that is that you can't really use these things like you can use like traditional software, at least not without jumping through extra hoops.

00:21:33.920 --> 00:21:42.620
So like you make a small change to your Jupyter notebook, you get a gigantic git diff because, you know, the binary representation of some object changed by a large amount.

00:21:43.400 --> 00:21:51.120
You want to reuse the Python code in that Jupyter notebook when you have to run it through like a Jupytext or some other thing to strip it out.

00:21:51.190 --> 00:22:00.360
And then so you oftentimes you get this like situation where people just like end up copy pasting a bunch of things across a bunch of notebooks and it quickly gets really messy.

00:22:00.440 --> 00:22:09.880
And that was another thing we wanted to solve for, making notebooks like Git-friendly and interoperable with other Python tooling like Git, pytest, etc.

00:22:10.280 --> 00:22:18.580
Yeah, there's some things that will run them kind of function module-like, but yeah, it's not really the intended use case, is it?

00:22:18.780 --> 00:22:33.180
Yeah, it's not, but people want to, which is, I think, like the, it's funny because like the intended use case, I think, of like traditional notebooks like Jupyter was like interactive REPL, explore data, produce like simple narrative text.

00:22:33.580 --> 00:22:41.580
But then like they just got used for so much more than that in situations where reproducibility, reusability is like really important.

00:22:41.880 --> 00:22:44.480
And I think that that's what we're trying to solve for.

00:22:45.900 --> 00:22:49.320
This portion of Talk Python To Me is brought to you by Worth Recruiting.

00:22:49.840 --> 00:22:52.400
Are you tired of applying for jobs and never hearing back?

00:22:53.060 --> 00:23:01.560
Have you been getting the runaround or having trouble making it past the AI resume screeners that act as the new gatekeepers for your next level Python job?

00:23:01.840 --> 00:23:03.560
You should reach out to Worth Recruiting.

00:23:04.260 --> 00:23:08.540
Worth Recruiting specializes in placing senior level Python developers and data scientists.

00:23:09.300 --> 00:23:15.260
They work directly with hiring managers at startups, helping them grow their software engineering and data science teams.

00:23:16.060 --> 00:23:49.820
with Worth it's not just connecting you with the company it will guide you through the interview process and help make sure you're ready with their detailed preparation approach they can even coach you on salary negotiations and other important decision making processes so if you're ready to see what new opportunities are out there for you reach out to Worth Recruiting let them be your partner and specialist to find the right Python developer or data scientist position for you fill out their short contact form at talkpython.fm/worth. It only takes a minute. That's talkpython.fm/worth.

00:23:50.240 --> 00:24:15.660
The link is in your podcast player's show notes. Thank you to Worth Recruiting for supporting the show. I was just wondering out loud, you know, that study. I know it was not your study, so I'm not asking you for answers. Just, just what do you think? If it's that low of a percentage of reproducibility because people fell down on their like rigorous software engineering, for example, like no requirements file or hard-coded pass instead of relative pass or whatever.

00:24:16.050 --> 00:24:27.080
If it's that number for notebooks, I wonder about just plain Python files that are also meant to act to solve like science problems and stuff that just didn't happen to be in notebooks.

00:24:27.360 --> 00:24:28.420
I wonder if they're any better.

00:24:28.900 --> 00:24:29.160
Yeah,

00:24:29.360 --> 00:24:30.640
it's a good question.

00:24:31.480 --> 00:24:32.720
I think they will be better.

00:24:33.110 --> 00:24:36.380
I can just give an anecdote to why I think they would be better.

00:24:36.710 --> 00:24:48.160
And so one example, and this happened to me many times, But like one particular example is like when I was working on my PhD thesis, which was about vector embeddings, it was me and a couple of co-authors.

00:24:48.720 --> 00:24:57.060
And, you know, both of us did our, like created the examples for this embedding algorithm in like Jupyter Notebooks.

00:24:57.130 --> 00:24:59.240
And these notebooks produced a bunch of plots, et cetera.

00:25:00.100 --> 00:25:04.500
And so at the end of the, once the thesis was written, I was putting up all our code on GitHub.

00:25:04.710 --> 00:25:09.080
And so I asked one of my co-authors, like, hey, like, can you share your notebooks with me?

00:25:09.310 --> 00:25:10.340
And this co-author is amazing.

00:25:10.520 --> 00:25:13.660
He's really smart, but not necessarily trained as a software engineer.

00:25:14.320 --> 00:25:16.380
And he shares his Jupyter notebook with me.

00:25:16.860 --> 00:25:17.500
And I run it.

00:25:17.940 --> 00:25:19.160
It doesn't work at all.

00:25:19.220 --> 00:25:22.240
And the reason it doesn't work at all is that there's like multiple cells.

00:25:22.320 --> 00:25:28.780
And there's like this branching path where like it's clear that like he ran like, you know, you see the execution order serialized in the notebook.

00:25:29.300 --> 00:25:29.760
And it's not like

00:25:29.760 --> 00:25:29.940
one,

00:25:30.120 --> 00:25:30.880
two, three, four.

00:25:31.020 --> 00:25:32.840
It's like one, two, seven, four.

00:25:33.340 --> 00:25:33.600
It's like

00:25:33.600 --> 00:25:34.520
these cells were

00:25:34.520 --> 00:25:35.960
ran in this path dependent way.

00:25:36.260 --> 00:25:38.980
And then also it's like there's like three cells in the middle.

00:25:39.420 --> 00:25:40.360
He ran just one of them.

00:25:40.600 --> 00:25:41.960
I'm not exactly sure which one.

00:25:42.560 --> 00:25:46.420
And like, whereas if you had a Python script, there's only one way to, I mean, sure, you can have

00:25:46.420 --> 00:25:46.760
data files.

00:25:46.760 --> 00:25:47.280
That's a good point.

00:25:47.620 --> 00:25:48.980
You do not really get a choice.

00:25:49.660 --> 00:25:50.100
It runs

00:25:50.100 --> 00:25:50.600
top to bottom.

00:25:51.140 --> 00:25:51.380
Exactly.

00:25:51.500 --> 00:25:51.700
Depending

00:25:51.700 --> 00:25:52.380
on the data.

00:25:52.530 --> 00:25:52.620
Okay.

00:25:53.140 --> 00:25:53.880
So yeah,

00:25:53.950 --> 00:26:00.320
that is something that's really, it's just very counter to the concept of reproducibility is that you

00:26:00.320 --> 00:26:00.480
can

00:26:00.480 --> 00:26:10.240
run them in any order and there's not, you know, I feel like Jupyter Notebooks should almost have like a red bar to the cross, like an out of order bar.

00:26:10.700 --> 00:26:13.400
warning across the top if it's not top to bottom.

00:26:14.010 --> 00:26:15.060
It doesn't have to be 1, 2, 3.

00:26:15.090 --> 00:26:17.240
It could be 1, 5, 6, 9.

00:26:17.560 --> 00:26:21.560
But it should be a monotonic increase in function as you

00:26:21.560 --> 00:26:22.580
do the numbers top

00:26:22.580 --> 00:26:23.000
to bottom.

00:26:24.300 --> 00:26:29.100
Otherwise, it should be like a big warning or like a weird, like some kind of indicator, like, hey, you're in the danger zone.

00:26:29.230 --> 00:26:29.760
You know what I mean?

00:26:30.080 --> 00:26:40.220
Yeah, and there's actually another thing that actually has happened to me way more often than I should care to admit while working with Jupyter Notebooks is that it's not just the order.

00:26:40.280 --> 00:27:07.680
you run the cells it's also like what happens if you delete a cell because when you delete a cell you no longer so say a cell declares a variable x and you deleted that cell you're like i don't want x anymore but you may forget that just by deleting the cell um you're not removing the variables from memory and so like x still exists and so then you're running other cells that depend on x everything's fine uh but then you come back and you run your notebook and everything's broken and you don't You have no idea.

00:27:07.820 --> 00:27:10.140
The first time this happened to me, it took me forever to debug.

00:27:11.039 --> 00:27:11.440
I

00:27:11.440 --> 00:27:12.060
can imagine

00:27:12.060 --> 00:27:12.820
that is so rough.

00:27:13.380 --> 00:27:13.520
Yeah.

00:27:13.980 --> 00:27:17.020
Later on, you realize, okay, this is a pattern that happens.

00:27:17.260 --> 00:27:22.440
But it's like, yeah, so that's another thing that we also wanted to solve for in Marimo notebooks.

00:27:23.200 --> 00:27:23.440
Awesome.

00:27:23.860 --> 00:27:23.960
All right.

00:27:23.960 --> 00:27:24.780
Well, tell us about Marimo.

00:27:26.560 --> 00:27:26.720
Okay.

00:27:27.080 --> 00:27:27.740
So let's see.

00:27:28.040 --> 00:27:31.060
So Marimo is, it's an open source notebook for Python.

00:27:31.840 --> 00:27:37.780
The main thing that's different between Marimo and Jupyter is that Marimo is reactive.

00:27:38.550 --> 00:27:55.000
And what that means is that unlike a Jupyter notebook where you can run cells in any arbitrary order you like, in Marimo, when you run one cell, it knows what other cells need to be run in order to make sure that your code and outputs are synchronized.

00:27:55.480 --> 00:27:56.780
So it's kind of like Excel, right?

00:27:56.780 --> 00:27:58.020
So you have two cells.

00:27:58.320 --> 00:27:59.060
One declares X.

00:27:59.440 --> 00:28:00.460
Another one references X.

00:28:00.800 --> 00:28:09.200
you run the cell that declares X or defines X, all other cells that reference X will automatically run or they'll be marked as stale.

00:28:09.320 --> 00:28:12.520
You can configure it if you're scared of automatic execution.

00:28:12.900 --> 00:28:18.020
But the point is that it manages your variables for you so

00:28:18.020 --> 00:28:18.480
that you

00:28:18.480 --> 00:28:22.560
don't have to worry about outputs becoming decohered from your code.

00:28:22.760 --> 00:28:33.460
And similarly, if you delete a cell, the variable will be scrubbed from memory and then cells that are dependent on it will either be marked as stale a big warning or automatically run and invalidate it.

00:28:34.120 --> 00:28:37.560
So that reactivity provides some amount of reproducibility.

00:28:38.720 --> 00:28:44.460
And then it also, some of the key features, and then we can dive into each of them, is an additional reactivity.

00:28:44.980 --> 00:28:49.360
Marima notebooks are stored as pure Python files, which makes them easy to version with Git.

00:28:50.300 --> 00:28:57.540
And then we've also made it easy to run Marima notebooks as Python scripts and then share them as interactive web apps with little UI elements.

00:28:58.300 --> 00:28:59.820
Yeah, I'm excited to talk about that.

00:29:00.040 --> 00:29:00.780
Some cool stuff there.

00:29:01.340 --> 00:29:09.300
Okay, so when you create a variable, if you say like x equals one, it's not just a pi long pointer in memory, right?

00:29:09.460 --> 00:29:21.060
It's something that kind of looks at the read and write that get in the set of it and creates like a relationship where it says if you were to push a change into it, it says, okay, I have been changed.

00:29:21.400 --> 00:29:23.060
Who else is interested in reading from me?

00:29:23.120 --> 00:29:24.760
And it can sort of work that out, right?

00:29:25.040 --> 00:29:25.400
How does that work?

00:29:25.580 --> 00:29:26.100
Actually,

00:29:26.240 --> 00:29:28.940
it's not really implemented in that way.

00:29:29.820 --> 00:29:29.900
Okay.

00:29:30.500 --> 00:29:31.260
So, okay.

00:29:31.460 --> 00:29:32.040
So let's see.

00:29:32.300 --> 00:29:37.400
Yeah, this is interesting to dive into because there's like two ways that you can like get at reactivity.

00:29:37.560 --> 00:29:40.900
Like so in Marima, what we actually do is we do static analysis.

00:29:41.560 --> 00:29:41.740
So we

00:29:41.740 --> 00:29:43.080
look for

00:29:43.080 --> 00:29:46.080
definitions and references on like of global variables.

00:29:46.620 --> 00:29:48.320
And then so we just make a graph out of that.

00:29:48.320 --> 00:29:53.400
So for every cell, we look at the, I guess, the loads in the ASTs and then like

00:29:53.400 --> 00:29:56.820
the assignments.

00:29:57.780 --> 00:30:03.080
And so we can see statically who declares what and who reads what, but who is a cell.

00:30:04.600 --> 00:30:09.680
And so that makes it like performant and also predictable of like how your notebook is going to run.

00:30:10.980 --> 00:30:13.900
A alternative, I think what you were getting at was like runtime tracing.

00:30:14.540 --> 00:30:20.060
More like a JavaScript front end sort of deal, like a view binding model binding type thing or something like that.

00:30:20.420 --> 00:30:27.020
Yeah. So yeah, we, everything we do is static, is done with static analysis.

00:30:27.120 --> 00:30:39.720
this there was another project called ipyflow which was like a reactive kernel for jupiter it's still around um they took like the runtime tracing approach of like checking on every assignment like okay

00:30:39.720 --> 00:30:40.520
okay

00:30:40.520 --> 00:30:58.320
there's a read and now where is that where is that object in memory and then running cells that depend on it um i think in practice you know i was talking to steven mackie the author of that article of that extension and then also like based on some work that i saw at Google TensorFlow, that's really hard to get 100% right.

00:30:58.350 --> 00:31:00.460
It's basically impossible to get 100% right.

00:31:00.880 --> 00:31:05.260
So you will miss some low references and definitions.

00:31:06.100 --> 00:31:11.840
And so there's this weird usability cliff as a user where when you run a cell, you're not sure what else will run.

00:31:12.210 --> 00:31:17.760
Whereas if you do it based on static analysis, you can give guarantees on what will run and what won't.

00:31:18.210 --> 00:31:23.580
Yeah, I guess the static analysis is a good choice because there's only so many cells.

00:31:23.700 --> 00:31:31.840
You don't have to track it down to like, well, within the DOM and all the JavaScript objects, we're linking all these together and they can do whatever they want from all these different angles.

00:31:32.040 --> 00:31:35.620
It's just like, when this cell runs, what other cells do we need to think about?

00:31:35.800 --> 00:31:37.460
So it's kind of like, what does this create?

00:31:38.060 --> 00:31:38.860
What does it change?

00:31:39.240 --> 00:31:40.760
And then push that along, right?

00:31:40.860 --> 00:31:42.040
So it's a little more constrained.

00:31:42.500 --> 00:31:43.080
Exactly, yeah.

00:31:43.240 --> 00:31:45.380
So basically, yeah, that's exactly right.

00:31:45.480 --> 00:31:49.740
And so it's a data flow graph where the data flowing on the edges is the variables across cells.

00:31:51.420 --> 00:31:52.320
Yeah, I don't know.

00:31:52.360 --> 00:31:58.060
I think I've been thinking about Dataflow Grass for a long time, ever since TensorFlow, doing my PhD too when I worked on CVXPY.

00:31:58.240 --> 00:32:02.460
So it's just a thing that I enjoy thinking about and working on.

00:32:02.620 --> 00:32:11.440
Yeah, well, what about your experience working on TensorFlow and at Google and at Stanford and stuff that sort of influenced this project?

00:32:11.940 --> 00:32:13.960
Yeah, a couple of things.

00:32:14.780 --> 00:32:27.840
So definitely a big thing that influenced this project was working as a scientist at Stanford where like I and my colleagues use Jupyter Notebooks like on almost a daily basis because they want to see our data while we worked on it.

00:32:29.020 --> 00:32:37.300
And so really valued the iterative programming environment, really didn't like all the bugs that we kept on running into, which are

00:32:37.300 --> 00:32:37.800
like kind of our

00:32:37.800 --> 00:32:38.320
fault, right?

00:32:38.460 --> 00:32:40.800
Because of like, oh, we forget to run a cell, et cetera.

00:32:42.280 --> 00:32:48.400
Didn't like that it was not easy to reuse the code in a notebook in just other Python modules.

00:32:49.140 --> 00:32:55.120
Didn't like that I couldn't share my artifacts in a meaningful way with my PhD advisor who can't run Python notebooks.

00:32:55.480 --> 00:32:58.220
I couldn't make a little app to showcase my

00:32:58.220 --> 00:32:58.920
research project.

00:32:59.860 --> 00:33:15.640
It's so interesting how PhD advisors and just professors in general, how they're either embracing or their inability to embrace or their prejudices for or against the technology so influence science, the people in the research teams, everything.

00:33:15.860 --> 00:33:21.840
It's like, well, we'd like to use this, but the principal author really doesn't like it, doesn't want to run it, so we're not using that.

00:33:21.910 --> 00:33:22.240
Or, you

00:33:22.240 --> 00:33:22.700
know, just

00:33:22.700 --> 00:33:24.240
these little edge cases.

00:33:24.290 --> 00:33:26.480
Like, I was made to learn Fortran in college.

00:33:26.660 --> 00:33:27.720
I'm still sour about it.

00:33:29.800 --> 00:33:30.220
That's funny.

00:33:30.420 --> 00:33:31.080
Yeah, no, it's true.

00:33:31.280 --> 00:33:32.860
Yeah, it does have a big effect.

00:33:33.380 --> 00:33:37.880
And then at Google, I guess the things that influenced – so we used Notebooks 2 there.

00:33:39.340 --> 00:33:49.820
Since I was doing the systems engineering work at Google, I personally didn't use them too much, although I did use like Google Colab for like training, like creating training courses and stuff for, for like other engineers and for demos.

00:33:50.440 --> 00:33:55.520
But I guess the part of Google that influenced it was just like thinking about data flow graphs for a

00:33:55.520 --> 00:33:56.780
year. And you

00:33:56.780 --> 00:34:13.220
know, I, we were, there was like a couple of parable projects, like one that was using runtime tracing for like figuring out like how to make a DAG. And it was just, I don't know, kind of traumatic just because you like you miss things and the user experience is just like it kind of falls over.

00:34:13.340 --> 00:34:18.460
And so I guess the part from there just made me not want to use runtime

00:34:18.460 --> 00:34:18.899
tracing,

00:34:19.080 --> 00:34:20.960
made me embrace static analysis for this.

00:34:22.340 --> 00:34:22.520
Yeah.

00:34:22.899 --> 00:34:23.740
Yeah, it makes a lot of sense.

00:34:24.159 --> 00:34:24.520
All right.

00:34:25.340 --> 00:34:27.419
Well, let's talk some features here.

00:34:27.840 --> 00:34:37.240
What are the, I guess probably the premier feature is the reactivity, in which case it doesn't matter which cell you run, they're never going to get out of date, right?

00:34:37.560 --> 00:34:38.679
Yeah, that's correct.

00:34:38.980 --> 00:34:44.379
So the reactivity, in other words, the data flow graph behind it is the premier feature.

00:34:45.159 --> 00:34:47.820
And it lets you reason about your code locally, right, which is really nice.

00:34:48.060 --> 00:34:49.639
Like you can just look at your one cell.

00:34:49.970 --> 00:34:54.179
You don't really have to worry about, you know, you know what variables it reads and what it defines.

00:34:54.669 --> 00:34:57.800
And you don't have to worry about, oh, but what cells do I need to run before this?

00:34:58.780 --> 00:35:06.960
So not only does it like make sure your code and outputs are in sync, it also like makes it really like fun and useful.

00:35:08.420 --> 00:35:11.320
to really rapidly experiment with ideas.

00:35:11.960 --> 00:35:25.880
As long as your cells aren't too expensive, if you enable automatic execution, you can change a parameter, run a particular cell, and it'll run only what's required to update subsequent outputs.

00:35:27.820 --> 00:35:39.600
And then another consequence of reactivity that I think is really neat and our users really like is it makes it far easier to use interactive UI widgets than it is in like a Jupyter notebook.

00:35:40.540 --> 00:35:46.820
And the way that this works is that, so Marimo is like both a notebook and also a library.

00:35:47.140 --> 00:35:49.740
So you can import Marimo as Mo into your notebook.

00:35:50.220 --> 00:36:11.220
And when you do this, you get access to a bunch of things, including a bunch of different UI widgets, ranging from the simple ones like sliders, drop-down menus, to like cooler ones like interactive selectable charts and data frame transformers that automatically generate the Python code needed for your transformation.

00:36:12.180 --> 00:36:30.920
And the way that reactivity comes into here is that because we know when you create a UI element, as long as you bind it to a global variable, just say my slider equals mo.ui.slider, then when you interact with the slider anywhere on the screen, well, we can just say, okay, that slider is bound to X.

00:36:31.130 --> 00:36:33.260
We just need to run all other cells that depend on X.

00:36:33.840 --> 00:36:41.140
all of a sudden you have really nice interactivity, interactive elements controlling your code execution without ever having to write a callback.

00:36:42.380 --> 00:36:44.460
And so I think people find that really liberating too.

00:36:44.900 --> 00:36:47.840
So you don't really have to hit backspace, change

00:36:47.840 --> 00:36:48.740
a

00:36:48.740 --> 00:36:51.720
character value for your variable, shift, enter, shift, enter, shift, enter.

00:36:52.980 --> 00:36:55.860
Just change a number and everything automatically recalculates.

00:36:56.200 --> 00:36:56.460
Yeah.

00:36:56.820 --> 00:37:02.060
In this dependency flow, is it possible to have a cyclical graph?

00:37:02.460 --> 00:37:09.860
Like if I did this in Jupyter, I could go down to the third cell and define X and then go back up and then use X.

00:37:09.950 --> 00:37:12.660
If I run it in the right order, it won't know that there's a problem.

00:37:13.720 --> 00:37:16.060
Imagine it's only possible to go one way, right?

00:37:16.060 --> 00:37:17.560
You can't get into a weird cycle.

00:37:19.040 --> 00:37:19.100
Yeah.

00:37:19.370 --> 00:37:21.740
So we do give people escape patches.

00:37:22.060 --> 00:37:26.860
We ask them, please don't use it unless you really know what you're doing and you really want to do this.

00:37:27.410 --> 00:37:39.980
Because in most cases we find, especially for like if your goal is to just like work with data data scientist, data engineer scientist. We feel you don't need that cycles. You don't need cycles.

00:37:40.480 --> 00:38:07.080
But if you're making an app, and I guess I should mention Marimo lets you run any notebook as well a notebook, but also from the command line, you can serve your notebook as a web app, like similar to Streamlit if you've seen that. In those cases, sometimes you do want state basically, right? Like cyclic references. So by default, Marimo actually checks for cycles. If you have a cycle across cells, politely tells you, hey, that's not really cool in Marimo.

00:38:07.780 --> 00:38:08.560
Please break your cycle.

00:38:08.920 --> 00:38:10.380
Here's some suggestions how to do that.

00:38:11.180 --> 00:38:20.280
But if you're really insistent, then you can go to our docs and learn about the state object that we have that does let you get into some runtime-based cell execution.

00:38:20.620 --> 00:38:26.240
You can update a state object and kind of in a React from 10D way, it'll run dependence of that state.

00:38:26.480 --> 00:38:27.420
Okay, interesting.

00:38:27.710 --> 00:38:28.880
Yeah, I guess that makes sense for apps.

00:38:28.880 --> 00:38:31.660
You definitely need some sort of global state there.

00:38:32.460 --> 00:38:34.680
Yeah, I

00:38:34.680 --> 00:38:41.280
think we've seen that sometimes our users will reach for state in call VIX just because that's what they're used to.

00:38:41.400 --> 00:38:44.780
And that's what they maybe were required to use in Jupyter, et cetera.

00:38:45.260 --> 00:38:48.800
So we're trying to tell them, hey, in most cases, you actually don't need this.

00:38:49.160 --> 00:38:49.780
Yeah, very cool.

00:38:50.620 --> 00:38:55.600
So when you create a Jupyter notebook, you don't really create Python files.

00:38:56.100 --> 00:39:05.460
you create the notebook files, and those notebook files are JSON with both embedded cell execution bits, the code, but also the answers that go below.

00:39:05.680 --> 00:39:16.080
That's why if you go to GitHub and you look at a notebook, you can instantly see what could be super expensive computation, but pictures and stuff there because it's residual in the artifact, right?

00:39:16.380 --> 00:39:16.500
Yeah.

00:39:17.760 --> 00:39:18.780
If you guys do Python

00:39:18.780 --> 00:39:25.960
files, do you have a way to save that state in a sort of presentation style or something like that?

00:39:26.170 --> 00:39:26.460
You know what I mean?

00:39:26.540 --> 00:39:28.880
Is there like an associated state file?

00:39:29.840 --> 00:39:30.020
Yeah,

00:39:30.130 --> 00:39:31.240
so that's a really good question.

00:39:31.540 --> 00:39:35.200
And the answer is yes, but that is the biggest trade-off, I think, of our file format.

00:39:35.430 --> 00:39:47.780
So like a surprising number of people actually have come to us and told us, I didn't expect this, but they tell us the reason we decided to try Marima Notebooks is because you say it is versionable with Git.

00:39:47.930 --> 00:39:52.240
Like that's like, they're like, that's the one reason I, especially like people in software and industry.

00:39:52.800 --> 00:39:54.120
And then they stay for all the other things.

00:39:55.180 --> 00:40:00.440
So that's what the pure Python file format allows, in addition to modularity, running it as a script.

00:40:02.480 --> 00:40:05.840
For seeing outputs, yeah, they're not saved in the Python file.

00:40:05.970 --> 00:40:09.380
So we have a couple of ways to get around that.

00:40:09.650 --> 00:40:14.280
So one, you can export any Marimo notebook to an IPython notebook file, actually.

00:40:14.550 --> 00:40:14.980
So you

00:40:14.980 --> 00:40:17.860
can set up this, we have a feature, automatic snapshotting.

00:40:18.360 --> 00:40:26.820
You can automatically snapshot your notebook to like a parallel IPIMB file that's stored in a subdirectory of your notebook folder.

00:40:28.300 --> 00:40:30.920
And so you can push that up or share that if you like.

00:40:32.580 --> 00:40:45.280
When working locally, though, we actually have this cool feature that my co-finder Miles recently built is that we actually – so when you're working, you're working with your notebook, the outputs are actually saved.

00:40:45.520 --> 00:40:50.560
The representation of the outputs are saved in this subdirectory, underscore underscore marimo.

00:40:51.200 --> 00:40:59.900
So that the next time you open the notebook, it just picks up those outputs and then like loads them into the browser so that you can see where you left off.

00:41:01.160 --> 00:41:01.480
So

00:41:01.720 --> 00:41:03.900
I see. So kind of like PyCache.

00:41:04.360 --> 00:41:04.600
Yeah.

00:41:04.900 --> 00:41:09.080
I would actually assume given the name, but I haven't actually looked into PyCache too much.

00:41:09.320 --> 00:41:14.400
Well, I mean, just in the sense that it's saved like right there in your project using that directory.

00:41:14.620 --> 00:41:16.520
Oh, yes, yes. You have a PyCache folder. Exactly.

00:41:16.860 --> 00:41:16.980
Yeah,

00:41:17.020 --> 00:41:17.560
yeah, yeah. Exactly.

00:41:18.280 --> 00:41:18.980
And we have one

00:41:18.980 --> 00:41:32.300
other feature that another contributor, his name is Dylan, has been developing, which I think is really cool, which is along those same lines, but based on Nick's style caching.

00:41:32.800 --> 00:41:39.360
So it'll actually save the Python objects themselves using a variety of different protocols.

00:41:40.240 --> 00:41:47.280
And because we have the DAG, he can actually guarantee consistency of the cache.

00:41:47.720 --> 00:41:47.860
But that

00:41:47.860 --> 00:41:49.160
means not only are your outputs

00:41:49.160 --> 00:41:54.200
automatically loaded, also the variables are loaded, so you can literally pick up where you left off.

00:41:54.960 --> 00:42:01.100
Yeah, it sounds like some sweet SQLite could be in action there instead of just flat files or whatever.

00:42:01.500 --> 00:42:01.720
Yeah.

00:42:02.060 --> 00:42:02.600
Yeah, very cool.

00:42:02.970 --> 00:42:10.020
So you talked about when the reactivity fires, it can sometimes be expensive to recompute the cells.

00:42:10.420 --> 00:42:11.580
Sometimes they're super simple.

00:42:12.060 --> 00:42:15.160
Sometimes they're trained in the machine learning model for two days.

00:42:16.500 --> 00:42:16.740
Yeah.

00:42:17.300 --> 00:42:19.440
Are there caching mechanisms?

00:42:19.620 --> 00:42:33.140
You know, in a Python script, we've got functools.lrucache, and then there's other things that are kind of cool, in-process caches, like PyMocha is kind of like the functool stuff, but way more flexible and so on.

00:42:33.440 --> 00:42:43.420
And you could put those onto functions that then would have really interesting caching characteristics, like, hey, if you're going to rerun it, but I've run it before with this other value, here's the same answer back, right?

00:42:43.540 --> 00:42:49.680
Is there a way to set up that kind of caching or performance memoization type stuff?

00:42:50.100 --> 00:42:50.700
Yeah, definitely.

00:42:51.220 --> 00:42:52.980
And that same contributor, Dylan.

00:42:53.840 --> 00:42:57.140
So he's implemented these and is continuing to build it out.

00:42:57.820 --> 00:43:01.420
But we have, I guess, two options.

00:43:02.180 --> 00:43:10.080
One is in-memory cache, which is basically the API is the same as functools.cache, but is designed to work in an iterative programming environment.

00:43:10.140 --> 00:43:17.080
If you use functools.cache naively, if a cell defining a function reruns, your cache gets busted.

00:43:18.320 --> 00:43:24.720
So modoc.cache is a little smarter, and using the DAG can know whether or not it needs to bust the cache.

00:43:25.370 --> 00:43:27.240
But to the user, it feels the same.

00:43:28.340 --> 00:43:37.520
And then we also have a persistent cache, which is the one that I was alluding to when I mentioned you can automatically pick up where you left off by loading objects from disk.

00:43:37.940 --> 00:43:43.260
And so you can put an entire cell in a context manager with MoDub persistent cache.

00:43:44.160 --> 00:43:45.440
It'll sort of do the right thing.

00:43:46.420 --> 00:43:55.940
We've been talking about experimenting with letting users opt into global cell-wide caching, just automatically memorize cells or just have a UI element

00:43:55.940 --> 00:43:57.440
to do something like that.

00:43:57.580 --> 00:43:59.100
But we haven't quite done that yet.

00:43:59.380 --> 00:44:01.240
Yeah, I mean, it sounds real tricky for Jupyter.

00:44:01.660 --> 00:44:11.020
But because you all know the inputs and the outputs, It's almost as if you could sort of drive a hidden LRU cache equivalent at the cell level.

00:44:11.200 --> 00:44:11.660
You know what I mean?

00:44:12.079 --> 00:44:13.120
That's exactly right.

00:44:13.360 --> 00:44:13.460
Yeah.

00:44:14.580 --> 00:44:19.520
I think, yeah, because we know the inputs and outputs, that's kind of how everything flows from a project.

00:44:19.960 --> 00:44:23.920
You can think about projects like if you turn a notebook into a data flow graph, what can you do?

00:44:24.320 --> 00:44:27.260
And yeah, caching is, smart caching is definitely one of them.

00:44:27.480 --> 00:44:27.700
Yeah.

00:44:27.830 --> 00:44:31.760
I mean, it's not a, I make a sense like, well, you know, the inputs, outputs, so it's fine.

00:44:32.080 --> 00:44:39.420
But, you know, you could have the same data frame, but you could have added a column to the data frame, and the LRU cache goes, is it the same pointer?

00:44:39.640 --> 00:44:40.100
It is.

00:44:40.210 --> 00:44:40.740
We're good to go.

00:44:40.820 --> 00:44:41.760
It's like, well, yes.

00:44:41.960 --> 00:44:42.140
However,

00:44:42.460 --> 00:44:43.860
it's

00:44:43.860 --> 00:44:44.400
not the same.

00:44:44.570 --> 00:44:47.040
You know, you almost got to, like, hash it or do something funky.

00:44:47.740 --> 00:44:48.940
Yeah, it's not perfect.

00:44:48.940 --> 00:44:49.580
Automatic sounds hard.

00:44:49.910 --> 00:44:50.000
No.

00:44:50.280 --> 00:44:51.160
Yeah, yeah, exactly.

00:44:51.440 --> 00:44:53.380
That's why we haven't quite enabled it.

00:44:54.660 --> 00:44:55.580
Yeah, it is hard.

00:44:56.000 --> 00:44:56.180
Yeah.

00:44:56.800 --> 00:44:58.800
Side effects, too, network requests, all these things.

00:44:59.600 --> 00:44:59.900
All right.

00:45:00.240 --> 00:45:04.460
I have three more topics I want to cover before we run out of time here.

00:45:04.540 --> 00:45:07.240
We may cover more, but three are required.

00:45:07.600 --> 00:45:09.800
First one, because this is the one I'm going to forget most likely.

00:45:10.720 --> 00:45:20.180
You were at Google, and then by way of going through a PhD, you now are not at Google creating this project, which is open source on GitHub.

00:45:20.740 --> 00:45:24.300
And I don't see a pricing page at the top, but I do see it for enterprises.

00:45:24.720 --> 00:45:27.660
Like, how is this sustaining itself?

00:45:27.940 --> 00:45:28.940
Like, what's the business model?

00:45:29.780 --> 00:45:30.040
So

00:45:30.040 --> 00:45:41.860
when we first started right after my PhD, so that was early 2022, we were actually lucky enough to get funding from a national lab associated with Stanford.

00:45:42.040 --> 00:45:44.080
So the Stanford Linear Accelerator.

00:45:44.660 --> 00:45:45.500
So I was talking with

00:45:45.500 --> 00:45:46.960
some scientists there

00:45:46.960 --> 00:45:50.360
and we were talking about, I knew I wanted to make this thing.

00:45:50.660 --> 00:45:51.560
And they were like, what are you up to?

00:45:51.620 --> 00:45:57.680
And I was like, oh, well, I want to make this like notebook thing that like, you know, fixes all notebooks inspired by Pluto JL.

00:45:57.820 --> 00:45:58.920
And they were like, that's awesome.

00:45:59.080 --> 00:45:59.520
We're scientists.

00:45:59.640 --> 00:46:03.240
We use notebooks every day and we're getting a little tired of reproducibility issues.

00:46:03.460 --> 00:46:04.280
We want to make apps.

00:46:04.720 --> 00:46:06.120
So they're like, we'll fund you to do this.

00:46:06.440 --> 00:46:07.240
And so we...

00:46:07.240 --> 00:46:07.600
Awesome.

00:46:07.780 --> 00:46:10.800
So they kind of wrote you into one of their larger grants, something like that.

00:46:11.300 --> 00:46:14.500
We got like a subcontract that like was covered by one of their grants.

00:46:14.760 --> 00:46:14.880
Yeah.

00:46:15.960 --> 00:46:21.480
So that wasn't enough for me and my co-founder, Miles, to work on it for two years full time alone.

00:46:21.780 --> 00:46:26.160
And like, I think it really let us polish the product and develop

00:46:26.160 --> 00:46:26.460
it.

00:46:27.020 --> 00:46:28.500
And then mid

00:46:28.500 --> 00:46:40.420
last year, in July. One of our users is like one of our probably biggest power users actually is Anthony Goldblum, who is the founder and former CEO of Kaggle. So

00:46:40.420 --> 00:46:41.960
really

00:46:41.960 --> 00:46:57.360
into data science. So he's been one of our biggest power users. And at a certain point he last year became, I guess, passionate enough about our project that he reached out to us and asked us, hey, like, can this venture fund I'm part of, can we invest?

00:46:58.320 --> 00:47:00.180
And so that was July of last year.

00:47:00.690 --> 00:47:09.680
And so we raised money from them as well as from a bunch of prominent angel investors like Jeff Dean from Google, Clem from Hugging Face, Lucas B.

00:47:09.730 --> 00:47:10.460
Walt from Weights &

00:47:10.460 --> 00:47:11.020
Bias and others.

00:47:12.000 --> 00:47:17.040
So now our team is funded primarily through the venture funding.

00:47:18.400 --> 00:47:22.900
Right now our business model is build open source software based on our venture

00:47:22.900 --> 00:47:23.220
funding.

00:47:23.280 --> 00:47:28.100
We do have plans for commercialization, but we're just not at a point where it makes sense to work on that right now.

00:47:28.760 --> 00:47:33.000
But what I can promise is that Marima will always be open source Apache 2.0 license.

00:47:33.240 --> 00:47:38.660
We never plan to sell the notebook itself, but instead plan to work on complementary infrastructure.

00:47:39.360 --> 00:47:42.180
Yeah, I can already think of two good ones.

00:47:43.680 --> 00:47:43.860
Cool.

00:47:44.360 --> 00:47:44.480
Yeah.

00:47:45.280 --> 00:47:45.400
Awesome.

00:47:45.800 --> 00:47:49.640
Okay. The reason I ask is, you know, people always just want to know either

00:47:49.640 --> 00:47:50.460
how,

00:47:51.140 --> 00:48:05.660
what is kind of the success story of open source, but sustainable, you know, as a full-time thing, or if they're buying into it, how likely is that going to stay open source or like what's the catch, you know, that kind of stuff?

00:48:06.440 --> 00:48:07.960
Yeah, no, it's a good question.

00:48:08.180 --> 00:48:18.340
I mean, honestly, I think when we raised money, it actually assuaged some of our users because they were like, oh, Miles and Akshay are really cool.

00:48:18.480 --> 00:48:21.820
They're building this really cool stuff, but how are they paying rent?

00:48:22.200 --> 00:48:28.240
And so when we told them, yeah, we raised a few million dollars from X Ventures, they were like, okay, that's great.

00:48:28.400 --> 00:48:29.000
You deserve it.

00:48:29.240 --> 00:48:30.040
Please continue building.

00:48:31.560 --> 00:48:31.800
Nice.

00:48:32.620 --> 00:48:32.820
Yeah.

00:48:33.440 --> 00:48:34.000
Yeah, that's awesome.

00:48:34.540 --> 00:48:34.840
All right.

00:48:35.300 --> 00:48:37.520
Let's see, which one are we going to talk about next?

00:48:37.950 --> 00:48:38.060
Not

00:48:38.060 --> 00:48:38.900
this one yet.

00:48:39.340 --> 00:48:42.000
We'll talk about this because there's a nice comment from Amir out in the audience.

00:48:42.220 --> 00:48:44.100
I love the new AI feature in Mario.

00:48:44.640 --> 00:48:47.040
So you have an AI capability.

00:48:47.290 --> 00:48:55.120
And then the other thing I want to talk about is, so we save some time for it, is publishing or running your Reactive Notebook as an app.

00:48:55.480 --> 00:48:58.660
But let's talk AI first because we started the show that way.

00:48:59.020 --> 00:48:59.720
I don't want to start to

00:48:59.720 --> 00:49:00.800
round it

00:49:00.800 --> 00:49:01.560
out that way, you know?

00:49:02.460 --> 00:49:06.740
So we have like a few different ways that AI is, I guess, integrated into the project.

00:49:08.260 --> 00:49:14.560
So one thing that we're trying really hard to do is like build like a modern editor, like designed specifically for working with data.

00:49:15.170 --> 00:49:19.260
And I think these days modern means one of the requirements is you have AI stuff built in.

00:49:20.360 --> 00:49:22.320
So you can like generate code with AI.

00:49:22.510 --> 00:49:31.960
You can like even tell the, you can like tag like data frames and like tables that you have in memory and like give them as context, give their schemas as context to your assistant.

00:49:32.340 --> 00:49:32.760
in

00:49:32.760 --> 00:49:33.760
like a cursor-like way.

00:49:35.700 --> 00:49:50.920
We're also like experimenting with a new service right now like marimo.amp.ai where you can go type a little prompt like generate me a notebook that plots a 3D quadratic surface with Matplotlib because I always forget how to do that.

00:49:51.740 --> 00:50:02.520
And then it'll do its best to in one shot create that notebook for you and then you can play around with it and then you can either download it locally or share it out.

00:50:04.060 --> 00:50:04.900
Yeah, very cool.

00:50:05.200 --> 00:50:09.340
I'll put a link to the online AI feature that people can play with.

00:50:09.340 --> 00:50:12.580
It looks really, really nice and it worked super quick when I asked it to go.

00:50:12.680 --> 00:50:21.840
Now, one thing I want to talk about really quick now that I'm looking at this is you've got the code, but it's below the presentation of the result of the code.

00:50:22.240 --> 00:50:22.540
Yeah.

00:50:23.860 --> 00:50:30.040
So that is a stylistic choice, which is configurable because people told us, Many of them told us we don't like this.

00:50:30.250 --> 00:50:31.420
Please just put the output below.

00:50:31.990 --> 00:50:32.080
But

00:50:32.080 --> 00:50:33.000
other people like it.

00:50:33.330 --> 00:50:33.880
Okay, you love

00:50:33.880 --> 00:50:34.020
it.

00:50:34.320 --> 00:50:34.880
Okay, yeah.

00:50:34.990 --> 00:50:35.460
And so this

00:50:35.460 --> 00:50:35.720
is...

00:50:35.720 --> 00:50:36.600
Okay, well, what is the point?

00:50:36.660 --> 00:50:38.740
Is the point for me to see the code or the answer?

00:50:39.760 --> 00:50:42.680
The point is to see the graph and the tables and

00:50:42.680 --> 00:50:43.740
if I care,

00:50:43.880 --> 00:50:44.560
I'll look at the code.

00:50:44.940 --> 00:50:46.740
So the way that I...

00:50:46.740 --> 00:50:49.620
So I think I mentioned Pluto JL really briefly.

00:50:49.710 --> 00:50:51.720
So Pluto JL is one of our biggest inspirations.

00:50:51.810 --> 00:50:53.560
It's a Julia project, a reactive notebook.

00:50:54.160 --> 00:51:23.900
Now, a lot of the great ideas that I think are great about Marimo came, honestly, very straight from pluto and one thing that fawns like the creator of pluto's you know he likes to say is he said code is the code of a cell is a caption for its output and that's the that's the way you think about it and when you think about it that way it makes a lot of sense um but i think like pluto and then observable also both have outputs on top i don't know it's like i feel like if you it's like one of those heuristics you look at a notebook output on top it's a reactive notebook otherwise it's imperative

00:51:23.900 --> 00:51:30.460
i gotcha gotcha yeah i can see why you might not like it but i like it so i think

00:51:30.460 --> 00:51:31.360
it's pretty

00:51:31.360 --> 00:51:40.320
cool yeah and then this um marmo.app slash ai once you create one of these you have a shareable link that you can hand off to other people right yeah

00:51:40.320 --> 00:51:48.400
so you can open a new tab which i think will so actually this all of this actually interestingly enough is running in our WebAssembly playground um

00:51:48.400 --> 00:51:49.140
yeah so there's

00:51:49.140 --> 00:51:56.720
that url right there which you can just share You can also do like the little, there's a hamburger menu, which you can click on to get a permalink that's shorter.

00:51:58.620 --> 00:51:59.020
But

00:51:59.020 --> 00:51:59.420
yeah,

00:52:01.200 --> 00:52:05.280
honestly, we just built this generate with AI feature like a little over a week ago.

00:52:05.980 --> 00:52:08.300
And just curious to see what people use it for.

00:52:08.580 --> 00:52:08.720
There's a

00:52:08.720 --> 00:52:09.660
lot more we could invest

00:52:09.660 --> 00:52:09.980
here.

00:52:10.020 --> 00:52:11.960
I mean, you know, everyone talks about agents.

00:52:12.020 --> 00:52:14.140
You can think about, oh, data science agent.

00:52:14.580 --> 00:52:18.800
But for now, we're just trying to one shot thing and see how it lands with folks.

00:52:19.220 --> 00:52:19.580
Yeah, sure.

00:52:20.060 --> 00:52:20.600
Let's start with that.

00:52:20.680 --> 00:52:21.720
Well, it looks really great.

00:52:21.810 --> 00:52:23.740
And the UI is super nice.

00:52:23.960 --> 00:52:24.760
So well done.

00:52:25.420 --> 00:52:25.740
Appreciate it.

00:52:25.800 --> 00:52:26.700
I'll pass that on to Miles.

00:52:26.880 --> 00:52:29.700
He built this as a weeknight project.

00:52:30.859 --> 00:52:32.300
Sometimes you just get inspired.

00:52:32.390 --> 00:52:33.220
Just like, you know what?

00:52:33.800 --> 00:52:34.320
I'm doing it.

00:52:34.780 --> 00:52:35.680
I'm just taking

00:52:35.680 --> 00:52:38.340
two days off the regular work and I'm just doing this.

00:52:38.350 --> 00:52:38.680
You know what I

00:52:38.680 --> 00:52:38.760
mean?

00:52:38.980 --> 00:52:39.100
Yeah.

00:52:39.480 --> 00:52:39.920
Yeah, definitely.

00:52:40.620 --> 00:52:40.720
Yeah.

00:52:41.280 --> 00:52:41.540
All right.

00:52:41.740 --> 00:52:50.180
So the final thing I want to talk about, which you kind of hinted at a little bit there with the WebAssembly stuff, is I want to run my app.

00:52:50.460 --> 00:52:54.920
So tell us about, as I'm fumbling around to find a place to show you.

00:52:55.000 --> 00:52:57.920
Anyway, tell us about running the app.

00:52:58.660 --> 00:52:59.100
Yeah, so there's

00:52:59.100 --> 00:52:59.860
a few different ways.

00:53:02.060 --> 00:53:08.160
The sort of traditional way, if you have a client-server architecture,

00:53:08.760 --> 00:53:09.400
so you have your notebook

00:53:09.400 --> 00:53:12.160
file, notebook.py.

00:53:12.580 --> 00:53:14.260
It has some UI elements, et cetera.

00:53:14.920 --> 00:53:15.560
It has some code.

00:53:15.840 --> 00:53:18.140
You get an app, but just by default, you hide all the code.

00:53:18.240 --> 00:53:19.820
Now you have text, outputs, UI elements.

00:53:20.220 --> 00:53:21.240
You can think of it as an app.

00:53:21.880 --> 00:53:36.040
So if you type marimorun, notebook.py, at the command line, it'll start a web server that's serving your notebook in a read-only session that you can connect to, et cetera.

00:53:36.600 --> 00:53:37.340
Can you do the widgets?

00:53:40.500 --> 00:53:44.020
Like if it's read-only, can I slide the widgets to see it do stuff?

00:53:44.560 --> 00:53:44.900
You know what I mean?

00:53:44.960 --> 00:53:45.100
Yeah,

00:53:45.160 --> 00:53:45.620
yeah, yeah.

00:53:45.760 --> 00:53:47.160
So you can slide the widgets, see it do stuff.

00:53:47.240 --> 00:53:49.140
You just can't change the underlying Python code.

00:53:49.700 --> 00:53:50.500
Like you can't like,

00:53:50.860 --> 00:53:51.140
got it.

00:53:51.740 --> 00:53:52.980
But yes, that's true.

00:53:53.080 --> 00:53:53.280
That is

00:53:53.280 --> 00:53:53.560
real.

00:53:53.960 --> 00:53:54.960
Exact RM dash RF.

00:53:55.160 --> 00:53:55.240
Okay.

00:53:55.460 --> 00:53:55.820
Let's go.

00:53:56.440 --> 00:53:56.600
Yeah.

00:53:56.780 --> 00:53:57.120
Yeah.

00:53:57.600 --> 00:53:58.420
So that is not allowed.

00:53:58.730 --> 00:54:00.860
And so that's the traditional way client server.

00:54:01.720 --> 00:54:04.960
but, last year we actually, I think it was last year.

00:54:05.210 --> 00:54:13.480
we, we added support for, WebAssembly through the PyDype project, which is a port of CPython to, to Wasm slash Unscriptum.

00:54:14.140 --> 00:54:17.020
And so now you can actually take any Marima notebook.

00:54:17.240 --> 00:54:27.300
And as long as you satisfy some constraints, which are documented on our website, you can export it as like static HTML and some assets and just throw it up on GitHub pages or server it wherever you like.

00:54:28.380 --> 00:54:30.480
And that's also what our online playground is powered by.

00:54:31.040 --> 00:54:39.120
And we found this to be just like a really easy way to share notebooks, easy for folks in industry, easy for educators, and also just incredibly satisfying.

00:54:39.240 --> 00:54:52.140
In our docs, we have tons of little Marima notebooks iframed into various API pages, etc., that just let you actually interact with the code as opposed to just reading it statically.

00:54:52.500 --> 00:54:53.040
Yeah, that's nice.

00:54:53.460 --> 00:54:53.900
That's super cool.

00:54:54.320 --> 00:54:56.700
So it's pretty low effort, it sounds like.

00:54:57.000 --> 00:55:04.100
And it's a lot of work to run a server and maintain it, especially if you're going to put it up there so other people can interact with it.

00:55:04.260 --> 00:55:07.140
And you've got to worry about abuse and all that kind of stuff.

00:55:07.220 --> 00:55:11.920
If you can ship it as a static website, people are just abusing themselves if they mess with it anyway.

00:55:12.520 --> 00:55:13.040
Exactly.

00:55:13.880 --> 00:55:17.920
I had to give huge props to the PyDive maintainers.

00:55:19.260 --> 00:55:23.580
They are amazing, really responsive, and just building this labor of love.

00:55:24.760 --> 00:55:31.800
They are really pushing the needle on the accessibility of Python.

00:55:32.260 --> 00:55:33.000
Yeah, that's awesome.

00:55:33.190 --> 00:55:34.460
Have you done anything with PyScript?

00:55:35.280 --> 00:55:37.100
I haven't done anything with it.

00:55:37.120 --> 00:55:37.860
I know of them.

00:55:37.900 --> 00:55:39.920
So they also use Pyodide underneath the hood.

00:55:40.380 --> 00:55:41.000
Yeah, they let you

00:55:41.000 --> 00:55:43.560
pick between Pyodide for more data science-y stuff and

00:55:43.560 --> 00:55:45.620
MicroPython for more faster

00:55:45.620 --> 00:55:46.320
stuff.

00:55:47.760 --> 00:55:51.280
I am pretty not educated about MicroPython.

00:55:51.340 --> 00:55:56.680
I read about it, but I'd be curious on your take also on choosing one versus the end.

00:55:56.960 --> 00:56:00.920
Yeah, well, I think it's brilliant if you want a front-end framework equivalent.

00:56:01.000 --> 00:56:05.260
If you want PyView or PyReact or whatever,

00:56:05.680 --> 00:56:06.060
You don't

00:56:06.060 --> 00:56:07.500
need all the extras.

00:56:07.580 --> 00:56:12.160
You kind of need the Python language and a little bit of extras and the ability to call APIs, right?

00:56:12.440 --> 00:56:21.780
And so MicroPython is a super cut-down version that's built to run on like little tiny chips and self-contained systems on a chip type things.

00:56:22.240 --> 00:56:23.520
So it's just way lighter.

00:56:23.600 --> 00:56:26.640
It's 100K versus 10 megs or something like that.

00:56:26.980 --> 00:56:27.780
And if

00:56:27.780 --> 00:56:35.240
it solves the problem, right, if it gives you enough Python, I guess is the way to think of it, then it's a really cool option for front-end things.

00:56:35.500 --> 00:56:36.980
I don't know that it works for you guys, right?

00:56:37.180 --> 00:56:41.360
Because you want as much compatibility with like Matplotlib

00:56:41.360 --> 00:56:42.620
and Seaborn

00:56:42.620 --> 00:56:43.320
and all these things.

00:56:43.520 --> 00:56:52.200
But if your goal is like, I want to replace the JavaScript language with the Python language, and I know I'm in a browser, so I'm willing to make concessions, I think it's a pretty good option.

00:56:52.580 --> 00:56:53.340
Yeah, that makes sense.

00:56:53.480 --> 00:56:53.860
Yeah, you're right.

00:56:53.910 --> 00:56:55.020
We want max compatibility.

00:56:55.420 --> 00:57:05.100
Like we have one demo where like you can load sklearn, take PCA of these like images of numerical digits, put it in all Terraplot, select them, get it back as a data frame.

00:57:05.360 --> 00:57:06.420
That's all running in the browser.

00:57:06.640 --> 00:57:06.940
And, like,

00:57:07.280 --> 00:57:08.060
it's magical.

00:57:08.480 --> 00:57:09.560
It's on your home screen.

00:57:09.720 --> 00:57:10.860
People can watch the little

00:57:10.860 --> 00:57:12.280
embeddings

00:57:12.280 --> 00:57:12.680
explore.

00:57:12.820 --> 00:57:13.300
It's super cool.

00:57:13.640 --> 00:57:14.180
It's very cool.

00:57:14.480 --> 00:57:18.100
It's honestly magical what PyDat has been able to enable.

00:57:18.920 --> 00:57:19.040
Yeah.

00:57:19.480 --> 00:57:20.660
I imagine it's just getting started.

00:57:21.160 --> 00:57:21.900
I think so.

00:57:22.380 --> 00:57:22.540
Yeah.

00:57:22.840 --> 00:57:23.040
Yeah.

00:57:23.420 --> 00:57:24.380
They're constantly shipping.

00:57:24.440 --> 00:57:26.240
They just added support for Wasm GC.

00:57:27.760 --> 00:57:29.240
So performance is increasing.

00:57:29.680 --> 00:57:30.080
Expose

00:57:30.080 --> 00:57:30.380
the bug

00:57:30.380 --> 00:57:31.500
in WebKit.

00:57:31.920 --> 00:57:32.720
along the way.

00:57:33.200 --> 00:57:33.900
Wow, okay.

00:57:34.420 --> 00:57:34.660
That's good.

00:57:35.360 --> 00:57:35.540
Yeah.

00:57:36.700 --> 00:57:36.860
Cool.

00:57:37.300 --> 00:57:40.420
All right, well, we're getting to the end of our time here.

00:57:40.640 --> 00:57:42.540
So, you know, people are interested in this.

00:57:42.920 --> 00:57:44.020
They might want to try it for themselves.

00:57:44.400 --> 00:57:49.000
Maybe they're part of a science team or a data science team at a company.

00:57:49.320 --> 00:57:52.720
What do you tell them if they're interested in Marmo and they want to check it out?

00:57:53.700 --> 00:57:57.520
The easiest way, I think, is to just start running it locally.

00:57:57.960 --> 00:58:00.960
And so our sort of source of truth is our GitHub repo.

00:58:01.500 --> 00:58:08.620
So GitHub.com, marimoteam.com, or if it's easy to remember, our homepage is marimo.io, which links to our GitHub.

00:58:09.410 --> 00:58:14.860
But then you can install from pip or uv or whatever your favorite package manager is and just sort of go to town.

00:58:15.500 --> 00:58:24.680
If you really just don't have the ability to do that for whatever reason, you can go to marimo.new, which will create a blank Marimo notebook powered by WebAssembly in your browser.

00:58:25.740 --> 00:58:29.700
It has links to various Marimo tutorials, as an example, notebooks.

00:58:31.180 --> 00:58:38.740
We didn't even get to talk about the uv integration, which may be another time, but that's another way that Marimo makes notebooks reproducible down to the packages.

00:58:39.580 --> 00:58:40.320
Oh, yeah, okay.

00:58:41.160 --> 00:58:41.680
UV is fantastic.

00:58:42.000 --> 00:58:44.680
I'm a huge fan of uv and Charlie Marsh and team.

00:58:45.000 --> 00:58:50.300
Yeah, but GitHub, Marimo.io, and docs.marimo.io is what I would recommend.

00:58:51.040 --> 00:58:52.280
Thank you so much for being on the show.

00:58:52.980 --> 00:58:54.060
Congratulations on the project.

00:58:55.000 --> 00:58:58.020
It's really come a long way, it sounds like, so it looks great.

00:58:58.520 --> 00:58:59.700
Thanks, Michael. I appreciate it.

00:58:59.740 --> 00:59:00.620
It was a lot of fun to chat.

00:59:00.960 --> 00:59:01.700
Yeah, you bet. Bye.

00:59:02.120 --> 00:59:02.220
Bye.

00:59:03.420 --> 00:59:06.000
This has been another episode of Talk Python To Me.

00:59:06.920 --> 00:59:07.760
Thank you to our sponsors.

00:59:08.230 --> 00:59:09.460
Be sure to check out what they're offering.

00:59:09.680 --> 00:59:10.900
It really helps support the show.

00:59:11.640 --> 00:59:14.140
This episode is sponsored by Worth Recruiting.

00:59:14.720 --> 00:59:19.120
Worth Recruiting specializes in placing senior-level Python developers and data scientists.

00:59:19.760 --> 00:59:24.500
Let Worth help you find your next Python opportunity at talkpython.fm/worth.

00:59:25.200 --> 00:59:26.080
Want to level up your Python?

00:59:26.540 --> 00:59:30.140
We have one of the largest catalogs of Python video courses over at Talk Python.

00:59:30.660 --> 00:59:35.340
Our content ranges from true beginners to deeply advanced topics like memory and async.

00:59:35.670 --> 00:59:37.880
And best of all, there's not a subscription in sight.

00:59:38.350 --> 00:59:40.880
Check it out for yourself at training.talkpython.fm.

00:59:41.560 --> 00:59:45.760
Be sure to subscribe to the show, open your favorite podcast app, and search for Python.

00:59:46.170 --> 00:59:47.080
We should be right at the top.

00:59:47.600 --> 00:59:56.460
You can also find the iTunes feed at /itunes, the Google Play feed at /play, and the direct RSS feed at /rss on talkpython.fm.

00:59:57.100 --> 00:59:59.360
We're live streaming most of our recordings these days.

00:59:59.800 --> 01:00:07.200
If you want to be part of the show and have your comments featured on the air, be sure to subscribe to our YouTube channel at talkpython.fm/youtube.

01:00:08.200 --> 01:00:09.340
This is your host, Michael Kennedy.

01:00:09.760 --> 01:00:10.600
Thanks so much for listening.

01:00:10.780 --> 01:00:11.740
I really appreciate it.

01:00:12.060 --> 01:00:13.700
Now get out there and write some Python code.