This release is a pre-release and may not be stable for production use.
OpenTernary
Open-source tooling for researching, calibrating, benchmarking, and eventually deploying ternary LLMs.
Documentation: elrdn.github.io/OpenTernary (English / 日本語): installation, a 5-minute offline tutorial, concepts, guides and the complete CLI reference.
OpenTernary is an experimental CLI-first project for exploring how existing open-weight language models can be converted toward ternary weights such as {-1, 0, +1} while retaining as much model quality as possible.
The project begins with Gemma 4 E2B as the first research target and focuses on building a reproducible quantization pipeline before attempting a GUI or large-model scaling.
Product planning: CLI Product Roadmap covers CLI reliability, backend integration, artifacts, export, and automation. Model-quality research remains tracked in Research Roadmap and the P0–P7 acceptance plan.
CLI implementation update (2026-09-23): Offline planning, backend/adapter services, atomic manifests, packed export, bounded search, JSON output, and plugin discovery are implemented. Validation now includes seeded synthetic Llama/Diffusers networks, real TorchAO, Windows/WSL installed wheels, RX 9070 XT FP32/BF16 execution, and pinned llama.cpp CPU generation. Pretrained-model quality, native low-bit kernel certification, and release acceptance remain pending. See the CLI guide and implementation/validation matrix.
Install
From PyPI (after the first release), as a command available everywhere:
uv tool install openternary --python 3.12
openternary setup # detect the GPU and install a matching PyTorch build
openternary doctor
Run openternary with no arguments in a terminal (or openternary ui) to open the full-screen interface: runs, live job progress, compare, doctor and update in one place. Jobs started there are the ordinary CLI in a child process, so their results, exit codes and JSON are the same as from scripts. Details: docs/CLI.md.
openternary update checks PyPI, upgrades, and reinstalls the PyTorch build that openternary setup recorded. On Windows it prints the commands to run from a new terminal, because a running openternary cannot replace itself.
Quickstart (core CLI)
推奨: uv で再現可能な環境を構築
git clone https://github.com/ELRdn/OpenTernary.git
cd OpenTernary
uv sync
uv run openternary --help
uv run --frozen openternary doctor --json
uv run --frozen openternary backends list --json
uv run --frozen openternary plan --json
開発時チェック:
uv run --frozen ruff check src tests
uv run --frozen ruff format --check src tests
uv run --frozen mypy src/openternary
Fallback (pip):
pip install -e .
openternary --help
openternary doctor --json
openternary をどこからでも使う(推奨)
uv sync だけではコマンドはリポジトリ内の .venv にしか入らないため、uv run openternary ... で呼ぶか、仮想環境を有効化する(Windows: .venv\Scripts\Activate.ps1、macOS/Linux: source .venv/bin/activate)。どのフォルダからでも openternary と打てるようにするには、リポジトリのフォルダで次を実行する。
uv tool install --editable . --python 3.12
uv tool update-shell
uv tool update-shell は初回だけ必要で、実行後にターミナルを開き直す。--python 3.12 を付けないと、uvはPCにある最新のPythonを選ぶことがある(CIで検証しているのは3.11と3.12)。このコマンドで入るのは本体だけなので、量子化・校正には uv run openternary ...(uv sync --extra ml --extra calibration 済みの .venv)を使うか、uv tool install --editable ".[ml,calibration]" --python 3.12 --reinstall で機械学習の依存ごと入れる。--editable なので git pull した変更はそのまま反映される。依存パッケージが増えた更新のあとは uv tool install --editable . --reinstall を実行する。Windowsはコマンド名の大文字小文字を区別しないため OpenTernary でも動く。
GPU用のPyTorchは openternary setup で入れられる。GPU(NVIDIA / AMD / Apple)を検出して合うビルドを提案し、確認のうえ openternary を動かしている環境に入れ、実際のデバイスで動作を確認する(openternary setup --list で候補の一覧、--dry-run で計画だけ表示)。詳細は CLI guide の「PyTorchの環境構築」。
--json を付けると、結果のJSON 1行だけがstdoutに出て、人間向けの表示はstderrに回る。ターミナルでは両方が見えるので2回出たように見えるが、> result.json のようにリダイレクトすると1行だけが保存される。
- Python 3.12 を推奨(
uv python pin 3.12で固定、requires-python >=3.11) uv.lock+.python-version+config.yaml+environment.jsonで再現性を担保
詳細は docs/ENVIRONMENT.md を参照。
The core install does not include PyTorch. Tensor conversion requires [ml]; optional integrations use [ml,torchao] or [ml,diffusion]. Keep hardware-specific environments separate. Run python scripts/validate_cli_offline.py in an existing development environment for the fixture-only checks; this script installs nothing and uses empty Hugging Face caches.
Why OpenTernary?
Current low-bit LLM tooling is powerful, but the path from:
open-weight model
↓
weight analysis
↓
ternary conversion
↓
calibration / reconstruction
↓
benchmark
↓
packed deployment
is still difficult to explore as a single, reproducible workflow.
OpenTernary aims to make that workflow inspectable and repeatable.
The first goal is not to immediately create the smallest possible model.
The first goal is:
Make a ternary Gemma 4 E2B that can be generated, loaded, benchmarked, and iterated on reproducibly.
Project Principles
-
CLI first, GUI later
- Research interfaces change quickly.
- Stabilize the quantization pipeline before building a desktop/web GUI.
-
Measure before optimizing
- Every conversion must be compared against a fixed baseline.
-
Quality per byte, not bit-count vanity
- Hybrid precision is allowed when it preserves substantially more capability.
-
Reproducibility
- Every experiment should record config, model revision, code commit, hardware, dataset split, and metrics.
-
Model adapters, not model-specific spaghetti
- Gemma 4 is the first target, not the only possible target.
-
Research claims require evidence
- Do not claim CAT-Q, ScaleQ, Bonsai, BitNet, or any paper/framework reproduction unless the implementation has actually been verified against its source.
Initial Scope
First target
- Gemma 4 E2B instruction model
- Text path first
- Transformer linear layers first
- Embeddings / PLE / LM head / multimodal components handled separately
First quantization target
Ternary weights:
{-1, 0, +1}
with group-wise scaling.
Initial development order
Inspect
↓
Baseline benchmark
↓
Naive ternary fake quant
↓
Compare
↓
Calibration / reconstruction
↓
Japanese-focused evaluation
↓
Packed export
↓
Scale to larger Gemma 4 variants
↓
GUI
CLI
Commands: ui (full-screen interface), inspect, plan, doctor, setup, update, backends list/info, quantize, calibrate, benchmark, quality, evaluate, compare, export, artifacts validate, optimize, plugins, cache list/remove, and the compatible cache-info entry point.
Model-free planning (no download, inference, or output directory):
openternary plan /path/to/local-snapshot --backend ternary --scheme absmean --json
openternary quantize /path/to/local-snapshot --scale-granularity per_group --group-size 128 --dry-run --json
openternary calibrate --config configs/gemma4-e2b-calibration.yaml --dry-run --json
The following is a future model-validation sequence, not evidence that a particular model works:
openternary quantize /path/to/local-snapshot --device cpu --output runs/cli-ternary
openternary export runs/cli-ternary --format ternary-packed --output runs/cli-packed
openternary export runs/cli-packed --format safetensors --output runs/cli-restored
openternary artifacts validate runs/cli-restored --json
openternary benchmark runs/cli-restored --suite smoke --output runs/cli-smoke
artifacts validate checks the manifest and file integrity; model reload and quality are separate checks. Packed artifacts require unpacking for inference. GGUF uses an explicitly selected local llama.cpp converter, currently restricted to Llama/Mistral/Qwen2 metadata and floating-point output. Synthetic Llama FP32 has passed pinned llama.cpp CPU validation; other architectures and precisions remain unverified. Full options, JSON/exit-code contracts, and migration notes are in docs/CLI.md.
Research Stages
Stage A — Naive PTQ
Purpose: prove the pipeline.
- Load model
- Find quantizable tensors
- Group weights
- Compute scale
- Map weights to ternary values
- Dequantize for fake-quant inference
- Run benchmark
- Save experiment metadata
Performance may be poor. That is acceptable.
Stage B — Calibration / Reconstruction
Purpose: preserve the original model's internal behavior.
Potential research directions include:
- learnable scale
- learnable threshold
- softened ternarization
- layer/window reconstruction
- teacher/student activation matching
- sensitivity-aware mixed precision
These methods must be implemented and validated incrementally.
Stage C — Deployment
Purpose: turn research weights into something useful.
- packed ternary representation
- runtime integration
- GGUF or other practical export
- RAM / VRAM / throughput measurement
Repository Structure
OpenTernary/
├─ src/openternary/
│ ├─ cli/
│ ├─ config/
│ ├─ services/
│ ├─ backends/
│ ├─ experiment/
│ ├─ utils/
│ ├─ adapters/
│ ├─ quant/
│ ├─ calibration/
│ ├─ benchmark/
│ └─ export/
├─ configs/
├─ docs/
├─ tests/
├─ pyproject.toml
├─ uv.lock
├─ .python-version
├─ README.md
├─ ROADMAP.md
├─ PROJECT_SPEC.md
├─ ARCHITECTURE.md
├─ RESEARCH_PLAN.md
├─ BENCHMARKS.md
├─ AGENTS.md
├─ EXPERIMENT_LOG.md
└─ CONTRIBUTING.md
AI Development Workflow
OpenTernary is initially developed with:
- DSH — lead development/research agent
- Codex — implementation/review sub-agent
The exact division of responsibilities is defined in AGENTS.md.
High-level rule:
DSH
Plan / Research / Integrate
↓
Codex
Focused implementation / tests / review
↓
DSH
Merge / benchmark / next experiment
No agent should silently modify the experimental target, benchmark protocol, or model scope.
Definition of the First MVP
The first MVP is complete when all of the following work:
- Gemma 4 E2B can be inspected
- Quantizable tensors are listed correctly
- Baseline inference works
- Baseline benchmark can be reproduced
- Naive group-wise ternary fake quantization works
- Quantized model can run inference without NaN/crash
- Baseline vs ternary metrics can be compared
- Run configuration is saved automatically
- At least one Japanese evaluation set is held out from calibration
- Tests cover core ternary math and tensor mapping
The MVP does not require:
- competitive quality
- Bonsai-level results
- complete CAT-Q reproduction
- GGUF export
- GUI
- MoE support
Long-Term Vision
OpenTernary should eventually become a model-agnostic research and conversion toolkit:
Gemma
Qwen
Llama
DeepSeek-style models
Other open-weight LLMs
↓
OpenTernary
↓
Inspect
Quantize
Calibrate
Benchmark
Export
A later GUI can make these workflows accessible without hiding the underlying experiment configuration.
Status
The CLI product status is recorded separately in CLI_IMPLEMENTATION_STATUS.md. The research milestones below are historical evidence; the new CLI integrations have not yet been tested with real models.
Phase 3 — Model-Level Ternarization (bounded sharded fake-quant): CLOSED (2026-08-21)
- Phase 0 (Foundation) ✅, Phase 1a (Inspection) ✅, Phase 1b (BF16 Baseline v1) ✅, Phase 2 (AbsMean + 2bit-v1) ✅, Phase 3 (LD-RW per_group + bounded sharded fake-quant) ✅
- Per-tensor
scale=mean(abs(W))and per-group LD-RWlast-dim-rowwise-v1vectorized, zero-branch,G>=D→rowsgroups,00=-1/01=0/10=+1packedceil(N/4)per-tensor sum,ideal_ternary_bits≈1.585vspackedvsscale_overhead(per_tensor205*32vs per_group14.3M*32) separated - Bounded sharded writer
512 MiBflush-before-add, over-size single allowed, HFblobs/symlink dereferenced, content fingerprint MUST vs file hash SHOULD, JSON storesscale_stats+scale_fingerprint(no scale array) - Whole-model
e2b-naive-pt(12 shards, 10.2GB) ande2b-naive-g128-rw(14.3M groups, 12 shards) both loadable viaAutoModelForMultimodalLMand smokeprotocol True/result observational differentPASS - See
ROADMAP.mdfor M1–M13 andEXPERIMENT_LOG.mdfor whole-model validation
Current focus:
Phase 4 — Calibration / reconstruction (learnable scales) —
inspect→quantize→benchmark→comparepipeline now stable
License
The source code is licensed under the Apache License 2.0. Copyright 2026 The OpenTernary Authors.
- Forks and other redistributions must keep the NOTICE file, which names this project as the origin (Apache-2.0, Section 4(d)), and mark files they changed (Section 4(b)).
- The OpenTernary name and logo are not licensed under Apache-2.0: see TRADEMARKS.md. Public forks should use their own name and logo.
- Contributions are accepted under the same license (Apache-2.0, Section 5).
The project must not copy code from external implementations until their licenses and attribution requirements have been checked.
Metadata
Release files for openternary 0.1.0a2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| openternary-0.1.0a2.tar.gz | 1.5 MB | With provenance | Details for openternary-0.1.0a2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| openternary-0.1.0a2-py3-none-any.whl | Python 3 | none | any | Details for openternary-0.1.0a2-py3-none-any.whl |
Total release size: 1.8 MB
Release files / openternary-0.1.0a2.tar.gz
| Download URL | openternary-0.1.0a2.tar.gz |
|---|---|
| Size | 1.5 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9e8649773bec5e8b99dea8a7ecff94611598f05bf2bcb17b6745aa7b9ec65ca5
|
|
BLAKE2b-256 checksum How to use checksums |
d0eb3ffa05289b0edbb9ca19b9d276fde24fe0bb89b5ee5636182226683146db
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.
Transparency logRelease files / openternary-0.1.0a2-py3-none-any.whl
| Download URL | openternary-0.1.0a2-py3-none-any.whl |
|---|---|
| Size | 329.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f229c628e34509397dcb5daabd9079eac2b2a6bc2756a46426b6ac21f37857d5
|
|
BLAKE2b-256 checksum How to use checksums |
b53876c846fff8e928862bd591f3bd0b1398f1c72648154e5dcb8163e3d912db
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.
Transparency logSecurity for openternary 0.1.0a2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for openternary-0.1.0a2.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 3, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.