1
0
Fork 0
forked from lthn/LEM
LEM/CLAUDE.md
Snider f75458bce6 refactor: apply go fix modernizers for Go 1.26
Automated fixes: interface{} → any, range-over-int, t.Context(),
wg.Go(), strings.SplitSeq, strings.Builder, slices.Contains,
maps helpers, min/max builtins.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-22 21:00:17 +00:00

211 lines
10 KiB
Markdown

# CLAUDE.md
## Project Overview
LEM (Lethean Ethics Model) — training protocol and tooling for ethical alignment of language models via layered curriculum training.
LEM is the first external consumer of the **Core Go Framework** (`forge.lthn.ai/core/*`). The framework provides Metal inference, grammar scoring, CLI/TUI, lifecycle management, and cross-platform backends. LEM brings the protocol — curriculum, sandwich format, training philosophy — and imports the framework for everything else.
## Architecture
### Framework Dependency
```
lthn/LEM (binary — this repo)
├── core/go Framework: DI, lifecycle, CLI/TUI, config, process, storage, logging
├── core/go-ml Scoring engine, backends, Metal memory management
├── core/go-inference Shared TextModel/Backend/Token interfaces (platform-agnostic)
├── core/go-mlx Native Metal GPU inference (darwin/arm64, SetMemoryLimit/SetCacheLimit)
├── core/go-i18n Grammar v3 scoring engine (reversal)
└── core/go-api REST framework (future: LEM Lab API)
```
LEM's own binary, own repo, own identity — but 90% of the logic is supported by the Core Go Framework. The framework was prepared specifically for this phase (14-22 Feb 2026).
**Cross-platform**: `go-inference` provides shared interfaces that work with both `go-mlx` (Apple Metal, macOS) and `go-rocm` (AMD ROCm, Linux homelab). LEM runs wherever the framework runs.
**Wiki documentation**: All core repos have wikis at `forge.lthn.ai/core/{repo}.wiki.git` (e.g. `core/go.wiki.git`).
### Core Go Package Map (`forge.lthn.ai/core/go`)
| Package | Purpose | LEM Use |
|---------|---------|---------|
| `pkg/framework/core` | DI container, service lifecycle, message bus | Service orchestration |
| `pkg/cli` | CLI framework, command routing, TUI | Commands, Viewport, Spinner, ProgressBar |
| `pkg/lab` | LEM Lab monitoring dashboard (collectors, SSE, web UI) | Training progress, benchmarks, golden set stats |
| `pkg/process` | Process execution with streaming output | Training subprocess management |
| `pkg/config` | Configuration management | `.core/ai/` config hierarchy |
| `pkg/log` | Structured logging service | Training logs |
| `pkg/io` | Abstract storage (local, S3, SFTP, WebDAV) | Model/adapter storage |
| `pkg/workspace` | Encrypted workspace storage | Secure model data |
| `pkg/cache` | Caching utilities | Inference caching |
| `pkg/store` | Key-value storage | Training state persistence |
| `pkg/manifest` | Package manifest signing and verification | Model provenance |
| `pkg/plugin` | Plugin installation, loading, versioning | Future: training plugins |
| `pkg/ws` | WebSocket hub for real-time streaming | Future: LEM Lab live UI |
| `pkg/webview` | Chrome DevTools Protocol client | Future: LEM Lab browser UI |
| `pkg/help` | Help/documentation search | CLI help system |
| `pkg/ratelimit` | Rate limiting | API rate control |
| `pkg/repos` | Git repository registry | Multi-repo management |
| `pkg/marketplace` | Plugin/service marketplace | Future: model marketplace |
| `pkg/session` | Session management | Training sessions |
| `pkg/coredeno` | Deno runtime sidecar integration | Future: scripting |
### Planned: core/go-lem
`pkg/lab` (currently in `core/go`) will be extracted to a new `core/go-lem` package. This becomes the LEM protocol layer:
- Lab dashboard (collectors, SSE, web UI)
- Distill logic (bare probes, sandwich output, grammar gate, best-of-N)
- Training types and curriculum definitions
- LEM-specific config (`.core/ai/` hierarchy)
```
lthn/LEM (thin binary — wires everything together)
├── core/go-lem LEM protocol layer (distill, lab, curriculum)
├── core/go-ml Scoring engine, Backend interface
├── core/go-mlx Metal GPU
├── core/go-i18n Grammar v3
└── core/go Framework (CLI/TUI, lifecycle)
```
### Distill Migration: go-inference → go-ml Backend
LEM's `distill.go` currently imports `go-inference` directly with no Metal memory management. This causes unbounded memory growth. The fix is to migrate to `go-ml`'s `Backend` interface, which wraps `go-inference` with memory controls.
**Current** (distill.go — broken memory):
```go
model, err := inference.LoadModel(modelCfg.Paths.Base) // no memory limits
for token := range model.Chat(ctx, messages, opts...) { ... } // raw iter.Seq
```
**Target** (following `core ml ab` pattern):
```go
mlx.SetCacheLimit(cacheGB * 1024 * 1024 * 1024) // e.g. 8GB
mlx.SetMemoryLimit(memGB * 1024 * 1024 * 1024) // e.g. 16GB
backend, err := ml.NewMLXBackend(modelPath) // wraps go-inference
resp, err := backend.Chat(ctx, messages, ml.GenOpts{ // managed inference
Temperature: 0.4,
MaxTokens: 1024,
})
runtime.GC() // between probes
```
`ml.NewMLXBackend()``inference.LoadModel()``InferenceAdapter` (satisfies `ml.Backend` + `ml.StreamingBackend`). Same model, same Metal inference, but with memory limits and GC discipline.
### core ml train (go-ml, blocked)
`cmd_train.go` exists in go-ml but is `//go:build ignore` — blocked on go-mlx exporting the concrete model type needed for training (`ApplyLoRA`, `Forward`, `NewCache`, `Tokenizer`). The full loop is written: LoRA, AdamW, VJP, masked cross-entropy loss, Gemma + Qwen3 chat templates. When go-mlx exports the training API, `core ml train` becomes the training backend.
### Kernel A/B Testing
The `.txt` kernel was a quick glob/cat of the kernel directory — not scientifically selected. Kernel format must be A/B tested properly.
**Kernel variants** (in `Axioms-of-Conscious-Systems/kernel/`):
- `axioms.json` — Canonical (identical to `lek-1-kernel.json`). 5 axioms with id, name, statement, function, resolution.
- `terms.json` — Expands on axioms.json. Precision definitions (consciousness, prime-imperative, reality-anchoring, etc.). Same domain, deeper grind.
- `claude-native.json` — Claude's compact interpretation. Core[] array, operational map (fn/when/weight), fast paths (harm→1,3,5; autonomy→4,5; self-doubt→2).
- `claude.json` — Agent-specific operational layer extending axioms.json.
**Test with `core ml ab`** on base (untrained) models:
```bash
core ml ab --model-path /Volumes/Data/lem/gemma-3-1b-it-base \
--kernel axioms=data/kernels/lek-1-kernel.json \
--kernel claude-native=/path/to/claude-native.json \
--kernel terms=/path/to/terms.json \
--cache-limit 8 --mem-limit 16
```
Baseline (no kernel) + each kernel condition → heuristic scores → comparison table with delta per probe. True science, not hunches.
### Lineage
`core ml sandwich` pioneered the sandwich generation pattern. `lem distill` borrowed it and added grammar v3 scoring, quality gate, and best-of-N selection. The core framework then matured with proper Metal memory management (`mlx.SetMemoryLimit`, `mlx.SetCacheLimit`), TUI utilities, and lifecycle support. Now LEM imports the full framework stack.
## Build & Run
```bash
go build -o lem . # Build the lem binary
go install . # Install to $GOPATH/bin
```
## Key Commands
```bash
lem distill --model gemma3/1b --probes eval # Distill probes through LEM model (bare probes, sandwich output)
lem score --input responses.jsonl # Score with grammar v3
lem probe --model gemma3-4b-it # Generate + score probes
lem compare --old old.json --new new.json # Compare score files
lem export # Export golden set to training JSONL
```
## Configuration
- `.core/ai/ai.yaml` — Global AI config (backend, scorer, generation defaults, distill settings)
- `.core/ai/models/gemma3/{size}.yaml` — Per-model config (paths, kernel, lessons, baselines)
- `.core/ai/probes.yaml` — Probe sets mapped to curriculum phases
## Training Curriculum
| Phase | Probe Set | Format | Description |
|-------|-----------|--------|-------------|
| 0 | `core` | Sandwich | 101 core probes — LEK axiom absorption |
| 1 | `zen` | No LEK | Allen/Watts/composure — philosophical substrate |
| 2 | `eval` | Sandwich | 200 expanded probes — deeper alignment |
| 3 | `ethics` | Freeflow | 260 adversarial/cultural/sovereignty probes |
| 4 | `tension` | Freeflow | Geopolitical multi-perspective scenarios |
| 5 | `creative` | Freeflow | Voice and style probes |
### Sandwich Format
```
[LEK-1 kernel JSON]
[Probe prompt]
[LEK-1-Sig quote]
```
Single user message. No system role. Kernel is `data/kernels/lek-1-kernel.json`. Sig is `data/kernels/lek-1-sig.txt`.
### LEM Models as Distillation Engines
LEM models (e.g. LEM-Gemma3-1B) have axioms in their weights. When distilling:
- **Do NOT** send the kernel in the inference prompt — the model already has it
- Model sees bare probes only. Output JSONL gets sandwich wrapping (kernel + probe + sig as user message).
- The 1B serves as the lab distillation engine (700MB, runs alongside larger models)
### Scoring
- **Grammar v3** (`go-i18n/reversal`) — Primary metric. Composite of tense entropy, vocab richness, question ratio, verb/noun diversity
- **Delta mode** — Uplift, echo, enrichment, sycophancy between prompt and response
- **Quality gate** — `min_score` in `ai.yaml` (default 40.0), responses below are rejected
### Data Layout
```
data/
kernels/ lek-1-kernel.json, lek-1-sig.txt
models/gemma3/ Symlinks to /Volumes/Data/lem/
training/
lem/
ethics/ Core (101), rephrased (404), adversarial, cultural, naive, sovereignty
zen/ Golden lessons, seeds, config
eval/ test-200.json (P2 candidates)
model/gemma3/ Training configs + assembled JSONL per model size
pkg/lem/ Go code (distill, scoring, config, export)
```
## Rules
Read `RULES.md` for the full protocol. Key points:
- No Python in production — Go tooling only
- Once fused, it stays — verify before merging adapters
- LEK must never appear in production chat data
- JSON kernel for models (`lek-1-kernel.json` is canonical, `.txt` removed)
- Distill and Teach are different operations — never confuse them
## Coding Standards
- Go 1.25+, standard library where possible
- UK English in comments and docs
- Licence: EUPL-1.2