@miller-tech/uap 1.13.14 → 1.13.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/docs/INDEX.md CHANGED
@@ -43,6 +43,7 @@
43
43
 
44
44
  - [Validation Plan](benchmarks/VALIDATION_PLAN.md) -- Benchmark methodology and test cases
45
45
  - [Validation Results](benchmarks/VALIDATION_RESULTS.md) -- Benchmark results
46
+ - [Speculative Decoding Journey (2026-03)](benchmarks/SPECULATIVE_DECODING_JOURNEY_2026-03.md) -- End-to-end tuning, fixes, and soak outcomes
46
47
  - [Token Optimization](benchmarks/TOKEN_OPTIMIZATION.md) -- Per-feature token savings analysis
47
48
  - [Accuracy Analysis](benchmarks/ACCURACY_ANALYSIS.md) -- Internal vs Terminal-Bench comparison
48
49
 
@@ -0,0 +1,221 @@
1
+ # Speculative Decoding Journey (2026-03)
2
+
3
+ This document records the end-to-end speculative decoding stabilization journey across `llama.cpp` runtime tuning and `uap-anthropic-proxy` guardrails, including fixes, benchmark results, and the production profile now in use.
4
+
5
+ ## Scope
6
+
7
+ - Runtime: `llama.cpp` with Qwen3.5 models, CUDA, `ctx-size=262144`.
8
+ - Gateway: Anthropic-compatible proxy (`tools/agents/scripts/anthropic_proxy.py`).
9
+ - Client behavior: agentic coding loops with tool calls (Claude Code style).
10
+
11
+ ## Goals
12
+
13
+ 1. Preserve high speculative decoding throughput.
14
+ 2. Eliminate pathological loops and malformed visible output.
15
+ 3. Keep tool-call behavior reliable under long sessions.
16
+ 4. Keep production context window at `262144`.
17
+
18
+ ## Phase 1 - Llama.cpp Speculative Stability
19
+
20
+ ### Problems Observed
21
+
22
+ - Rollback loops and instability under aggressive speculative settings.
23
+ - `find_slot` and related server warnings during long agentic sessions.
24
+ - Throughput regressions compared to known fast baseline.
25
+
26
+ ### Work Performed
27
+
28
+ - Implemented and tested multiple rollback strategies in `llama.cpp` worktree branches.
29
+ - Compared baseline fast commit vs newer speculative logic.
30
+ - Restored proven fast runtime path for production service while preserving learned guardrails.
31
+
32
+ ### Key Runtime Decisions
33
+
34
+ - Keep production on fast validated binary lineage (`029edcafc` baseline family).
35
+ - Use strict balanced speculative profile for 35B operations:
36
+ - `speculative.n_max=12`
37
+ - `speculative.n_min=2`
38
+ - `speculative.p_min=0.80`
39
+
40
+ ### Representative Throughput Findings
41
+
42
+ - Qwen3.5-27B, `ctx=262144`, q4 KV cache:
43
+ - No spec: ~43 tok/s coding, ~41 tok/s pattern.
44
+ - Spec (balanced): ~43 tok/s coding, ~102 tok/s pattern.
45
+ - Main uplift appears in pattern-heavy turns, not all coding turns.
46
+
47
+ ## Phase 2 - Proxy Reasoning Fallback Leak Fix
48
+
49
+ ### Problems Observed
50
+
51
+ - Empty visible output (`output_tokens=0`) with large hidden reasoning payloads.
52
+ - Proxy emitted malformed chain-of-thought text as fallback, causing user-visible garbage:
53
+ - repeated fragments like `</parameter>`, tool schema echoes, policy text loops.
54
+
55
+ ### Fixes Implemented
56
+
57
+ - Added explicit streaming fallback policy:
58
+ - `PROXY_STREAM_REASONING_FALLBACK=off|sanitized|visible`
59
+ - `PROXY_STREAM_REASONING_MAX_CHARS`
60
+ - Set production default to `off`.
61
+
62
+ ### Result
63
+
64
+ - Malformed reasoning fallback leakage is suppressed by default.
65
+ - Debugging remains possible with `sanitized`/`visible` modes when intentionally enabled.
66
+
67
+ ## Phase 3 - Token Floor and Prune Controls
68
+
69
+ ### Problems Observed
70
+
71
+ - Hardcoded `max_tokens` floor (`16384`) forced very long failure turns.
72
+ - Pruning threshold flag alone could trigger pruning path without meaningful message reduction.
73
+
74
+ ### Fixes Implemented
75
+
76
+ - Added configurable max token floor:
77
+ - `PROXY_MAX_TOKENS_FLOOR` (`0` disables floor)
78
+ - Added configurable prune target:
79
+ - `PROXY_CONTEXT_PRUNE_TARGET_FRACTION`
80
+
81
+ ### Live A/B Result (Production-Like)
82
+
83
+ `PROXY_MAX_TOKENS_FLOOR=16384` vs `4096`:
84
+
85
+ - Silent reasoning-heavy turn:
86
+ - `16384`: avg `78.749s`
87
+ - `4096`: avg `19.777s`
88
+ - Latency reduction: ~`74.9%`
89
+ - Predicted throughput unchanged (~`208 tok/s` class)
90
+ - Normal tool turns remained stable and slightly faster with `4096`.
91
+
92
+ ## Phase 4 - Malformed Tool-Loop Hardening
93
+
94
+ ### Problem Pattern
95
+
96
+ Under adversarial or degraded prompt states, the model can emit pseudo-tool text instead of valid tool calls, e.g.:
97
+
98
+ - `</parameter>` fragments
99
+ - echoed policy snippets (`you MUST call a tool...`)
100
+ - long no-progress text with no `tool_calls`
101
+
102
+ ### Feature Set Added (Flag Controlled)
103
+
104
+ 1. **Malformed tool guardrail + retry**
105
+ - `PROXY_MALFORMED_TOOL_GUARDRAIL`
106
+ - `PROXY_MALFORMED_TOOL_RETRY_MAX`
107
+ - `PROXY_MALFORMED_TOOL_RETRY_MAX_TOKENS`
108
+ - `PROXY_MALFORMED_TOOL_RETRY_TEMPERATURE`
109
+
110
+ 2. **Strict stream guardrail path**
111
+ - `PROXY_MALFORMED_TOOL_STREAM_STRICT`
112
+ - For stream+tools requests, proxy runs guarded non-stream upstream call, then replays SSE.
113
+
114
+ 3. **Tool narrowing (optional)**
115
+ - `PROXY_TOOL_NARROWING`
116
+ - `PROXY_TOOL_NARROWING_KEEP`
117
+ - `PROXY_TOOL_NARROWING_MIN_TOOLS`
118
+
119
+ 4. **Disable thinking on tool turns (optional)**
120
+ - `PROXY_DISABLE_THINKING_ON_TOOL_TURNS`
121
+
122
+ 5. **Session contamination breaker (optional safety net)**
123
+ - `PROXY_SESSION_CONTAMINATION_BREAKER`
124
+ - `PROXY_SESSION_CONTAMINATION_THRESHOLD`
125
+ - `PROXY_SESSION_CONTAMINATION_KEEP_LAST`
126
+
127
+ 6. **Agentic supplement mode**
128
+ - `PROXY_AGENTIC_SUPPLEMENT_MODE=clean|legacy`
129
+
130
+ ### Test Coverage
131
+
132
+ - Unit tests in `tools/agents/tests/test_anthropic_proxy_streaming.py`
133
+ - Current targeted suite count in this workstream: `16` passing tests.
134
+
135
+ ## Benchmark Highlights (Per-Option Toggles)
136
+
137
+ ### Artifact Stress Benchmark (v3)
138
+
139
+ Source: `/tmp/proxy_visibility_benchmark_v3.json`
140
+
141
+ | Mode | Key Flags | Outcome Summary |
142
+ | --- | --- | --- |
143
+ | Baseline | none | no tool call, policy-echo text surfaced |
144
+ | Option 1 | malformed guardrail + strict stream | malformed detected and retried; returned `tool_use` with empty visible text |
145
+ | Option 2 | tool narrowing only | not sufficient alone in stress case |
146
+ | Option 3 | disable thinking only | not sufficient alone in stress case |
147
+ | Option 4 | contamination breaker only | not sufficient alone in this synthetic workload |
148
+ | Option 5 | clean supplement only | not sufficient alone in stress case |
149
+
150
+ ### Practical Conclusion
151
+
152
+ - Strongest primary mitigation: **Option 1** (malformed guardrail + strict stream + bounded retry).
153
+ - Other options are secondary tuning aids and should not replace Option 1 for this failure class.
154
+
155
+ ## 10-Turn Live Stability Soak
156
+
157
+ Source: `/tmp/proxy_10turn_soak_results.json`
158
+
159
+ - 10 turns, alternating malformed-stress and normal tool-call turns, single live session id.
160
+ - Results:
161
+ - Error rate: `0.0%`
162
+ - Malformed visible output rate (stress turns): `0.0%`
163
+ - Normal tool-call success rate: `100.0%`
164
+ - Duration p50/p95: `10.2s` / `21.366s`
165
+ - Stop reasons: `tool_use=6`, `max_tokens=3`, `end_turn=1`
166
+
167
+ ## Production Profile (Current)
168
+
169
+ File: `/home/cogtek/.config/uap/anthropic-proxy.env`
170
+
171
+ ```bash
172
+ PROXY_MAX_TOKENS_FLOOR=4096
173
+ PROXY_STREAM_REASONING_FALLBACK=off
174
+
175
+ PROXY_MALFORMED_TOOL_GUARDRAIL=on
176
+ PROXY_MALFORMED_TOOL_STREAM_STRICT=on
177
+ PROXY_MALFORMED_TOOL_RETRY_MAX=1
178
+ PROXY_MALFORMED_TOOL_RETRY_MAX_TOKENS=512
179
+ PROXY_MALFORMED_TOOL_RETRY_TEMPERATURE=0
180
+
181
+ PROXY_TOOL_NARROWING=off
182
+ PROXY_DISABLE_THINKING_ON_TOOL_TURNS=off
183
+ PROXY_SESSION_CONTAMINATION_BREAKER=off
184
+ PROXY_AGENTIC_SUPPLEMENT_MODE=legacy
185
+ ```
186
+
187
+ Rationale:
188
+
189
+ - Keep the strongest practical fix enabled (malformed guardrail + strict stream path).
190
+ - Keep latency-optimized floor (`4096`).
191
+ - Keep optional secondary heuristics off unless new evidence warrants enablement.
192
+
193
+ ## Reproduction Checklist
194
+
195
+ 1. Restart services:
196
+
197
+ ```bash
198
+ systemctl --user restart uap-llama-server.service
199
+ systemctl --user restart uap-anthropic-proxy.service
200
+ ```
201
+
202
+ 2. Run targeted unit tests:
203
+
204
+ ```bash
205
+ python3 -m pytest tools/agents/tests/test_anthropic_proxy_streaming.py -q
206
+ ```
207
+
208
+ 3. Run soak script (or equivalent alternating malformed/normal stream sequence).
209
+
210
+ 4. Validate logs:
211
+
212
+ - `MALFORMED TOOL PAYLOAD`
213
+ - `MALFORMED RETRY ...`
214
+ - `STRICT STREAM GUARDRAIL`
215
+ - Absence of user-visible malformed fragments.
216
+
217
+ ## Open Follow-Ups
218
+
219
+ - Add a dedicated persistent benchmark harness under `scripts/` for this exact soak profile.
220
+ - Add branch/commit links from `llama.cpp` worktrees for cross-repo traceability.
221
+ - Optionally evaluate enabling `PROXY_TOOL_NARROWING` in production only after longer mixed-workload soak data.
@@ -221,11 +221,38 @@ All settings are via environment variables:
221
221
  | `PROXY_LOG_LEVEL` | `INFO` | Logging level (DEBUG/INFO/WARNING/ERROR) |
