arc-llama 0.1.0__tar.gz
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.
- arc_llama-0.1.0/.github/workflows/ci.yml +37 -0
- arc_llama-0.1.0/.gitignore +30 -0
- arc_llama-0.1.0/LICENSE +21 -0
- arc_llama-0.1.0/PKG-INFO +295 -0
- arc_llama-0.1.0/README.md +260 -0
- arc_llama-0.1.0/pyproject.toml +65 -0
- arc_llama-0.1.0/src/arc_llama/__init__.py +3 -0
- arc_llama-0.1.0/src/arc_llama/__main__.py +4 -0
- arc_llama-0.1.0/src/arc_llama/arch.py +225 -0
- arc_llama-0.1.0/src/arc_llama/benchmark.py +441 -0
- arc_llama-0.1.0/src/arc_llama/cli.py +705 -0
- arc_llama-0.1.0/src/arc_llama/config.py +287 -0
- arc_llama-0.1.0/src/arc_llama/detect.py +247 -0
- arc_llama-0.1.0/src/arc_llama/gguf_meta.py +112 -0
- arc_llama-0.1.0/src/arc_llama/launcher.py +247 -0
- arc_llama-0.1.0/src/arc_llama/models.py +410 -0
- arc_llama-0.1.0/src/arc_llama/recipes.py +159 -0
- arc_llama-0.1.0/src/arc_llama/router.py +209 -0
- arc_llama-0.1.0/src/arc_llama/server.py +349 -0
- arc_llama-0.1.0/src/arc_llama/static/app.js +242 -0
- arc_llama-0.1.0/src/arc_llama/static/index.html +57 -0
- arc_llama-0.1.0/src/arc_llama/static/style.css +184 -0
- arc_llama-0.1.0/src/arc_llama/tui.py +378 -0
- arc_llama-0.1.0/tests/conftest.py +61 -0
- arc_llama-0.1.0/tests/test_benchmark.py +310 -0
- arc_llama-0.1.0/tests/test_config.py +59 -0
- arc_llama-0.1.0/tests/test_detect.py +128 -0
- arc_llama-0.1.0/tests/test_gguf_meta.py +65 -0
- arc_llama-0.1.0/tests/test_launcher.py +227 -0
- arc_llama-0.1.0/tests/test_models.py +86 -0
- arc_llama-0.1.0/tests/test_recipes.py +194 -0
- arc_llama-0.1.0/tests/test_router.py +64 -0
- arc_llama-0.1.0/tests/test_server.py +146 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
name: Python ${{ matrix.python-version }}
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Check out repository
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Set up Python
|
|
22
|
+
uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
cache: pip
|
|
26
|
+
|
|
27
|
+
- name: Install package
|
|
28
|
+
run: python -m pip install -e '.[dev]'
|
|
29
|
+
|
|
30
|
+
- name: Lint
|
|
31
|
+
run: ruff check .
|
|
32
|
+
|
|
33
|
+
- name: Test
|
|
34
|
+
run: pytest
|
|
35
|
+
|
|
36
|
+
- name: Build package
|
|
37
|
+
run: python -m build
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
.mypy_cache/
|
|
2
|
+
.ruff_cache/
|
|
3
|
+
.uv-cache/
|
|
4
|
+
__pycache__/
|
|
5
|
+
*.py[cod]
|
|
6
|
+
*.egg-info/
|
|
7
|
+
.eggs/
|
|
8
|
+
build/
|
|
9
|
+
dist/
|
|
10
|
+
.venv/
|
|
11
|
+
venv/
|
|
12
|
+
.env
|
|
13
|
+
.env.local
|
|
14
|
+
|
|
15
|
+
# arc-llama runtime state
|
|
16
|
+
*.log
|
|
17
|
+
*.pid
|
|
18
|
+
state/
|
|
19
|
+
models/
|
|
20
|
+
|
|
21
|
+
# IDE
|
|
22
|
+
.vscode/
|
|
23
|
+
.idea/
|
|
24
|
+
*.swp
|
|
25
|
+
.DS_Store
|
|
26
|
+
|
|
27
|
+
# pytest / coverage
|
|
28
|
+
.pytest_cache/
|
|
29
|
+
.coverage
|
|
30
|
+
htmlcov/
|
arc_llama-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 arc-llama contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
arc_llama-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: arc-llama
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Plug-and-play llama.cpp runtime for Intel Arc GPUs. Auto-detects your card, picks safe SYCL defaults, and exposes an OpenAI-compatible API.
|
|
5
|
+
Project-URL: Homepage, https://github.com/offbyonebit/arc-llama
|
|
6
|
+
Project-URL: Issues, https://github.com/offbyonebit/arc-llama/issues
|
|
7
|
+
License: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Keywords: alchemist,arc,battlemage,inference,intel,llama.cpp,llm,sycl
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Requires-Dist: click>=8.1
|
|
17
|
+
Requires-Dist: fastapi>=0.110
|
|
18
|
+
Requires-Dist: gguf>=0.10
|
|
19
|
+
Requires-Dist: httpx>=0.27
|
|
20
|
+
Requires-Dist: huggingface-hub>=0.20
|
|
21
|
+
Requires-Dist: rich>=13.0
|
|
22
|
+
Requires-Dist: tomli-w>=1.0
|
|
23
|
+
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
24
|
+
Requires-Dist: uvicorn[standard]>=0.27
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
27
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
31
|
+
Requires-Dist: textual>=0.60; extra == 'dev'
|
|
32
|
+
Provides-Extra: tui
|
|
33
|
+
Requires-Dist: textual>=0.60; extra == 'tui'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# arc-llama
|
|
37
|
+
|
|
38
|
+
> Plug-and-play `llama.cpp` runtime for Intel Arc GPUs.
|
|
39
|
+
|
|
40
|
+
`arc-llama` is a single command-line tool that detects your Intel Arc card,
|
|
41
|
+
applies the right SYCL/oneAPI environment for your generation, downloads or
|
|
42
|
+
registers GGUF models, and runs an OpenAI-compatible server in front of them.
|
|
43
|
+
It encodes the gotchas (SIGSEGVs in the persistent device-code cache, IPEX-LLM
|
|
44
|
+
bundle env-var traps, KV-cache quant behaviour per architecture) so you don't
|
|
45
|
+
have to discover them the hard way.
|
|
46
|
+
|
|
47
|
+
It's built for the day you unbox an Arc card, install drivers, and want
|
|
48
|
+
something useful before lunch.
|
|
49
|
+
|
|
50
|
+
> [!IMPORTANT]
|
|
51
|
+
> **Status: 0.1 alpha.** Core code is in place. End-to-end runs and tests
|
|
52
|
+
> haven't been exercised yet , issue and PR feedback welcome.
|
|
53
|
+
|
|
54
|
+
## What you get
|
|
55
|
+
|
|
56
|
+
- **Auto-discovery of GPUs *and models*.** `arc-llama init` finds your Intel
|
|
57
|
+
card and walks the configured scan paths for `.gguf` files, registering
|
|
58
|
+
every one with a sensible recipe , context length sized to your VRAM,
|
|
59
|
+
KV-cache class inferred from the filename. You should never need
|
|
60
|
+
`arc-llama add` for a GGUF that's already on disk.
|
|
61
|
+
- **Auto-discovery** of every Intel GPU on the host (`Alchemist`, `Battlemage`,
|
|
62
|
+
Lunar Lake iGPU). PCI device-ID table covers the common SKUs and falls back
|
|
63
|
+
to OpenCL device-name parsing for the rest.
|
|
64
|
+
- **Per-arch SYCL profiles** , env vars like `SYCL_CACHE_PERSISTENT=0` are
|
|
65
|
+
applied automatically, and known-bad ones (e.g. `GGML_SYCL_DISABLE_OPT`,
|
|
66
|
+
`SYCL_PI_LEVEL_ZERO_USE_IMMEDIATE_COMMANDLISTS`) are stripped from the
|
|
67
|
+
inherited shell environment.
|
|
68
|
+
- **Smart defaults** for `-ctx`, `--cache-type-k/v`, and `-ngl` based on the
|
|
69
|
+
detected VRAM and the model file size , never starts a model you can't fit.
|
|
70
|
+
- **Model registry** in TOML at `$XDG_CONFIG_HOME/arc-llama/config.toml`,
|
|
71
|
+
trivially editable.
|
|
72
|
+
- **One process per model**, swapped in/out by an internal router. Default
|
|
73
|
+
policy is single-resident across all GPUs (good for thermals); flip it to
|
|
74
|
+
multi-resident if you have headroom.
|
|
75
|
+
- **OpenAI-compatible API** at `http://127.0.0.1:11437/v1/...`. Plug it into
|
|
76
|
+
Open WebUI, OpenCode, anything that speaks OpenAI.
|
|
77
|
+
- **A web UI** at `http://127.0.0.1:11437/` , ships with the install. Model
|
|
78
|
+
picker, load/stop buttons, **inline ctx + KV-quant editing**, GPU + VRAM
|
|
79
|
+
panel. Pure HTML/JS, no build step.
|
|
80
|
+
- **A terminal UI** (`arc-llama tui`) using Textual , same load/stop/edit
|
|
81
|
+
controls, no browser needed. Optional install: `pip install 'arc-llama[tui]'`.
|
|
82
|
+
- **No magic with your existing stack.** It uses your `llama-server` binary;
|
|
83
|
+
you're never locked into a specific build.
|
|
84
|
+
|
|
85
|
+
## Quick start
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# 1. Install (editable, while we're in alpha)
|
|
89
|
+
git clone https://github.com/offbyonebit/arc-llama
|
|
90
|
+
cd arc-llama
|
|
91
|
+
pip install -e .
|
|
92
|
+
|
|
93
|
+
# 2. Detect GPUs and write a starter config
|
|
94
|
+
arc-llama init --llama-server /path/to/your/built/llama-server
|
|
95
|
+
|
|
96
|
+
# 3. Look at what was found
|
|
97
|
+
arc-llama doctor
|
|
98
|
+
arc-llama gpus
|
|
99
|
+
|
|
100
|
+
# 4. Auto-register every GGUF found under your scan paths.
|
|
101
|
+
# `init` ran this once; rerun any time you drop new files in.
|
|
102
|
+
arc-llama scan
|
|
103
|
+
# (or for one-offs: arc-llama add /path/to/some.gguf,
|
|
104
|
+
# or HF: arc-llama add unsloth/gemma-4-31B-it-GGUF:Q4_K_M --from-hf)
|
|
105
|
+
|
|
106
|
+
# 5. Run the OpenAI-compatible server (also serves the web UI at /)
|
|
107
|
+
arc-llama serve
|
|
108
|
+
|
|
109
|
+
# 6. (Optional) Open the terminal UI in another window
|
|
110
|
+
arc-llama tui
|
|
111
|
+
|
|
112
|
+
# 7. (Optional) Install a systemd --user unit
|
|
113
|
+
arc-llama systemd --write
|
|
114
|
+
systemctl --user daemon-reload
|
|
115
|
+
systemctl --user enable --now arc-llama.service
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Then point any OpenAI-compatible client at `http://127.0.0.1:11437/v1`:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
curl http://127.0.0.1:11437/v1/chat/completions \
|
|
122
|
+
-H "Content-Type: application/json" \
|
|
123
|
+
-d '{
|
|
124
|
+
"model": "gemma-4-31b-q4_k_m",
|
|
125
|
+
"messages": [{"role": "user", "content": "hi"}]
|
|
126
|
+
}'
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Requirements
|
|
130
|
+
|
|
131
|
+
- Linux, kernel **6.8+** for Battlemage (`xe` driver) or 5.17+ for Alchemist
|
|
132
|
+
(`i915`).
|
|
133
|
+
- ReBAR enabled in BIOS , without it llama.cpp falls back to slow paths on Arc.
|
|
134
|
+
- A `llama-server` built with the SYCL backend. The Intel oneAPI Base Toolkit
|
|
135
|
+
is the supported build path:
|
|
136
|
+
```bash
|
|
137
|
+
source /opt/intel/oneapi/setvars.sh
|
|
138
|
+
cmake -B build -DGGML_SYCL=ON -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx
|
|
139
|
+
cmake --build build --config Release -j
|
|
140
|
+
```
|
|
141
|
+
- User in the `render` and `video` groups (`arc-llama doctor` will tell you).
|
|
142
|
+
|
|
143
|
+
## Multi-GPU
|
|
144
|
+
|
|
145
|
+
`arc-llama init` registers every Intel GPU it finds. Each model in the config
|
|
146
|
+
is bound to a specific PCI slot, and the SYCL device selector
|
|
147
|
+
(`ONEAPI_DEVICE_SELECTOR=level_zero:N`) is set per-model. Add your second card,
|
|
148
|
+
re-run `arc-llama init --force` to refresh `[[gpus]]`, then add models against
|
|
149
|
+
either GPU.
|
|
150
|
+
|
|
151
|
+
The default swap policy is **single-resident across all GPUs** , pick a model,
|
|
152
|
+
the router stops anything else first. Flip `server.single_resident = false` in
|
|
153
|
+
the config if you want different-GPU models to coexist.
|
|
154
|
+
|
|
155
|
+
## Configuration reference
|
|
156
|
+
|
|
157
|
+
`$XDG_CONFIG_HOME/arc-llama/config.toml`:
|
|
158
|
+
|
|
159
|
+
```toml
|
|
160
|
+
version = 1
|
|
161
|
+
|
|
162
|
+
[server]
|
|
163
|
+
host = "127.0.0.1"
|
|
164
|
+
port = 11437
|
|
165
|
+
single_resident = true
|
|
166
|
+
|
|
167
|
+
[paths]
|
|
168
|
+
llama_server = "/usr/local/bin/llama-server"
|
|
169
|
+
models_dir = "~/.local/share/arc-llama/models"
|
|
170
|
+
state_dir = "~/.local/state/arc-llama"
|
|
171
|
+
|
|
172
|
+
[[gpus]]
|
|
173
|
+
pci_slot = "0000:03:00.0"
|
|
174
|
+
sycl_index = 0
|
|
175
|
+
arch = "battlemage"
|
|
176
|
+
vram_mb = 24480
|
|
177
|
+
enabled = true
|
|
178
|
+
name = "Arc Pro B60"
|
|
179
|
+
|
|
180
|
+
[[models]]
|
|
181
|
+
name = "qwen3-7b"
|
|
182
|
+
display_name = "Qwen 3 7B"
|
|
183
|
+
path = "/home/me/models/qwen3-7b-q4_k_m.gguf"
|
|
184
|
+
gpu_pci_slot = "0000:03:00.0"
|
|
185
|
+
port = 18080
|
|
186
|
+
kv_class = "default"
|
|
187
|
+
aliases = ["qwen3-7b-q4_k_m.gguf"]
|
|
188
|
+
|
|
189
|
+
[models.recipe]
|
|
190
|
+
ctx = 32768
|
|
191
|
+
cache_type_k = "q8_0"
|
|
192
|
+
cache_type_v = "q8_0"
|
|
193
|
+
n_gpu_layers = 999
|
|
194
|
+
parallel = 1
|
|
195
|
+
extra_flags = []
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
`kv_class` controls the KV-cache size estimate that `arc-llama add` uses to
|
|
199
|
+
pick a context length. Currently:
|
|
200
|
+
|
|
201
|
+
| value | per-token f16 KV | typical for |
|
|
202
|
+
|-------------------|------------------|----------------------------------------------|
|
|
203
|
+
| `default` | ~80 KiB | most ≤30B dense models, conservative ceiling |
|
|
204
|
+
| `qwen3_27b_dense` | ~70 KiB | Qwen 3 27B dense |
|
|
205
|
+
| `moe_a3b` | ~24 KiB | Qwen 3 30B/35B-A3B MoE |
|
|
206
|
+
| `gemma_swa` | ~16 KiB | Gemma 3/4 (interleaved sliding-window attn) |
|
|
207
|
+
|
|
208
|
+
## Architecture
|
|
209
|
+
|
|
210
|
+
```
|
|
211
|
+
┌──────────────────────┐
|
|
212
|
+
│ OpenAI client │ Open WebUI, OpenCode, curl, ...
|
|
213
|
+
│ (port 11437) │
|
|
214
|
+
└──────────┬───────────┘
|
|
215
|
+
│
|
|
216
|
+
▼
|
|
217
|
+
┌──────────────────────┐
|
|
218
|
+
│ arc-llama serve │ FastAPI, /v1/chat/completions etc.
|
|
219
|
+
│ (router + state) │
|
|
220
|
+
└──────────┬───────────┘
|
|
221
|
+
│ ensure_active(model)
|
|
222
|
+
▼
|
|
223
|
+
┌──────────────────────┐
|
|
224
|
+
│ Router │ swaps llama-server subprocesses per request
|
|
225
|
+
│ (single/multi-res) │ applies arch SYCL env, picks safe ctx/KV
|
|
226
|
+
└──────────┬───────────┘
|
|
227
|
+
│ subprocess.Popen
|
|
228
|
+
▼
|
|
229
|
+
┌──────────────────────┐
|
|
230
|
+
│ llama-server (SYCL) │ one per registered model, on demand
|
|
231
|
+
│ bound to GPU N │
|
|
232
|
+
└──────────────────────┘
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
The router serialises swaps with an `asyncio.Lock`, so concurrent requests for
|
|
236
|
+
the same model fan out to one warm backend. Health is polled at
|
|
237
|
+
`{backend_url}/health`; cold-start budget is 120 s by default to absorb the
|
|
238
|
+
SYCL JIT recompile that plain `llama.cpp` pays on each fresh launch.
|
|
239
|
+
|
|
240
|
+
## Why not just use Ollama / vLLM?
|
|
241
|
+
|
|
242
|
+
- **Ollama (IPEX-LLM bundle):** the Intel-supported port has reproducible
|
|
243
|
+
inference bugs on Battlemage with Qwen2.5-class models , sequential calls
|
|
244
|
+
collapse to NaN-derived gibberish. arc-llama runs `llama-server` directly so
|
|
245
|
+
you avoid that path entirely.
|
|
246
|
+
- **vLLM-XPU:** still maturing on Arc; weaker quant support. Worth trying for
|
|
247
|
+
dense >30B if you want throughput, but not yet a one-command experience.
|
|
248
|
+
- **Plain `llama-server` + scripts:** what most Arc owners do today. arc-llama
|
|
249
|
+
is the formalisation of those scripts, with the gotchas baked in.
|
|
250
|
+
|
|
251
|
+
## UIs
|
|
252
|
+
|
|
253
|
+
Two front-ends are bundled and both talk to the same admin endpoints
|
|
254
|
+
(`/admin/status`, `/admin/load/{name}`, `/admin/stop/{name}`, `/admin/stop-all`):
|
|
255
|
+
|
|
256
|
+
- **Web UI** at `http://<host>:<port>/` (default `127.0.0.1:11437`). Single
|
|
257
|
+
static page polled every 5 s. Status, GPUs, model list, per-model
|
|
258
|
+
Load/Stop buttons, "Stop all" panic button. No build step, no JS deps.
|
|
259
|
+
- **Terminal UI** via `arc-llama tui` , Textual-based. Bindings: `r` refresh,
|
|
260
|
+
`l` load selected model, `s` stop selected, `S` stop all, `q` quit. Run it
|
|
261
|
+
alongside `arc-llama serve` (or against a remote one with `--server`).
|
|
262
|
+
|
|
263
|
+
Both use brightness/dim for status (loaded vs idle) , no red/green palettes.
|
|
264
|
+
|
|
265
|
+
## Roadmap
|
|
266
|
+
|
|
267
|
+
- Smoke test on Alchemist (A770, A380) and Battlemage (B580) hardware.
|
|
268
|
+
- `arc-llama benchmark` , quick prompt-eval/gen tok/s harness.
|
|
269
|
+
- IPEX-LLM Ollama as an optional backend for users who prefer it.
|
|
270
|
+
- Container image with `llama-server` + arc-llama prebuilt.
|
|
271
|
+
|
|
272
|
+
## Contributing
|
|
273
|
+
|
|
274
|
+
PRs and issues welcome. The most useful contributions today are:
|
|
275
|
+
|
|
276
|
+
1. Confirming or fixing PCI device-ID → arch mappings for your card. If
|
|
277
|
+
`arc-llama gpus` shows `unknown` for a working Arc card, please open an
|
|
278
|
+
issue with `lspci -nn` output.
|
|
279
|
+
2. Reporting architectures where the default SYCL env profile crashes or
|
|
280
|
+
underperforms.
|
|
281
|
+
3. Trying the smoke tests on hardware other than the maintainer's Battlemage
|
|
282
|
+
B60 development box.
|
|
283
|
+
|
|
284
|
+
## Support
|
|
285
|
+
|
|
286
|
+
This project is free and I don't ask for anything. If it's useful to you,
|
|
287
|
+
a star on the repo is appreciated, and if you want to follow along with
|
|
288
|
+
other things I'm building, you can find them under
|
|
289
|
+
[@offbyonebit](https://github.com/offbyonebit).
|
|
290
|
+
|
|
291
|
+
If you'd like to support development, you can [sponsor me on GitHub](https://github.com/sponsors/offbyonebit).
|
|
292
|
+
|
|
293
|
+
## License
|
|
294
|
+
|
|
295
|
+
MIT , see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# arc-llama
|
|
2
|
+
|
|
3
|
+
> Plug-and-play `llama.cpp` runtime for Intel Arc GPUs.
|
|
4
|
+
|
|
5
|
+
`arc-llama` is a single command-line tool that detects your Intel Arc card,
|
|
6
|
+
applies the right SYCL/oneAPI environment for your generation, downloads or
|
|
7
|
+
registers GGUF models, and runs an OpenAI-compatible server in front of them.
|
|
8
|
+
It encodes the gotchas (SIGSEGVs in the persistent device-code cache, IPEX-LLM
|
|
9
|
+
bundle env-var traps, KV-cache quant behaviour per architecture) so you don't
|
|
10
|
+
have to discover them the hard way.
|
|
11
|
+
|
|
12
|
+
It's built for the day you unbox an Arc card, install drivers, and want
|
|
13
|
+
something useful before lunch.
|
|
14
|
+
|
|
15
|
+
> [!IMPORTANT]
|
|
16
|
+
> **Status: 0.1 alpha.** Core code is in place. End-to-end runs and tests
|
|
17
|
+
> haven't been exercised yet , issue and PR feedback welcome.
|
|
18
|
+
|
|
19
|
+
## What you get
|
|
20
|
+
|
|
21
|
+
- **Auto-discovery of GPUs *and models*.** `arc-llama init` finds your Intel
|
|
22
|
+
card and walks the configured scan paths for `.gguf` files, registering
|
|
23
|
+
every one with a sensible recipe , context length sized to your VRAM,
|
|
24
|
+
KV-cache class inferred from the filename. You should never need
|
|
25
|
+
`arc-llama add` for a GGUF that's already on disk.
|
|
26
|
+
- **Auto-discovery** of every Intel GPU on the host (`Alchemist`, `Battlemage`,
|
|
27
|
+
Lunar Lake iGPU). PCI device-ID table covers the common SKUs and falls back
|
|
28
|
+
to OpenCL device-name parsing for the rest.
|
|
29
|
+
- **Per-arch SYCL profiles** , env vars like `SYCL_CACHE_PERSISTENT=0` are
|
|
30
|
+
applied automatically, and known-bad ones (e.g. `GGML_SYCL_DISABLE_OPT`,
|
|
31
|
+
`SYCL_PI_LEVEL_ZERO_USE_IMMEDIATE_COMMANDLISTS`) are stripped from the
|
|
32
|
+
inherited shell environment.
|
|
33
|
+
- **Smart defaults** for `-ctx`, `--cache-type-k/v`, and `-ngl` based on the
|
|
34
|
+
detected VRAM and the model file size , never starts a model you can't fit.
|
|
35
|
+
- **Model registry** in TOML at `$XDG_CONFIG_HOME/arc-llama/config.toml`,
|
|
36
|
+
trivially editable.
|
|
37
|
+
- **One process per model**, swapped in/out by an internal router. Default
|
|
38
|
+
policy is single-resident across all GPUs (good for thermals); flip it to
|
|
39
|
+
multi-resident if you have headroom.
|
|
40
|
+
- **OpenAI-compatible API** at `http://127.0.0.1:11437/v1/...`. Plug it into
|
|
41
|
+
Open WebUI, OpenCode, anything that speaks OpenAI.
|
|
42
|
+
- **A web UI** at `http://127.0.0.1:11437/` , ships with the install. Model
|
|
43
|
+
picker, load/stop buttons, **inline ctx + KV-quant editing**, GPU + VRAM
|
|
44
|
+
panel. Pure HTML/JS, no build step.
|
|
45
|
+
- **A terminal UI** (`arc-llama tui`) using Textual , same load/stop/edit
|
|
46
|
+
controls, no browser needed. Optional install: `pip install 'arc-llama[tui]'`.
|
|
47
|
+
- **No magic with your existing stack.** It uses your `llama-server` binary;
|
|
48
|
+
you're never locked into a specific build.
|
|
49
|
+
|
|
50
|
+
## Quick start
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# 1. Install (editable, while we're in alpha)
|
|
54
|
+
git clone https://github.com/offbyonebit/arc-llama
|
|
55
|
+
cd arc-llama
|
|
56
|
+
pip install -e .
|
|
57
|
+
|
|
58
|
+
# 2. Detect GPUs and write a starter config
|
|
59
|
+
arc-llama init --llama-server /path/to/your/built/llama-server
|
|
60
|
+
|
|
61
|
+
# 3. Look at what was found
|
|
62
|
+
arc-llama doctor
|
|
63
|
+
arc-llama gpus
|
|
64
|
+
|
|
65
|
+
# 4. Auto-register every GGUF found under your scan paths.
|
|
66
|
+
# `init` ran this once; rerun any time you drop new files in.
|
|
67
|
+
arc-llama scan
|
|
68
|
+
# (or for one-offs: arc-llama add /path/to/some.gguf,
|
|
69
|
+
# or HF: arc-llama add unsloth/gemma-4-31B-it-GGUF:Q4_K_M --from-hf)
|
|
70
|
+
|
|
71
|
+
# 5. Run the OpenAI-compatible server (also serves the web UI at /)
|
|
72
|
+
arc-llama serve
|
|
73
|
+
|
|
74
|
+
# 6. (Optional) Open the terminal UI in another window
|
|
75
|
+
arc-llama tui
|
|
76
|
+
|
|
77
|
+
# 7. (Optional) Install a systemd --user unit
|
|
78
|
+
arc-llama systemd --write
|
|
79
|
+
systemctl --user daemon-reload
|
|
80
|
+
systemctl --user enable --now arc-llama.service
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Then point any OpenAI-compatible client at `http://127.0.0.1:11437/v1`:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
curl http://127.0.0.1:11437/v1/chat/completions \
|
|
87
|
+
-H "Content-Type: application/json" \
|
|
88
|
+
-d '{
|
|
89
|
+
"model": "gemma-4-31b-q4_k_m",
|
|
90
|
+
"messages": [{"role": "user", "content": "hi"}]
|
|
91
|
+
}'
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Requirements
|
|
95
|
+
|
|
96
|
+
- Linux, kernel **6.8+** for Battlemage (`xe` driver) or 5.17+ for Alchemist
|
|
97
|
+
(`i915`).
|
|
98
|
+
- ReBAR enabled in BIOS , without it llama.cpp falls back to slow paths on Arc.
|
|
99
|
+
- A `llama-server` built with the SYCL backend. The Intel oneAPI Base Toolkit
|
|
100
|
+
is the supported build path:
|
|
101
|
+
```bash
|
|
102
|
+
source /opt/intel/oneapi/setvars.sh
|
|
103
|
+
cmake -B build -DGGML_SYCL=ON -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx
|
|
104
|
+
cmake --build build --config Release -j
|
|
105
|
+
```
|
|
106
|
+
- User in the `render` and `video` groups (`arc-llama doctor` will tell you).
|
|
107
|
+
|
|
108
|
+
## Multi-GPU
|
|
109
|
+
|
|
110
|
+
`arc-llama init` registers every Intel GPU it finds. Each model in the config
|
|
111
|
+
is bound to a specific PCI slot, and the SYCL device selector
|
|
112
|
+
(`ONEAPI_DEVICE_SELECTOR=level_zero:N`) is set per-model. Add your second card,
|
|
113
|
+
re-run `arc-llama init --force` to refresh `[[gpus]]`, then add models against
|
|
114
|
+
either GPU.
|
|
115
|
+
|
|
116
|
+
The default swap policy is **single-resident across all GPUs** , pick a model,
|
|
117
|
+
the router stops anything else first. Flip `server.single_resident = false` in
|
|
118
|
+
the config if you want different-GPU models to coexist.
|
|
119
|
+
|
|
120
|
+
## Configuration reference
|
|
121
|
+
|
|
122
|
+
`$XDG_CONFIG_HOME/arc-llama/config.toml`:
|
|
123
|
+
|
|
124
|
+
```toml
|
|
125
|
+
version = 1
|
|
126
|
+
|
|
127
|
+
[server]
|
|
128
|
+
host = "127.0.0.1"
|
|
129
|
+
port = 11437
|
|
130
|
+
single_resident = true
|
|
131
|
+
|
|
132
|
+
[paths]
|
|
133
|
+
llama_server = "/usr/local/bin/llama-server"
|
|
134
|
+
models_dir = "~/.local/share/arc-llama/models"
|
|
135
|
+
state_dir = "~/.local/state/arc-llama"
|
|
136
|
+
|
|
137
|
+
[[gpus]]
|
|
138
|
+
pci_slot = "0000:03:00.0"
|
|
139
|
+
sycl_index = 0
|
|
140
|
+
arch = "battlemage"
|
|
141
|
+
vram_mb = 24480
|
|
142
|
+
enabled = true
|
|
143
|
+
name = "Arc Pro B60"
|
|
144
|
+
|
|
145
|
+
[[models]]
|
|
146
|
+
name = "qwen3-7b"
|
|
147
|
+
display_name = "Qwen 3 7B"
|
|
148
|
+
path = "/home/me/models/qwen3-7b-q4_k_m.gguf"
|
|
149
|
+
gpu_pci_slot = "0000:03:00.0"
|
|
150
|
+
port = 18080
|
|
151
|
+
kv_class = "default"
|
|
152
|
+
aliases = ["qwen3-7b-q4_k_m.gguf"]
|
|
153
|
+
|
|
154
|
+
[models.recipe]
|
|
155
|
+
ctx = 32768
|
|
156
|
+
cache_type_k = "q8_0"
|
|
157
|
+
cache_type_v = "q8_0"
|
|
158
|
+
n_gpu_layers = 999
|
|
159
|
+
parallel = 1
|
|
160
|
+
extra_flags = []
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`kv_class` controls the KV-cache size estimate that `arc-llama add` uses to
|
|
164
|
+
pick a context length. Currently:
|
|
165
|
+
|
|
166
|
+
| value | per-token f16 KV | typical for |
|
|
167
|
+
|-------------------|------------------|----------------------------------------------|
|
|
168
|
+
| `default` | ~80 KiB | most ≤30B dense models, conservative ceiling |
|
|
169
|
+
| `qwen3_27b_dense` | ~70 KiB | Qwen 3 27B dense |
|
|
170
|
+
| `moe_a3b` | ~24 KiB | Qwen 3 30B/35B-A3B MoE |
|
|
171
|
+
| `gemma_swa` | ~16 KiB | Gemma 3/4 (interleaved sliding-window attn) |
|
|
172
|
+
|
|
173
|
+
## Architecture
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
┌──────────────────────┐
|
|
177
|
+
│ OpenAI client │ Open WebUI, OpenCode, curl, ...
|
|
178
|
+
│ (port 11437) │
|
|
179
|
+
└──────────┬───────────┘
|
|
180
|
+
│
|
|
181
|
+
▼
|
|
182
|
+
┌──────────────────────┐
|
|
183
|
+
│ arc-llama serve │ FastAPI, /v1/chat/completions etc.
|
|
184
|
+
│ (router + state) │
|
|
185
|
+
└──────────┬───────────┘
|
|
186
|
+
│ ensure_active(model)
|
|
187
|
+
▼
|
|
188
|
+
┌──────────────────────┐
|
|
189
|
+
│ Router │ swaps llama-server subprocesses per request
|
|
190
|
+
│ (single/multi-res) │ applies arch SYCL env, picks safe ctx/KV
|
|
191
|
+
└──────────┬───────────┘
|
|
192
|
+
│ subprocess.Popen
|
|
193
|
+
▼
|
|
194
|
+
┌──────────────────────┐
|
|
195
|
+
│ llama-server (SYCL) │ one per registered model, on demand
|
|
196
|
+
│ bound to GPU N │
|
|
197
|
+
└──────────────────────┘
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
The router serialises swaps with an `asyncio.Lock`, so concurrent requests for
|
|
201
|
+
the same model fan out to one warm backend. Health is polled at
|
|
202
|
+
`{backend_url}/health`; cold-start budget is 120 s by default to absorb the
|
|
203
|
+
SYCL JIT recompile that plain `llama.cpp` pays on each fresh launch.
|
|
204
|
+
|
|
205
|
+
## Why not just use Ollama / vLLM?
|
|
206
|
+
|
|
207
|
+
- **Ollama (IPEX-LLM bundle):** the Intel-supported port has reproducible
|
|
208
|
+
inference bugs on Battlemage with Qwen2.5-class models , sequential calls
|
|
209
|
+
collapse to NaN-derived gibberish. arc-llama runs `llama-server` directly so
|
|
210
|
+
you avoid that path entirely.
|
|
211
|
+
- **vLLM-XPU:** still maturing on Arc; weaker quant support. Worth trying for
|
|
212
|
+
dense >30B if you want throughput, but not yet a one-command experience.
|
|
213
|
+
- **Plain `llama-server` + scripts:** what most Arc owners do today. arc-llama
|
|
214
|
+
is the formalisation of those scripts, with the gotchas baked in.
|
|
215
|
+
|
|
216
|
+
## UIs
|
|
217
|
+
|
|
218
|
+
Two front-ends are bundled and both talk to the same admin endpoints
|
|
219
|
+
(`/admin/status`, `/admin/load/{name}`, `/admin/stop/{name}`, `/admin/stop-all`):
|
|
220
|
+
|
|
221
|
+
- **Web UI** at `http://<host>:<port>/` (default `127.0.0.1:11437`). Single
|
|
222
|
+
static page polled every 5 s. Status, GPUs, model list, per-model
|
|
223
|
+
Load/Stop buttons, "Stop all" panic button. No build step, no JS deps.
|
|
224
|
+
- **Terminal UI** via `arc-llama tui` , Textual-based. Bindings: `r` refresh,
|
|
225
|
+
`l` load selected model, `s` stop selected, `S` stop all, `q` quit. Run it
|
|
226
|
+
alongside `arc-llama serve` (or against a remote one with `--server`).
|
|
227
|
+
|
|
228
|
+
Both use brightness/dim for status (loaded vs idle) , no red/green palettes.
|
|
229
|
+
|
|
230
|
+
## Roadmap
|
|
231
|
+
|
|
232
|
+
- Smoke test on Alchemist (A770, A380) and Battlemage (B580) hardware.
|
|
233
|
+
- `arc-llama benchmark` , quick prompt-eval/gen tok/s harness.
|
|
234
|
+
- IPEX-LLM Ollama as an optional backend for users who prefer it.
|
|
235
|
+
- Container image with `llama-server` + arc-llama prebuilt.
|
|
236
|
+
|
|
237
|
+
## Contributing
|
|
238
|
+
|
|
239
|
+
PRs and issues welcome. The most useful contributions today are:
|
|
240
|
+
|
|
241
|
+
1. Confirming or fixing PCI device-ID → arch mappings for your card. If
|
|
242
|
+
`arc-llama gpus` shows `unknown` for a working Arc card, please open an
|
|
243
|
+
issue with `lspci -nn` output.
|
|
244
|
+
2. Reporting architectures where the default SYCL env profile crashes or
|
|
245
|
+
underperforms.
|
|
246
|
+
3. Trying the smoke tests on hardware other than the maintainer's Battlemage
|
|
247
|
+
B60 development box.
|
|
248
|
+
|
|
249
|
+
## Support
|
|
250
|
+
|
|
251
|
+
This project is free and I don't ask for anything. If it's useful to you,
|
|
252
|
+
a star on the repo is appreciated, and if you want to follow along with
|
|
253
|
+
other things I'm building, you can find them under
|
|
254
|
+
[@offbyonebit](https://github.com/offbyonebit).
|
|
255
|
+
|
|
256
|
+
If you'd like to support development, you can [sponsor me on GitHub](https://github.com/sponsors/offbyonebit).
|
|
257
|
+
|
|
258
|
+
## License
|
|
259
|
+
|
|
260
|
+
MIT , see [LICENSE](LICENSE).
|