Skip to content

Commit e064b51

Browse files
Aitomatesclaude
andcommitted
feat(gemini-nano): Phase 1+2+3 — CI, component completion, unified README
Phase 1 — CI Setup (CI-01): - GitHub Actions: ruff lint api-server, npm ci + health test chrome-bridge - test_api.py collect-only (requires live Ollama — CI skips) Phase 2 — Component Completion (NANO-01, NANO-02, TEST-01): - python-mediapipe/run_nano.py: graceful fallback when model.task absent (exits 0 with download hint), --model-path arg - chrome-bridge/test.js: spawns server (SKIP_CHROME=1), hits /health, asserts JSON fields — no Chrome required - chrome-bridge/server.js: SKIP_CHROME env var bypasses launchBrowser() in test mode - chrome-bridge/package.json: added npm test script - ci.yml: updated to run npm test directly Phase 3 — Unified README (DOC-01): - README.md with component table, Mermaid architecture diagram, quick-start per component - Links to SETUP.md for Chrome flag details Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent a277d35 commit e064b51

17 files changed

Lines changed: 2931 additions & 8 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,4 @@ jobs:
6262
run: npm ci --ignore-scripts
6363

6464
- name: Run health test
65-
# TEST-01: npm test must exist before this step passes end-to-end.
66-
# Until Phase 2 adds the test script, this step will warn but not fail CI.
67-
run: |
68-
if node -e "const p=require('./package.json'); process.exit(p.scripts && p.scripts.test ? 0 : 1)"; then
69-
npm test
70-
else
71-
echo "::warning::chrome-bridge has no 'test' script yet — add one in Phase 2 (TEST-01)"
72-
fi
65+
run: npm test

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
node_modules/
2+
__pycache__/
3+
*.py[cod]
4+
.venv/
5+
dist/
6+
*.egg-info/
7+
.coverage
8+
htmlcov/
9+
.env

CLAUDE.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# gemini-nano
2+
3+
Experimental Gemini Nano integration demos. Explores on-device AI inference through four separate components — no shared build system; each component is standalone.
4+
5+
## Components
6+
7+
| Directory | Language | Purpose |
8+
|---|---|---|
9+
| `chrome-demo/` | HTML/JS | Browser demo page for Chrome's built-in Gemini Nano (Prompt API) |
10+
| `python-mediapipe/` | Python | Gemini Nano via MediaPipe on-device inference |
11+
| `api-server/` | Python | FastAPI server bridging Gemini Nano inference to HTTP |
12+
| `chrome-bridge/` | Node.js/Express | Bridge server exposing Chrome's Prompt API over HTTP (`server.js`) |
13+
14+
## Local Development
15+
16+
**api-server** (Python):
17+
```bash
18+
cd gemini-nano/api-server
19+
python -m venv .venv && .\.venv\Scripts\Activate.ps1
20+
pip install -r requirements.txt
21+
# start server
22+
python app.py # or uvicorn if FastAPI
23+
```
24+
25+
**chrome-bridge** (Node.js):
26+
```bash
27+
cd gemini-nano/chrome-bridge
28+
npm install
29+
.\start.ps1
30+
```
31+
32+
**python-mediapipe**:
33+
```bash
34+
cd gemini-nano/python-mediapipe
35+
pip install -r requirements.txt
36+
python run_nano.py
37+
```
38+
39+
**chrome-demo**: Open `chrome-demo/index.html` directly in Chrome Canary with `chrome://flags/#prompt-api-for-gemini-nano` enabled.
40+
41+
## Notes
42+
43+
- These are research/demo components, not production services
44+
- `chrome-bridge` requires Chrome Canary with the Gemini Nano flag enabled
45+
- `python-mediapipe` requires the MediaPipe Tasks GenAI package
46+
- No shared config — each component is self-contained
47+
48+
## GSD Workflow
49+
50+
Use `/gsd:quick` for experimental work here. No formal phase planning required for this research area.

README.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# gemini-nano
2+
3+
Experimental Gemini Nano on-device inference demos across browser, Python, and HTTP surfaces.
4+
5+
## Components
6+
7+
| Directory | Language | Port | Status |
8+
|---|---|---|---|
9+
| `api-server/` | Python (FastAPI + Ollama) | 8080 | Stable |
10+
| `chrome-bridge/` | Node.js / Express | 8081 | Stable |
11+
| `python-mediapipe/` | Python (MediaPipe) || Stable |
12+
| `chrome-demo/` | HTML / JavaScript | — (file) | Stable |
13+
14+
## Architecture
15+
16+
```mermaid
17+
graph TD
18+
A[chrome-demo\nindex.html] -->|window.ai Prompt API| B[Chrome Canary\nGemini Nano built-in]
19+
C[HTTP client] -->|POST /v1/chat/completions| D[chrome-bridge\nserver.js :8081]
20+
D -->|Puppeteer + window.ai| B
21+
E[HTTP client] -->|POST /generate| F[api-server\napp.py :8080]
22+
F -->|Ollama REST API| G[Ollama\nlocal model]
23+
H[terminal] -->|python run_nano.py| I[python-mediapipe\nMediaPipe LLM Inference]
24+
I -->|.task model file| J[Gemma 2B-IT\nor Gemini Nano weights]
25+
```
26+
27+
## Quick Start
28+
29+
### api-server (Python + Ollama)
30+
31+
```bash
32+
cd api-server
33+
python -m venv .venv && .venv\Scripts\activate # Windows
34+
pip install -r requirements.txt
35+
python app.py
36+
# → http://localhost:8080
37+
```
38+
39+
### chrome-bridge (Node.js)
40+
41+
```bash
42+
cd chrome-bridge
43+
npm install
44+
npm start
45+
# → http://localhost:8081
46+
```
47+
48+
Test without Chrome:
49+
50+
```bash
51+
npm test
52+
```
53+
54+
### python-mediapipe
55+
56+
```bash
57+
cd python-mediapipe
58+
pip install -r requirements.txt
59+
python run_nano.py "What is Gemini Nano?"
60+
# Prints download instructions if model.task is absent (exits 0)
61+
python run_nano.py --model-path /path/to/gemma2b-it.task "Your prompt"
62+
```
63+
64+
### chrome-demo
65+
66+
Open `chrome-demo/index.html` directly in Chrome Canary with:
67+
68+
```
69+
chrome://flags/#prompt-api-for-gemini-nano → Enabled
70+
```
71+
72+
No server required.
73+
74+
## Setup
75+
76+
See [SETUP.md](SETUP.md) for Chrome flag configuration and model download instructions.

