-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathstart.sh
More file actions
executable file
·119 lines (112 loc) · 5.8 KB
/
Copy pathstart.sh
File metadata and controls
executable file
·119 lines (112 loc) · 5.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env bash
#
# Start the Jupyter AI (v3) environment.
#
# Chat is served by the Jupyternaut agent; pick the model in Jupyternaut
# Settings and @-mention @Jupyternaut in a chat.
#
# Backend: Ollama (local, default) or OpenRouter (hosted). Ollama is required
# unless OPENROUTER_API_KEY is set, in which case a missing Ollama server is a
# warning rather than an error (so you can run OpenRouter-only).
#
# Steps performed:
# 1. Check the Ollama server (fatal unless OPENROUTER_API_KEY is set).
# 2. Activate the local virtualenv (creating/installing it if missing).
# 3. Launch JupyterLab with the Jupyter AI chat enabled.
#
set -euo pipefail
cd "$(dirname "$0")"
OLLAMA_HOST_URL="${OLLAMA_HOST:-http://127.0.0.1:11434}"
# Ollama's OLLAMA_HOST convention allows a bare host:port (no scheme).
case "$OLLAMA_HOST_URL" in
*://*) ;;
*) OLLAMA_HOST_URL="http://${OLLAMA_HOST_URL}" ;;
esac
# 1. Is Ollama running?
if curl -sf "${OLLAMA_HOST_URL}/api/tags" >/dev/null 2>&1; then
OLLAMA_UP=1
else
OLLAMA_UP=0
if [ -n "${OPENROUTER_API_KEY:-}" ]; then
echo "WARNING: Ollama not reachable at ${OLLAMA_HOST_URL}, but OPENROUTER_API_KEY is set."
echo " Continuing for OpenRouter use (local Ollama models will be unavailable)."
else
echo "ERROR: Ollama server not reachable at ${OLLAMA_HOST_URL}"
echo "Start it with 'ollama serve', or set OPENROUTER_API_KEY to use OpenRouter instead."
exit 1
fi
fi
# 2. Ensure the virtualenv exists and its dependencies are in sync.
if [ ! -d .venv ]; then
echo "Creating virtualenv (first run)..."
python3 -m venv .venv
.venv/bin/python -m pip install --upgrade pip
fi
# (Re)install deps whenever requirements.txt is newer than the last install.
# Installing only on venv creation would mean dependencies ADDED to
# requirements.txt later silently never land in an existing .venv. The stamp
# makes start.sh idempotent and self-healing while staying fast on unchanged runs.
REQ_STAMP=.venv/.requirements-installed
if [ ! -f "$REQ_STAMP" ] || [ requirements.txt -nt "$REQ_STAMP" ]; then
echo "Installing/updating dependencies from requirements.txt..."
.venv/bin/python -m pip install -r requirements.txt
touch "$REQ_STAMP"
fi
# Pin the Jupyter kernelspec to THIS venv's interpreter (absolute path).
# ipykernel ships a default kernelspec whose argv[0] is the bare string "python"
# (PATH-relative). jupyter_client usually substitutes the server interpreter, but
# that behavior is version-dependent: on a machine where bare `python` resolves to
# another interpreter (e.g. /opt/anaconda3/bin/python), notebooks would silently
# run OUTSIDE this venv and miss its deps (pandas/numpy/matplotlib). Rewriting the
# spec via `ipykernel install` pins argv[0] to .venv/bin/python deterministically.
# Self-healing: re-pins whenever the spec is missing or not already absolute.
KERNEL_JSON=.venv/share/jupyter/kernels/python3/kernel.json
VENV_PY="${PWD}/.venv/bin/python"
if [ ! -f "$KERNEL_JSON" ] || ! grep -q "$VENV_PY" "$KERNEL_JSON"; then
echo "Pinning Jupyter kernelspec to the venv interpreter..."
.venv/bin/python -m ipykernel install --sys-prefix --name python3 \
--display-name "Python 3 (.venv)" >/dev/null 2>&1 \
|| { echo "ERROR: failed to pin the Jupyter kernelspec to the venv interpreter."; exit 1; }
fi
# Jupyter AI v3 ships no model agent by default; the Ollama/OpenRouter chat needs
# the optional Jupyternaut agent (the [jupyternaut] extra). Warn if it's missing.
if ! .venv/bin/python -c "import jupyter_ai_jupyternaut" >/dev/null 2>&1; then
echo "WARNING: the Jupyternaut agent isn't installed in .venv, so @Jupyternaut"
echo " won't appear in chats. Reinstall deps: .venv/bin/python -m pip install -r requirements.txt"
fi
# 3. Launch JupyterLab.
# DEFAULT_MODEL is the default *Ollama* model (only used for the message + check
# below). The model Jupyter AI actually loads comes from Jupyternaut Settings,
# saved in ~/.../jupyter_ai/config.json — OpenRouter models are selected there too.
# gemma4:12b is the repo default on every platform; Apple-Silicon `-mlx` builds
# are an advanced option (see docs/TEACHERS-GUIDE.md).
DEFAULT_MODEL="gemma4:12b"
if [ "$OLLAMA_UP" -eq 1 ]; then
echo "Ollama OK at ${OLLAMA_HOST_URL}. Default Ollama model for this repo: ${DEFAULT_MODEL}"
echo "Available models:"
ollama list || true
if ! ollama list 2>/dev/null | grep -q "${DEFAULT_MODEL}"; then
echo "NOTE: default model '${DEFAULT_MODEL}' not pulled yet. Run: ollama pull ${DEFAULT_MODEL}"
fi
# RAM sanity check: the default 12B model wants ~16 GB. On a smaller machine
# warn (don't block) and point to the lighter model from the Teacher's Guide.
# Any detection hiccup is silently skipped — this is advisory only.
if RAM_BYTES="$( { sysctl -n hw.memsize 2>/dev/null || awk '/^MemTotal:/ {print $2 * 1024; exit}' /proc/meminfo 2>/dev/null; } )" \
&& [ -n "$RAM_BYTES" ] && [ "$RAM_BYTES" -gt 0 ] 2>/dev/null; then
RAM_GIB=$(( RAM_BYTES / 1024 / 1024 / 1024 ))
# 15, not 16: Linux MemTotal under-reports nominal RAM (kernel-reserved
# memory), so a real 16 GB machine can compute 15 and would false-warn.
if [ "$RAM_GIB" -lt 15 ]; then
echo "NOTE: this machine has about ${RAM_GIB} GB RAM; the default '${DEFAULT_MODEL}' wants ~16 GB"
echo " and may be slow or stall. A lighter model that still works well:"
echo " ollama pull gemma4:e2b-it-qat (then pick ollama_chat/gemma4:e2b-it-qat in Settings)"
fi
fi
fi
echo
echo "Tip: open a chat from the launcher (Chat card) and @-mention @Jupyternaut,"
echo " or @-mention @Tutor for the built-in Python tutor persona."
echo " Pick the model in Settings -> Jupyternaut Settings (e.g. ollama_chat/${DEFAULT_MODEL})."
echo
# --config applies jupyter_ai_config.py (e.g. the ollama/gemma4:26b-mlx num_ctx cap).
exec .venv/bin/jupyter lab --config="${PWD}/jupyter_ai_config.py" "$@"