Sign inSign up

maheshvaikri/snapllm

By maheshvaikri

•Updated about 1 month ago

Local Multi-Model LLM Inference

Image
Integration & delivery
Machine learning & AI
Developer tools
0

1.9K

maheshvaikri/snapllm repository overview

SnapLLM Logo

⁠SnapLLM - Local Multi-Model LLM Inference with Desktop UI, CLI & API

Preprint Paper Link (https://doi.org/10.32388/7MLDM5)
🤩 Star this repository - It helps others discover SnapLLM 🤩

Features⁠ | Installation⁠ | Quick Start⁠ | API Reference⁠ | Architecture⁠ | Demo Videos⁠ | Contributing⁠ | Sponsors⁠

Version CI License: MIT Stars Issues PRs welcome C++17 CUDA 12.x llama.cpp

Developed by Mahesh Vaikri
AroorA AI Labs ⁠


⁠What is SnapLLM?

SnapLLM is a local inference engine built on llama.cpp and stable-diffusion.cpp. It can keep multiple models loaded and select an already-resident model without reloading its weights. Actual load, switch, and generation latency depends on model size, hardware, memory pressure, and build configuration; benchmark your own workload before setting latency targets.

⁠The Problem

One common single-resident-model workflow:

Load Model A
Use Model A
Unload Model A
Load Model B
Use Model B
⁠The SnapLLM Solution
Load Model A
Load Model B
Select A or B without an avoidable reload while both remain resident

⁠Features

⁠Core Capabilities
FeatureDescription
Resident Model SelectionSelect between loaded models without reloading their weights
Reload After EvictionMemory mapping can benefit from the operating-system page cache
Multi-Model ManagementLoad and manage multiple models simultaneously
GPU/CPU HybridAutomatic layer distribution based on available VRAM
OpenAI-Compatible APIDrop-in replacement for OpenAI API
Multi-Modal SupportLLM, Vision (VLM), and Stable Diffusion models
KV Cache PersistencePersist context state and use indexed cache lookup; generation work still depends on query and context size
Web UIReact dashboard served by Vite at localhost:9780; the API listens on localhost:6930
Desktop ApplicationBeautiful React-based UI for model management
⁠Supported Model Types
  • Text LLMs: Llama 1/2/3, Mistral, Mixtral, Qwen, Gemma, Phi, DeepSeek, and all GGUF models
  • Vision Models: Gemma 3 Vision, Qwen-VL, LLaVA (with mmproj files)
  • Diffusion Models: Stable Diffusion 1.5, SDXL, SD3, FLUX (via stable-diffusion.cpp)
⁠Performance

SnapLLM reports operation timing at runtime where available. Published end-to-end latency guarantees require a reproducible benchmark that records the model, quantization, prompt, build flags, hardware, cache state, and sampling configuration. No such guarantee is made by this README.


⁠Installation

⁠Prerequisites
  • Windows: Visual Studio 2022 with C++ workload
  • Linux: GCC 11+ or Clang 14+
  • CUDA: 12.x (for GPU acceleration)
  • CMake: 3.18+
  • Node.js: 18+ (for desktop app)
⁠Build from Source
⁠Windows (GPU)
# Clone the repository
git clone https://github.com/snapllm/snapllm.git
cd snapllm

# Build with CUDA support
build_gpu.bat
⁠Windows (CPU only)
build_cpu.bat
⁠Linux (GPU)
chmod +x build.sh
./build.sh gpu
⁠Verify Installation
# Check the build
build_gpu/bin/snapllm --help

# Start the server
build_gpu/bin/snapllm --server --port 6930

⁠How to Start the Server

Start_Server.bat

This launcher auto-detects the newest build and starts the server on 127.0.0.1:6930. If the desktop app is built, it will launch the UI; otherwise it opens the browser.

⁠Windows (manual)
build_gpu\bin\snapllm.exe --server --host 127.0.0.1 --port 6930
⁠Start with a model preloaded
build_gpu\bin\snapllm.exe --server --host 127.0.0.1 --port 6930 --load-model mymodel D:\Models\mymodel.gguf
⁠Linux/macOS
chmod +x start_server.sh
./start_server.sh
⁠Docker

The Compose service binds inside its container on 0.0.0.0, publishes only to host loopback, and requires a runtime API key:

mkdir -p workspace models
export SNAPLLM_API_KEY='replace-with-a-random-value-at-least-32-characters'
docker compose up --build
⁠Docker Hub image

Tagged releases publish a CPU image to Docker Hub as <dockerhub-user>/snapllm:<version> and latest through the protected docker-publish GitHub environment. Configure repository secrets DOCKERHUB_USERNAME and DOCKERHUB_TOKEN, then create a release tag. The published image listens on 0.0.0.0:6930 inside the container and includes a health check for /health. The -cuda image uses the NVIDIA CUDA 12.6 runtime and requires NVIDIA Container Toolkit plus --gpus all; the unqualified image is CPU-only.

The container runs as an unprivileged user with a read-only root filesystem, dropped Linux capabilities, a read-only model mount, and a writable workspace mount. Changing the host port mapping to a public interface is a deployment decision: keep the API key enabled and put TLS plus network access controls in front of SnapLLM.

⁠Optional launch overrides (scripts)
  • SNAPLLM_SERVER_EXE: Full path to the SnapLLM binary
  • SNAPLLM_HOST: Host bind address (default 127.0.0.1)
  • SNAPLLM_PORT: Server port (default 6930)
  • SNAPLLM_WORKSPACE_ROOT: Workspace root directory
  • SNAPLLM_API_KEY: Runtime-only API key; required when binding beyond loopback
  • SNAPLLM_CORS_ORIGINS: Comma-separated exact browser origins to allow

⁠Quick Start

⁠1. Start the Server
# Start with a model pre-loaded
./snapllm --server --port 6930 --load-model mymodel /path/to/model.gguf

# Or start empty and load models via API
./snapllm --server --port 6930
⁠2. Load Models via API
# Load first model
curl -X POST http://localhost:6930/api/v1/models/load \
  -H "Content-Type: application/json" \
  -d '{
    "model_id": "llama3",
    "file_path": "/models/llama-3-8b-instruct.Q5_K_M.gguf"
  }'

