https://github.com/z0u/mi-ni
Template project for AI experiments
https://github.com/z0u/mi-ni
ai experiments gpu jupyter ml notebooks research-tool
Last synced: 3 months ago
JSON representation
Template project for AI experiments
- Host: GitHub
- URL: https://github.com/z0u/mi-ni
- Owner: z0u
- License: mit
- Created: 2025-02-25T23:29:58.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-03-23T07:47:35.000Z (over 1 year ago)
- Last Synced: 2025-03-23T08:27:39.977Z (over 1 year ago)
- Topics: ai, experiments, gpu, jupyter, ml, notebooks, research-tool
- Language: Python
- Homepage:
- Size: 664 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
> **見みに /mi·ni/** — _with intent to see_ [^etymology]
[^etymology]: From 見に行く (mi-ni iku), meaning "to go for the purpose of seeing something." This library is about small AI experiments—quick, lightweight explorations to try and see what happens.
This is a template repository for doing AI research. Features:
- **Local Python notebooks**
- **Remote per-function GPU compute** [^modal]
- **Inline visualization** with remote-to-local callbacks
- **AI-assisted coding** with Copilot/VS Code
[](https://codespaces.new/z0u/mi-ni/tree/v1)

> Above: screen recording of a local notebook running a remote training job [^edited]. **a:** `track` is a function that runs locally — even when called from the remote function. **a':** The plot is displayed directly in the notebook, showing training metrics in real time. **b:** `train` is a function that runs in the cloud (with a GPU). **b':** The message "Training complete" is printed remotely, but the output is shown locally (no callback needed). **c:** A `with` statement creates a context that bridges the remote and local environments.
[^edited]: The recording was edited: 1. labels were added; 2. the remote `train()` function was moved to the right so that the video wouldn't take up so much vertical space.
Read about how it works in [Hither-thither architecture](docs/hither-thither.md).
Code for the above demo
The code shown in the screen recording is:
```python
@run.hither
async def track(loss: float):
history.append(loss)
plot(history)
@run.thither(gpu='L4')
async def train(epochs: int, track):
for _ in range(epochs):
track(some_training_function())
print('Training complete')
async with run(), track as callback:
await train(25, callback)
```
More cool features
- [Dev container][dc] for a consistent environment, both locally and in [Codespaces][codespaces]
- ML stack ([PyTorch, Polars, etc.](pyproject.toml))
- Modern package management with [uv]
- Pre-configured for good engineering practices: tests, linting, type-checking (optional!)
[^modal]: [Modal] is used for remote compute. They charge per-second, billed for the duration of your function.
## Getting started
First, [open in GitHub Codespaces](https://codespaces.new/z0u/mi-ni). Then:
```bash
./go install # CPU deps for local venv
./go auth # Authenticate with Modal for remote compute
```
Open the [Getting Started notebook](./docs/getting-started.ipynb) and try it out (choose `.venv/bin/python3` as the kernel). For a more complete example, have a look at the [nanoGPT notebook](./docs/nanogpt.ipynb).
[codespaces]: https://github.com/features/codespaces
Virtual environment
The Python environment is configured when the dev container is created.
Use [uv] to add and remove packages, and to run scripts:
```bash
uv add plotly --group local
uv run python example.py
```
Instead of using `uv sync` to install the added packages, use `./go install` instead. It remembers whether you have installed cpu or gpu packages.
Restarting the language server (VS Code)
If you open a Python file before the setup is complete, you may need to restart the Python language server.
- Open a `.py` or `.ipynb` file
- Open the command pallette with ⇧⌘P or CtrlShiftP
- Run _Python: Restart Language Server_.
Working with large files (Git LFS)
This project is preconfigured to use [Git LFS](https://git-lfs.com). If you commit a matching file, it won't clog up your main Git history. By default, files in `docs/large-assets/` are stored in LFS, but you can change that by editing `.gitattributes`.
Typically, you would store _data_ rather than code in LFS:
- training data
- model weights
- visualizations (images and video)
For matplotlib figures, use `utils.nb.save_fig` instead of displaying them directly: that stores them outside the notebook, which makes the notebook easier to view in `git diff`, and easier for AI assistants to process (because the notebook contains fewer tokens).
[dc]: https://containers.dev
[Modal]: https://modal.com
[uv]: https://astral.sh/uv
## Contributing & licence
This project is dedicated to the public domain [^unlicense][^attrib]. In your own experiments, there's no need to contribute back! The code is yours to modify as you please.
If you do want to contribute to _this template_, then fork it as usual. Before making a pull request, run:
```bash
./go check
```
[^not-fork]: Since your project isn't a fork, you don't need to worry about keeping the code in sync, and you can add and remove Python packages as you wish.
[^unlicense]: Technically, the licence is the [Unlicense](https://unlicense.org), which is about as close as you can get to "do whatever you want".
[^attrib]: Exception: Code in `src/experiment` is derived from [nanoGPT](https://github.com/karpathy/nanoGPT) by Andrej Karpathy and is subject to MIT license terms. See the [LICENSE](LICENSE) file for details.