222
222
  | `PROXY_READ_TIMEOUT` | `600` | Read timeout (seconds) for LLM streaming |
223
223
  | `PROXY_MAX_CONNECTIONS` | `20` | Max concurrent upstream connections |
224
+ | `PROXY_MAX_TOKENS_FLOOR` | `16384` | Minimum floor applied to incoming `max_tokens` (`0` disables floor) |
225
+ | `PROXY_CONTEXT_PRUNE_TARGET_FRACTION` | `0.65` | Target context utilization after pruning (`0.0 < value < 1.0`) |
224
226
  | `PROXY_STREAM_REASONING_FALLBACK` | `off` | Streaming behavior for reasoning-only empty turns (`off`, `sanitized`, `visible`) |
225
227
  | `PROXY_STREAM_REASONING_MAX_CHARS` | `240` | Max fallback length when `PROXY_STREAM_REASONING_FALLBACK=sanitized` |
228
+ | `PROXY_TOOL_NARROWING` | `off` | Narrow large tool lists to top relevant tools per turn |
229
+ | `PROXY_TOOL_NARROWING_KEEP` | `8` | Number of tools to keep when narrowing is enabled |
230
+ | `PROXY_TOOL_NARROWING_MIN_TOOLS` | `12` | Minimum tool count before narrowing activates |
231
+ | `PROXY_DISABLE_THINKING_ON_TOOL_TURNS` | `off` | Sends `enable_thinking=false` when tools are present |
232
+ | `PROXY_MALFORMED_TOOL_GUARDRAIL` | `on` | Detects malformed pseudo tool payloads and retries with strict settings |
233
+ | `PROXY_MALFORMED_TOOL_RETRY_MAX` | `1` | Number of malformed-tool retries |
234
+ | `PROXY_MALFORMED_TOOL_RETRY_MAX_TOKENS` | `2048` | Retry cap for `max_tokens` during malformed-tool recovery |
235
+ | `PROXY_MALFORMED_TOOL_RETRY_TEMPERATURE` | `0` | Retry temperature for malformed-tool recovery |
236
+ | `PROXY_MALFORMED_TOOL_STREAM_STRICT` | `off` | For stream+tools requests, use guarded non-stream upstream path then replay SSE |
237
+ | `PROXY_SESSION_CONTAMINATION_BREAKER` | `on` | Resets long-running malformed sessions to recent context |
238
+ | `PROXY_SESSION_CONTAMINATION_THRESHOLD` | `3` | Consecutive malformed turns before reset |
239
+ | `PROXY_SESSION_CONTAMINATION_KEEP_LAST` | `8` | Number of latest messages to preserve during contamination reset |
240
+ | `PROXY_AGENTIC_SUPPLEMENT_MODE` | `clean` | Agentic system supplement variant (`clean`, `legacy`) |
226
241
 
227
242
  For agentic coding workloads, keep `PROXY_STREAM_REASONING_FALLBACK=off` (default) to avoid leaking malformed internal reasoning as user-visible output. Use `sanitized` only for debugging.
228
243
 
244
+ For Claude Code + Qwen malformed-tool loops, recommended starting profile:
245
+
246
+ ```bash
247
+ PROXY_STREAM_REASONING_FALLBACK=off
248
+ PROXY_MAX_TOKENS_FLOOR=4096
249
+ PROXY_MALFORMED_TOOL_GUARDRAIL=on
250
+ PROXY_TOOL_NARROWING=on
251
+ PROXY_DISABLE_THINKING_ON_TOOL_TURNS=on
252
+ PROXY_SESSION_CONTAMINATION_BREAKER=on
253
+ PROXY_AGENTIC_SUPPLEMENT_MODE=clean
254
+ ```
255
+
229
256
  ### Example: Custom upstream
230
257
 
231
258
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miller-tech/uap",
3
- "version": "1.13.14",
3
+ "version": "1.13.15",
4
4
  "description": "Autonomous AI agent memory system with CLAUDE.md protocol enforcement",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",