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
39 changes: 29 additions & 10 deletions client/src/components/settings/LocalLlmTab.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,36 @@ const BACKENDS = [
];
const labelFor = (id) => BACKENDS.find((b) => b.id === id)?.label || id;

const DFLASH_PRESETS = [
// llama.cpp exposes one `--spec-type` per drafter family. `draft-dspark` merged
// upstream on 2026-07-28 (ggml-org/llama.cpp#25173) and works on a stock
// `brew install llama.cpp`; `draft-dflash` covers DFlash v1, while the DFlash 2
// modules are still an open PR (#27342) and need a from-source build. Hence the
// DSpark presets lead — see docs/research/2026-08-19-dspark-vs-dflash2.md.
const SPEC_DECODE_PRESETS = [
{
id: 'qwen3.8-27b-dspark',
label: 'Qwen 3.8 27B + DSpark Drafter (Recommended — stock llama.cpp)',
model: 'models/Qwen3.8-27B-Instruct-Q4_K_M.gguf',
draftModel: 'models/Qwen3.8-27B-DSpark-bf16.gguf',
specType: 'draft-dspark',
},
{
id: 'qwen3-8b-dspark',
label: 'Qwen 3 8B + DSpark Drafter (small target)',
model: 'models/Qwen3-8B-Instruct-Q4_K_M.gguf',
draftModel: 'models/dspark_qwen3_8b_block7-bf16.gguf',
specType: 'draft-dspark',
},
{
id: 'qwen3.8-27b',
label: 'Qwen 3.8 27B + DFlash 2 Drafter (Recommended)',
label: 'Qwen 3.8 27B + DFlash 2 Drafter (needs llama.cpp PR #27342 build)',
model: 'models/Qwen3.8-27B-Instruct-Q4_K_M.gguf',
draftModel: 'models/Qwen3.8-27B-DFlash2-Q4_K_M.gguf',
specType: 'draft-dflash',
},
{
id: 'muse-glimmer-30b',
label: 'Muse-Glimmer 30B + DFlash 2 Drafter',
label: 'Muse-Glimmer 30B + DFlash 2 Drafter (needs llama.cpp PR #27342 build)',
model: 'models/Muse-Glimmer-30B-Instruct-Q4_K_M.gguf',
draftModel: 'models/Muse-Glimmer-30B-DFlash2-Q4_K_M.gguf',
specType: 'draft-dflash',
Expand All @@ -42,7 +61,7 @@ const DFLASH_PRESETS = [
label: 'Custom GGUF / Manual Paths',
model: '',
draftModel: '',
specType: 'draft-dflash',
specType: 'draft-dspark',
},
];

Expand Down Expand Up @@ -411,7 +430,7 @@ export function LocalLlmTab() {
const [llamaForm, setLlamaForm] = useState({
model: '',
draftModel: '',
specType: 'draft-dflash',
specType: 'draft-dspark',
port: 8080,
host: '127.0.0.1',
ctxSize: 32768,
Expand Down Expand Up @@ -771,7 +790,7 @@ export function LocalLlmTab() {
};

const handlePresetSelect = (presetId) => {
const preset = DFLASH_PRESETS.find((p) => p.id === presetId);
const preset = SPEC_DECODE_PRESETS.find((p) => p.id === presetId);
if (!preset) return;
if (preset.id !== 'custom') {
setLlamaForm((prev) => ({
Expand Down Expand Up @@ -940,7 +959,7 @@ export function LocalLlmTab() {
</div>

<p className="text-xs text-gray-400 leading-relaxed">
DFlash 2 enables multi-token speculative drafting (yielding 2.5–3× speedups on local models like Qwen 2.5 / Qwen 3.8 and Muse-Glimmer). You can launch and manage a local <code className="text-gray-300">llama-server</code> with DFlash 2 speculative drafting directly from PortOS and connect using the <strong className="text-white">OpenCode llama TUI</strong> provider.
Speculative decoding pairs a small drafter with your target model for 2–3× faster generation at identical output. You can launch and manage a local <code className="text-gray-300">llama-server</code> from PortOS and connect using the <strong className="text-white">OpenCode llama TUI</strong> provider. <strong className="text-white">DSpark</strong> (<code className="text-gray-300">draft-dspark</code>) works on a stock <code className="text-gray-300">brew install llama.cpp</code>; the DFlash 2 presets need a from-source build of an unmerged llama.cpp branch.
</p>

{llamaStatus?.running ? (
Expand All @@ -952,7 +971,7 @@ export function LocalLlmTab() {
<p><span className="text-gray-500">Base Model:</span> <code className="text-gray-300">{llamaStatus.config.model}</code></p>
)}
{llamaStatus.config?.draftModel && (
<p><span className="text-gray-500">DFlash Drafter:</span> <code className="text-port-accent">{llamaStatus.config.draftModel}</code> ({llamaStatus.config.specType || 'draft-dflash'})</p>
<p><span className="text-gray-500">Drafter:</span> <code className="text-port-accent">{llamaStatus.config.draftModel}</code> ({llamaStatus.config.specType || 'draft-dflash'})</p>
)}
</div>
{llamaStatus.managed ? (
Expand Down Expand Up @@ -981,10 +1000,10 @@ export function LocalLlmTab() {
id="llama-preset-select"
aria-label="Preset"
onChange={(e) => handlePresetSelect(e.target.value)}
defaultValue="qwen3.8-27b"
defaultValue="qwen3.8-27b-dspark"
className="bg-port-card border border-port-border rounded px-2 py-1 text-xs text-port-accent focus:outline-none"
>
{DFLASH_PRESETS.map((p) => (
{SPEC_DECODE_PRESETS.map((p) => (
<option key={p.id} value={p.id}>
{p.label}
</option>
Expand Down
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Start with the [product surface map](./features/product-surfaces.md) for a compl

App management: [app-wizard](./features/app-wizard.md) · [autofixer](./features/autofixer.md) · [browser](./features/browser.md) · [error-handling](./features/error-handling.md) · [jira-sprint-manager](./features/jira-sprint-manager.md)

Chief of Staff: [chief-of-staff](./features/chief-of-staff.md) · [cos-agent-runner](./features/cos-agent-runner.md) · [cos-enhancement](./features/cos-enhancement.md) · [agent-context](./features/agent-context.md) · [agent-skills](./features/agent-skills.md) · [memory-system](./features/memory-system.md) · [claude-ollama](./features/claude-ollama.md) · [mtplx](./features/mtplx.md) · [dflash2](./features/dflash2.md) · [prompt-manager](./features/prompt-manager.md)
Chief of Staff: [chief-of-staff](./features/chief-of-staff.md) · [cos-agent-runner](./features/cos-agent-runner.md) · [cos-enhancement](./features/cos-enhancement.md) · [agent-context](./features/agent-context.md) · [agent-skills](./features/agent-skills.md) · [memory-system](./features/memory-system.md) · [claude-ollama](./features/claude-ollama.md) · [mtplx](./features/mtplx.md) · [dflash2](./features/dflash2.md) ([DSpark vs DFlash 2](./research/2026-08-19-dspark-vs-dflash2.md)) · [prompt-manager](./features/prompt-manager.md)

Identity & self: [digital-twin](./features/digital-twin.md) · [identity-system](./features/identity-system.md) · [soul-system](./features/soul-system.md) · [privacy-center](./features/privacy-center.md) · [post](./features/post.md) (insights design spike: [plans/2026-06-03](./plans/2026-06-03-cross-domain-insights-engine.md))

Expand Down
47 changes: 40 additions & 7 deletions docs/features/dflash2.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
# DFlash 2 Speculative Decoding — llama.cpp & OpenCode llama TUI
# Speculative Decoding (DSpark / DFlash 2) — llama.cpp & OpenCode llama TUI

[DFlash 2](https://huggingface.co/z-lab) provides deep, ultra-fast block-level speculative drafting for large language models (such as Qwen 2.5, Qwen 3.8, and Muse-Glimmer). By pairing a small speculative drafter model (typically 1.5–3 GB) with a target foundation model (e.g. 27B–30B), DFlash 2 achieves 2.5–3× end-to-end token generation speedups without sacrificing output quality.

PortOS provides direct integration with DFlash 2 through the **OpenCode llama TUI** provider preset and local OpenAI-compatible inference servers like `llama-server`.
[DSpark](https://arxiv.org/html/2607.05147v1) (DeepSeek) is the sibling drafter family — same lossless block-drafting idea, a rank-256 Markov head instead of DFlash 2's candidate selector, and a much wider set of published drafters.

PortOS integrates both through the **OpenCode llama TUI** provider preset and the managed local `llama-server`.

> **Which one to run:** `--spec-type draft-dspark` **merged into llama.cpp on 2026-07-28** ([#25173](https://github.com/ggml-org/llama.cpp/pull/25173)) and works on a stock `brew install llama.cpp`. DFlash 2's engine modules are **still an open PR** ([#27342](https://github.com/ggml-org/llama.cpp/pull/27342)) and need a from-source build of that branch. llama.cpp falls back **silently** on a spec-type/drafter mismatch rather than erroring, so a DFlash 2 drafter on a stock build degrades quietly. Start with DSpark unless you have built the DFlash 2 branch. Full comparison: [DSpark vs DFlash 2](../research/2026-08-19-dspark-vs-dflash2.md).

---

## What PortOS Adds

1. **OpenCode llama TUI Provider**:
- An attachable `tui` coding-agent provider preset (`opencode-llama-tui`) configured to connect to `http://127.0.0.1:8080/v1`.
- Seeded with default model aliases `["dflash", "qwen3.8-27b-dflash2", "Muse-Glimmer-30B-DFlash2"]` with default `dflash`.
- Seeded with default model aliases `["dflash", "qwen3.8-27b-dflash2", "Muse-Glimmer-30B-DFlash2"]` with default `dflash`. The launcher keeps `--alias dflash` for every drafter family so this alias resolves regardless of which one you run.
- Fully enabled by default and equipped with OpenCode's agentic file-writing harness, tool calling, and session persistence.
2. **Model Refresh**:
- Support for dynamic model discovery via the **Refresh Models** button on AI Providers, querying the local `llama-server` `/v1/models` endpoint.
Expand All @@ -22,7 +26,21 @@ PortOS provides direct integration with DFlash 2 through the **OpenCode llama TU
## Setup & Running with llama-server

### 1. Download Base & Draft Models
Download your base GGUF and corresponding DFlash 2 drafter GGUF from Hugging Face:
Download your base GGUF and a matching drafter GGUF from Hugging Face. Drafter
checkpoints are **not standalone models** — they only produce text once an engine
pairs them with their specific target, which is why PortOS's model search filters
them out of the install picker.

DSpark pairs (stock llama.cpp):

- **Qwen 3.8 27B**: base `Qwen/Qwen3.8-27B-Instruct-GGUF` + drafter `DimInfer/Qwen3.8-27B-Dspark-v1`
- **Qwen 3 8B**: base `Qwen/Qwen3-8B-Instruct-GGUF` + drafter converted from `deepseek-ai/dspark_qwen3_8b_block7`

DSpark drafters ship without tokenizers — converting one to GGUF requires passing
`--target-model-dir` so it reuses the target's tokenizer. Keep the drafter at bf16;
the target can be any quant.

DFlash 2 pairs (require a source build of llama.cpp [#27342](https://github.com/ggml-org/llama.cpp/pull/27342)):

- **Qwen 3.8 27B Draft Pair**:
- Base: `Qwen/Qwen3.8-27B-Instruct-GGUF` (e.g. `Qwen3.8-27B-Instruct-Q4_K_M.gguf`)
Expand All @@ -32,13 +50,14 @@ Download your base GGUF and corresponding DFlash 2 drafter GGUF from Hugging Fac
- Drafter: `z-lab/Muse-Glimmer-30B-DFlash2-GGUF`

### 2. Launch llama-server
Start `llama-server` on loopback port `8080` with speculative decoding enabled:
Start `llama-server` on loopback port `8080` with speculative decoding enabled
(`--spec-type draft-dflash` for a DFlash drafter, `draft-dspark` for a DSpark one):

```bash
llama-server \
-m models/Qwen3.8-27B-Instruct-Q4_K_M.gguf \
--draft-model models/Qwen3.8-27B-DFlash2-Q4_K_M.gguf \
--spec-type draft-dflash \
--draft-model models/Qwen3.8-27B-DSpark-bf16.gguf \
--spec-type draft-dspark \
--port 8080 \
--host 127.0.0.1 \
--alias dflash \
Expand All @@ -51,3 +70,17 @@ llama-server \
2. Verify **OpenCode llama TUI** is enabled.
3. Click **Refresh Models** to pull the live aliases from `llama-server`, or use the default `dflash` model.
4. Select **OpenCode llama TUI** in the CoS task creator or terminal runner to execute coding and agent tasks with speculative acceleration.

---

## Ollama

Ollama's vendored llama.cpp engine has carried DSpark since **0.32.6**
([#17545](https://github.com/ollama/ollama/pull/17545)), but Ollama surfaces no
control for it — its server hardcodes `--spec-type draft-mtp` whenever
speculative decoding is on. Selecting DSpark requires overriding
`LLAMA_ARG_SPEC_TYPE` / `LLAMA_ARG_SPEC_DRAFT_MODEL` on the Ollama process and
pointing at a raw blob-store path; the one reported measurement through that
path was ~13%, far below what the drafter delivers natively. Tracked upstream in
[ollama#17016](https://github.com/ollama/ollama/issues/17016). **Use
`llama-server` for speculative decoding in PortOS, not the Ollama backend.**
Loading
Loading