@octocodeai/freellama-mcp-server 0.1.0 → 0.6.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 +108 -0
- package/DEVELOPING.md +109 -0
- package/LICENSE-APACHE +202 -0
- package/LICENSE-MIT +18 -0
- package/README.md +261 -243
- package/assets/logo.jpg +0 -0
- package/dist/index.js +2305 -1332
- package/dist/research/bash-agent.js +2435 -0
- package/dist/research/octocode-agent.js +1639 -0
- package/docs/ARCHITECTURE.md +294 -87
- package/docs/CLI.md +171 -53
- package/docs/CPU_GPU_ROUTING.md +69 -23
- package/docs/MODEL_SELECTION.md +126 -3
- package/docs/MONITORING.md +293 -0
- package/docs/PRODUCTION.md +53 -25
- package/docs/README.md +36 -0
- package/docs/SCOPES_AND_WARMING.md +225 -0
- package/docs/TESTING.md +113 -8
- package/native/index.d.ts +186 -150
- package/native/index.js +3 -3
- package/package.json +15 -11
- package/adapters/agent_context.py +0 -663
- package/adapters/agent_transport.py +0 -84
- package/adapters/bash_agent.py +0 -370
- package/adapters/octocode_agent.py +0 -394
- package/docs/ADR_RESOURCE_AWARE_BACKEND_ROUTING.md +0 -55
- package/docs/ECONOMICS.md +0 -105
- package/docs/INDEX.md +0 -15
- package/docs/OLLAMA_SIDECAR.md +0 -76
- package/docs/OLLAMA_SYSTEM_OPTIMIZATION.md +0 -254
- package/docs/PRODUCT_POSITIONING.md +0 -291
package/docs/CLI.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# CLI reference
|
|
2
2
|
|
|
3
|
-
The `freellama` command
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
The `freellama` command starts and inspects the local management layer that agents use to offload
|
|
4
|
+
work. It exposes diagnostics, model routing, managed execution, resource controls, benchmarking,
|
|
5
|
+
and Ollama-compatible passthrough. Use the [README CLI section](https://github.com/bgauryy/FreeLlama/blob/main/README.md#or-use-the-cli) for first
|
|
6
|
+
use and this reference to look up commands and controls.
|
|
6
7
|
|
|
7
8
|
## Choose a command
|
|
8
9
|
|
|
@@ -11,34 +12,34 @@ flowchart TD
|
|
|
11
12
|
Q{"What do you need?"}
|
|
12
13
|
Q -->|"Prepare first use"| I["init"]
|
|
13
14
|
Q -->|"Inspect this machine"| D["doctor or machine"]
|
|
14
|
-
Q -->|"Inspect or choose a model"| M["models
|
|
15
|
-
Q -->|"Execute a managed request"| T["session
|
|
15
|
+
Q -->|"Inspect or choose a model"| M["models or route"]
|
|
16
|
+
Q -->|"Execute a managed request"| T["session or task"]
|
|
16
17
|
Q -->|"Run the control plane"| S["serve"]
|
|
17
18
|
Q -->|"Preserve only Ollama APIs"| P["proxy"]
|
|
18
|
-
Q -->|"Measure
|
|
19
|
-
Q -->|"
|
|
20
|
-
Q -->|"Compare CLI and MCP"| L["tools"]
|
|
19
|
+
Q -->|"Measure models"| B["bench-all"]
|
|
20
|
+
Q -->|"Write a routing policy"| PE["policy from-eval"]
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
| Command | Purpose | Needs `freellama serve` |
|
|
24
24
|
|---|---|---|
|
|
25
|
-
| `init` | Inspect prerequisites and print a side-effect-free first-run plan | No |
|
|
25
|
+
| `init` | Inspect prerequisites and print a side-effect-free first-run plan with readiness flags | No |
|
|
26
26
|
| `serve` | Run the control plane and Ollama-compatible proxy | Starts it |
|
|
27
27
|
| `auth-token` | Create a new mode-0600 bearer-token file without printing the secret | No |
|
|
28
28
|
| `models` | List installed models, capabilities, residency, and evidence | Yes |
|
|
29
29
|
| `machine` | Print portable host RAM, CPU, OS, architecture, disk, and the local Ollama endpoint | Yes |
|
|
30
|
-
| `
|
|
30
|
+
| `status` | Live queues (also as a page at `http://127.0.0.1:11435/_freellama/ui`), current and adaptive limits, circuit breakers, loaded models, host memory, Ollama's effective settings, today's usage | Yes |
|
|
31
|
+
| `usage` | Task and token totals per day and per model (`--days`, default 7) | Yes |
|
|
32
|
+
| `config` | Effective runtime settings and the source of each; `--reload` re-reads the runtime file | Yes |
|
|
33
|
+
| `session` | Create model affinity for related tasks | Yes |
|
|
34
|
+
| `scope` | Create, inspect, fork, or delete bounded message history | Yes |
|
|
35
|
+
| `warm` | Warm an installed model through managed admission | Yes |
|
|
31
36
|
| `route` | Choose a model and request profile without executing it | Yes |
|
|
32
|
-
| `recommend` | Return an installed route or a reviewed installation plan | Yes |
|
|
33
|
-
| `natural-route` | Convert natural language to a route intent locally, then route it | Yes |
|
|
34
37
|
| `task` | Route and execute one nonstreaming task | Yes |
|
|
38
|
+
| `jobs` | List, inspect, cancel, or remove deferred tasks and warming operations | Yes |
|
|
35
39
|
| `proxy` | Run only the Ollama-compatible retry and telemetry sidecar | No |
|
|
36
40
|
| `bench-all` | Measure installed models by capability group | No |
|
|
37
|
-
| `policy
|
|
38
|
-
| `tools` | Print MCP tools and their CLI equivalents | No |
|
|
41
|
+
| `policy from-eval` | Write a task policy (`platform.toml`) from a quality-evaluation aggregate and the installed tags | No |
|
|
39
42
|
| `doctor` | Inspect Ollama, hardware, versions, and effective settings | No |
|
|
40
|
-
| `run` | Run a frozen suite against one Ollama build | No |
|
|
41
|
-
| `eval` | Compare the same frozen suite against stock and candidate builds | No |
|
|
42
43
|
|
|
43
44
|
Run `npx @octocodeai/freellama <command> --help` for every accepted flag and enum value. The executable's help
|
|
44
45
|
is authoritative; this page explains how the commands fit together.
|
|
@@ -46,13 +47,16 @@ is authoritative; this page explains how the commands fit together.
|
|
|
46
47
|
## Start the control plane
|
|
47
48
|
|
|
48
49
|
```bash
|
|
49
|
-
npx @octocodeai/freellama serve
|
|
50
|
+
npx @octocodeai/freellama serve
|
|
50
51
|
```
|
|
51
52
|
|
|
52
53
|
The default listener is `http://127.0.0.1:11435`, and the default Ollama upstream is
|
|
53
54
|
`http://127.0.0.1:11434`. Use `--listen` and `--upstream` to change them. Nonloopback listeners
|
|
54
55
|
require `--allow-remote` and a token from `--auth-token-file` or
|
|
55
|
-
`FREELLAMA_AUTH_TOKEN_FILE`. Authentication applies to managed and passthrough routes.
|
|
56
|
+
`FREELLAMA_AUTH_TOKEN_FILE`. Authentication applies to managed and passthrough routes. The token
|
|
57
|
+
file must be a regular file, not a symlink, and hold one token of at least 32 bytes; surrounding
|
|
58
|
+
whitespace is trimmed. On Unix it must also be owner-only (mode 0600). Windows file permissions
|
|
59
|
+
(ACLs) are not checked, so protect the file with your user profile's permissions there.
|
|
56
60
|
|
|
57
61
|
`serve` persists bounded adaptive feedback under the platform data directory by default. Override
|
|
58
62
|
the path with `--feedback-file`; use `--ephemeral-feedback` only for disposable runs. See the
|
|
@@ -91,20 +95,80 @@ placement.
|
|
|
91
95
|
|
|
92
96
|
### Bound admission
|
|
93
97
|
|
|
94
|
-
`--max-concurrent-tasks` is the primary/GPU cost budget, not a request count
|
|
95
|
-
|
|
96
|
-
|
|
98
|
+
`--max-concurrent-tasks` is the primary/GPU cost budget, not a request count. Without a flag or
|
|
99
|
+
runtime-file value it defaults to 2 units per `OLLAMA_NUM_PARALLEL` slot of
|
|
100
|
+
the Ollama server (read from its process environment where visible; Ollama's own default is 1, so 2).
|
|
101
|
+
`freellama config` shows the effective value and where it came from.
|
|
102
|
+
`--cpu-max-concurrent-tasks` controls the independent CPU pool and defaults to 1. Default base costs
|
|
103
|
+
are embedding 1, chat 2, and vision 4. Embeddings multiply their base by `ceil(input_items/4)`;
|
|
104
|
+
the acquired charge is capped to the selected backend's pool. Configure overrides in `[task_costs]`;
|
|
105
|
+
see [monitoring controls](MONITORING.md#adaptive-concurrency). A saturated GPU pool does
|
|
97
106
|
not consume CPU permits. `--max-queue-wait-seconds` defaults to 120; when no permit becomes
|
|
98
|
-
available, FreeLlama refuses the task with HTTP 503 instead of waiting forever.
|
|
107
|
+
available, FreeLlama refuses the task with HTTP 503 (`admission_timeout`) instead of waiting forever.
|
|
108
|
+
A task can ask for a shorter wait with `max_wait_seconds` (`maxWaitSeconds` in MCP); it can never
|
|
109
|
+
exceed the configured one. Omit it to use the server's waiting budget.
|
|
110
|
+
That deadline covers weighted admission, host-resource waiting, and model-transition locking together.
|
|
111
|
+
`--max-queued-tasks` (default 16) and `--cpu-max-queued-tasks` (default 8) also bound how many
|
|
112
|
+
parsed requests can be retained per backend; a full queue receives 429 (`admission_queue_full`)
|
|
113
|
+
immediately, and cancelled clients release their waiter. Every capacity refusal carries a
|
|
114
|
+
`Retry-After` header and `retry_after_seconds`, estimated from queue depth and the backend's recent
|
|
115
|
+
task duration, so clients back off instead of retrying hot. Health exposes the queue depth, oldest wait, in-flight work, and
|
|
116
|
+
refusal/timeout/cancellation counters.
|
|
99
117
|
|
|
100
118
|
These are conservative workload-unit defaults, not detected core or RAM counts. Tune them from
|
|
101
119
|
queue-wait receipts and resident-memory observations on the target host. Ollama still controls
|
|
102
120
|
decoding concurrency with `OLLAMA_NUM_PARALLEL`. It also owns a separate internal queue through
|
|
103
121
|
`OLLAMA_MAX_QUEUE`: managed tasks enter that queue only after FreeLlama admission, while raw proxy
|
|
104
122
|
traffic enters it directly. Start an unmeasured deployment with one loaded model and one parallel
|
|
105
|
-
stream per Ollama process.
|
|
106
|
-
|
|
107
|
-
|
|
123
|
+
stream per Ollama process. In `serve`, raw passthrough defaults to one full-lifetime streaming
|
|
124
|
+
request; override with `--raw-proxy-max-concurrent-requests` only after measurement. A raw request
|
|
125
|
+
over the cap waits up to `--raw-queue-wait-seconds` (default 10) and is then refused with 429 and
|
|
126
|
+
`Retry-After`; `0` restores immediate refusal.
|
|
127
|
+
|
|
128
|
+
All of these, plus pinned models, idle eviction, adaptive concurrency, the circuit breaker, and
|
|
129
|
+
context sizing, can also live in a runtime file (`--runtime-config`) that `serve` re-reads when it
|
|
130
|
+
changes. See [Monitoring and live tuning](MONITORING.md). The standalone
|
|
131
|
+
`proxy` command keeps its cap opt-in for compatibility.
|
|
132
|
+
|
|
133
|
+
The local host-pressure gate reports low available RAM below 15% and clears it above 20% after two
|
|
134
|
+
healthy samples; minimum reserves are 1 GiB and 2 GiB, respectively. Tune the percentages with
|
|
135
|
+
`--resource-hold-available-percent` and `--resource-resume-available-percent`; the hold value must be
|
|
136
|
+
lower than the resume value, and neither can exceed 100. Health reports the policy, sampled signals,
|
|
137
|
+
unknown measurements, and reserved memory. These flags do not change Ollama or OS settings.
|
|
138
|
+
|
|
139
|
+
On macOS, low available RAM is advisory and never refuses a task. Effective available RAM is free
|
|
140
|
+
memory plus a bounded reclaimable estimate, so it can be far lower than what the OS can actually
|
|
141
|
+
reclaim. When it does not cover already-reserved bytes, the task's estimated bytes, and the reserve,
|
|
142
|
+
FreeLlama first unloads idle unpinned runners, then dispatches anyway: the receipt reports
|
|
143
|
+
`status: "admitted_low_memory_estimate"` and `assessment.memory_advisory: "below_reserve"` with
|
|
144
|
+
`required_with_reserve_bytes` and `effective_available_bytes`. Ollama and the OS decide whether the
|
|
145
|
+
load fits. On Linux, Windows, and other platforms, where available RAM already counts reclaimable
|
|
146
|
+
cache (and is the hard cap in a container), the same shortfall unloads idle runners and then holds the
|
|
147
|
+
new load with `held_insufficient_capacity` until capacity returns, refusing with 503 at its deadline.
|
|
148
|
+
OS memory pressure holds work on every platform. Active swapping and low RAM hold new loads only:
|
|
149
|
+
an already-resident runner adds no memory and stays admitted. CPU-load (one-minute load at or above
|
|
150
|
+
1.5 per logical CPU) and thermal-throttling holds apply to CPU-assigned work and to cold loads, which
|
|
151
|
+
decode weights on the host cores and add a new heat source; a bounded request on a runner already
|
|
152
|
+
resident on the GPU neither waits for the cores nor cools the package by waiting, so it proceeds. The receipt's `resource_admission.assessment.held_by`
|
|
153
|
+
lists the holds that applied to the request.
|
|
154
|
+
Both `serve` and `proxy` accept `--resource-telemetry-policy`:
|
|
155
|
+
|
|
156
|
+
- `require-memory` (default): wait or refuse local inference when available RAM is unknown, including
|
|
157
|
+
raw requests with zero forecast bytes. Missing thermal data alone does not block this policy.
|
|
158
|
+
- `require-all`: require all signals applicable to the collector. The built-in Linux collector does
|
|
159
|
+
not provide OS pressure or thermal signals and marks those as unsupported; custom collectors must
|
|
160
|
+
provide them. Unsupported signals are not evidence of healthy hardware.
|
|
161
|
+
- `best-effort`: explicitly permit unknown telemetry unless an observed pressure hold is active.
|
|
162
|
+
|
|
163
|
+
Remote upstreams bypass local host policy. Raw metadata and empty unload requests remain available
|
|
164
|
+
during a hold. Route receipts separate `queue_readiness` from `resource_readiness`, and include
|
|
165
|
+
`resource_assessment` without acquiring a permit. Resource refusals return a human-readable `error`,
|
|
166
|
+
a stable `code`, and an object-valued `resource_admission`; timeout during metadata inspection reports
|
|
167
|
+
its phase and omits estimates that were not obtained.
|
|
168
|
+
|
|
169
|
+
See [resource admission](ARCHITECTURE.md#managed-task-execution) for scope and limitations.
|
|
170
|
+
|
|
171
|
+
`route` and `task` accept
|
|
108
172
|
`--execution-preference auto|prefer-cpu|prefer-gpu`. This is a fallback-capable hint over models
|
|
109
173
|
already assigned by the operator; it never rewrites raw passthrough and never makes an ineligible
|
|
110
174
|
model eligible. Preview the route and inspect the `execution` receipt to confirm whether the hint
|
|
@@ -115,6 +179,10 @@ placement; the default `configured` accepts the operator assignment and observes
|
|
|
115
179
|
|
|
116
180
|
Start with the read-only guided receipt, then inspect available models. `init` never pulls a model;
|
|
117
181
|
it stops at exact-tag approval and prints the next prerequisite, serve, managed-task, and MCP steps.
|
|
182
|
+
Its `status` is `blocked` when Ollama is unavailable, `setup_required` when the managed service or
|
|
183
|
+
installed models are missing, and `ready` when all three are present. Separate `readiness` flags
|
|
184
|
+
identify the missing part. Readiness does not qualify a model for a particular task; use a route
|
|
185
|
+
preview to inspect eligibility and rejection reasons.
|
|
118
186
|
|
|
119
187
|
```bash
|
|
120
188
|
npx @octocodeai/freellama init
|
|
@@ -135,14 +203,10 @@ npx @octocodeai/freellama route \
|
|
|
135
203
|
|
|
136
204
|
Task kinds are `completion`, `coding`, `code-repair`, `tools`, `browser`, `vision`, `embedding`, and
|
|
137
205
|
`long-context`. Objectives are `fastest`, `balanced`, and `quality`. `fastest` can use capability
|
|
138
|
-
and local benchmark evidence alone
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
`natural-route` asks the configured local intent model to produce structured intent, validates that
|
|
144
|
-
intent, and then invokes the same deterministic router as `route`. It does not let the intent model
|
|
145
|
-
choose the final model directly.
|
|
206
|
+
and local benchmark evidence alone. Default `balanced` prefers eligible task-policy candidates;
|
|
207
|
+
without them it falls back to capability/context-compatible models and reports low confidence
|
|
208
|
+
and missing quality evidence. `quality` requires a policy unless you supply an explicit model.
|
|
209
|
+
An explicit minimum-confidence gate still refuses insufficient evidence in every objective.
|
|
146
210
|
|
|
147
211
|
## Execute tasks
|
|
148
212
|
|
|
@@ -157,19 +221,43 @@ Useful task options include:
|
|
|
157
221
|
|
|
158
222
|
- `--model` for an exact installed model.
|
|
159
223
|
- `--session` for affinity across related requests.
|
|
160
|
-
- `--
|
|
224
|
+
- `--scope-id` and `--scope-revision` together for bounded message history.
|
|
225
|
+
- `--keep-alive` for an explicit residency duration.
|
|
226
|
+
- `--context-tokens` for the complete input and output context window (`num_ctx`).
|
|
161
227
|
- repeatable `--required-capability` constraints.
|
|
162
228
|
- repeatable `--image` paths for vision tasks.
|
|
163
229
|
- `--input-file` for batched embedding input, one item per line.
|
|
164
230
|
- `--min-confidence low|medium` to refuse insufficiently evidenced routes before generation.
|
|
231
|
+
- `--priority interactive|normal|background` for fair admission scheduling.
|
|
232
|
+
- `--max-wait-seconds` for a shorter admission/resource wait budget.
|
|
233
|
+
- `--timeout-seconds` for a total deadline including discovery, waiting, loading, and inference.
|
|
234
|
+
- `--stop-on-repetition` to stream the task and stop once the output repeats itself, keeping all
|
|
235
|
+
generated text.
|
|
236
|
+
- `--defer` to return a job ID immediately.
|
|
237
|
+
|
|
238
|
+
Inspect deferred work with `jobs`, retrieve a result with `jobs --id <uuid>`, and cancel one task
|
|
239
|
+
with `jobs --id <uuid> --cancel`. Remove one task with `jobs --id <uuid> --remove`: active work is
|
|
240
|
+
cancelled first, then its retained record and result are deleted. Use the exact ID returned at
|
|
241
|
+
submission; `--cancel` and `--remove` are mutually exclusive. The same operations are available
|
|
242
|
+
through MCP `task_jobs`.
|
|
243
|
+
Cancellation and removal wait for local execution permits to be released; they do not unload a shared model
|
|
244
|
+
or confirm that the physical runner has stopped.
|
|
245
|
+
|
|
246
|
+
Jobs stay in server memory: at most 64 receipts, 1 MiB per input, and 2 MiB per retained result or
|
|
247
|
+
error. Finished receipts expire after 10 minutes and can be evicted earlier to make room for new
|
|
248
|
+
work. A restart discards all jobs. Admission queue limits still apply, and deferred work can fail
|
|
249
|
+
after acceptance. See [monitoring](MONITORING.md) for states and waiting reasons.
|
|
165
250
|
|
|
166
251
|
Create a session with `session`, then pass its identifier to related `route` or `task` calls. A
|
|
167
252
|
route preview honors an existing affinity but does not create or change one. Only a successfully
|
|
168
253
|
admitted task execution binds the session to its selected model. Reuse never bypasses capability,
|
|
169
254
|
policy, or memory checks.
|
|
170
255
|
|
|
171
|
-
|
|
172
|
-
`"-1"`
|
|
256
|
+
`task --keep-alive` and MCP `run_task.keepAlive` control residency: `"0"` requests immediate
|
|
257
|
+
unload, `"-1"` requests indefinite retention, and omission selects finite adaptive retention.
|
|
258
|
+
`session` retains affinity only; use `scope` for revision-protected message history and `warm`
|
|
259
|
+
for an admitted runner load. See [Scope history and model warming](SCOPES_AND_WARMING.md) for
|
|
260
|
+
input shapes, limits, and CLI examples.
|
|
173
261
|
|
|
174
262
|
## Earn medium routing confidence
|
|
175
263
|
|
|
@@ -178,7 +266,7 @@ benchmark record for the selected model.
|
|
|
178
266
|
|
|
179
267
|
```mermaid
|
|
180
268
|
flowchart LR
|
|
181
|
-
Q["Quality evaluation aggregate"] --> P["policy
|
|
269
|
+
Q["Quality evaluation aggregate"] --> P["freellama policy from-eval"]
|
|
182
270
|
P --> PF["platform.toml"]
|
|
183
271
|
T["Local throughput benchmark"] --> BR["benchmark-report.json"]
|
|
184
272
|
PF --> S["freellama serve"]
|
|
@@ -186,34 +274,64 @@ flowchart LR
|
|
|
186
274
|
S --> C["Medium confidence for configured, measured routes"]
|
|
187
275
|
```
|
|
188
276
|
|
|
189
|
-
Generate the policy from correctness data and the benchmark report from
|
|
277
|
+
Generate the policy from correctness data with `policy from-eval` and the benchmark report from
|
|
278
|
+
local runtime data:
|
|
190
279
|
|
|
191
280
|
```bash
|
|
192
|
-
npx @octocodeai/freellama policy
|
|
193
|
-
--aggregate
|
|
281
|
+
npx @octocodeai/freellama policy from-eval \
|
|
282
|
+
--aggregate aggregate.json \
|
|
194
283
|
--task coding \
|
|
195
284
|
--min-pass 0.8 \
|
|
196
285
|
--out platform.toml
|
|
197
286
|
|
|
198
287
|
npx @octocodeai/freellama bench-all --output benchmark-report.json
|
|
199
|
-
npx @octocodeai/freellama serve
|
|
288
|
+
npx @octocodeai/freellama serve
|
|
200
289
|
```
|
|
201
290
|
|
|
202
|
-
`serve`
|
|
203
|
-
|
|
291
|
+
`serve` resolves each file in this order: the explicit flag, its environment variable, the working
|
|
292
|
+
directory, then the per-user config directory (`$XDG_CONFIG_HOME/freellama/` or
|
|
293
|
+
`~/.config/freellama/`; `%APPDATA%\FreeLlama\` on Windows).
|
|
204
294
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
295
|
+
| File | Flag | Environment variable | Discovered name |
|
|
296
|
+
|---|---|---|---|
|
|
297
|
+
| Task policy | `--policy-file` | `FREELLAMA_POLICY_FILE` | `platform.toml` |
|
|
298
|
+
| Benchmark report | `--benchmark-report` | `FREELLAMA_BENCHMARK_REPORT` | `benchmark-report.json` |
|
|
208
299
|
|
|
209
|
-
|
|
300
|
+
A task policy file has this shape:
|
|
210
301
|
|
|
211
|
-
```
|
|
212
|
-
|
|
302
|
+
```toml
|
|
303
|
+
schema_version = 1
|
|
304
|
+
|
|
305
|
+
[policies.code_repair]
|
|
306
|
+
qualified_models = ["qwen3.8:27b-mlx"] # best first; quality-qualified only
|
|
307
|
+
|
|
308
|
+
# Optional request defaults for one exact tag on this task: think and num_predict (>= 1).
|
|
309
|
+
[policies.code_repair.model_options."qwen3.8:27b-mlx"]
|
|
310
|
+
think = false
|
|
311
|
+
num_predict = 512
|
|
213
312
|
```
|
|
214
313
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
`
|
|
314
|
+
`serve` rejects unknown fields, including `num_ctx`: context size is routing-owned, so set
|
|
315
|
+
`context_tokens` per request instead. Caller request options win over `model_options`, and
|
|
316
|
+
`think = true` applies only to models with the thinking capability. See the annotated
|
|
317
|
+
[platform.example.toml](https://github.com/bgauryy/FreeLlama/blob/main/platform.example.toml).
|
|
318
|
+
|
|
319
|
+
The MCP server autostarts `serve` with its own environment and an arbitrary working directory, so
|
|
320
|
+
put a machine-wide policy in the config directory or set the variables in the MCP client's `env`.
|
|
321
|
+
`serve` prints each file it picked up.
|
|
322
|
+
|
|
323
|
+
Replace `MODEL` with the directory containing your completed quality-evaluation aggregate.
|
|
324
|
+
|
|
325
|
+
`policy from-eval` reads `pass_at_1`, not the throughput produced by `bench-all`. It refuses
|
|
326
|
+
expired aggregates and fewer than three trials unless `--allow-smoke` is explicit, and it skips
|
|
327
|
+
models that are not installed on `--ollama-endpoint` (default `FREELLAMA_OLLAMA_ENDPOINT`, then
|
|
328
|
+
`http://127.0.0.1:11434`). This prevents speed data from being mislabeled as quality evidence.
|
|
329
|
+
It accepts the task kinds `route` accepts, with `-` or `_` (`code-repair` or `code_repair`), writes
|
|
330
|
+
to stdout unless `--out` is given, and reports a refusal as one `error: ...` line with exit status 1.
|
|
331
|
+
|
|
332
|
+
## Compare the CLI and MCP surfaces
|
|
333
|
+
|
|
334
|
+
MCP-only operations are `delegate_research` and the online `models { view: "library" }` view.
|
|
335
|
+
CLI-only operations include `serve`, `proxy`, `bench-all`, `policy from-eval`, and `auth-token`.
|
|
218
336
|
|
|
219
|
-
For the
|
|
337
|
+
For the MCP tool contracts, read the [MCP package reference](https://github.com/bgauryy/FreeLlama/blob/main/packages/mcp/README.md).
|
package/docs/CPU_GPU_ROUTING.md
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
# Run models on CPU and GPU
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
To separate GPU work from CPU helpers, configure two Ollama processes and assign exact helper-model
|
|
4
|
+
tags to the secondary process. FreeLlama routes managed tasks within those assignments, applies
|
|
5
|
+
`num_gpu: 0` to CPU requests, and reports both the selected backend and observed processor placement.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
The calling agent submits tasks and placement preferences. FreeLlama coordinates admission,
|
|
8
|
+
memory checks, and model transitions for each backend; the operator configures the processes and
|
|
9
|
+
eligible tags. A configured CPU backend is intent: inspect the placement observation before
|
|
10
|
+
treating it as proof of CPU execution.
|
|
11
|
+
|
|
12
|
+
This configuration is useful for embeddings, short classification, and other small helper models.
|
|
8
13
|
Benchmark large CPU workloads before adopting them. Apple silicon shares memory bandwidth; systems
|
|
9
14
|
with discrete GPUs have different contention and transfer costs, so neither result transfers
|
|
10
15
|
without measurement.
|
|
@@ -23,7 +28,9 @@ machine-specific:
|
|
|
23
28
|
|
|
24
29
|
`doctor` reports `machine.memory_bytes` on macOS, Linux, and Windows. It reports
|
|
25
30
|
`machine.unified_memory_bytes` only when unified memory is known; that compatibility field is not a
|
|
26
|
-
VRAM estimate on discrete-GPU hosts.
|
|
31
|
+
VRAM estimate on discrete-GPU hosts. `machine.gpu` names the accelerator when the OS reports it
|
|
32
|
+
(Apple model and core count, or NVIDIA name and memory on Linux), and `performance_cpus` /
|
|
33
|
+
`efficiency_cpus` split hybrid CPUs on macOS. These are identity facts, not placement proof. Model-library fit is therefore a host-memory preflight, and
|
|
27
34
|
actual accelerator placement must come from Ollama's resident-runner report.
|
|
28
35
|
|
|
29
36
|
An agent can choose `auto`, `prefer_cpu`, or `prefer_gpu`, but it cannot invent topology. The
|
|
@@ -110,7 +117,10 @@ unsafe or ambiguous configurations:
|
|
|
110
117
|
- A CPU model assignment without `--cpu-upstream`
|
|
111
118
|
- Empty model names
|
|
112
119
|
- The same socket expressed through aliases such as `localhost:11434` and `127.0.0.1:11434`
|
|
113
|
-
- A
|
|
120
|
+
- A nonloopback upstream
|
|
121
|
+
|
|
122
|
+
A nonloopback FreeLlama listener requires `--allow-remote` and bearer-token authentication.
|
|
123
|
+
See the [production runbook](PRODUCTION.md) for remote ingress requirements.
|
|
114
124
|
|
|
115
125
|
Set independent admission budgets when the defaults do not fit the workload:
|
|
116
126
|
|
|
@@ -120,13 +130,18 @@ Set independent admission budgets when the defaults do not fit the workload:
|
|
|
120
130
|
--cpu-upstream http://127.0.0.1:11436 \
|
|
121
131
|
--cpu-model nomic-embed-text:latest \
|
|
122
132
|
--max-concurrent-tasks 2 \
|
|
123
|
-
--cpu-max-concurrent-tasks 1
|
|
133
|
+
--cpu-max-concurrent-tasks 1 \
|
|
134
|
+
--max-queued-tasks 16 \
|
|
135
|
+
--cpu-max-queued-tasks 8
|
|
124
136
|
```
|
|
125
137
|
|
|
126
138
|
The defaults above admit one ordinary primary-backend chat (cost 2) and one CPU embedding (cost 1)
|
|
127
139
|
at the same time. They are conservative workload units for the common `OLLAMA_NUM_PARALLEL=1`
|
|
128
140
|
layout, not a profile of the development Mac. Increase them only after measuring queue wait,
|
|
129
141
|
resident memory, and Ollama's own parallel setting on the target host.
|
|
142
|
+
Queue cardinality and wait time are separate bounds: excess waiters are refused immediately, while
|
|
143
|
+
an admitted waiter may remain until `--max-queue-wait-seconds`. Automatic backend selection checks
|
|
144
|
+
that the actual task cost fits the current slot snapshot before following historical speed.
|
|
130
145
|
|
|
131
146
|
## Let an agent express placement intent
|
|
132
147
|
|
|
@@ -194,12 +209,14 @@ The `execution` object separates the configured `backend`, requested compatibili
|
|
|
194
209
|
post-run `observation`. The source is Ollama `/api/ps`; direct inspection remains useful:
|
|
195
210
|
|
|
196
211
|
```bash
|
|
197
|
-
curl --silent http://127.0.0.1:11434/api/ps | jq '.models[] | {name, size_vram}'
|
|
198
|
-
curl --silent http://127.0.0.1:11436/api/ps | jq '.models[] | {name, size_vram}'
|
|
212
|
+
curl --silent http://127.0.0.1:11434/api/ps | jq '.models[] | {name, size, size_vram}'
|
|
213
|
+
curl --silent http://127.0.0.1:11436/api/ps | jq '.models[] | {name, size, size_vram}'
|
|
199
214
|
```
|
|
200
215
|
|
|
201
|
-
A fully CPU-loaded model reports `size_vram:0`; a fully GPU-loaded model reports positive
|
|
202
|
-
|
|
216
|
+
A fully CPU-loaded model reports `size_vram:0`; a fully GPU-loaded model reports positive VRAM
|
|
217
|
+
covering its resident `size`. Compare both values from the same `/api/ps` entry. Installed `/api/tags`
|
|
218
|
+
file bytes can differ from resident memory and cannot prove a mixed placement. Positive VRAM without
|
|
219
|
+
total resident size stays unknown. `observation.status` is `verified`, `mismatch`, or unavailable. Unknown, mixed, and mismatched
|
|
203
220
|
samples are reported but excluded from adaptive feedback.
|
|
204
221
|
|
|
205
222
|
## Understand concurrency
|
|
@@ -208,10 +225,16 @@ Each backend has its own weighted admission pool and its own resident/shared and
|
|
|
208
225
|
transition/exclusive lock. CPU and GPU model transitions therefore do not block each other, and a
|
|
209
226
|
GPU burst cannot spend the CPU helper's permit:
|
|
210
227
|
|
|
228
|
+
Both pools also share local host-pressure sampling and forecast-memory reservations. Independent
|
|
229
|
+
queues do not imply independent RAM on a unified-memory machine. A request can wait for available
|
|
230
|
+
headroom even when its backend has a free weighted permit. Inspect `admission.resources` in health
|
|
231
|
+
and `execution.resource_admission` in task receipts. Unknown thermal or GPU measurements are not
|
|
232
|
+
reported as healthy readings. See [the execution architecture](ARCHITECTURE.md) for the complete gate.
|
|
233
|
+
|
|
211
234
|
```mermaid
|
|
212
235
|
flowchart TD
|
|
213
236
|
T["Managed task"] --> B{"Selected backend"}
|
|
214
|
-
B -->|"GPU"| GA["GPU admission pool<br/>default 2 units"]
|
|
237
|
+
B -->|"GPU"| GA["GPU admission pool<br/>default 2 units per Ollama slot"]
|
|
215
238
|
B -->|"CPU"| CA["CPU admission pool<br/>default 1 unit"]
|
|
216
239
|
GA --> GL{"Resident?"}
|
|
217
240
|
CA --> CL{"Resident?"}
|
|
@@ -229,16 +252,28 @@ FreeLlama can overlap requests across the two servers even when each Ollama proc
|
|
|
229
252
|
`OLLAMA_NUM_PARALLEL=1`. Raising `OLLAMA_NUM_PARALLEL` affects parallel requests within one server
|
|
230
253
|
and multiplies K/V-cache memory; it is a separate tuning decision. `OLLAMA_MAX_QUEUE` likewise
|
|
231
254
|
bounds each Ollama process after FreeLlama admission. It does not replace either backend's weighted
|
|
232
|
-
FreeLlama budget or queue-wait deadline.
|
|
255
|
+
FreeLlama budget, bounded waiter count, or queue-wait deadline. Raw passthrough uses a separate
|
|
256
|
+
one-stream default cap in `serve`; its permit is held until the streamed response ends or is dropped.
|
|
257
|
+
|
|
258
|
+
The runtime file's `[task_costs]` table can tune individual task-kind weights without increasing
|
|
259
|
+
the entire pool's ceiling. Default vision weight four can serialize two vision requests under a
|
|
260
|
+
four-unit budget even when Ollama has two slots. A lower weight requires a qualified workload;
|
|
261
|
+
it does not add engine slots or relax memory checks. See
|
|
262
|
+
[monitoring controls](MONITORING.md#adaptive-concurrency).
|
|
263
|
+
Mutating raw requests also require exclusive access to the primary backend's managed transition
|
|
264
|
+
lock and receive 503 while it is busy. Metadata GET/HEAD calls remain available. This prevents raw
|
|
265
|
+
inference or model lifecycle calls from overlapping a managed generation on that backend.
|
|
233
266
|
|
|
234
267
|
## Understand automatic feedback
|
|
235
268
|
|
|
236
269
|
With `executionPreference: "auto"`, unpinned `fastest` and `balanced` work can select a backend from
|
|
237
|
-
observed warm task duration.
|
|
270
|
+
comparable observed warm task duration. Learned hints require two eligible backends, explicit
|
|
271
|
+
context, and a known execution payload-control projection. A decision-only preview cannot supply
|
|
272
|
+
that payload projection and uses capacity and policy signals. The loop is bounded:
|
|
238
273
|
|
|
239
274
|
```mermaid
|
|
240
275
|
flowchart LR
|
|
241
|
-
X["
|
|
276
|
+
X["Comparable warm serial task"] --> O["Record duration by<br/>task + backend + profile"]
|
|
242
277
|
O --> N{"At least 3 samples<br/>on both backends?"}
|
|
243
278
|
N -->|"No"| D["Keep deterministic default"]
|
|
244
279
|
N -->|"Yes"| C{"More than 10% faster<br/>per work unit?"}
|
|
@@ -248,13 +283,25 @@ flowchart LR
|
|
|
248
283
|
```
|
|
249
284
|
|
|
250
285
|
Generation compares decode nanoseconds per output token; embeddings compare total nanoseconds per
|
|
251
|
-
input token.
|
|
252
|
-
|
|
286
|
+
input token. Each task/backend has one current profile window, reset when identity changes.
|
|
287
|
+
Identity includes installed/resident digest, rate metric kind, explicit observed context, effective controls,
|
|
288
|
+
endpoint-attributed process settings, and serial admission class. Unknown or changed evidence,
|
|
289
|
+
cold transitions, and overlapping managed work supply no speed sample. A difference
|
|
253
290
|
of 10% or less is treated as noise. Feedback never overrides an explicit model, session affinity,
|
|
254
291
|
capability or policy guards, or the `quality` objective. The CLI persists the bounded, versioned,
|
|
255
|
-
prompt-free
|
|
256
|
-
|
|
257
|
-
|
|
292
|
+
prompt-free snapshot atomically by default; `--ephemeral-feedback` opts into reset-on-restart
|
|
293
|
+
behavior. Legacy aggregate fields survive loading but do not qualify learned hints. Health's
|
|
294
|
+
`decision_ready` describes the stored profile window; the current request must independently
|
|
295
|
+
match it before routing can use its speed. `GET /_freellama/v1/health` exposes profile identity,
|
|
296
|
+
profile sample counts, persistence status, and per-backend admission capacity. Physically verified
|
|
297
|
+
warm completions still contribute legacy duration diagnostics even when their interval cannot
|
|
298
|
+
qualify a speed-learning sample.
|
|
299
|
+
|
|
300
|
+
Configured processor intent, verified placement, and speed-learning eligibility remain separate
|
|
301
|
+
receipt fields. Missing endpoint-attributed process inspection disables learned hints and recovery,
|
|
302
|
+
including remote backends; ordinary routing, admission, and pressure/error safeguards still work.
|
|
303
|
+
Fresh process probes run for candidate serial learning or an eligible learned-route lookup, not
|
|
304
|
+
for pinned, quality-only, preview-only, or single-backend route selection.
|
|
258
305
|
|
|
259
306
|
## Interpret the measured Mac result
|
|
260
307
|
|
|
@@ -307,7 +354,6 @@ and `execution.lifecycle`; a failed unload is reported without discarding the co
|
|
|
307
354
|
Prefer the following assignments:
|
|
308
355
|
|
|
309
356
|
- Small embedding models
|
|
310
|
-
- Lightweight intent models
|
|
311
357
|
- Short extraction or classification helpers with measured CPU behavior
|
|
312
358
|
|
|
313
359
|
Benchmark these assignments before adopting them:
|
|
@@ -318,7 +364,7 @@ Benchmark these assignments before adopting them:
|
|
|
318
364
|
|
|
319
365
|
The local measurement receipt is written to
|
|
320
366
|
`.octocode/evals/cpu-gpu-concurrency-benchmark.md`. Git intentionally ignores that path, so the
|
|
321
|
-
trial table in "Interpret the measured result" carries the durable result while the local artifact
|
|
367
|
+
trial table in ["Interpret the measured Mac result"](#interpret-the-measured-mac-result) carries the durable result while the local artifact
|
|
322
368
|
retains the full run detail.
|
|
323
369
|
|
|
324
370
|
## Troubleshoot the secondary backend
|
|
@@ -337,7 +383,7 @@ can also be unavailable until the secondary server returns. Raw passthrough to t
|
|
|
337
383
|
continues to work because it does not depend on catalog discovery.
|
|
338
384
|
|
|
339
385
|
For the surrounding runtime settings, see
|
|
340
|
-
[Ollama and FreeLlama optimization](OLLAMA_SYSTEM_OPTIMIZATION.md). For all `serve` flags, see the
|
|
386
|
+
[Ollama and FreeLlama optimization](dev/OLLAMA_SYSTEM_OPTIMIZATION.md). For all `serve` flags, see the
|
|
341
387
|
[CLI reference](CLI.md).
|
|
342
388
|
|
|
343
389
|
## Upstream sources
|