# Load second model
curl -X POST http://localhost:6930/api/v1/models/load \
  -H "Content-Type: application/json" \
  -d '{
    "model_id": "gemma",
    "file_path": "/models/gemma-2-9b-it.Q5_K_M.gguf"
  }'
⁠3. Select a Loaded Model
# Select gemma without reloading it if it is still resident
curl -X POST http://localhost:6930/api/v1/models/switch \
  -H "Content-Type: application/json" \
  -d '{"model_id": "gemma"}'
⁠4. Chat with the Active Model
# OpenAI-compatible chat endpoint
curl -X POST http://localhost:6930/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemma",
    "messages": [
      {"role": "user", "content": "Explain quantum computing in simple terms"}
    ],
    "max_tokens": 256
  }'
⁠5. Use the Web UI

Start_Server.bat starts the API and, when the desktop binary is unavailable, starts the Vite web UI at http://localhost:9780. The API health endpoint remains available at http://localhost:6930/health.

To run the standalone desktop app (development mode):

cd desktop-app
npm install
npm run dev
# Open http://localhost:9780

⁠API Reference

⁠Base URL
http://localhost:6930

The default loopback listener can be used without an API key. For any non-loopback bind, set SNAPLLM_API_KEY to 32–4096 visible ASCII characters before starting the process. Send that value as either Authorization: Bearer <key> or X-API-Key: <key>. The key is read from the environment only and is not persisted or returned by the API.

All requests are checked against the configured Host. Browser requests also use an exact Origin allowlist; add trusted origins with repeatable --cors-origin options or SNAPLLM_CORS_ORIGINS. Wildcards and reflected origins are not accepted. Model and workspace paths are canonicalized and must remain inside their configured roots.

⁠Endpoints Overview
⁠Health & Status
MethodEndpointDescription
GET/API information
GET/healthServer health check
GET/v1/modelsList models (OpenAI format)
GET/api/v1/modelsList models (extended info)
⁠Model Management
MethodEndpointDescription
POST/api/v1/models/loadLoad a model
POST/api/v1/models/switchSelect an already-loaded model
POST/api/v1/models/unloadUnload a model
DELETE/api/v1/models/{id}Delete a model
POST/api/v1/models/scanScan folder for models
⁠Text Generation
MethodEndpointDescription
POST/v1/chat/completionsChat completion (OpenAI)
POST/api/v1/generateText generation
POST/api/v1/generate/batchBatch generation
⁠Vision (Multimodal)
MethodEndpointDescription
POST/api/v1/vision/generateAnalyze images
⁠Image Generation
MethodEndpointDescription
POST/api/v1/diffusion/generateGenerate images
⁠Context API (vPID L2)
MethodEndpointDescription
POST/api/v1/contexts/ingestPre-compute KV cache
GET/api/v1/contextsList contexts
POST/api/v1/contexts/{id}/queryQuery with indexed cache lookup
DELETE/api/v1/contexts/{id}Delete context
⁠Detailed API Examples
⁠Load Model
POST /api/v1/models/load

