Vipera
A local AI gateway that plans before it runs.
One .gguf in, an OpenAI-compatible HTTP server out — on hardware where the
model does not quite fit.
The problem it solves
A 14B model on a 4 GB card looks like a CPU-only model. It is not: 17 of its 40 layers fit in VRAM at 8K context, and putting them there is the difference between 6.6 and 0.2 tokens/second.
Vipera measures the machine, budgets VRAM and RAM per layer, and hands
llama.cpp a plan it can justify:
vipera system doctor # what the machine actually has
vipera serve start # plan, load, serve
curl localhost:8686/health # {"status": "ok", "model": "..."}
Measured on a GTX 1650 4 GB, Hermes-4-14B Q3_K_M at 8K context:
| layers on GPU | VRAM used | decode | |
|---|---|---|---|
| CPU only | 0/40 | — | 0.2 t/s |
| Vipera's plan | 17/40 | 3.37 GB | 6.57 t/s |
The whole plan is printed before the model loads, and every flag in it is
traceable to a measurement: planner.py carries the
numbers in comments, docs/benchmarks.md carries the runs.
Install and run
pip install "vipera-ai[llama,gguf,nvidia]" # llama-cpp-python builds for your platform
vipera model search # fetch a GGUF from Hugging Face
vipera serve start # → http://127.0.0.1:8686/v1
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8686/v1", api_key="none")
stream = client.chat.completions.create(
model="qwen2.5-7b-instruct", # the alias from GET /v1/models; omit to use the loaded model
messages=[{"role": "user", "content": "Explain MoE in one paragraph."}],
stream=True,
)
for chunk in stream:
print(chunk.choices[0].delta.content or "", end="")
Verified clients: openai-python, LangChain, LlamaIndex, Continue, the OpenAI
Playground.
Should you use it?
| You want | Use |
|---|---|
| A model that spills VRAM or RAM, placed layer by layer instead of failing at load | Vipera |
An OpenAI-compatible endpoint from a .gguf with no separate inference stack |
Vipera |
| A reviewable answer to "why were these flags chosen" | Vipera (planner, plan docs) |
| Peak tokens/second on hardware you already tuned | llama.cpp/server directly |
| A desktop app with a model browser and chat UI | LM Studio |
| Multi-model routing, auth, TLS, or a web dashboard | Not this — one model per process, loopback by default |
Feature-by-feature with sources: docs/comparison.md.
How it decides
flowchart LR
subgraph Client
C1["openai-python"]
C2["curl"]
end
subgraph Vipera["Vipera Gateway"]
S["FastAPI server"]
E["Engine"]
P["Planner"]
H["Hardware probe"]
R["Registry"]
end
M[("GGUF file")]
C1 & C2 -->|"HTTP / SSE"| S
S -->|"chat()"| E
E -->|"reads"| M
P -->|"flags"| E
H --> P
R --> P
| Module | Job |
|---|---|
hardware.py |
Cores, RAM, GPU, VRAM. No side effects. |
planner.py |
(model meta, hardware) → Plan: layers, KV dtype, batch, mlock, KQV offload. |
engine.py |
Drives llama.cpp; owns the GPU → CPU ladder and the bake-off between backends. |
server.py |
FastAPI with real SSE, flushed per token. |
registry.py, ui.py |
Model store and the Rich terminal UI. |
Concurrency model, fallback ladder, and known gaps: docs/architecture.md. The terminal's visual rules: docs/design/visual-system.md.
CLI
| Command | What it does |
|---|---|
vipera |
Start the gateway with the default model. |
vipera serve start |
Serve a model over the OpenAI API. |
vipera model search |
Search Hugging Face and download a GGUF. |
vipera model add ollama:qwen2.5:7b |
Import a model Ollama already pulled, without copying it. |
vipera chat repl |
Chat against a local model in the terminal. |
vipera bench run |
Measure prompt and generation throughput. |
vipera system doctor |
Runtime, library, and hardware check. |
Every command, flag, and default: docs/cli.md.
HTTP API
| Method | Path | Returns |
|---|---|---|
GET |
/health |
{"status": "ok", "model": "<alias>"} |
GET |
/v1/models |
OpenAI-shaped model list |
POST |
/v1/chat/completions |
Chat completion, streaming or not |
POST |
/v1/embeddings |
Embeddings, with embeddings: true in the config |
POST |
/api/chat |
Same chat through the Ollama layer (--protocol openai,ollama) |
curl http://127.0.0.1:8686/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"messages": [{"role": "user", "content": "Hello"}]}'
Schemas, SSE framing, and Python/JavaScript examples: docs/http-api.md.
Configuration
Config lives at ~/.vipera/config.json. Change it with vipera system config
or edit the JSON. The keys that change behavior most: profile (auto, cpu,
gpu, lowmem, honored by serve, chat, and bench), ctx, kv_cache (f16,
q8_0, q4_0), spec_type (draft-free n-gram speculation, on by default),
default_model. Invalid values are repaired on load; vipera system config
refuses to write them.
The optimization layer (shaping, tuning, both on) trims a request that is
larger than the loaded context instead of letting llama.cpp cut the system
prompt, and reuses the layer split a previous vipera bench measured on this
machine. /health reports prefix-cache reuse. Details:
docs/architecture.md.
Full table: docs/configuration.md.
What the numbers look like
Two findings from docs/benchmarks.md, both on consumer hardware:
- Quantize with an importance matrix, not blindly. Q3_K_M + imatrix is 18.7% smaller than Q4_K_M (7.32 vs 9.00 GB), loads 25% faster, prefills 27% faster, and lands within the eval-set error on perplexity (6.9805 vs 7.0056, a 0.11σ gap). Say "same quality, 19% lighter", not "better".
kv_cache: q8_0halves KV memory for about 3% decode throughput.q5_1andiq4_nlcost 14–18%: use them only when KV size blocks the context you need.
Contributing
git clone https://github.com/vipera-iso/vipera
cd vipera
python -m venv .venv && .venv/bin/pip install -e ".[dev,llama,gguf]"
.venv/bin/pre-commit install
.venv/bin/pytest -q
CONTRIBUTING.md (dev setup, PR flow, demo GIF) · SECURITY.md (vulnerability reporting) · CHANGELOG.md (release history) · Code of conduct
MIT © 2026 Vipera — see LICENSE.
Metadata
Release files for vipera-ai 1.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| vipera_ai-1.2.1.tar.gz | 94.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vipera_ai-1.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 202.0 kB
Release files / vipera_ai-1.2.1.tar.gz
| Download URL | vipera_ai-1.2.1.tar.gz |
|---|---|
| Size | 94.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8d4869bd54c746d5864a37d091190b0d8f243835028cc19386b7f147391f9c91
|
|
BLAKE2b-256 checksum How to use checksums |
da4eb471a5fb681c629187ef802660eac3968018745eae001e068c3d9e24fb90
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Release files / vipera_ai-1.2.1-py3-none-any.whl
| Download URL | vipera_ai-1.2.1-py3-none-any.whl |
|---|---|
| Size | 107.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d60a63c817daddf2ca5e39659eebca3d71d1f2c617cf928f4b005b8b0d58f431
|
|
BLAKE2b-256 checksum How to use checksums |
c27d1be0d49f73b99305a46a0d241040dd8d792fc02f953a76e63466f7b19a8b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Security for vipera-ai 1.2.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.