Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- name: gofmt
run: test -z "$(gofmt -l cmd internal)" || (gofmt -l cmd internal; exit 1)
- name: vet
run: go vet ./...
run: go vet ./... && CGO_ENABLED=1 go vet -tags onnx ./...
- name: install GNU Go (arena integration test)
run: sudo apt-get install -y gnugo
- name: test
Expand All @@ -24,6 +24,12 @@ jobs:
run: go test -race -short -count=1 ./...
- name: pure-Go build
run: CGO_ENABLED=0 go build -o bin/gofer ./cmd/gofer
- name: WebAssembly engine (web/engine/gofer.wasm)
run: GOOS=js GOARCH=wasm go vet ./cmd/gofer-wasm && GOOS=js GOARCH=wasm go build -o /tmp/gofer.wasm ./cmd/gofer-wasm
- name: site scripts and data
run: |
node --check web/site.js && node --check web/engine.js
for f in web/data/*.json; do node -e "JSON.parse(require('fs').readFileSync('$f', 'utf8'))" || exit 1; done

python:
runs-on: ubuntu-latest
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@ A rewrite of the engine core and the training pipeline. See
- Evaluation: arena with paired openings, GNU Go (or any GTP engine) as anchors with dead-stone
adjudication, Wilson intervals, Elo, SPRT, and a Bradley-Terry ladder across generations

### Web

- Redesigned landing page: hand-written CSS and self-hosted fonts (no CSS build step, no runtime CDN
for styles), canvas boards, inline SVG charts, new icons and social image
- Play the real engine in the browser: `cmd/gofer-wasm` compiles rules and search to WebAssembly and
evaluates the network with onnxruntime-web, loaded on demand. The search yields to the browser
every 16 visits, so the page stays responsive while Gofer thinks; a new game or undo cancels a
running search
- The hero replays a real win over GNU Go level 10 with Gofer's own analysis of every position
- "Watch it learn": all 18 generations with one self-play game each, the raw opening policy, and the
Elo ladder against GNU Go, generated from the training run by `cmd/sitedata` (`make site-data`)
- Players pass once the opponent has passed and passing wins on the count, instead of filling their
own territory

### Removed

- HTTP inference sidecar, heuristic evaluator, JSONL samples, SGF-to-JSONL converter, Lightsail/AWS
Expand Down
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ PYTHON ?= .venv/bin/python
MODEL ?= models/gofer-9x9.onnx
RUN ?= runs/9x9

.PHONY: build build-nocgo test test-go test-py race lint bench gtp play train ort
.PHONY: build build-nocgo test test-go test-py race lint bench gtp play train ort site site-data

# Engine with ONNX Runtime (needs CGO and scripts/install-ort.sh).
build:
Expand Down Expand Up @@ -43,3 +43,11 @@ train: build

ort:
scripts/install-ort.sh

# Static site in web/: the engine as WebAssembly plus the released network (outputs are committed).
site:
scripts/build-site.sh

# The page's data (hero analysis, per-generation openings, games, Elo) from a training run.
site-data:
CGO_ENABLED=1 go run -tags onnx ./cmd/sitedata -run $(RUN)
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ In Sabaki: *Engines → Manage engines → Add*, path `bin/gofer`, arguments
`gtp -model models/gofer-9x9.onnx`. Live analysis (`lz-analyze`) works out of
the box.

## Play it in the browser

The landing page in [`web/`](web/) runs the same engine compiled to
WebAssembly, with the network evaluated by onnxruntime-web: play Gofer,
watch its analysis of a win over GNU Go, and scrub through all 18
generations of the training run. The page is plain HTML, CSS and JavaScript;
`make site` rebuilds the engine (`GOOS=js GOARCH=wasm`) and copies the model,
and `make site-data RUN=runs/9x9` regenerates `web/data/` from a training run
(`cmd/sitedata`). Outputs are committed, so any static host can serve `web/`;
preview with `python3 -m http.server -d web 8000`.

## Train your own

```bash
Expand Down Expand Up @@ -79,6 +90,8 @@ bin/gofer arena -a nn:models/gofer-9x9.onnx,visits=400 -b gnugo,level=10 -games
| `internal/nn` | features, batched evaluator, ONNX Runtime backend |
| `internal/selfplay`, `internal/arena`, `internal/gtp`, `internal/sgf` | applications |
| `cmd/gofer` | CLI |
| `cmd/gofer-wasm`, `web/` | the engine in WebAssembly and the landing page |
| `cmd/sitedata` | builds the landing page's data from a training run |
| `training/` | model, data, trainer, export, loop, Elo, report (+ tests) |
| `docs/` | [architecture](docs/architecture.md), [training](docs/training.md), [v2 audit](docs/v2-audit.md) |

Expand Down
8 changes: 8 additions & 0 deletions cmd/gofer-wasm/bits.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//go:build js && wasm

package main

import "math"

func mathFloat32bits(f float32) uint32 { return math.Float32bits(f) }
func mathFloat32frombits(u uint32) float32 { return math.Float32frombits(u) }
Loading
Loading