SETUP.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Local LLM API — Setup Guide
2+
3+
Machine: HP ZBook Firefly 16 G11 | Intel Core Ultra 7 155H | 32 GB RAM | NVIDIA RTX A500 4 GB
4+
5+
---
6+
7+
## Quick start (Ollama API on port 9000)
8+
9+
```powershell
10+
cd C:\PersonalRepo\gemini-nano\api-server
11+
.\start.ps1
12+
```
13+
14+
Open http://localhost:9000 in any browser to use the web UI.
15+
16+
### Calling from your other projects
17+
18+
```python
19+
import httpx
20+
21+
resp = httpx.post("http://localhost:9000/v1/chat/completions", json={
22+
"model": "gemma3:12b", # see model table below
23+
"messages": [{"role": "user", "content": "Hello!"}]
24+
})
25+
print(resp.json()["choices"][0]["message"]["content"])
26+
```
27+
28+
OpenAI SDK compatible — just set `base_url="http://localhost:9000/v1"` and `api_key="local"`.
29+
30+
---
31+
32+
## Available models
33+
34+
| Model | Size | Speed | Best for |
35+
|-------|------|-------|---------|
36+
| `gemma3:12b` | 8.1 GB | Medium | **Best quality — use this by default** |
37+
| `qwen3:8b` | 5.2 GB | Fast | Multilingual, thinking/reasoning mode |
38+
| `phi3:mini` | 2.2 GB | Fast | Reasoning, structured output |
39+
| `gemma3:1b` | 815 MB | Fastest | Latency-critical, embedded use |
40+
41+
Aliases work too: `"best"` → gemma3:12b, `"nano"` → gemma3:1b, `"qwen"` → qwen3:8b
42+
43+
---
44+
45+
## IMPORTANT — Fix before first use (non-ASCII username path bug)
46+
47+
The `ä` in your Windows username `KimHarjamäki` causes llama.cpp to fail loading
48+
any model. Fix it once with these four commands (run PowerShell **as Administrator**):
49+
50+
```powershell
51+
# 1. Junction: ASCII alias for the existing model folder (no data copied)
52+
New-Item -ItemType Junction -Path "C:\ollama-models" -Target "C:\Users\KimHarjamäki\.ollama\models"
53+
54+
# 2. Persist the path for your user account
55+
[System.Environment]::SetEnvironmentVariable("OLLAMA_MODELS", "C:\ollama-models", "User")
56+
57+
# 3. Stop Ollama
58+
Stop-Process -Name "ollama" -Force -ErrorAction SilentlyContinue
59+
60+
# 4. Restart Ollama tray app
61+
Start-Process "$env:LOCALAPPDATA\Programs\Ollama\ollama app.exe"
62+
```
63+
64+
---
65+
66+
## Chrome Built-in Gemini Nano (optional — requires Chrome Dev/Canary)
67+
68+
This lets you run actual Gemini Nano inside Chrome. Different from the Ollama models above.
69+
70+
1. Install Chrome Dev: https://www.google.com/chrome/dev/
71+
2. Enable flags in Chrome:
72+
- `chrome://flags/#optimization-guide-on-device-model`**Enabled BypassPerfRequirement**
73+
- `chrome://flags/#prompt-api-for-gemini-nano`**Enabled**
74+
3. Restart Chrome, go to `chrome://components/`, update **Optimization Guide On Device Model**
75+
4. Open `chrome-demo/index.html` in Chrome — banner turns green when ready
76+
77+
Chrome bridge API (port 8081) — exposes window.ai as HTTP:
78+
```powershell
79+
cd C:\PersonalRepo\gemini-nano\chrome-bridge
80+
.\start.ps1
81+
# Then POST to http://localhost:8081/v1/chat/completions with model "gemini-nano"
82+
```
83+
84+
---
85+
86+
## Folder structure
87+
88+
```
89+
gemini-nano/
90+
SETUP.md <- you are here
91+
api-server/
92+
server.py <- FastAPI server (port 9000)
93+
start.ps1 <- run this
94+
test_api.py <- smoke test all models
95+
requirements.txt
96+
chrome-bridge/
97+
server.js <- Chrome Gemini Nano HTTP bridge (port 8081)
98+
start.ps1
99+
package.json
100+
chrome-demo/
101+
index.html <- browser demo for Chrome built-in AI
102+
python-mediapipe/
103+
run_nano.py <- MediaPipe fallback (for when Google releases desktop weights)
104+
requirements.txt
105+
```

api-server/requirements.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fastapi>=0.115.0
2+
uvicorn[standard]>=0.32.0
3+
httpx>=0.27.0
4+
pydantic>=2.0.0

0 commit comments

Comments
 (0)