@octocodeai/freellama-mcp-server 0.9.0 → 0.12.0
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/CONFIGURATION.md +82 -3
- package/DEVELOPING.md +40 -9
- package/README.md +317 -172
- package/dist/agent-cli.js +16963 -0
- package/dist/index.js +5424 -4320
- package/dist/research/bash-agent.js +308 -120
- package/dist/research/coder-agent.js +476 -139
- package/dist/research/github-agent.js +298 -107
- package/dist/research/octocode-agent.js +297 -106
- package/docs/AGENT_CLI.md +234 -0
- package/docs/API.md +160 -0
- package/docs/ARCHITECTURE.md +158 -50
- package/docs/ASSESSMENT.md +131 -0
- package/docs/BENCHMARK.md +381 -0
- package/docs/BUILD_AND_NOTES.md +12 -3
- package/docs/CLI.md +62 -17
- package/docs/CPU_GPU_ROUTING.md +22 -9
- package/docs/DEFERRED_JOBS.md +17 -4
- package/docs/FEATURES.md +97 -43
- package/docs/LLAMACPP.md +133 -0
- package/docs/LOCAL_MODELS.md +26 -20
- package/docs/MODEL_FORMS_AND_RESULTS.md +14 -6
- package/docs/MODEL_INTROSPECTION.md +9 -2
- package/docs/MODEL_SELECTION.md +39 -10
- package/docs/MONITORING.md +110 -12
- package/docs/OLLAMA_REVIEW.md +226 -0
- package/docs/PRODUCTION.md +68 -25
- package/docs/PROMPTS.md +119 -0
- package/docs/README.md +22 -6
- package/docs/RELIABILITY.md +207 -0
- package/docs/RUST_RESOURCE_AUDIT.md +65 -0
- package/docs/SCOPES_AND_WARMING.md +12 -5
- package/docs/TESTING.md +112 -6
- package/docs/TUNING.md +12 -8
- package/docs/assets/benchmark-results-2026-11-14.html +4 -0
- package/docs/assets/tool-calling-2026-11-14-bonsai-9b/TABLE.md +14 -0
- package/docs/assets/tool-calling-2026-11-14-lfm3-vl/TABLE.md +14 -0
- package/docs/assets/tool-calling-table.md +14 -0
- package/docs/cookbooks/README.md +9 -2
- package/docs/cookbooks/batch-text.md +4 -2
- package/docs/cookbooks/classify.md +19 -3
- package/docs/cookbooks/coding.md +13 -4
- package/docs/cookbooks/find-code.md +8 -3
- package/docs/cookbooks/jobs.md +8 -8
- package/docs/cookbooks/memory-and-caching.md +2 -2
- package/docs/cookbooks/ocr.md +3 -3
- package/docs/cookbooks/research-agent.md +32 -2
- package/docs/cookbooks/speech-to-text.md +1 -1
- package/docs/cookbooks/sweep.md +4 -1
- package/docs/octocode/GITHUB.md +4 -4
- package/docs/octocode/LOCAL.md +5 -4
- package/native/index.d.ts +1 -1
- package/package.json +6 -6
- package/docs/COMPARISON.md +0 -40
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
# Benchmark
|
|
2
|
+
|
|
3
|
+
One run, measured on 2026-11-14 on an Apple M2 Pro (32 GB): FreeLlama against Ollama alone,
|
|
4
|
+
llama.cpp, llama-swap and LocalAI, all loading the same hash-verified model file. Every one of the
|
|
5
|
+
360 measured answers was correct and byte-identical for that single extraction fixture.
|
|
6
|
+
This is separate from [result-check accuracy and local tool-calling evidence](RELIABILITY.md).
|
|
7
|
+
The current explicit [managed llama.cpp text path](LLAMACPP.md) is also separate from these
|
|
8
|
+
Ollama-backed FreeLlama measurements.
|
|
9
|
+
|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
Then the [features](#features): what FreeLlama's management changes, each measured against the
|
|
13
|
+
same work without it.
|
|
14
|
+
|
|
15
|
+
## What the measured scenarios show
|
|
16
|
+
|
|
17
|
+
FreeLlama manages model selection, admission and receipts around external engines. The
|
|
18
|
+
FreeLlama rows below used Ollama. In this workload, its layer added a few milliseconds and
|
|
19
|
+
used about 30 MB of server RSS. These results describe the recorded configurations:
|
|
20
|
+
|
|
21
|
+
| Scenario | Setup measured here | Observations in this run |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| An agent (Claude Code, Cursor, scripts) that offloads bounded work to local models on a machine that also runs editors, browsers and builds | **FreeLlama on Ollama** | Same speed as Ollama (274 vs 272 ms median, first streamed token 95 vs 93 ms); its own work is 3.7 ms per task and its server uses 26–31 MB. Its built-in workflow prompts passed 45/46 completed graded cases versus 25/48 for one-line prompts (planned-denominator limits below), in less time and fewer tokens. An interactive task behind 8 queued ones answered in 1.40 s instead of 3.52 s; repeated code searches and sweeps reuse saved work (55.9 s → 0.13 s, 49.8 s → 18 ms); long tasks return a job id in 29 ms. It refuses a load that would not fit and names what holds the memory (live: needed 7.2 GB, 4.2 GB free, refused), selects eligible installed models with runtime admission, and returns a receipt with per-phase timing. 9.7 ms CPU per task. MCP server, CLI and an Ollama/OpenAI/Anthropic gateway. |
|
|
24
|
+
| One application, one model you chose, little else running | **Ollama alone** | Fastest here by 2 ms (272 ms), one-line install, the largest model library. You size models and watch memory yourself. |
|
|
25
|
+
| Many concurrent requests to one model | **llama.cpp `llama-server`** | Slower per request here (336 ms) but 291 tasks/min at 4 clients against 225 for Ollama, which serves one request at a time unless `OLLAMA_NUM_PARALLEL` is set (not measured). Model loads at process start. |
|
|
26
|
+
| Several models swapped on demand behind one OpenAI endpoint, on any engine | **llama-swap** | 332 ms, the best 4-client throughput (305 tasks/min), 1.58 s to load on first request. Limits are pools you declare, not measured memory. |
|
|
27
|
+
| One server for many modalities and backends (images, speech, video) | **LocalAI** | About 3× slower on this task (802 ms; 541 ms to first token) and 3.39 s cold, in exchange for breadth. |
|
|
28
|
+
| A desktop app for people | LM Studio, Jan | Not measured here. |
|
|
29
|
+
|
|
30
|
+
FreeLlama and Ollama are not either-or: FreeLlama runs on the Ollama you have, and Ollama's own
|
|
31
|
+
clients keep working through it.
|
|
32
|
+
|
|
33
|
+
## KPIs
|
|
34
|
+
|
|
35
|
+
Six setups, the same request, 60 measured requests each over two run orders (forward and
|
|
36
|
+
reversed), after 2 warm-ups per pass.
|
|
37
|
+
|
|
38
|
+
| KPI | What it measures | How | Ollama alone | FreeLlama | FreeLlama streamed | llama.cpp | LocalAI | llama-swap |
|
|
39
|
+
|---|---|---|---:|---:|---:|---:|---:|---:|
|
|
40
|
+
| Correct answers | The task's JSON, field by field | Exact match against the known answer | 60/60 | 60/60 | 60/60 | 60/60 | 60/60 | 60/60 |
|
|
41
|
+
| Median task time | What one request costs | Client wall clock, warm model, pooled over both orders | **272 ms** | **274 ms** | **273 ms** | 336 ms | 802 ms | 332 ms |
|
|
42
|
+
| p95 task time | The slow tail | Same samples | 290 ms | 303 ms | 299 ms | 375 ms | 911 ms | 372 ms |
|
|
43
|
+
| First token | When text starts to appear | Client clock to the first non-empty content | 93 ms | — | 95 ms | 128 ms | 541 ms | 130 ms |
|
|
44
|
+
| Throughput, 1 client | Tasks finished per minute in sequence | Verified tasks ÷ measured window, mean of both orders | 209 | 206 | 217 | 178 | 76 | 178 |
|
|
45
|
+
| Throughput, 4 clients | Tasks per minute under contention | 4 concurrent clients, 30 requests (forward pass) | 225 | 221 | 222 | 291 | 145 | 305 |
|
|
46
|
+
| Cold request | First answer when the model is not loaded | 3 samples after an unload (`keep_alive: 0`) or a process restart | 1.13 s | 1.21 s | 1.17 s | n/c¹ | 3.39 s | 1.58 s |
|
|
47
|
+
| Decode speed | Engine token rate | Ollama's own timing, median of each order, averaged | 124 tok/s | 125 tok/s | 124 tok/s | — | — | — |
|
|
48
|
+
| Layer overhead | Time added on top of the engine | Client time minus Ollama engine time, 40 requests | — | 3.7 ms (p90 5.6) | — | — | — | — |
|
|
49
|
+
| Layer memory | RAM the management process itself uses | Peak RSS of the FreeLlama server process | — | 26–31 MB | 26–31 MB | — | — | — |
|
|
50
|
+
| Swap growth | Whether the run pushed the host into swap | Swap used at block start versus peak | 0 | 0 | 0 | 0 | 0 | 0 |
|
|
51
|
+
| Layer CPU | CPU the management process uses per task | `ps` CPU time of FreeLlama's server over 100 warm tasks | — | 9.7 ms | — | — | — | — |
|
|
52
|
+
| GPU placement | Whether the model ran fully on the GPU | Ollama `/api/ps` after each answer, from the receipt | — | 59/60 | 60/60 | — | — | — |
|
|
53
|
+
|
|
54
|
+
¹ llama.cpp loads the model before it reports ready, so its first request after a restart is warm
|
|
55
|
+
(0.33 s); its load time is part of process start, not the request.
|
|
56
|
+
|
|
57
|
+
Bold marks the three setups within 2 ms of each other. Gaps under about 50 ms changed order
|
|
58
|
+
between earlier runs on a busier host; read them as ties.
|
|
59
|
+
|
|
60
|
+
## Results
|
|
61
|
+
|
|
62
|
+
[Full report](assets/benchmark-results-2026-11-14.html): pooled and per-order tables,
|
|
63
|
+
host samples. Between the two run orders LocalAI's median moved by 100 ms (851 → 751 ms) and
|
|
64
|
+
llama.cpp's by 34 ms (311 → 345 ms); Ollama, FreeLlama and FreeLlama streamed stayed within
|
|
65
|
+
268–275 ms in both.
|
|
66
|
+
|
|
67
|
+
**Concurrent clients** (forward pass, 30 requests per level):
|
|
68
|
+
|
|
69
|
+
| System | 2 clients: p50, tasks/min | 4 clients: p50, tasks/min |
|
|
70
|
+
|---|---:|---:|
|
|
71
|
+
| Ollama alone | 527 ms, 226 | 1,058 ms, 225 |
|
|
72
|
+
| FreeLlama | 534 ms, 221 | 1,068 ms, 221 |
|
|
73
|
+
| FreeLlama streamed | 535 ms, 220 | 1,074 ms, 222 |
|
|
74
|
+
| llama.cpp | 561 ms, 210 | 777 ms, 291 |
|
|
75
|
+
| llama-swap | 564 ms, 213 | 787 ms, 305 |
|
|
76
|
+
| LocalAI | 913 ms, 128 | 1,621 ms, 145 |
|
|
77
|
+
|
|
78
|
+
Ollama serves one request at a time by default, so its time per request doubles with two clients;
|
|
79
|
+
FreeLlama keeps its throughput within 2%. llama.cpp's parallel slots overlap requests.
|
|
80
|
+
|
|
81
|
+
### FreeLlama's overhead, profiled
|
|
82
|
+
|
|
83
|
+
Each receipt carries `timing`: milliseconds per phase inside `serve`. On 40 warm requests the old
|
|
84
|
+
build spent its time on three things every request paid for: reading Ollama's `/api/tags` for a
|
|
85
|
+
pinned model (21 ms median; Ollama reads every manifest from disk), waiting for a fresh host
|
|
86
|
+
sample every 2 s (55 ms at p90), and writing learned feedback to SQLite (5 ms median). The new
|
|
87
|
+
build caches each endpoint's tag list for 10 s, samples the host and probes Ollama's settings in
|
|
88
|
+
the background, and writes feedback after the response.
|
|
89
|
+
|
|
90
|
+
| Client time minus Ollama engine time | Old build | New build |
|
|
91
|
+
|---|---:|---:|
|
|
92
|
+
| Median | 22.9 ms | 3.7 ms |
|
|
93
|
+
| p90 | 60.3 ms | 5.6 ms |
|
|
94
|
+
| Max | 81.5 ms | 29.6 ms |
|
|
95
|
+
|
|
96
|
+
Both builds measured back to back on the same host at the same load (load average about 7).
|
|
97
|
+
|
|
98
|
+
### Memory gate, live
|
|
99
|
+
|
|
100
|
+
With the host under pressure (load average 16, swapping, 5.9 GB free of 32 GB), a FreeLlama
|
|
101
|
+
`summarize-text` task was held for its 20 s wait limit and then refused: "needs 7.2 GB incl. 3.6 GB reserve, 4.2 GB
|
|
102
|
+
free; largest memory users: Google Chrome Helper ×54 4.6 GB, Code Helper ×3 2.6 GB, node ×13
|
|
103
|
+
2.4 GB…". Nothing was loaded and nothing swapped. The suite has no matching row for the other
|
|
104
|
+
systems yet (`--hog-gb` exists but was not run).
|
|
105
|
+
|
|
106
|
+
## Features
|
|
107
|
+
|
|
108
|
+

|
|
109
|
+
|
|
110
|
+
Each feature measured against the same work without it, through the MCP server an agent uses,
|
|
111
|
+
with a fresh `serve` on the build above (`scripts/bench/features.mjs`). Same Mac, 2026-11-14. Raw
|
|
112
|
+
numbers: [`benchmark-features-raw-2026-11-14.json`](assets/benchmark-features-raw-2026-11-14.json).
|
|
113
|
+
|
|
114
|
+
| Feature | Measured against | Without it | With FreeLlama | How |
|
|
115
|
+
|---|---|---:|---:|---|
|
|
116
|
+
| Priority under load | One interactive task sent after 8 background tasks | 3.52 s (Ollama alone, arrival order) | **1.40 s** | Median of 7 rounds; `priority: "interactive"` vs `"background"`. The whole batch of 9 took 3.62 s and 3.67 s (+1%) |
|
|
117
|
+
| Built-in workflow prompts | The one-line prompt an agent would write | 52% of graded cases | **98%** | 24 cases × 2 samples on `bonsai-2:9b`; [per workflow](#built-in-prompts-measured) |
|
|
118
|
+
| Code search index | The first search of `packages/mcp/src` by meaning | 55.9 s | **0.13 s** (repeat) | Job `find-code` with `nearest`; the repeat embeds no unchanged chunk and returns the same top file |
|
|
119
|
+
| Sweep with a baseline | A first sweep: 83 chunks judged one by one by `strands-decider:2b` | 49.8 s | **18 ms** | `sweep {baseline}` reused all 83 unchanged chunks |
|
|
120
|
+
| Long task as a job | Waiting on one call | — | **29 ms** to a job id | `run_task {defer:true}` for `summarize-log` over `CHANGELOG.md`; done in 19.2 s while the caller polled `task_jobs` |
|
|
121
|
+
| Memory gate | Loading a model that does not fit | — | **Refused** | 7.2 GB needed with 4.2 GB free; nothing was loaded ([details](#memory-gate-live)) |
|
|
122
|
+
| GPU placement | — | — | **119/120** verified | Ollama `/api/ps` after each answer showed the whole model in VRAM |
|
|
123
|
+
| Layer cost | — | — | **9.7 ms CPU, 26–31 MB** per task and server | `ps` CPU time over 100 tasks; peak server RSS |
|
|
124
|
+
|
|
125
|
+
The first index and sweep runs include embedding or judging every chunk; their repeats read saved
|
|
126
|
+
results, so the size of the gain depends on how much changed.
|
|
127
|
+
|
|
128
|
+
Not a FreeLlama-only gain, so not in the table: a second question about the same 3,144-token
|
|
129
|
+
document took 5.1 s instead of 11.9 s (2,120 of 3,151 prompt tokens from cache). That is Ollama's
|
|
130
|
+
prompt cache; FreeLlama keeps the context size and settings stable between calls so the cache
|
|
131
|
+
stays usable, and Ollama alone gives the same when a client does the same. Ollama reuses it across
|
|
132
|
+
turns only for attention models such as `bonsai-2:9b`, not hybrid ones such as `lfm3`.
|
|
133
|
+
|
|
134
|
+
### Built-in prompts, measured
|
|
135
|
+
|
|
136
|
+
FreeLlama's workflows send model-specific prompts evaluated on the dated cases below. To measure what that adds, the
|
|
137
|
+
workflow evaluation (`scripts/local-test/workflows.mjs`) ran the 9 text workflows' graded cases on
|
|
138
|
+
`bonsai-2:9b`, 2 samples each, once with the shipped prompts and once with the one-line prompt an
|
|
139
|
+
agent would write itself ([`baseline-prompts.mjs`](../scripts/local-test/baseline-prompts.mjs),
|
|
140
|
+
naming the answer format where the workflow needs one). Everything else (model, options, grading)
|
|
141
|
+
was the same. On the 24 cases graded both ways:
|
|
142
|
+
|
|
143
|
+
| | Shipped workflow prompts | One-line prompts |
|
|
144
|
+
|---|---:|---:|
|
|
145
|
+
| Pass among completed graded samples | **45/46 (98%)** | 25/48 (52%) |
|
|
146
|
+
| Pass / nominal 48 planned trials | 45/48 (94%) | 25/48 (52%) |
|
|
147
|
+
| Median time per task | **2.54 s** | 3.29 s |
|
|
148
|
+
| Median output tokens | **46.5** | 72.5 |
|
|
149
|
+
|
|
150
|
+
Per workflow (pass rate, median time per task):
|
|
151
|
+
|
|
152
|
+
| Workflow | Built-in prompt | One-line prompt |
|
|
153
|
+
|---|---:|---:|
|
|
154
|
+
| `summarize-text` | 7/7, 1.1 s | 6/8, 1.5 s |
|
|
155
|
+
| `summarize-log` | 9/9, 4.0 s | 2/10, 6.6 s |
|
|
156
|
+
| `summarize-diff` | 4/4, 3.1 s | 4/4, 5.2 s |
|
|
157
|
+
| `extract-json` | 9/10, 2.1 s | 9/10, 1.7 s |
|
|
158
|
+
| `explain-code` | 2/2, 6.9 s | 0/2, 27.7 s |
|
|
159
|
+
| `review-code` | 6/6, 1.6 s | 2/6, 13.2 s |
|
|
160
|
+
| `fix-bug` | 4/4, 3.0 s | 0/4, 2.7 s |
|
|
161
|
+
| `change-code` | 2/2, 2.7 s | 1/2, 2.8 s |
|
|
162
|
+
| `write-tests` | 2/2, 13.6 s | 1/2, 28.6 s |
|
|
163
|
+
|
|
164
|
+
`extract-json` is a tie: a schema-shaped task the one-line prompt already states.
|
|
165
|
+
|
|
166
|
+
The one-line prompts failed by padding past length limits (a log summary of 170 words for a 90-word
|
|
167
|
+
bound), inventing causes ("database" in a log that never mentions one), missing the failed step,
|
|
168
|
+
and leaving out the edit block. The retained aggregates contain 46 shipped completions versus 48
|
|
169
|
+
baseline completions over a nominal 48 planned trials per arm. The 98% figure is 45/46 completed
|
|
170
|
+
samples; counting the two absent shipped completions as not passed gives 45/48 (93.75%). The
|
|
171
|
+
individual traces for those absent samples are not in the checked-in aggregates. Earlier notes
|
|
172
|
+
report six memory-held attempts, but the retained data does not reconstruct those attempts or
|
|
173
|
+
explain their relationship to these two missing completions. Treat this as
|
|
174
|
+
incomplete completion evidence, not a production reliability percentage. The newer
|
|
175
|
+
[tool-calling smoke suite](RELIABILITY.md#public-tool-calling-smoke-suite) tests a different scope.
|
|
176
|
+
|
|
177
|
+
## Scorecard
|
|
178
|
+
|
|
179
|
+
FreeLlama rated on measured numbers only: each target is parity with Ollama alone (which
|
|
180
|
+
FreeLlama runs on) or a fixed bar, and each value comes from this page.
|
|
181
|
+
|
|
182
|
+
| KPI | Target | Measured | How | Result |
|
|
183
|
+
|---|---|---|---|---|
|
|
184
|
+
| Quality: benchmark task | Same as Ollama (100%) | 60/60 correct, byte-identical to Ollama | [KPIs](#kpis) | Met |
|
|
185
|
+
| Quality: built-in prompts | Beat one-line prompts | 45/46 completed vs 25/48; nominal planned 45/48 vs 25/48 | [Denominators and limits](#built-in-prompts-measured) | Observed gain; incomplete shipped trials |
|
|
186
|
+
| Time: median task | Within 5% of Ollama | 274 vs 272 ms (+0.7%) | [KPIs](#kpis) | Met |
|
|
187
|
+
| Time: own overhead | p95 ≤ 15 ms | p95 9.8 ms, median 3.7 ms | [Overhead](#freellamas-overhead-profiled) | Met |
|
|
188
|
+
| Time: first token | Within 10% of Ollama | 95 vs 93 ms (+2%) | [KPIs](#kpis) | Met |
|
|
189
|
+
| Load: 4 clients | ≥ 95% of Ollama's throughput | 221 vs 225 tasks/min (98%) | [Results](#results) | Met |
|
|
190
|
+
| Switching: cold request | Within 5% of Ollama | 1.21 vs 1.13 s (+7%) | [KPIs](#kpis) | **Missed** |
|
|
191
|
+
| CPU | < 2% of one core while serving | 9.7 ms CPU per task, 1.6% of a core | below | Met |
|
|
192
|
+
| Memory: the layer | ≤ 50 MB | 26–31 MB server RSS | [KPIs](#kpis) | Met |
|
|
193
|
+
| Memory: under pressure | Refuse rather than swap | Refused 7.2 GB with 4.2 GB free; swap +0 in every block | [Memory gate](#memory-gate-live) | Met |
|
|
194
|
+
| GPU placement | Every receipt verified | 119/120 verified fully on the GPU | below | **Missed** |
|
|
195
|
+
|
|
196
|
+
The two misses: a cold request costs about 80 ms more through FreeLlama (admission, a host sample
|
|
197
|
+
and the residency watch around the load), and one receipt could not verify placement because the
|
|
198
|
+
model was no longer resident when FreeLlama looked after the answer.
|
|
199
|
+
|
|
200
|
+
**CPU** was measured as the `ps` CPU time (user + system) of FreeLlama's server process over 100
|
|
201
|
+
warm managed tasks, background host sampling included: 9.7 ms per task, against 10.8 ms for
|
|
202
|
+
Ollama's own server process over the same tasks, with tasks 0.6 s apart. **GPU placement** is the
|
|
203
|
+
receipt's `execution.observation`: Ollama's `/api/ps` after each answer showed the model's whole
|
|
204
|
+
size in VRAM (`processor: gpu`) for 119 of 120 FreeLlama tasks.
|
|
205
|
+
|
|
206
|
+
## Competitor landscape
|
|
207
|
+
|
|
208
|
+
Checked on 2026-11-13 using GitHub repository metadata (displayed stars and last push). Stars help
|
|
209
|
+
choose which tools to look at. They do not measure quality or speed.
|
|
210
|
+
|
|
211
|
+
**Runtimes and servers.** These load and run the model themselves.
|
|
212
|
+
|
|
213
|
+
| Project | Stars | Status here |
|
|
214
|
+
|---|---:|---|
|
|
215
|
+
| [Ollama](https://github.com/ollama/ollama) | 186.9k | Benchmarked (baseline; FreeLlama's upstream) |
|
|
216
|
+
| [llama.cpp](https://github.com/ggml-org/llama.cpp) | 134.9k | Benchmarked (`llama-server`) |
|
|
217
|
+
| [vLLM](https://github.com/vllm-project/vllm) | 96.9k | Not run: no Apple Metal backend |
|
|
218
|
+
| [GPT4All](https://github.com/nomic-ai/gpt4all) | 77.3k | Not run: desktop app, last push 2025-05 |
|
|
219
|
+
| [LocalAI](https://github.com/mudler/LocalAI) | 50.4k | Benchmarked |
|
|
220
|
+
| [exo](https://github.com/exo-explore/exo) | 48.4k | Not run: built for clusters of several machines |
|
|
221
|
+
| [textgen (oobabooga)](https://github.com/oobabooga/textgen) | 47.7k | Not run: desktop app |
|
|
222
|
+
| [Jan](https://github.com/janhq/jan) | 45.7k | Not run: desktop app |
|
|
223
|
+
| [SGLang](https://github.com/sgl-project/sglang) | 38.8k | Not run: GPU-server engine |
|
|
224
|
+
| [llamafile](https://github.com/mozilla-ai/llamafile) | 26.6k | Not run: same engine family as llama.cpp |
|
|
225
|
+
| [oMLX](https://github.com/jundot/omlx) | 23.6k | Not run: needs a separate MLX artifact and a third-party tap |
|
|
226
|
+
|
|
227
|
+
**Lifecycle, routing and agent layers.** These are FreeLlama's closest peers. They sit in front
|
|
228
|
+
of an engine.
|
|
229
|
+
|
|
230
|
+
| Project | Stars | Relation to FreeLlama | Status here |
|
|
231
|
+
|---|---:|---|---|
|
|
232
|
+
| [LiteLLM](https://github.com/BerriAI/litellm) | 63.2k | Gateway for many providers: budgets, retries | Not run: a different layer |
|
|
233
|
+
| [llama-swap](https://github.com/mostlygeek/llama-swap) | 6.2k | Starts engines on demand and swaps models | Benchmarked |
|
|
234
|
+
| [GPUStack](https://github.com/gpustack/gpustack) | 6.0k | Schedules models across GPU clusters | Not run: needs several machines |
|
|
235
|
+
|
|
236
|
+
Smaller runtimes, not run: [KoboldCpp](https://github.com/LostRuins/koboldcpp) (12.3k) and
|
|
237
|
+
[mlx-lm](https://github.com/ml-explore/mlx-lm) (7.7k) share an engine family or artifact format with
|
|
238
|
+
those above; [Lemonade](https://github.com/lemonade-sdk/lemonade) (6.2k),
|
|
239
|
+
[LM Studio's CLI](https://github.com/lmstudio-ai/lms) (5.4k), [RamaLama](https://github.com/containers/ramalama)
|
|
240
|
+
(3.1k) and [Docker Model Runner](https://github.com/docker/model-runner) (0.7k) were not installed.
|
|
241
|
+
Ollama-specific layers under 1k stars ([ollama-mcp-bridge](https://github.com/patruff/ollama-mcp-bridge),
|
|
242
|
+
[Olla](https://github.com/thushan/olla), [ollama-mcp](https://github.com/rawveg/ollama-mcp),
|
|
243
|
+
[herd](https://github.com/tom-swift-tech/herd), [ollama-queue-proxy](https://github.com/TadMSTR/ollama-queue-proxy))
|
|
244
|
+
cover one piece each: MCP pass-through, load balancing, GPU routing or a priority queue.
|
|
245
|
+
|
|
246
|
+
Tools at other layers (Open WebUI 158.6k, Fabric 44.6k, llm 12.8k, aichat 10.6k) are clients that
|
|
247
|
+
sit above FreeLlama, not peers. [TensorZero](https://github.com/tensorzero/tensorzero) is now archived,
|
|
248
|
+
and [RouteLLM](https://github.com/lm-sys/RouteLLM) was last pushed in 2024-08.
|
|
249
|
+
|
|
250
|
+
**How systems were chosen.** A system was benchmarked when it serves an HTTP API on this Mac and
|
|
251
|
+
can load the same GGUF bytes. llama-swap was added as the closest lifecycle manager. oMLX was left
|
|
252
|
+
out by the operator: it would need a third-party Homebrew tap plus a 1.71 GB MLX copy of the model
|
|
253
|
+
(`mlx-community/LFM3-VL-2B-OptiQ-4bit`), and that copy would be a separate cohort.
|
|
254
|
+
|
|
255
|
+
### Features beyond speed
|
|
256
|
+
|
|
257
|
+
Checked on 2026-11-14 against each project's README, docs and release notes, not by running
|
|
258
|
+
them. "Partial" means the feature exists with a limit named in the cell.
|
|
259
|
+
|
|
260
|
+
| System | Memory check before a load | Suggests a model that fits | MCP server for agents | OpenAI / Anthropic / Ollama API | Streaming | Prometheus metrics |
|
|
261
|
+
|---|---|---|---|---|---|---|
|
|
262
|
+
| FreeLlama 0.12.0 | Yes: refuses a cold load that would not fit live free memory and names what holds it | Yes: machine-local calibrated routing, then installed catalog fallback and runtime admission | Yes (13 tools), plus a CLI | Gateway: all three | Yes: managed tasks stream with their receipt (`stream: true`); gateway workflows stream through Ollama | Yes, plus a receipt per task |
|
|
263
|
+
| Ollama 0.40.16 | Partial: splits layers to fit VRAM; refuses only when total RAM is short | Partial: featured models, not fitted to the machine | No (`ollama launch` configures agents) | Yes / partial / native | Yes | No |
|
|
264
|
+
| llama.cpp 1.0.0 | Partial: `--fit` on by default; the router unloads to make room, then loads anyway | No | No (MCP client only) | Yes / yes / no | Yes | Yes (opt-in) |
|
|
265
|
+
| LM Studio 0.4.28 | Yes: resource guardrails, `lms load --estimate-only` | Partial: estimates | No (MCP client) | Yes / yes / no | Yes | No |
|
|
266
|
+
| LocalAI 4.12.1 | Yes: `--vram-budget` cap and context auto-fit | Yes: hardware-based recommendations | Unclear (client documented) | Yes / yes / yes | Yes | Yes |
|
|
267
|
+
| oMLX 0.8.0rc1 | Yes: process memory cap and eviction | Yes: first-run fit helper | No (MCP client) | Yes / yes / no | Yes | No |
|
|
268
|
+
| llama-swap v272 | Partial: evicts by declared pools, not measured memory | No | No | Yes / yes / no (passthrough) | Yes | Yes |
|
|
269
|
+
| vLLM 0.32.0 | Not found in docs | Partial: Metal recipes by Mac memory | No | Yes / yes / no | Yes | Yes |
|
|
270
|
+
| Jan 0.8.8 | Partial: fit check; auto-fit off by default since 0.8.1 | Partial | No (MCP client) | Chat completions / unknown / no | Unknown | Unknown |
|
|
271
|
+
| GPT4All 3.10.0 | No (static RAM labels) | Partial: static labels | No | Partial / no / no | Unknown | No |
|
|
272
|
+
|
|
273
|
+
FreeLlama inherits Ollama's engine, formats and modalities (vision, embeddings, speech) and adds
|
|
274
|
+
the gate, the pick and the receipts. Memory-aware loading is no longer rare: LocalAI, oMLX, LM
|
|
275
|
+
Studio and llama.cpp's router each have their own. FreeLlama's distinct parts are a gate driven
|
|
276
|
+
by live host signals, [machine-local calibrated picks with catalog fallback](MODEL_SELECTION.md#turn-measurements-into-routing-evidence),
|
|
277
|
+
job prompts, and an MCP server for bounded agent work. These current selection rules were not
|
|
278
|
+
measured by the pinned single-model comparison above.
|
|
279
|
+
|
|
280
|
+
The dated feature snapshot above lists llama.cpp 1.0.0 (2026-11-13) and Ollama 0.40.16; the measured
|
|
281
|
+
run used llama.cpp build 11960 and Ollama 0.40.15. Do not transfer the results to different versions.
|
|
282
|
+
|
|
283
|
+
## Setup
|
|
284
|
+
|
|
285
|
+
| Item | Value |
|
|
286
|
+
|---|---|
|
|
287
|
+
| Host | Apple M2 Pro, 12 CPUs, 32 GiB unified memory; other applications open; 1-minute load average 9.8 at the start, 5.3 at the end |
|
|
288
|
+
| Model | `lfm3-vl:2b-q4_K_M` (LFM3 1.7B, Q4_K_M), one GGUF file, SHA-256 `56dac2e192ff0d9ab8507f4f1aeb4aed0463449bbbefaac79497f041c95f21eb`, checked with `shasum -a 256` |
|
|
289
|
+
| Task | Extract `id`, `team` and `priority` from a support ticket as JSON; temperature 0, seed 42, 64 output tokens, 4,096 context, thinking off |
|
|
290
|
+
| Tokens per task | 75 prompt + 22 output (Ollama, FreeLlama, LocalAI); 74 + 24 (llama.cpp, llama-swap): each server applies the model's chat template its own way |
|
|
291
|
+
| Ollama | 0.40.15 (`/api/chat`) |
|
|
292
|
+
| FreeLlama | 0.12.0 plus the unreleased changes in the [changelog](../CHANGELOG.md): managed tasks (`/_freellama/v1/tasks`), streamed with `stream: true` |
|
|
293
|
+
| llama.cpp | `llama-server` 0.8.0, build 11960 (`8642541b2`), `-ngl 99 --jinja --reasoning-budget 0` |
|
|
294
|
+
| llama-swap | v272 (`802f1c4`) over the same `llama-server` |
|
|
295
|
+
| LocalAI | 4.12.1, `llama-cpp-development` backend, `gpu_layers: 99`, reasoning off |
|
|
296
|
+
| Procedure | One system at a time; 2 warm-ups, 30 measured requests per pass; forward and reversed order; then 2- and 4-client levels and 3 cold requests (forward only). After each Ollama-backed block the harness unloads the model it loaded |
|
|
297
|
+
|
|
298
|
+
llama.cpp 1.0.0 and Ollama 0.40.16 are outside this measured version cohort.
|
|
299
|
+
|
|
300
|
+
## Limits
|
|
301
|
+
|
|
302
|
+
- One machine, one small model, one short task. Larger models, long prompts and long outputs can
|
|
303
|
+
order the systems differently.
|
|
304
|
+
- Ollama ran with its defaults (`OLLAMA_NUM_PARALLEL` unset); with parallel slots its concurrent
|
|
305
|
+
throughput would change. Not measured.
|
|
306
|
+
- Whole-host CPU includes other applications, so it is recorded in the report, not compared.
|
|
307
|
+
- Process RSS undercounts GPU buffers on unified memory; only FreeLlama's own server RSS is quoted.
|
|
308
|
+
- The memory-pressure comparison (`--hog-gb`) and the agent-token meter are built but not run.
|
|
309
|
+
- Prompt quality was measured on one model (`bonsai-2:9b`), 2 samples per case, with deterministic
|
|
310
|
+
graders; other models gain differently. The one-line baseline is one reasonable agent prompt, not
|
|
311
|
+
the best an agent could write.
|
|
312
|
+
- The feature runs are one sample of each scenario on a busy workstation (load average 10–17),
|
|
313
|
+
except priority (7 rounds). An earlier priority run gave the same interactive gain (3.80 s →
|
|
314
|
+
1.57 s) but a 17% slower batch; the batch cost varies with load.
|
|
315
|
+
- CPU and the overhead before/after were measured outside the benchmark run, on the same host, with
|
|
316
|
+
the same request, minutes apart.
|
|
317
|
+
- Targets in the scorecard were set by the FreeLlama team: parity with Ollama, or the RFC's bars.
|
|
318
|
+
|
|
319
|
+
## Reproduce
|
|
320
|
+
|
|
321
|
+
1. Install the engines: `bash scripts/bench/setup-macos.sh --install` (llama.cpp, LocalAI, oMLX).
|
|
322
|
+
Get llama-swap from its [GitHub release](https://github.com/mostlygeek/llama-swap/releases) and
|
|
323
|
+
check the archive's SHA-256. No model is downloaded automatically.
|
|
324
|
+
2. Set up LocalAI from
|
|
325
|
+
[`localai-model.example.yaml`](../scripts/bench/localai-model.example.yaml). If the stable
|
|
326
|
+
`llama-cpp` backend rejects your model's architecture (4.12.1 rejected `lfm3`), use
|
|
327
|
+
`llama-cpp-development`. Keep
|
|
328
|
+
`reasoning.disable`, or LocalAI spends the 64-token cap on reasoning and returns an empty answer.
|
|
329
|
+
Set up llama-swap from [`llama-swap.example.yaml`](../scripts/bench/llama-swap.example.yaml).
|
|
330
|
+
3. Add `start` commands, or start each service yourself, then run preflight, a forward pass and a
|
|
331
|
+
reversed pass:
|
|
332
|
+
|
|
333
|
+
```sh
|
|
334
|
+
node scripts/bench/preflight.mjs --config CONFIG.json --hash-model --out NEW_PREFLIGHT_DIR
|
|
335
|
+
node scripts/bench/run.mjs --config CONFIG.json --samples 30 --out NEW_FORWARD_DIR
|
|
336
|
+
node scripts/bench/run.mjs --config CONFIG.reversed.json --samples 30 --out NEW_REVERSED_DIR
|
|
337
|
+
node scripts/bench/report.mjs --report NEW_FORWARD_DIR/summary.json --report NEW_REVERSED_DIR/summary.json --out NEW_REPORT.html
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
With two or more `--report` files, the page shows a pooled table (p50/p95 from each run's raw
|
|
341
|
+
`trials.jsonl`) and one table per run order. Preflight reports vendors with `start` as
|
|
342
|
+
`owned_start` and checks only their start command.
|
|
343
|
+
|
|
344
|
+
After each Ollama-backed block, the runner unloads the benchmark model it warmed (`keep_alive: 0`
|
|
345
|
+
at `ollama_base_url`, confirmed by `/api/ps`); `--keep-loaded` skips this. Optional coverage flags,
|
|
346
|
+
described in the [bench README](../scripts/bench/README.md#run-options):
|
|
347
|
+
|
|
348
|
+
- `--max-load-per-cpu X [--strict-load]`: record load and top CPU processes at each block start;
|
|
349
|
+
warn above X, or skip the block as `not_run`.
|
|
350
|
+
- `--concurrency 2,4,8`: C1, N concurrent clients per level on the warm model.
|
|
351
|
+
- `--cold [--cold-samples N]`: C3, unload or restart, then time the first request.
|
|
352
|
+
- `--hog-gb N [--force-hog]` with `--cold`: C2, hold N GiB during each block. Refused above
|
|
353
|
+
estimated available minus 2 GiB unless forced.
|
|
354
|
+
|
|
355
|
+
Keep the background workload fixed and note it. Before claiming a difference, compare it with the
|
|
356
|
+
drift between passes. The runner stops every later vendor if an inference outcome is uncertain or
|
|
357
|
+
if it cannot stop a server it started.
|
|
358
|
+
|
|
359
|
+
The [features](#features) run against a fresh `serve` with its own home and the installed models
|
|
360
|
+
(`--chat-model`, `--decide-model`); it pulls nothing:
|
|
361
|
+
|
|
362
|
+
```sh
|
|
363
|
+
node scripts/bench/features.mjs --binary target/release/freellama --out FEATURES.json
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Local evidence (Git-ignored): `.octocode/bench/live-2026-11-14-v2/` holds the configs, both
|
|
367
|
+
passes (`run-forward/`, `run-reversed/`), raw `trials.jsonl`, cold and concurrency samples, server
|
|
368
|
+
logs, host samples and `background-load.txt`. The charts are drawn from it by
|
|
369
|
+
`node scripts/bench/readme-charts.mjs --run DIR --run DIR --facts docs/assets/benchmark-facts-2026-11-14.json --out docs/assets`.
|
|
370
|
+
|
|
371
|
+
## Verification
|
|
372
|
+
|
|
373
|
+
Historical verification recorded on 2026-11-14 after the benchmark build (before the later
|
|
374
|
+
calibration, engine and refactor changes): `yarn test:js` **1,280 pass** (1 skipped), `yarn
|
|
375
|
+
test:bench` **112 pass**, MCP integration against live Ollama **160 pass**, and the Rust suite
|
|
376
|
+
all unit tests pass (427) with **3 integration-contract failures** (293 pass), all in tests the
|
|
377
|
+
earlier staged branch work did not update (digest-verified
|
|
378
|
+
placement and no inference retry after a 500); none touches the changes measured here. `cargo
|
|
379
|
+
clippy -D warnings` is clean. The production gate (`yarn verify:production`) was not run for that snapshot. These counts and
|
|
380
|
+
failures are preserved as historical context; they are not the current checkout's verification
|
|
381
|
+
status. Use [Testing](TESTING.md) for the current gate commands.
|
package/docs/BUILD_AND_NOTES.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Build from source and operating notes
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Published npm installs need Node.js 22+ and the matching prebuilt platform package; they do not
|
|
4
|
+
compile Rust. Use the [installation guide](../README.md) for that path. The commands below are for
|
|
5
|
+
developing this checkout or building your own executable and addon.
|
|
4
6
|
|
|
5
7
|
## Good to know
|
|
6
8
|
|
|
@@ -13,19 +15,26 @@ Moved from the root README.
|
|
|
13
15
|
- Without CA certificates, as in slim containers, FreeLlama still serves plain-HTTP Ollama. Install
|
|
14
16
|
`ca-certificates` for HTTPS upstreams.
|
|
15
17
|
- The service binds to loopback. For remote access, see [Production](PRODUCTION.md).
|
|
18
|
+
- Default loopback ports: 11434 Ollama, 11435 `freellama serve` (`--listen`), 11436 the CPU-only
|
|
19
|
+
Ollama that `serve --spawn-cpu-backend` starts (`--cpu-backend-port`), 11437 `freellama gateway`
|
|
20
|
+
(`--port`).
|
|
16
21
|
- Port 11435 is also Ollaya's default ([Ollaya API](https://github.com/ollaya-dev/ollaya/blob/main/docs/api.md)).
|
|
17
22
|
To run both, use `serve --listen` on another port and set the MCP server's
|
|
18
23
|
`FREELLAMA_SERVE_ENDPOINT` to match.
|
|
19
24
|
|
|
20
25
|
## Build from source
|
|
21
26
|
|
|
22
|
-
Requires
|
|
27
|
+
Requires Node.js 22.12+ with Corepack and the Rust compiler selected by `rust-toolchain.toml`
|
|
28
|
+
(currently 1.99.0). `Cargo.toml` declares a 1.89 minimum; that floor is separate from the pinned
|
|
29
|
+
development compiler and needs its own check before claiming minimum-version compatibility.
|
|
23
30
|
|
|
24
31
|
```bash
|
|
25
32
|
corepack enable && yarn install && yarn build
|
|
26
33
|
./target/release/freellama serve
|
|
27
34
|
node packages/mcp/dist/index.js # MCP server from this checkout
|
|
35
|
+
node packages/cli/bin/freellama.js run --help # the agent commands (run, chat, gateway…)
|
|
28
36
|
```
|
|
29
37
|
|
|
30
38
|
npm releases can lag this checkout. [Testing](TESTING.md) describes the checks; the release gate
|
|
31
|
-
is `yarn verify:production`.
|
|
39
|
+
is `yarn verify:production`. It includes live-system tiers and all-platform release artifacts;
|
|
40
|
+
building successfully on the current host does not satisfy that complete gate.
|
package/docs/CLI.md
CHANGED
|
@@ -5,6 +5,9 @@ work. It exposes diagnostics, model routing, managed execution, resource control
|
|
|
5
5
|
and Ollama-compatible passthrough. Use the [README CLI section](https://github.com/bgauryy/FreeLlama/blob/main/README.md#from-the-terminal) for first
|
|
6
6
|
use and this reference to look up commands and controls.
|
|
7
7
|
|
|
8
|
+
To use local models from a shell the way `ollama run` works, with job picks, workflows and files,
|
|
9
|
+
use the [agent commands](AGENT_CLI.md) (`freellama run`, `chat`, `gateway`…). [Every API](API.md) puts all the surfaces on one page.
|
|
10
|
+
|
|
8
11
|
## Choose a command
|
|
9
12
|
|
|
10
13
|
```mermaid
|
|
@@ -73,6 +76,12 @@ model; see [client keys and other engines](PRODUCTION.md#client-keys). The runti
|
|
|
73
76
|
`[preload]` table loads models at startup and predicts the next one; see
|
|
74
77
|
[Preload](SCOPES_AND_WARMING.md#preload).
|
|
75
78
|
|
|
79
|
+
An upstream with an explicit `[upstream.llamacpp]` configuration also supports bounded managed
|
|
80
|
+
text tasks through an exact `--model NAME/MODEL` assignment. It requires fixed context/output
|
|
81
|
+
limits and a conservative memory reservation; physical placement and benchmark confidence stay
|
|
82
|
+
unknown. It does not participate in automatic job selection or Ollama model lifecycle controls.
|
|
83
|
+
See [managed llama.cpp](LLAMACPP.md) for setup and supported fields.
|
|
84
|
+
|
|
76
85
|
`serve` exposes both managed routes under `/_freellama/v1/*` and byte-preserving Ollama routes under
|
|
77
86
|
`/api/*` and `/v1/*`. Use `proxy` when you need only the latter. See
|
|
78
87
|
[Architecture](ARCHITECTURE.md) for the request flow.
|
|
@@ -93,10 +102,12 @@ Or let `serve` start and own the CPU process (stopped when `serve` exits; a port
|
|
|
93
102
|
is refused):
|
|
94
103
|
|
|
95
104
|
```bash
|
|
96
|
-
npx @octocodeai/freellama serve --spawn-cpu-backend
|
|
97
|
-
|
|
105
|
+
npx @octocodeai/freellama serve --spawn-cpu-backend \
|
|
106
|
+
--cpu-model nomic-embed-text:latest --cpu-backend-port 11436
|
|
98
107
|
```
|
|
99
108
|
|
|
109
|
+
Use `--ollama-binary /absolute/path/to/ollama` if the intended executable is not `ollama` on `PATH`.
|
|
110
|
+
|
|
100
111
|
FreeLlama rejects a CPU upstream with no assignments, `--cpu-model` without `--cpu-upstream` or
|
|
101
112
|
`--spawn-cpu-backend`, both of those together, and a CPU upstream that is the same Ollama endpoint as
|
|
102
113
|
`--upstream`, including loopback aliases on one port.
|
|
@@ -121,7 +132,7 @@ runtime-file value it defaults to 2 units per `OLLAMA_NUM_PARALLEL` slot of
|
|
|
121
132
|
the Ollama server (read from its process environment where visible; Ollama's own default is 1, so 2).
|
|
122
133
|
`freellama config` shows the effective value and where it came from.
|
|
123
134
|
`--cpu-max-concurrent-tasks` controls the independent CPU pool and defaults to 1. Default base costs
|
|
124
|
-
are embedding 1, chat 2, and vision 4. Embeddings multiply their base by `ceil(input_items/4)`;
|
|
135
|
+
are embedding and decision 1, chat 2, and vision 4. Embeddings multiply their base by `ceil(input_items/4)`;
|
|
125
136
|
the acquired charge is capped to the selected backend's pool. Configure overrides in `[task_costs]`;
|
|
126
137
|
see [monitoring controls](MONITORING.md#adaptive-concurrency). A saturated GPU pool does
|
|
127
138
|
not consume CPU permits. `--max-queue-wait-seconds` defaults to 120; when no permit becomes
|
|
@@ -129,6 +140,8 @@ available, FreeLlama refuses the task with HTTP 503 (`admission_timeout`) instea
|
|
|
129
140
|
A task can ask for a shorter wait with `max_wait_seconds` (`maxWaitSeconds` in MCP); it can never
|
|
130
141
|
exceed the configured one. Omit it to use the server's waiting budget.
|
|
131
142
|
That deadline covers weighted admission, host-resource waiting, and model-transition locking together.
|
|
143
|
+
`FREELLAMA_MAX_REQUEST_BYTES` also caps each managed Ollama response at 64 MiB by default, including
|
|
144
|
+
embedding, decision, error and NDJSON wire bytes; an oversized response fails with nonretryable 502.
|
|
132
145
|
`--max-queued-tasks` (default 16) and `--cpu-max-queued-tasks` (default 8) also bound how many
|
|
133
146
|
parsed requests can be retained per backend; a full queue receives 429 (`admission_queue_full`)
|
|
134
147
|
immediately, and cancelled clients release their waiter. Every capacity refusal carries a
|
|
@@ -160,15 +173,15 @@ unknown measurements, and reserved memory. These flags do not change Ollama or O
|
|
|
160
173
|
When effective available RAM does not cover already-reserved bytes, the task's estimated bytes and the
|
|
161
174
|
reserve, FreeLlama first unloads idle unpinned runners, then holds the new load with
|
|
162
175
|
`held_insufficient_capacity` until capacity returns, refusing with 503 at its deadline. This is the
|
|
163
|
-
default on every platform: Linux
|
|
164
|
-
|
|
165
|
-
|
|
176
|
+
default on every platform: Linux uses kernel `MemAvailable` capped by a smaller cgroup limit,
|
|
177
|
+
Windows uses CIM `FreePhysicalMemory`, and macOS adds a bounded reclaimable estimate to free RAM.
|
|
178
|
+
A load already resident is never held by this capacity check. `--low-memory advisory` (or
|
|
166
179
|
`FREELLAMA_LOW_MEMORY=advisory`) instead dispatches such a load: the receipt reports
|
|
167
180
|
`status: "admitted_low_memory_estimate"` and `assessment.memory_advisory: "below_reserve"` with
|
|
168
181
|
`required_with_reserve_bytes` and `effective_available_bytes`, and Ollama and the OS decide whether
|
|
169
182
|
it fits.
|
|
170
183
|
OS memory pressure holds new loads where the OS reports it (macOS, and Linux when the kernel
|
|
171
|
-
exposes `/proc/pressure/memory`; Windows
|
|
184
|
+
exposes `/proc/pressure/memory`; Windows does not expose this signal through its collector), and holds already-resident
|
|
172
185
|
runners too only at the critical level: a warning is what a large load itself raises. Active
|
|
173
186
|
swapping and low RAM hold new loads only: an already-resident runner adds no memory and stays
|
|
174
187
|
admitted, for raw passthrough requests too when the request's `model` is in Ollama's `/api/ps`. The CPU-load hold (one-minute load at
|
|
@@ -181,15 +194,17 @@ request on a runner already resident on the GPU proceeds. The receipt's `resourc
|
|
|
181
194
|
lists the holds that applied to the request.
|
|
182
195
|
Both `serve` and `proxy` accept `--resource-telemetry-policy`:
|
|
183
196
|
|
|
184
|
-
- `require-memory` (default on Linux and
|
|
197
|
+
- `require-memory` (default on Linux, macOS and Windows): wait or refuse local inference when available RAM is
|
|
185
198
|
unknown, including raw requests with zero forecast bytes. Missing thermal data alone does not block
|
|
186
199
|
this policy.
|
|
187
200
|
- `require-all`: require all signals applicable to the collector. The built-in Linux collector reads
|
|
188
201
|
OS memory pressure from `/proc/pressure/memory` when the kernel provides it, but has no thermal
|
|
189
202
|
signal and marks it as unsupported; custom collectors must provide it. Unsupported signals are not
|
|
190
203
|
evidence of healthy hardware.
|
|
191
|
-
- `best-effort`: explicitly permit unknown telemetry unless an observed pressure hold is active.
|
|
192
|
-
|
|
204
|
+
- `best-effort`: explicitly permit unknown telemetry unless an observed pressure hold is active.
|
|
205
|
+
Unsupported platforms without a collector use this default. Windows instead requires its bounded
|
|
206
|
+
PowerShell/CIM memory observation; its CPU-load, OS-pressure, thermal, swap and GPU signals remain
|
|
207
|
+
unknown, so `require-all` holds work there. See [Windows memory telemetry](MONITORING.md#read-the-live-status).
|
|
193
208
|
|
|
194
209
|
Remote upstreams bypass local host policy. Raw metadata and empty unload requests remain available
|
|
195
210
|
during a hold. Route receipts separate `queue_readiness` from `resource_readiness`, and include
|
|
@@ -291,6 +306,10 @@ Useful task options include:
|
|
|
291
306
|
- `--stop-on-repetition` to stream the task and stop once the output repeats itself, keeping all
|
|
292
307
|
generated text.
|
|
293
308
|
- `--defer` to return a job ID immediately.
|
|
309
|
+
- repeatable `--fallback-model TAG` for an ordered fallback chain (up to 4): each model runs only
|
|
310
|
+
after the one before it was refused before anything executed (no room by the wait deadline, input
|
|
311
|
+
over its context window, not installed or ineligible, circuit open), never after a model started.
|
|
312
|
+
The receipt's `fallback` lists every attempt ([fallback chains](FEATURES.md#fallback-chains)).
|
|
294
313
|
|
|
295
314
|
Inspect deferred work with `jobs`, retrieve a result with `jobs --id <uuid>`, and cancel one task
|
|
296
315
|
with `jobs --id <uuid> --cancel`. Remove one task with `jobs --id <uuid> --remove`: active work is
|
|
@@ -300,10 +319,13 @@ through MCP `task_jobs`.
|
|
|
300
319
|
Cancellation and removal wait for local execution permits to be released; they do not unload a shared model
|
|
301
320
|
or confirm that the physical runner has stopped.
|
|
302
321
|
|
|
303
|
-
|
|
322
|
+
By default jobs stay in server memory: at most 64 receipts, 16 MiB per input (64 MiB across queued and running
|
|
304
323
|
jobs), and 2 MiB per retained result or error. Finished receipts expire after 10 minutes and can be evicted earlier to make room for new
|
|
305
324
|
work. A restart discards all jobs. Admission queue limits still apply, and deferred work can fail
|
|
306
325
|
after acceptance. See [monitoring](MONITORING.md) for states and waiting reasons.
|
|
326
|
+
Opt-in durable receipts retain terminal results and idempotency records in the file-backed store;
|
|
327
|
+
they never replay prompts after restart. See [durable deferred jobs](DEFERRED_JOBS.md) before
|
|
328
|
+
enabling `FREELLAMA_DURABLE_JOBS` or using an idempotency key.
|
|
307
329
|
|
|
308
330
|
Create a session with `session`, then pass its identifier to related `route` or `task` calls. A
|
|
309
331
|
route preview honors an existing affinity but does not create or change one. Only a successfully
|
|
@@ -345,6 +367,15 @@ npx @octocodeai/freellama bench-all --output benchmark-report.json
|
|
|
345
367
|
npx @octocodeai/freellama serve
|
|
346
368
|
```
|
|
347
369
|
|
|
370
|
+
Without `--output`, `bench-all` writes `benchmark-report.json` in the FreeLlama home so the next
|
|
371
|
+
`serve` start discovers it automatically. Use repeated `--include EXACT_TAG` flags to bound the run.
|
|
372
|
+
Reports qualify only their measured host/hardware, endpoint and artifact digests; old or foreign
|
|
373
|
+
reports do not qualify routing. Schema-2 reports record a hashed machine identity and observed
|
|
374
|
+
hardware; missing identity or remote endpoints cannot establish machine-local throughput. A primary
|
|
375
|
+
endpoint report does not qualify a separately assigned CPU runner. Throughput screens do not
|
|
376
|
+
establish job accuracy; that requires task-quality evidence and verification. See
|
|
377
|
+
[machine calibration](MODEL_SELECTION.md#turn-measurements-into-routing-evidence).
|
|
378
|
+
|
|
348
379
|
`serve` resolves each file in this order: the explicit flag, its environment variable, the working
|
|
349
380
|
directory, then the FreeLlama home (`~/.octocode/freellama`, or `--home` / `FREELLAMA_HOME`). The home also holds
|
|
350
381
|
`runtime.toml`, read when neither `--runtime-config` nor `FREELLAMA_RUNTIME_CONFIG` is set.
|
|
@@ -362,6 +393,10 @@ schema_version = 1
|
|
|
362
393
|
[policies.code_repair]
|
|
363
394
|
qualified_models = ["qwen3.8:27b-mlx"] # best first; quality-qualified only
|
|
364
395
|
|
|
396
|
+
# Preserve the digest recorded by the evaluation, never substitute today's tag digest.
|
|
397
|
+
[policies.code_repair.model_digests]
|
|
398
|
+
"qwen3.8:27b-mlx" = "sha256:REPLACE_WITH_EVALUATED_DIGEST"
|
|
399
|
+
|
|
365
400
|
# Optional request defaults for one exact tag on this task: think and num_predict (>= 1).
|
|
366
401
|
[policies.code_repair.model_options."qwen3.8:27b-mlx"]
|
|
367
402
|
think = false
|
|
@@ -374,11 +409,12 @@ num_predict = 512
|
|
|
374
409
|
[platform.example.toml](https://github.com/bgauryy/FreeLlama/blob/main/platform.example.toml).
|
|
375
410
|
|
|
376
411
|
The MCP server autostarts `serve` with its own environment and an arbitrary working directory, so
|
|
377
|
-
put a machine-wide policy in the
|
|
412
|
+
put a machine-wide policy in the FreeLlama home or set the variables in the MCP client's `env`.
|
|
378
413
|
`serve` prints each file it picked up.
|
|
379
414
|
|
|
380
415
|
`policy from-eval` reads `pass_at_1`, not the throughput produced by `bench-all`. It refuses
|
|
381
|
-
expired aggregates and fewer than three trials unless `--allow-smoke` is explicit
|
|
416
|
+
expired aggregates and fewer than three trials unless `--allow-smoke` is explicit. That flag
|
|
417
|
+
produces smoke-only output for inspection, which `serve` refuses as a routing policy. It skips
|
|
382
418
|
models that are not installed on `--ollama-endpoint` (default `FREELLAMA_OLLAMA_ENDPOINT`, then
|
|
383
419
|
`http://127.0.0.1:11434`). This prevents speed data from being mislabeled as quality evidence.
|
|
384
420
|
It accepts the task kinds `route` accepts, with `-` or `_` (`code-repair` or `code_repair`), writes
|
|
@@ -386,7 +422,16 @@ to stdout unless `--out` is given, and reports a refusal as one `error: ...` lin
|
|
|
386
422
|
|
|
387
423
|
## Compare the CLI and MCP surfaces
|
|
388
424
|
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
425
|
+
| Need | Operator commands | MCP | Agent commands (`run`, `chat`, `gateway`, `tool`) |
|
|
426
|
+
|---|---|---|---|
|
|
427
|
+
| Run the service, the proxy, benchmarks, policies, tokens | `serve`, `proxy`, `bench-all`, `policy from-eval`, `auth-token` | — | — |
|
|
428
|
+
| One task with a job's pick, prompts and files | `task` (by task kind, no jobs) | `run_task {job\|workflow, files}` | `freellama run -j\|-w … -f …` |
|
|
429
|
+
| Batches, embeddings with `nearest`, decisions | `task` (one item) | `run_task {tasks}`, `nearest`, `questions` | `freellama run -j find-code`, `--ask`; batches through `freellama tool run_task` |
|
|
430
|
+
| Model library search and pulls | — | `models {view:"library"}`, `ollama_pull` | `freellama tool models\|ollama_pull` (approval still applies) |
|
|
431
|
+
| Research, sweeps, speech, saved responses | — | `delegate_research`, `sweep`, `audio`, `read_response` | `freellama tool NAME JSON` |
|
|
432
|
+
| Ollama, OpenAI and Anthropic clients | `serve` passthrough (real tags) | — | `freellama gateway` (virtual models and real tags) |
|
|
433
|
+
|
|
434
|
+
`freellama tool` reaches all 13 MCP tools with the same schemas, because both surfaces register from
|
|
435
|
+
one list. For the MCP tool contracts, read the
|
|
436
|
+
[MCP package reference](https://github.com/bgauryy/FreeLlama/blob/main/packages/mcp/README.md)
|
|
437
|
+
and [Every API](API.md#mcp-tools).
|