Request:

{
  "model_id": "medical-llm",
  "file_path": "D:/Models/medicine-llm.Q8_0.gguf",
  "model_type": "auto"
}

Response:

{
  "status": "success",
  "message": "Model loaded: medical-llm",
  "model": "medical-llm",
  "model_type": "Text LLM",
  "load_time_ms": 2500.5,
  "active": true
}
⁠Chat Completion
POST /v1/chat/completions

Request:

{
  "model": "medical-llm",
  "messages": [
    {"role": "system", "content": "You are a medical assistant."},
    {"role": "user", "content": "What are the symptoms of diabetes?"}
  ],
  "max_tokens": 512,
  "temperature": 0.7,
  "stream": false
}

Chat completions stream by default. Set "stream": false when a buffered JSON response is required.

Response:

{
  "id": "chatcmpl-abc123",
  "object": "chat.completion",
  "created": 1234567890,
  "model": "medical-llm",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Common symptoms of diabetes include..."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 25,
    "completion_tokens": 150,
    "total_tokens": 175,
    "tokens_per_second": 64.5
  }
}
⁠Load Vision Model
POST /api/v1/models/load

Request:

{
  "model_id": "gemma-vision",
  "file_path": "/models/gemma-3-4b-it.gguf",
  "model_type": "vision",
  "mmproj_path": "/models/mmproj-gemma-3-4b.gguf"
}
⁠Vision Analysis
POST /api/v1/vision/generate

Request:

{
  "prompt": "Describe this image in detail",
  "images": ["<base64-encoded-image>"],
  "max_tokens": 256
}

Response:

{
  "status": "success",
  "response": "The image shows a beautiful sunset over mountains...",
  "model": "gemma-vision",
  "generation_time_s": 2.5,
  "tokens_per_second": 57.5
}
⁠Context Ingestion (vPID L2)
POST /api/v1/contexts/ingest

Request:

{
  "content": "Your large document text here...",
  "model_id": "llama3",
  "name": "company-handbook",
  "ttl_seconds": 86400
}

Response:

{
  "status": "success",
  "context_id": "ctx_abc123",
  "token_count": 5000,
  "storage_size_mb": 125.5,
  "tier": "hot",
  "ingest_time_ms": 1500.5
}
⁠Query with Cached Context
POST /api/v1/contexts/ctx_abc123/query

Request:

{
  "query": "What is the vacation policy?",
  "max_tokens": 100
}

Response:

{
  "status": "success",
  "context_id": "ctx_abc123",
  "response": "According to the handbook, employees receive...",
  "cache_hit": true,
  "latency_ms": 15.2
}

⁠Architecture

⁠vPID (Virtual Processing-In-Disk) System

SnapLLM uses a vPID architecture to select already-loaded models without an avoidable weight reload:

+--------------------------------------------------------------------+
|                          SnapLLM Server                             |
+--------------------------------------------------------------------+
|  Model A (vPID 1)  |  Model B (vPID 2)  |  Model C (vPID 3)  | ... |
+---------+----------+---------+----------+---------+----------+-----+
          |                    |                    |
          +--------------------+--------------------+
                               |
                               v
+--------------------------------------------------------------------+
|                    Unified Memory Manager                           |
|   HOT (GPU VRAM)    |   WARM (CPU RAM)    |    COLD (SSD)           |
+--------------------------------------------------------------------+
|               HTTP API Server (OpenAI-compatible)                   |
+--------------------------------------------------------------------+

Request flow (simplified):

Client -> HTTP API -> Router -> Model Manager -> Active Model -> Response
                           |                      ^
                           v                      |
                             vPID Cache (L1/L2) 
⁠vPID Levels
LevelNamePurpose
L1Model CacheModel workspace metadata and engine-managed cache data
L2Context CacheKV cache persistence with hash-indexed lookup
⁠Memory Tiers
TierStorageRelative accessCapacity constraint
HOTGPU VRAMHighestAvailable VRAM
WARMCPU RAMIntermediateAvailable system RAM
COLDSSDLowestAvailable storage
⁠Per-Model Workspace Structure
SnapLLM_Workspace/
|-- index.json                          # Model registry
|-- medicine-llm/
|   `-- Q8_0/
|       `-- workspace.bin               # Engine-managed workspace
|-- legal-llama/
|   `-- Q4_K_M/
|       `-- workspace.bin
|-- gemma-3-4b/
|   `-- Q5_K_M/
|       `-- workspace.bin
|-- diffusion/
|   `-- sd15/
|       `-- workspace.bin
`-- contexts/                           # vPID L2 KV caches
    |-- hot/
    |-- warm/
    `-- cold/

