What You'll Build
A local browser computer-use agent (CUA) on a single RTX 4080: llama-server hosting Fara1.5-9B as a Q8_0 GGUF plus its vision projector, with Microsoft's own fara-cli harness pointed at it, driving a Playwright-launched Chromium at 1440×900. You give it a task in English; it takes a screenshot, reasons, and emits a click, a keystroke or a URL visit, then loops.
On 16 GB the interesting question about Fara1.5-9B stops being whether it fits and becomes what to spend the slack on — a higher quantisation tier, or a longer context window. This recipe answers it deliberately and shows the arithmetic for the alternative. It also marks the ceiling: the 9B is the largest size in this family a 16 GB card can serve, because the 27B's Q4_K_M build — the tier this catalogue leads for it, and the one costed below — is already over the card before its projector is loaded.
Hardware data: RTX 4080 (16GB VRAM) · Q8_0 + f16 mmproj + 65,536 context = 11.942 GiB of accountable allocations, 4.058 GiB spare (derived below) · See benchmark data
⚠️ This model clicks, types and submits in a real browser, and the path documented here gives it no isolation of any kind. That the model acts is the product, not a side effect, and this is the thing to settle before anything else on this page.
The model card is blunt about the consequence: "Don't run this model with unrestricted browser access on a machine that has anything sensitive on it." That sentence closes its Recommended Deployment: MagenticLite section, which lists sandboxing, allow-lists, watch-mode and a pause control as MagenticLite features and then says: "If you integrate Fara1.5-9B directly, you're responsible for these controls." The Responsible AI section asks for the same thing in more detail — "run Fara in an isolated container with no access to host files, environment variables, or sensitive credentials".
fara-cliis a direct integration. Its install step isplaywright install, and it drives a plain local Playwright Chromium — a fresh browser profile, not your logged-in one, but no container, no allow-list and no pause control. The harness README offers the containerised option as an alternative to it, not as part of it: "instead of fara-cli you can use Magentic-UI", described there as "a sandboxed browser environment with auditable action logging and user prompts at critical points". For the CLI path the vendor's position is a recommendation, not something shipped: "We recommend running it in a sandboxed environment, monitoring its execution, and avoiding sensitive data or high-risk domains."So on the
fara-clipath you are the boundary. Practically: a throwaway OS user or a VM, signed out of everything, low-stakes public sites, and eyes on the run rather than leaving it unattended. The command in Running passes--headfulfor exactly that last reason.
ℹ️ Not a general-purpose vision chatbot. Fara1.5-9B is fine-tuned for one loop: screenshot in,
<tool_call>out. It is in ourmultimodalvertical because it takes images and text and emits text, but it is trained against a specific system prompt and a fixedcomputer_useaction schema. Per the model card: "The model is vision-only at perception time: it sees the browser through screenshots, not the DOM or accessibility tree." A Fara install that only serves text is a broken install — the--mmprojstep below is mandatory, and Step 4 exists to prove an image really reached the model before you let it drive anything.
⚠️ Runtime status — read before you commit an evening to this. llama.cpp support for this architecture is verifiable statically, and this recipe shows that evidence rather than asserting it. What does not exist anywhere public is a report of Fara1.5 decoding an image under
llama-serverorllama-mtmd-cli. The closest datapoint is a community user serving Fara1.5-27B underllama-serveron build b10107 and driving it from an agent harness successfully — but that thread is about tool-call parsing, not about the projector. Treat your first run as the test, and see Results for why there is no speed figure here either.
Requirements
| Component | Minimum | This recipe |
|---|---|---|
| GPU | 16GB VRAM, CUDA compute 8.9 (Ada Lovelace) | RTX 4080 (16GB) — not measured; budget below is derived (/contribute) |
| RAM | 16GB (weights are mmap'd on their way to VRAM; Playwright's Chromium sits on top) | — |
| Storage | 10.46 GB (Q8_0 + f16 mmproj) | 10,464,149,152 B = 9.745 GiB, plus the harness and Chromium |
| Software | llama.cpp b10087+ (CUDA), Python 3.10+, Playwright | — |
Microsoft ships safetensors only, and its own hardware line for this size asks for "A GPU with enough memory for a 9B model in bf16 (A6000, A100, H100, and B200 have been tested)". That request is not one a 16 GB card can meet for the 9B — the arithmetic below says so explicitly — so this recipe takes the highest-precision GGUF that does fit, and states what that costs.
Why the 9B on a 16 GB card
The 9B is the middle of three sizes and has to earn the tier. The model card's own evaluation table is the cleanest statement of what it buys:
| Model | WebVoyager | Online-Mind2Web | WebTailBench |
|---|---|---|---|
| Fara1.5-4B | 80.8 | 57.3 | 27.4 |
| Fara1.5-9B | 86.6 | 63.4 | 32.3 |
| Fara1.5-27B | 89.3 | 72.3 | 40.2 |
The 4B→9B step is the larger of the two on WebVoyager (+5.8 against +2.7), but read the other two rows before drawing a general conclusion: on Online-Mind2Web and WebTailBench the 9B→27B step is the larger one, so this is not the size at which the family stops improving. The reason the 9B belongs on this card is narrower and sufficient — it is the biggest size this card can serve. The 27B is out of reach here by arithmetic, not by preference: its Q4_K_M build is 16.329 GiB before a 0.864 GiB projector — 17,533,552,448 B and 927,607,456 B in the 27B GGUF tree — over the card outright. Full methodology is in the Fara1.5 paper.
What the tier costs on this card is unusually easy to state, because the 4B and 9B are architecturally identical everywhere except width. Both declare num_key_value_heads: 4, head_dim: 256, 32 blocks and full_attention_interval: 4 in config.json — so the per-token KV cost of the 9B is exactly the same as the 4B's, and so is its fixed recurrent state. The entire difference is weights. You pay it once, in VRAM you would otherwise leave idle, and nothing at all in running cost per token of context.
How it fits in 16 GB — the arithmetic
There is no benchmark for this pair yet — /check reports unknown with zero benchmark rows — so every number below is arithmetic from the artifacts' own metadata and from llama.cpp's source, not a measurement. Reproduce it rather than trusting it.
Weights. Byte counts read from the bartowski GGUF tree on the day this was written:
| File | Bytes | GiB |
|---|---|---|
Fara1.5-9B-Q4_K_M.gguf | 5,910,783,104 | 5.505 |
Fara1.5-9B-Q5_K_M.gguf | 6,852,928,640 | 6.382 |
Fara1.5-9B-Q6_K.gguf | 7,700,259,968 | 7.171 |
Fara1.5-9B-Q8_0.gguf | 9,545,983,104 | 8.890 |
Fara1.5-9B-bf16.gguf | 17,920,697,216 | 16.690 |
mmproj-Fara1.5-9B-f16.gguf | 918,166,048 | 0.855 |
(HuggingFace displays these as decimal GB — 9.55 GB for the Q8_0 file — which is the same bytes, not a different number.)
KV cache — smaller than you expect, because this is a hybrid model. config.json carries a layer_types array of 24 linear_attention + 8 full_attention entries, and llama.cpp agrees: LLM_ARCH_QWEN35 maps to "qwen35" in src/llama-arch.cpp, and src/models/qwen35.cpp assigns layers with hparams.is_recr_impl[i] = (i < hparams.n_layer()) && ((i + 1) % full_attn_interval != 0). With full_attention_interval = 4 and 32 blocks that leaves layers 3, 7, … 31 — 8 attention layers. Only those carry a cache that grows with context:
K+V per token per attention layer = 2 × n_head_kv(4) × head_dim(256) × 2 B (f16) = 4,096 B
× 8 full-attention layers = 32 KiB / token
n_ctx = 32,768 → 1.000 GiB
n_ctx = 65,536 → 2.000 GiB
n_ctx = 131,072 → 4.000 GiB
n_ctx = 262,144 → 8.000 GiB
A non-hybrid 32-layer model with the same head geometry would cost four times that. Context on this model is cheap — every doubling costs exactly 1.000 GiB more than the last — and that is the fact the whole budget turns on.
Recurrent state — fixed, and four times bigger than a single sequence's worth. The other 24 layers hold a context-independent state, sized by n_embd_r() / n_embd_s() in src/llama-hparams.cpp from this file's own GGUF keys (ssm.conv_kernel 4, ssm.inner_size 4096, ssm.group_count 16, ssm.state_size 128 — matching linear_conv_kernel_dim, linear_value_head_dim × linear_num_value_heads, linear_num_key_heads and linear_key_head_dim in the source config):
conv state : (4−1) × (4096 + 2×16×128) = 24,576 elems
ssm state : 128 × 4096 = 524,288 elems
per layer : 548,864 × 4 B (F32) = 2.094 MiB
× 24 recurrent layers = 50.25 MiB ← per sequence
× n_seq_max = 4 = 201.00 MiB = 0.196 GiB
That ×4 is not optional and it is easy to miss. src/llama-model.cpp sizes the recurrent cache with /* recurrent_rs_size */ std::max((uint32_t) 1, cparams.n_seq_max), and llama-server does not leave n_seq_max at 1: common/arg.cpp passes n_parallel = -1 for the server, and tools/server/server.cpp then resolves that with if (n_parallel < 0) { n_parallel = 4; kv_unified = true; }. So the recurrent state is allocated once per slot — four times — while the KV cache is not multiplied, because the same default makes it unified: a unified cache holds -c tokens in total rather than per sequence. The same line is also why -c 65536 gives a single trajectory the whole 65,536 tokens instead of a quarter of them.
The whole trade, in one table. Accountable allocations (text weights + f16 projector + KV + the 0.196 GiB recurrent state) in GiB, against a 16 GiB card:
| Context | Q4_K_M | Q5_K_M | Q6_K | Q8_0 | BF16 |
|---|---|---|---|---|---|
| 16,384 | 7.056 | 7.934 | 8.723 | 10.442 | 18.241 |
| 32,768 | 7.556 | 8.434 | 9.223 | 10.942 | 18.741 |
| 65,536 | 8.556 | 9.434 | 10.223 | 11.942 | 19.741 |
| 131,072 | 10.556 | 11.434 | 12.223 | 13.942 | 21.741 |
| 262,144 (native) | 14.556 | 15.434 | 16.223 | 17.942 | 25.741 |
Read that as three facts rather than twenty numbers.
- BF16 is excluded by arithmetic, not by margin. The unquantised build is 16.690 GiB of weights alone — 0.690 GiB over a 16 GiB card before a projector, a single KV byte or a compute buffer. There is no context setting that rescues it, because context is not what breaks it. This is the one place the 9B behaves differently from its 4B sibling on the identical card: the 4B's BF16 file is 7.846 GiB — 8,424,393,568 B in the 4B GGUF tree — and its recipe for this card leads with it. At 9B that option simply does not exist, and the recipe is honest about running quantised weights where the 4B does not have to.
- Q8_0 is therefore the top rung, and it fits with room. 11.942 GiB at 65,536 context leaves 4.058 GiB for the CUDA context, compute buffers, the vision encode graph and your desktop. Against the published 12 GB recipe for this model — Q5_K_M at 32,768 — 16 GB buys two quant rungs and a doubling of the window, which is a more useful way to describe this card than any single number.
- The native 262,144-token window stays out of reach, and buying it would cost more than it is worth. Q6_K reaches 16.223 GiB there (over the card); Q5_K_M lands at 15.434 and Q4_K_M at 14.556, leaving 0.566 and 1.444 GiB respectively — not enough working room to load. So the native window costs three quant rungs and still does not leave headroom. Declined.
Why quant before context, explicitly. This model's output is pixel coordinates: the card describes it predicting "the next action with grounded arguments (e.g., pixel coordinates for a click)", and its training data includes "Curated datasets for predicting actions and pixel coordinates from screenshots". No public evaluation measures what any quantisation tier costs a grounding model, so every rung down the ladder is an unmeasured risk. Context, by contrast, is a measured need with a documented floor: the harness README asks for "at least 15000 tokens", the card says "We only keep the most recent 3 screenshots" in history, and the per-round text is bounded. 65,536 is 4.3× the stated floor with a hundred rounds of slack. Spending the last 2.000 GiB on 131,072 instead would buy window nobody has shown this loop needs, and would cut the working headroom to 2.058 GiB. The 4B recipes for this tier reached the same conclusion one rung higher up the ladder; this one reaches it one rung lower only because BF16 is not on the menu.
Nothing in that table is free space you can plan against to the last byte: the CUDA context, compute buffers and the vision encoder's working set are allocated at load time and this recipe does not derive them. Read the CUDA0 compute buffer size lines llama-server prints on startup for the real figures on your build, and report what you see.
How the context is actually spent
A CUA sends a screenshot every step, so the per-image cost decides whether the budget above is realistic. The harness fixes the browser viewport at 1440×900 (viewport_width / viewport_height in fara15_agent.py), matching the card's note that "The screen resolution Fara is most commonly trained with is" 1440×900. It pre-resizes with Qwen's smart_resize at factor = patch_size × merge_size = 32, so 900 becomes 896. llama.cpp then counts patches the same way in tools/mtmd/clip.cpp and clamps this projector to 8–4096 merged tokens (hparams.set_limit_image_tokens(8, 4096) in the PROJECTOR_TYPE_QWEN3VL branch), which 1,290,240 px sits inside — so nothing is rescaled:
(1440 / 32) × (896 / 32) = 45 × 28 = 1,260 tokens per screenshot
× 3 retained screenshots = 3,780 tokens resident
The harness's own conservative default is image_token_estimate: 1500, a useful sanity check on that arithmetic, and the card confirms the retention: "We only keep the most recent 3 screenshots". So images are capped. What grows is the text trajectory, and that is what 65,536 is sized for.
Installation
1. Build llama.cpp with CUDA
Ada Lovelace is sm_89. Build from a release at or after b10087 — the release this GGUF was quantized on. The quantiser's card states the build it used and links that release tag directly.
git clone https://github.com/ggml-org/llama.cpp
cd llama.cpp
cmake -B build -DGGML_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES=89 -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release -j
Both halves of the model are first-class in mainline — worth confirming before you download 10 GB:
grep -n 'LLM_ARCH_QWEN35,' src/llama-arch.cpp # -> { LLM_ARCH_QWEN35, "qwen35" }
grep -n 'qwen3vl_merger' tools/mtmd/clip-impl.h # -> PROJECTOR_TYPE_QWEN3VL
2. Download the weights and the projector
Both files are required. The projector is a separate artifact — downloading only the text GGUF gives you a model that cannot see.
pip install -U huggingface_hub
hf download bartowski/Fara1.5-9B-GGUF \
Fara1.5-9B-Q8_0.gguf mmproj-Fara1.5-9B-f16.gguf \
--local-dir ~/models/fara1.5-9b
Microsoft publishes no first-party GGUF for Fara1.5 — the microsoft org ships Fara1.5-4B, Fara1.5-9B and Fara1.5-27B as safetensors only. Several independent community quantisers have converted the 9B including its vision tower, each publishing a matching mmproj; independent conversions succeeding is the strongest available evidence that the vision path converts cleanly, and it is still not a runtime test.
You can confirm the artifact you just downloaded declares the projector llama.cpp implements:
strings ~/models/fara1.5-9b/mmproj-Fara1.5-9B-f16.gguf | grep -m1 qwen3vl_merger
The same repo also ships mmproj-Fara1.5-9B-bf16.gguf at 921,704,992 B — 3 MiB larger. At the same two bytes per value, IEEE binary16 spends three more bits on the mantissa than bfloat16 does and three fewer on the exponent: a finer grid over a narrower range. This recipe takes the f16 build, as every other recipe for this model does; substitute the bf16 one and add 3 MiB to every figure above.
3. Serve it
./build/bin/llama-server \
-m ~/models/fara1.5-9b/Fara1.5-9B-Q8_0.gguf \
--mmproj ~/models/fara1.5-9b/mmproj-Fara1.5-9B-f16.gguf \
-ngl 99 -c 65536 --host 127.0.0.1 --port 5000 \
--image-min-tokens 1024 \
--reasoning-format none \
--temp 0
Three of those flags are load-bearing and none of them is a default:
--reasoning-format none— mandatory. Without it the agent loop silently receives nothing; see Troubleshooting for the mechanism. The server documents this value as "none: leaves thoughts unparsed inmessage.content".--image-min-tokens 1024— this projector ships no minimum-pixel key, so llama.cpp falls back to the floor set byhparams.set_limit_image_tokens(8, 4096)in thePROJECTOR_TYPE_QWEN3VLbranch oftools/mtmd/clip.cpp, and warns four lines later in the same branch: "Qwen-VL models require at minimum 1024 image tokens to function correctly on grounding tasks". Fara is a grounding model, so that warning is aimed precisely at this case. At the harness's viewport the image is already 1,260 tokens and the floor never binds; it protects you if you shrink the viewport.-c 65536— see the budget table. Do not leave it at the model's native 262,144: at Q8_0 that is 17.942 GiB and will not load.
If you would rather not manage files, -hf bartowski/Fara1.5-9B-GGUF:Q8_0 fetches the model, and per the server docs "mmproj is also downloaded automatically if available".
4. Prove the vision path works before going further
Check that the server advertises multimodal support, then send a real image. The server docs make the first part a client-side requirement rather than an optional nicety: "Clients should check /models or /v1/models for the multimodal capability before a multimodal request." Run GET /props alongside it — it reports which modalities loaded rather than merely that some did, which is the more useful signal when a projector silently failed to load.
curl -s http://127.0.0.1:5000/v1/models | grep -o multimodal
# supplementary — names the modality that actually loaded
curl -s http://127.0.0.1:5000/props | python3 -c "import sys,json; print(json.load(sys.stdin)['modalities'])"
# expect: {'vision': True}
curl -s http://127.0.0.1:5000/v1/chat/completions -H "Content-Type: application/json" -d '{
"model": "fara",
"temperature": 0,
"messages": [{"role": "user", "content": [
{"type": "text", "text": "Describe this image in one sentence."},
{"type": "image_url", "image_url": {"url": "https://raw.githubusercontent.com/ggml-org/llama.cpp/master/media/llama0-logo.png"}}
]}]
}' | python3 -m json.tool
If the reply describes the picture, the projector is wired up. If /v1/models never prints multimodal, if /props reports vision: False, or if the model answers as though no image were present, stop here — the agent loop below will produce confidently wrong actions rather than fail loudly.
5. Install the harness
git clone https://github.com/microsoft/fara.git
cd fara
python3 -m venv .venv && source .venv/bin/activate
pip install -e .
playwright install
Skip the README's [vllm] extra — that path serves BF16 safetensors on datacenter cards, which is exactly what this recipe cannot do on 16 GB.
Running
Two clients share the same llama-server endpoint. Path A (fara-cli) is the smoke test, with no isolation. Path B (Magentic-UI) is what the vendor recommends for anything real. They are not equivalent in risk; pick deliberately.
Path A — fara-cli, for a first smoke test
source .venv/bin/activate
fara-cli \
--base_url http://127.0.0.1:5000/v1 \
--api_key sk-no-key-required \
--model fara \
--task "find the current UTC time on time.is and tell me" \
--output_folder ./runs/first \
--save_screenshots \
--headful \
--max_rounds 15
--headful is in that command on purpose. The harness runs the browser headless by default — run_fara.py declares the flag with the help text "Run the browser in headful mode (show GUI, default is headless)", and both launch sites read headless=not args.headful; the README likewise shows it as an optional [--headful]. The safety callout above asks you to keep eyes on the run, and headless is the one mode in which you cannot. Drop the flag once you trust the loop and are reading the trajectory files instead. Either way this drives a real, unsandboxed Chromium on your machine.
Each step writes a screenshot and a data_point.json into --output_folder, which is how you tell a grounding failure (clicks landing in the wrong place) from a reasoning failure. Keep the task on a low-stakes public site and stay signed out. Fara is trained to stop and ask before entering personal information, making payments, submitting forms, signing in or sending messages; if you see it sail through one of those, stop the run — that is a wiring problem in your prompt path, not a quirk to tolerate.
Path B — Magentic-UI, for the container
Everything the model card assumes — the containerised browser, domain allow-lists, watch-mode and a pause control — lives in Magentic-UI, not in fara-cli. That is also where a Docker requirement would come from; there is no Docker step in Path A because Path A genuinely does not use one.
Magentic-UI takes the same OpenAI-compatible endpoint you started above, so nothing on this page changes except the client. Its setup is documented in its own repository rather than reproduced here, because this recipe has not verified those steps end to end on this GPU — give it http://127.0.0.1:5000/v1 as the model endpoint. Whichever client you use, match the trained resolution: the card is explicit — "Match this in your sandbox for the most reliable grounding."
Results
- Speed: omitted. No published measurement of Fara1.5-9B exists for this card or for any consumer GPU, and Microsoft publishes no throughput figures at all — the card names A6000, A100, H100 and B200 only as hardware its bf16 serving path was tested on, which says nothing about a Q8_0 build on Ada. Every 16 GB Ada card lands on the same memory budget as this one, because the derivation above depends only on capacity and on
sm_89. Throughput is exactly what those cards do not share, and with no measurement on any of them this recipe does not rank them. If you run this, please contribute your numbers so this line can be replaced with a measurement. - VRAM usage: 9.745 GiB of weights and projector; 11.942 GiB accountable including KV and the 4-slot recurrent state at 65,536 context, derived above from the GGUF's own metadata and llama.cpp's memory formulas. This is a derivation, not an observed peak — compute and vision buffers sit on top, and 4.058 GiB of the card is left for them. Track the empirical picture at /check/fara1-5-9b/rtx-4080.
- Quality notes: the vendor's published scores (86.6 WebVoyager, 63.4 Online-Mind2Web, 32.3 WebTailBench) are for the bf16 model on datacenter hardware. Neither the hardware nor the precision transfers here, and no public evaluation measures what Q8_0 costs a model whose job is predicting exact pixel coordinates — which is why this recipe leads the highest tier that fits rather than the cheapest one. The vision path is structurally proven, not runtime-proven: mainline llama.cpp registers the architecture and the
qwen3vl_mergerprojector, several quantisers converted it independently, and llama-server documents theimage_urlcontent parts the harness sends — but nobody has published a report of Fara1.5 grounding a click underllama-server. - Language: English only — the card puts languages other than English out of scope.
For the full benchmark data, see /check/fara1-5-9b/rtx-4080.
Troubleshooting
The agent does nothing — every step logs an empty response or list index out of range
This is the failure everyone hits, and it is not a bug in your setup. Fara opens a <think> block and never closes it — you can read that straight out of the chat template embedded in the GGUF you downloaded, whose generation prompt emits <think>\n with no closing tag unless enable_thinking is explicitly false. Under llama-server's default reasoning extraction the parser therefore treats the whole output — reasoning and the <tool_call> block together — as reasoning, returns it in reasoning_content, and leaves message.content empty. The harness parses message.content for <tool_call>, finds nothing, and the loop dies on round one.
Launch with --reasoning-format none, documented as "none: leaves thoughts unparsed in message.content". The raw output then begins with a stray unclosed <think> tag, which is cosmetic.
Reported for Fara1.5-27B by a community user on build b10107 in the model's HF discussions and acknowledged there by Microsoft — swhitehead, whose HF account carries the org-member flag on that repo, replied "Would you mind posting this as an issue on the Fara1.5 github repo so we can mention this in the hosting instructions?", which became microsoft/fara#82 — still open, titled "Hosting: llama.cpp needs --reasoning-format none". The same reporter adds: "If you have a router/proxy in front doing its own reasoning extraction, disable it there too."
The model answers but ignores the screenshot
Almost always the projector. Confirm --mmproj is on the command line, that the server logged an mmproj load stage, that /v1/models advertises the multimodal capability, and that Step 4's /props call reports vision: True. A text-only GGUF with no projector loads and runs perfectly happily — it simply cannot see, which in a CUA presents as confidently wrong actions rather than an error. Note the automatic projector download only happens on the -hf path; with -m you must pass --mmproj yourself.
Clicks land in the wrong place
Check the viewport first: the harness defaults to 1440×900 because that is what the model was mostly trained at, and a different window size changes both the grounding distribution and the token cost derived above. Then confirm --image-min-tokens 1024 is set, since llama.cpp's own warning ties sub-1024-token images to degraded grounding. Only after both should you suspect the weights — and this recipe already leads the highest quantisation tier that fits on the card, so the remaining rungs are all downward.
Out of memory at load
In order of what to try, with what each actually frees:
| Change | Frees | Cost |
|---|---|---|
-c 65536 → 32768 | 1.000 GiB | still 2.2× the harness's documented 15,000-token floor |
Q8_0 → Fara1.5-9B-Q6_K.gguf | 1.719 GiB | one rung down an unmeasured grounding ladder |
Q8_0 → Fara1.5-9B-Q5_K_M.gguf | 2.508 GiB | the 12 GB recipe's lead quant |
--no-mmproj-offload | 0.855 GiB | slower image encoding, once per agent turn |
Take the context first — it is the cheapest and the best-understood. Keep the f16 projector: at 0.855 GiB it is not where the savings are, and trading vision fidelity in a model whose entire job is looking at pixels is the worst rung on this list. Passing --parallel 1 would shrink the recurrent state from 201.00 MiB back to 50.25 MiB, but 0.147 GiB is the smallest lever on this page and it changes the server's default slot behaviour — reach for the table instead.
rope.dimension_sections has wrong array length; expected 4, got 3
This is a real open llama.cpp bug (PR #25334, titled "fix: load qwen35 Ollama GGUF exports"), but it belongs to Ollama-exported qwen35 blobs, not to the GGUF this recipe uses. If you see this error, you are loading a different file than the one downloaded in Step 2.
ollama run fara does nothing — there is no Ollama entry
There is no Ollama library entry for Fara1.5 in any form. The GGUF/LM Studio/Ollama line in the harness README refers to Fara-7B, the previous generation, reached with a --fara-7b flag — it is not about Fara1.5, and the two should never be mixed. llama.cpp built from source is the path this recipe documents.
Generation is slower than a 9B model should be
Two things to separate before you go bug-hunting. The first is expected: Q8_0 moves 1.39× the bytes per token that Q5_K_M does, and single-token decode on a model this size is bound by how many bytes leave memory per token — that is the cost you chose in exchange for staying off the unmeasured end of the quant ladder. A/B against Fara1.5-9B-Q5_K_M.gguf with llama-bench before treating it as a defect. The second is a lead rather than a known property: llama.cpp issue #25162 is an open, community-reported regression against exactly the SSM kernels this architecture leans on, titled "Performance regression on Turing GPUs after 9e58d4d69 — Qwen35 SSM kernels affected". Read the scope carefully: the title says Turing, the reporter measured on an RTX 2080 Ti, the thread has two comments and both are from community accounts with no maintainer response, and nobody has posted numbers for an Ada card. It is a thing to check with llama-bench across a couple of builds, not a property of this one.
Running it against your own accounts
Don't. The model is trained to pause before sign-ins, payments and submissions, and that training is a safety net, not a guarantee — the card lists prompt injection embedded in page content among its known risks, and a vision-only agent has no way to distinguish a legitimate button from a hostile one that renders like it. Keep it in a container, on an allow-list, with no credentials in reach.