You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(model): switch DEFAULT_MODEL to Qwen3-4B-Instruct-2507-GGUF
Decision driven by a head-to-head bench across 4 candidate LLMs on the
iran-showcase corpus (6 multi-event scenarios, same hardware, same
prompt v6, full results in /tmp/bench_1777810874/summary.md):
model pass avg batch p50
Qwen3-4B-Instruct-2507-GGUF 5/6 6.7 58s ~5s ← winner
Gemma-4-E4B-it-GGUF 6/6 7.0 170s 14s
Qwen3.5-4B-GGUF 4/6 6.4 80s 9s
Gemma-4-E2B-it-GGUF 0/6 5.2 64s 10s
Why Qwen3-4B-Instruct-2507 wins:
1. Highest pass-rate-per-second (5 PASSes in 58s = 5.2× Gemma's
throughput for one fewer pass).
2. Sub-5s p50 on 4 of 6 scenarios on M4 Pro — closest of the
candidates to spec § 7.2 target (5s p50 / 8s p95 on Toughbook).
3. **Non-thinking-only model** per HF card. Eliminates the entire
`enable_thinking` patch tower we built for Qwen3.5 (no chain-
of-thought leakage in reply text, no schema-template parroting
under thinking-mode reload, no reasoning-content-burns-budget
hangs). The chat_template_kwargs override and reply-text scrub
stay in as defense-in-depth but become inert.
4. Same Hermes tool-calling + same Qwen sampling distribution as
Qwen3.5, so all our existing patches (parallel-call interceptor,
server-side caps on free-text fields, sources coercion, insight
prefix-strip, presence + frequency penalty, tighter max_tokens)
apply unchanged.
Why NOT the alternates:
- Gemma-4-E4B: perfect 6/6 PASS but 3× wall-time. Pick this only
when the multi-axis-summary stress test has to pass.
- Qwen3.5-4B: thinking-leakage class of failures we patched but
can never fully eliminate. Strictly worse than 2507.
- Gemma-4-E2B: 0/6 PASS — 2B params is below the schema-discipline
threshold for Beacon's 14-tool extraction.
Across-repo updates (every Qwen3.5 reference now correctly listed as
a tested alternate, not the default):
- src/beacon/agent.py DEFAULT_MODEL + comment block + bench table
- src/beacon/telemetry.py docstring example (model_name + checkpoint)
- dashboard/src/LLMStatusChip.tsx header pill example comment
- CLAUDE.md Smoke baseline (with bench results) +
Local-first inference paragraph
- docs/manual-testing.md backend matrix
- docs/architecture-diagram.html Model fact card + footer
Test updates:
- test_qwen_model_injects_..._and_sampling: assertions on max_tokens
aligned with the new 2048 cap and the split-knob anti-repetition
(presence_penalty 0.3 + frequency_penalty 0.3, instead of
presence_penalty 0.5 alone).
- test_non_qwen_model_does_not_inject_chat_template_kwargs: asserts
Qwen sampling overrides + frequency_penalty don't leak onto
non-Qwen models, and the generic max_tokens=2048 floor still
applies.
367 tests pass; 1 e2e skipped.
Qwen3-4B-Instruct-2507 wins the tradeoff: highest pass-rate-per-second,
92
+
sub-5s on 4 of 6 scenarios on M4 Pro, AND it's a non-thinking-only model
93
+
per the HF card — so no `enable_thinking` patch tower is needed (eliminates
94
+
the chain-of-thought-leakage class of failures we saw on Qwen3.5).
95
+
96
+
Gemma-4-E4B-it-GGUF remains the highest-accuracy alternate at the cost of
97
+
3× wall-time; pick it via `BEACON_MODEL=Gemma-4-E4B-it-GGUF` when the
98
+
multi-axis-summary stress test must pass.
90
99
91
100
Latency on this dev box is not representative of fielding hardware (Ryzen AI
92
101
NPU acceleration is Windows/Linux only). On a Toughbook-class laptop the
@@ -201,7 +210,7 @@ Key seams that span multiple files:
201
210
202
211
-**InsightsEngine + ReasoningLog**: `src/beacon/insights.py` is a **trigger-lane subscriber with a 1s trailing debounce** that calls `agent.analyze(snapshot_json)` — a tool-less LLM pass that returns a JSON array of `Insight`. Heuristics were removed (commit `95e64d6` + the agent-only rewrite per `docs/superpowers/specs/2026-05-03-remove-heuristic-insights-design.md`). Per AGENTS.md § 2.3, parse failures and connection errors return `[]` and log; we **do not fabricate insights to fill the gap**. `src/beacon/reasoning.py` is a 500-step in-memory ring buffer; `_execute_tool` writes TOOL steps, the InsightsEngine writes QUERY/SURFACE. The dashboard's reasoning column streams from `/agent/reasoning/stream`.
203
212
204
-
- **Local-first inference**: Lemonade Server is the default. The agent's `DEFAULT_MODEL` is `Qwen3.5-4B-GGUF` (Unsloth's Qwen 3.5 4B, GGUF-quantised) — picked because it's 5-30× faster than Gemma-4-E4B on Apple Silicon for the same extraction tasks (iran-showcase batch: ~22s on Qwen vs ~6 minutes on Gemma), Lemonade-tagged `tool-calling` + `hot`, and vision-capable for the future image path. Override with `BEACON_MODEL=…` (other tested options: `Gemma-4-E4B-it-GGUF`, `Qwen3-4B-Instruct-2507-GGUF`). The 30B-class model the spec originally called for is still too large for current dev hardware; swap when Phase 0.1 is re-run on Ryzen AI silicon. OpenAI fallback is opt-in via `BEACON_USE_OPENAI=1`; Claude fallback is `BEACON_USE_CLAUDE=1`. If Lemonade is unreachable and no opt-in is set, the server returns 502 with an actionable detail — never silently fall back. The backend lifespan POSTs Lemonade `/api/v1/load` at startup with `ctx_size=BEACON_CTX_SIZE` (default 32768) so the active model serves with enough context for multi-turn extraction — Lemonade's server-wide `ctx_size` config (set once via `lemonade config set ctx_size=32768`) overrides per-request values, so changing `BEACON_CTX_SIZE` alone won't take effect unless the server config matches.
213
+
- **Local-first inference**: Lemonade Server is the default. The agent's `DEFAULT_MODEL` is `Qwen3-4B-Instruct-2507-GGUF` (Qwen 3 4B Instruct, July 2025 release, GGUF-quantised) — picked from the head-to-head bench above because it ties the throughput sweet spot (5/6 PASS in 58s) with being a non-thinking-only model (no `enable_thinking` patches needed, no chain-of-thought leakage). Same Hermes tool-calling + Qwen sampling distribution as Qwen3.5, so the parallel-call interceptor and Qwen-specific sampling overrides apply unchanged. Override with `BEACON_MODEL=…` (other tested options: `Gemma-4-E4B-it-GGUF` for highest accuracy at 3× latency cost, `Qwen3.5-4B-GGUF` for vision support). The 30B-class model the spec originally called for is still too large for current dev hardware; swap when Phase 0.1 is re-run on Ryzen AI silicon. OpenAI fallback is opt-in via `BEACON_USE_OPENAI=1`; Claude fallback is `BEACON_USE_CLAUDE=1`. If Lemonade is unreachable and no opt-in is set, the server returns 502 with an actionable detail — never silently fall back. The backend lifespan POSTs Lemonade `/api/v1/load` at startup with `ctx_size=BEACON_CTX_SIZE` (default 32768) so the active model serves with enough context for multi-turn extraction — Lemonade's server-wide `ctx_size` config (set once via `lemonade config set ctx_size=32768`) overrides per-request values, so changing `BEACON_CTX_SIZE` alone won't take effect unless the server config matches.
205
214
206
215
**Qwen-specific tuning** (lives in `BeaconAgent._intercept_chat_send`, fires whenever `"qwen" in self.model_id.lower()`):
207
216
-**Thinking mode is force-disabled.** Qwen3-family GGUFs ship with reasoning ON by default — the model emits a multi-page `Thinking Process:` chain-of-thought before any answer. With thinking ON, `agent.analyze()`'s JSON-array-output contract burns 4+ minutes generating reasoning and never reaches the final array (content stays empty, 0 insights). We pass `chat_template_kwargs={"enable_thinking": False}` on every send and bump `max_tokens` to 16384 so non-thinking outputs have room. If/when token-level streaming to the dashboard reasoning panel lands (Phase 2), re-enable thinking and use `_capture_reasoning_content` to surface `reasoning_content` live as `REASONING` reasoning steps.
Copy file name to clipboardExpand all lines: docs/manual-testing.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -24,7 +24,7 @@ LLM backend — pick one:
24
24
25
25
| Backend | How to enable | Notes |
26
26
|---|---|---|
27
-
| Local Lemonade (default) |`lemonade-server serve` in a separate shell | Default model is `Qwen3.5-4B-GGUF` (override via `BEACON_MODEL`; tested alternates: `Gemma-4-E4B-it-GGUF`, `Qwen3-4B-Instruct-2507-GGUF`). Beacon's lifespan startup POSTs `/api/v1/load` with `ctx_size=BEACON_CTX_SIZE` (default 32768) so multi-turn extraction has room — but Lemonade's server-wide config also caps it, so run `lemonade config set ctx_size=32768` once if requests overflow with the per-request override. |
27
+
| Local Lemonade (default) |`lemonade-server serve` in a separate shell | Default model is `Qwen3-4B-Instruct-2507-GGUF` (override via `BEACON_MODEL`; tested alternates: `Gemma-4-E4B-it-GGUF` for max accuracy at 3× latency, `Qwen3.5-4B-GGUF` for vision support). Beacon's lifespan startup POSTs `/api/v1/load` with `ctx_size=BEACON_CTX_SIZE` (default 32768) so multi-turn extraction has room — but Lemonade's server-wide config also caps it, so run `lemonade config set ctx_size=32768` once if requests overflow with the per-request override. |
28
28
| OpenAI |`export BEACON_USE_OPENAI=1 OPENAI_API_KEY=sk-…`| Use when no GPU / no Lemonade. |
29
29
| Claude |`export BEACON_USE_CLAUDE=1 ANTHROPIC_API_KEY=sk-…`| Same. |
30
30
| None (HTTP / dashboard smoke test only) |`export BEACON_SKIP_LEMONADE=1 BEACON_DEFER_AGENT=1`|`/agent/run` will 502, but `/health`, `/state`, dashboard polling all work. |
0 commit comments