⁠Desktop Application

SnapLLM includes a beautiful, modern desktop application built with React and Vite.

⁠Features
  • Dashboard: System overview and health metrics
  • Chat: Interactive chat with loaded models
  • Images: Stable Diffusion image generation
  • Vision: Multimodal image analysis
  • Models: Load, manage, and switch models
  • A/B Compare: Side-by-side model comparison
  • Quick Switch: select an already-loaded model
  • Contexts: vPID L2 KV cache management
  • Playground: API testing interface
  • Metrics: Performance analytics
⁠Running the Desktop App
cd desktop-app
npm install
npm run dev
# Open http://localhost:9780

⁠Demo Videos

⁠

⁠CLI Reference

⁠Server Options
./snapllm --server [OPTIONS]

Options:
  --port PORT              Server port (default: 6930)
  --host HOST              Bind address (default: 127.0.0.1)
  --cors-origin ORIGIN     Allow an exact browser origin (repeatable)
  --workspace-root PATH    Workspace directory
  --ui-dir PATH            Web UI directory (auto-detected)
  --load-model NAME PATH   Pre-load a model
⁠Text LLM Options
./snapllm --load-model NAME PATH [OPTIONS]

Options:
  --prompt TEXT            Generate text from prompt
  --max-tokens N           Maximum tokens to generate
  --temperature N          Sampling temperature
  --multi-model-test       Run multi-model switching benchmark
  --list-models            List all loaded models
  --stats                  Show cache statistics
⁠Image Generation Options
./snapllm --load-diffusion NAME PATH [OPTIONS]

Options:
  --generate-image PROMPT  Generate image from text
  --output PATH            Output image path
  --width N                Image width (default: 512)
  --height N               Image height (default: 512)
  --steps N                Sampling steps (default: 20)
  --cfg-scale N            CFG scale (default: 7.0)
  --seed N                 Random seed (-1 for random)
  --negative PROMPT        Negative prompt
⁠Vision Options
./snapllm --multimodal MODEL MMPROJ [OPTIONS]

Options:
  --image PATH             Input image file
  --vision-prompt TEXT     Prompt with <__media__> marker
  --max-tokens N           Maximum tokens to generate

⁠Configuration

⁠Environment Variables
VariableDescriptionDefault
SNAPLLM_HOMEWorkspace root directoryPlatform default
SNAPLLM_MODELS_PATHDefault models directoryPlatform default
SNAPLLM_CONFIG_PATHServer config file pathPlatform default
SNAPLLM_API_KEYRuntime-only API key (required off loopback)Unset
SNAPLLM_CORS_ORIGINSComma-separated exact browser originsUnset
SNAPLLM_MAX_ACTIVE_INFERENCESOptional concurrent inference slots; bounded by HTTP workers and defaults to 1 for GPU safety1

⁠Contributing

We welcome contributions! Here's how to get started:

⁠Development Setup
# Clone the repository
git clone https://github.com/snapllm/snapllm.git
cd snapllm

# Build debug version
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug
cmake --build .

# Run tests
ctest --output-on-failure
⁠Code Style
  • C++: snake_case functions, PascalCase classes, I* prefix for interfaces
  • TypeScript: ESLint + Prettier
  • Commits: Conventional commits format
⁠Submitting Changes
  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

⁠Sponsors

Support SnapLLM Development

SnapLLM is an open-source project maintained by passionate developers. Your sponsorship helps us:

  • Develop new features faster
  • Fix bugs and improve stability
  • Create better documentation
  • Maintain infrastructure and CI/CD
  • Support the open-source community
⁠Ways to Support
  • Star this repository - It helps others discover SnapLLM
  • Report bugs - Help us improve quality
  • Improve documentation - Clear docs help everyone
  • Join discussions - Share ideas and feedback
  • Spread the word - Share SnapLLM with others

⁠License

SnapLLM is released under the MIT License⁠.

Security issues should be reported privately as described in SECURITY.md⁠.

MIT License

Copyright (c) 2024-2026 SnapLLM Contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.

⁠Acknowledgments

SnapLLM is built on the shoulders of giants:


Switch models in a snap!

AroorA AI Labs ⁠

AroorA AI Lab

Follow SnapLLM in LinkedIn
SnapLLM ⁠

SnapLLM

Creator: Mahesh Vaikri
Developed by AroorA AI Labs
Made with care for the AI community

Report Bug⁠ | Request Feature⁠ |

Tag summary

Content type

Image

Digest

sha256:fb29f9b23…

Size

39.4 MB

Last updated

about 1 month ago

docker pull maheshvaikri/snapllm