north-translate/
north_translate/
__init__.py
_mcp_batch.py
config.py
corpus.py
inject.py
lw.py
metrics.py
prompts.py
providers.py
quality.py
report.py
run_bench.py
terminology.py
plans/
compare_de.yaml
results/
outputs/
bench.duckdb
compare_de.duckdb
report.md
report_compare_de.md
PROJECT.yaml
pyproject.toml
README.md
Übersetzungs-Benchmark CohereLabs/North-Small-Translate-1.0 gegen gemini-3.8-flash auf echten PDAI-Seiten — identische Instruktion, plus eine LWgrammar-Terminologie-Injektion (Dosen T0–T3) für Keplers geometrisches und astronomisches Vokabular, mit vollständigen Qualitäts-, Terminologie-, Laufzeit- und Speichermetriken.
Der Agent ist im Orchestrator registriert:
../ai-agent-orchestrator/agent-store/north_translate_agent/ (Runtime north:<model>).
North-Small-Translate-1.0 ist ein sparse Mixture-of-Experts: 25B aktive
Parameter, 218B totale, 128 Experten (8 aktiv), 16K In-/Out-Kontext,
Übersetzung über 50 Sprachen. Empfohlen ist greedy decoding. Antworten sind
in Marker gehüllt (<|START_TEXT|> … <|END_TEXT|>); zum Parsen dient Coheres
cohere_melody (Regex-Fallback eingebaut).
| Quantisierung | Minimum |
|---|---|
| BF16 | 4×B200 / 8×H100 |
| FP8 | 2×B200 / 4×H100 |
| NVFP4 W4A16 | 1×B200 / 2×H100 |
⚠️ zwei harte Blocker in dieser Umgebung
- Kein CUDA. Mac Studio (M1 Ultra, 128 GB); alle erreichbaren Hosts sind Macs ohne NVIDIA-GPU. Ein 218B-MoE ist hier nicht lauffähig.
- Gated Modell.
hf_hub_download(..., "config.json")→ 403, bis die Cohere-Labs-Lizenz für den HF-Token akzeptiert ist.Der North-Pfad ist vollständig verdrahtet, meldet ohne Endpunkt aber sauber
unavailable— es werden keine Ergebnisse erfunden.Ein MLX-Weg wird in
~/ai-mac-studio/development/north-mlx/vorbereitet (Architektur-Portcohere2_moe, numerisch verifiziert; Konvertierung selbst braucht ≥ 512 GB RAM und die HF-Lizenz). Nach der Konvertierung liefertmlx_lm.servereinen OpenAI-kompatiblen Endpunkt —NORTH_BASE_URLgenügt.
north-translate/
north_translate/
config.py Pfade, Collections, Endpunkte, LW-Dosen, Kepler-Kernterme
corpus.py PDAI-Seiten + Referenzen; auch „terms-rich"-Auswahl
prompts.py kanonische Instruktion translation/scholarly.j2 (v2)
lw.py LWgrammar-MCP-Bridge (lw_term / lw_usage_rules / lw_situate)
_mcp_batch.py ein MCP-Session für viele Tool-Calls (läuft in der Lemma-Venv)
terminology.py Kepler-Register: Erkennung, Injektionstext, Term-Metriken
inject.py baut die Instruktion je LW-Dosis (T0–T3)
providers.py north (vLLM/OpenAI) · gemini · ollama — jeweils streamend
metrics.py TTFT/Latenz/Tok-s + RSS-/System-/Server-Speicher
quality.py XML/Struktur/Dollar/Zahlen/chrF + Preamble-Metrik
run_bench.py resumierbarer Matrix-Runner (Seite × Engine × Dosis)
report.py results/report.md aus bench.duckdb
results/{bench.duckdb, report.md, outputs/…}
Corpus (read-only, in place): /Volumes/PDAI-1/pdai-collections —
enestroem · kepler-prim · karman-nachlass.
Interpreter: die Orchestrator-Venv hat alle Abhängigkeiten
(…/ai-agent-orchestrator/.venv/bin/python). Die LWgrammar-MCP-Calls laufen über
die Lemma-Venv (…/pdai/index/ai-lemma-index/.venv/bin/python, hat mcp+anyio).
cd ~/ai-mac-studio/development/north-translate
# Terminologie-Experiment: terminologisch reiche Kepler-Seiten, 4 Dosen
python -m north_translate.run_bench \
--collections kepler-prim --engines gemini \
--doses T0 T1 T2 T3 --terms-rich 8 --workers 5
python -m north_translate.report
# nur Baseline/Referenz über die drei Collections:
python -m north_translate.run_bench --engines gemini --max-pages 2 --limit 3
# North (sobald GPU-Host steht):
export NORTH_BASE_URL=http://GPU-HOST:8000/v1
python -m north_translate.run_bench --engines north gemini --doses T0 T2 --workers 8
Flags: --doses, --terms-rich K (K terminreichste Seiten je Collection),
--collections, --docs collection=doc1,doc2, --max-pages, --limit,
--workers, --parallel-engines, --no-mcp, --force, --dry-run.
| Familie | Metrik | Bedeutung |
|---|---|---|
| Struktur | xml_valid |
strikt: die Ausgabe selbst parst als XML |
preamble_chars |
Zeichen vor dem ersten < (Terminologie-/Kommentar-Vorspann) |
|
structure_agreement |
Tag-Sequenz vs. Quelle | |
| Mathematik | dollar_fidelity |
jedes $…$/$$…$$ byte-identisch & in Reihenfolge |
latex_fidelity |
\frac, \alpha, … erhalten |
|
| Inhalt | number_preservation |
Zahlen/Jahre/Seitenrefs erhalten |
length_ratio |
Länge Ausgabe/Quelle | |
| Referenz | chrf_ref, word_jaccard_ref |
gegen vorhandene PDAI-Referenz |
| Terminologie | term_recall |
erkannter Kepler-Term korrekt wiedergegeben (EN oder Latein) |
term_en_recall |
nur englische Entsprechung (strenger) | |
term_missing, term_wrong |
nicht wiedergegeben / bekannte Fehlsinne | |
composite |
Mittel aus XML/Struktur/Math/Zahlen (+chrF) |
Zeit/Speicher: latency_sec, ttft_sec,
decode_tok_s = completion_tokens/(latency−TTFT), prompt_tokens /
completion_tokens (Provider-Usage, nie geschätzt), cost_usd,
peak_rss_mb/delta_rss_mb (Client), system_used_delta_mb, und — wenn
erreichbar — server_rss_mb / server_gpu_cache_pct aus vLLMs Prometheus.
Grundlage ist das kuratierte Kepler-Register
LWgrammar/dictionary/kepler_technical_terms.json (129 Terme + 14 Phrasen,
geerntet aus kepler-prim / KGW) sowie die LWgrammar-MCP-Werkzeuge. Ein
kuratierter Kern (Kegelschnitte, Epizykel-/Orbitmodell, Himmelskoordinaten,
Optik, Harmonik, reguläre Körper, Physik) wird im lateinischen Quelltext erkannt;
die erkannteren Terme werden als Referenzblock vor die INPUT XML-Sektion
der Übersetzungsinstruktion gesetzt.
| Dosis | Injektion | Zweck |
|---|---|---|
| T0 | keine | Baseline |
| T1 | lw_usage_rules(tier=blocking) |
generelle Iron Rules (Kontrollbedingung) |
| T2 | lw_term je Term: Sinn + Verwendungsregel |
Terminologie-Präzision |
| T3 | T2 + lw_situate (7-Slot-Spezialinstruktion) |
„volle" Situierung |
Beispiel aus lw_term (author=kepler): umbilicus → „the navel of a circle is
its centre; umbilicus and focus are interchangeable in Kepler's conics";
aequatio → „a difference added or subtracted, not a modern algebraic
equation". Der Referenzblock trägt die Rahmung „reference material — do NOT copy
it into the answer".
MCP-Endpunkt http://127.0.0.1:5116/mcp; fällt der Server aus, wird --no-mcp
bzw. ein lokaler Glossar-Fallback genutzt (im Report als injection_source
sichtbar).
Seiten sind unabhängig; je Engine ein ThreadPoolExecutor:
| Engine | Pool | Grund |
|---|---|---|
north |
8 | vLLM continuous batching |
gemini |
4 | API-Rate-Limit |
ollama |
1 | ein lokales Modell, speichergebunden |
--workers N übersteuert; --parallel-engines fährt Engines gleichzeitig. Für
unverfälschte Client-Speicherwerte --workers 1; der Modellspeicher kommt
serverseitig aus vLLMs /metrics. LWgrammar-Lookups werden je Zelle in einer
MCP-Session gebündelt (nicht ein Call je Term).
Vollständig in results/report.md. term recall = Anteil erkannter Kepler-Terme
korrekt wiedergegeben.
| Dosis | term recall | Δ vs T0 | composite | Δ composite | XML valide | Preamble |
|---|---|---|---|---|---|---|
| T0 | 0.688 | — | 0.960 | — | 8/8 | 0 |
| T1 | 0.696 | +0.009 | 0.944 | −0.016 | 7/8 | 64 |
| T2 | 0.725 | +0.037 | 0.959 | −0.001 | 8/8 | 0 |
| T3 | 0.860 | +0.172 | 0.815 | −0.145 | 1/8 | 1 010 |
Befund:
- T2 (Termsinne) ist ein sicherer, kleiner Gewinn: +3,7 Punkte Term-Treue,
Composite und XML-Validität unverändert. Konkret korrigiert T2 gegenüber T0:
aequatio-centri (×2), proportio, anima-motrix, virtus, aequinoctium,
imago; Regression nur vis, statio (je ×1).
- T1 (generelle Regeln) hilft nicht und kann schaden (eine Seite ohne valides
XML).
- T3 (Situierung) ist für Übersetzung ungeeignet: der Recall-Gewinn (+17)
entsteht, weil das Modell seinen Terminologie-Vorspann wiedergibt; dadurch
bricht die XML-Validität (1/8), der Composite fällt um 0,145. Die Injektion ist
zu lang (≈17 k Zeichen) und stammt aus einem Paper-Schreibprofil.
Ehrliche Einordnung: die Stichprobe ist klein (8 Seiten); North fehlt (kein GPU-Host). Zahlen sind reproduzierbar aus
results/.
NORTH_BASE_URL setzen — dann
läuft die gleiche Dosen-Matrix auch für North.cohere_melody installieren (uv pip install cohere_melody>=0.9.0).lw_situate registrieren, damit T3
nicht auf ein Paper-Schreibprofil zurückgreifen muss.north-mlx)mlx-lm 0.31.3 unterstützt cohere2_moe nicht (nur das dense cohere2).
In ~/ai-mac-studio/development/north-mlx/ liegt daher:
models/cohere2_moe.py — MLX-Architektur als mlx_lm.models-Drop-in
(interleaved RoPE nur auf Sliding-Layern, Top-k→softmax/sigmoid-Router,
geteilte Experten, quantisierbare SwitchGLU-Experten). Numerisch verifiziert
gegen transformers (max |Δ| ≈ 1.1e-08 auf einem Mini-Modell; q4-Experten laufen).tools/convert_north.py — Preflight (Lizenz/RAM/Disk) + mlx_lm.convert.# Konvertierung — Streaming (kein Full-Model-RAM, auf 128 GB möglich):
python tools/convert_north.py --check --streaming # Preflight
python tools/convert_north.py --go --streaming # braucht nur die HF-Lizenz
# servieren (OpenAI-kompatibel, Stock mlx_lm.server):
python -m mlx_lm.server --model work/North-Small-Translate-1.0-4bit --port 8080
export NORTH_BASE_URL=http://127.0.0.1:8080/v1
export NORTH_MODEL_NAME=work/North-Small-Translate-1.0-4bit # served id (nicht HF-Repo!)
python -m north_translate.run_bench --engines north gemini --doses T0 T2
Verifiziert an Mini-/Medium-Modellen: Parität 1e-8, Streaming-q4 bit-identisch
zu In-Memory-q4 (Δ=0), 4.09 GiB bf16 → q4 bei 5.41 GiB Peak-RSS, Stock-Server
liefert HTTP 200. Offen ist nur die HF-Lizenz; Inferenz von q4 (≈101.6 GiB
Gewichte) auf 128 GB bleibt knapp (kurzer Kontext, iogpu.wired_limit_mb),
verlässlich ab 192 GB+ oder GPU-Host.