Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
128 lines (110 loc) · 5.66 KB
/
Copy pathMakefile
File metadata and controls
128 lines (110 loc) · 5.66 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
120
121
122
123
124
125
126
127
128
# Workbench on a local workstation. `make` alone runs `make workbench`.
#
# make workbench the workstation up, then Workbench on it
# make workbench DATA=./bench another data directory
# make workstation the workstation and the object store up, and the USB devices attached
# make usb attach the USB devices of this Mac to OrbStack's Linux
# make usb-detach give them back to macOS
# make stop stop the workstation; the volumes keep every file
# make logs follow the logs of sshd and the object store
# make shell a root shell in the workstation
# make ssh ACCOUNT=researcher a shell as one account, over ssh
# make test-workstation the workspace tier on the workstation, no model
# make reset remove the workstation and its volumes, after a prompt
# make voice whisper.cpp, Kokoros, and their models for /voice, once
# make pedal program a USB foot pedal to send F13, the hold-to-talk key
#
# workstation/README.md describes the workstation.
COMPOSE := docker compose -f workstation/compose.yaml
STATE := .workstation
CONFIG := $(STATE)/workstation.json
DATA ?= .data
ACCOUNT ?= researcher
WHISPER_MODEL := $(HOME)/.cache/whisper/ggml-large-v3.bin
WHISPER_URL := https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3.bin
KOKORO_DIR := $(HOME)/.cache/kokoro
KOKORO_MODEL := $(KOKORO_DIR)/kokoro-v1.0.onnx
KOKORO_VOICES := $(KOKORO_DIR)/voices-v1.0.bin
KOKORO_URL := https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files-v1.0
KOKORO_BIN := $(KOKORO_DIR)/bin/koko
KOKOROS_REV := dda39518d210ba48a63782e524eaee435eab17a7
.DEFAULT_GOAL := workbench
.PHONY: workbench workstation usb usb-detach stop logs shell ssh test-workstation reset voice pedal
# The dependencies, again when the manifest or the lockfile changes.
node_modules/.modules.yaml: package.json pnpm-lock.yaml
pnpm install --frozen-lockfile
@touch $@
# The keys and workstation.json, again when the account list changes.
# setup.sh keeps each key that exists.
$(CONFIG): workstation/setup.sh workstation/accounts
bash workstation/setup.sh $(STATE)
@touch $@
## The workstation up: build the image when a file of it changed, start the
## workstation and the object store, and wait until sshd and the store are
## healthy. The init job then makes the bucket and its user. Last, attach the
## USB devices, and the container makes their device files within 5 seconds.
workstation: $(CONFIG)
$(COMPOSE) up -d --build --wait workstation objects
$(COMPOSE) run --rm objects-init
@python3 workstation/usb.py attach
## Each USB device of this Mac goes to OrbStack's Linux, except keyboards,
## mice, a hub's billboard, and each device of workstation/usb-ignore. On a
## machine without OrbStack, the devices are native, and nothing happens.
usb:
@python3 workstation/usb.py attach
usb-detach:
@python3 workstation/usb.py detach
## Workbench, with the bash and git backends on the workstation.
workbench: workstation node_modules/.modules.yaml
WORKBENCH_WORKSTATION=$(CONFIG) pnpm start $(DATA)
## What /voice needs. Speech to text: whisper-server from Homebrew, and the
## large-v3 model of about 3 GB. Spoken replies: koko from Kokoros, built with
## cargo at a fixed commit, and the two Kokoro model files of about 340 MB. The
## build keeps its target folder in $(KOKORO_DIR)/build, because koko reads the
## espeak-ng data from the folder of the build at run time. koko goes to
## $(KOKORO_BIN). A download goes to a part file first, so a stopped download
## leaves no file that looks complete.
voice: $(WHISPER_MODEL) $(KOKORO_MODEL) $(KOKORO_VOICES)
@command -v whisper-server >/dev/null || brew install whisper-cpp
@test -x $(KOKORO_BIN) || ((command -v cargo >/dev/null || brew install rust) && \
brew install pkg-config opus cmake && \
cargo install --locked --git https://github.com/lucasjinreal/Kokoros --rev $(KOKOROS_REV) \
--root $(KOKORO_DIR) --target-dir $(KOKORO_DIR)/build koko)
## What a foot pedal needs: footswitch from a Homebrew tap. Homebrew loads a
## formula from a tap only when the formula is trusted. footswitch programs a
## USB pedal to send F13, and F13 holds to talk in voice mode like Space. The
## pedal is a HID keyboard, so `make usb` leaves it with macOS. footswitch
## finds a pedal by its USB IDs, and it stops with a message when none is
## plugged in. The last command prints what the pedal sends.
pedal:
@command -v footswitch >/dev/null || { \
brew tap rgerganov/footswitch https://github.com/rgerganov/footswitch.git && \
brew trust --formula rgerganov/footswitch/footswitch && \
brew install --HEAD footswitch; }
footswitch -k f13
footswitch -r
$(WHISPER_MODEL):
mkdir -p $(dir $@)
curl -fL --retry 3 -C - -o $@.part $(WHISPER_URL)
mv $@.part $@
$(KOKORO_MODEL) $(KOKORO_VOICES):
mkdir -p $(dir $@)
curl -fL --retry 3 -C - -o $@.part $(KOKORO_URL)/$(notdir $@)
mv $@.part $@
stop:
$(COMPOSE) stop
logs:
$(COMPOSE) logs -f
shell:
$(COMPOSE) exec workstation bash
ssh: workstation
ssh -p 2222 -i $(STATE)/keys/$(ACCOUNT) -o IdentitiesOnly=yes \
-o UserKnownHostsFile=$(STATE)/known_hosts $(ACCOUNT)@127.0.0.1
test-workstation: workstation node_modules/.modules.yaml
WORKBENCH_WORKSTATION=$(CONFIG) pnpm exec vitest run test/workstation.test.ts test/usb-camera-workstation.test.ts
## The workstation and its volumes go: the homes, the repositories, /library,
## /shared, and the snapshots. The keys and the credentials in .workstation stay.
reset:
@printf 'Remove the workstation and its volumes? Type yes: '; \
read answer; [ "$$answer" = yes ] || { echo 'Nothing removed.'; exit 1; }
$(COMPOSE) down -v