candle-vllm

repository·master·Indexed 20 days ago

https://github.com/ericlbuehler/candle-vllm

A high-performance platform for inference and serving local Large Language Models (LLMs) featuring an OpenAI-compatible API server and built-in Web UI. It supports cross-platform deployment on CUDA (Linux) and Metal (macOS), multi-GPU and multi-node inference via NCCL, and In-situ Quantization (ISQ). Key features include TurboQuant KV cache compression, an embedding server with a Rust API, and support for Model Context Protocol (MCP) and OpenAI-style tool calling.

Tokens
26.4K
Snippets
85
Records
105
Agent score
71%

What's inside candle-vllm

  1. Core Features of Candle-vLLM

    master

    Candle-vLLM is a high-performance LLM inference and serving platform with the following capabilities:

    • API Compatibility: Provides an OpenAI-compatible API service.
    • Inference Optimizations: Supports PagedAttention, Continuous Batching, Prefix Caching, and CUDA Graphs.
    • Quantization Support: Supports In-situ quantization (including Marlin format), GPTQ, AWQ, Marlin (4-bit), and hardware-specific FP8 (SM90+).
    • KV Cache Compression: Features TurboQuant (turbo8, turbo4, turbo3) for high-ratio KV cache compression using native Flash Attention kernels.
    • Multi-Device Support: Supports multi-GPU (multi-process and multi-thread tensor parallelism) and multi-node (TCP-based) inference.
    • Platform Support: Works on CUDA (Linux) and Metal (macOS).
    • Advanced Features: Supports Model Context Protocol (MCP), tool calling, speculative decoding (via --mtp), and chunked prefilling (default block size 8K).
  2. How MCP integration and tool calling work in candle-vllm

    master

    candle-vllm supports the Model Context Protocol (MCP) and OpenAI-style tool calling. It follows the standard OpenAI flow: the server injects tool definitions into the prompt and parses model-emitted tool calls, but the client remains responsible for executing the tools and sending the results back.

    The Tool Calling Workflow:

    1. Configure: Set up MCP servers via CLI flags or an MCP config file.
    2. Injection: candle-vllm loads tool definitions and injects them into the prompt.
    3. Emission: The model emits a tool call, and the response finishes with finish_reason="tool_calls".
    4. Execution: The client executes the tool locally.
    5. Follow-up: The client sends the result back to the server as a message with role="tool" and the corresponding tool_call_id.
    // 1. Request with tools
    {
      "model": "default",
      "messages": [
        {"role": "user", "content": "List files in the current directory"}
      ],
      "tools": [
        {
          "type": "function",
          "function": {
            "name": "list_files",
            "description": "List files in a directory",
            "parameters": {
              "type": "object",
              "properties": {
                "path": {"type": "string"}
              },
              "required": ["path"]
            }
          }
        }
      ]
    }
    
    // 2. Assistant response with tool_calls
    {
      "choices": [
        {
          "message": {
            "role": "assistant",
            "tool_calls": [
              {
                "id": "call_123",
                "type": "function",
                "function": {
                  "name": "list_files",
                  "arguments": "{\"path\":\".\"}"
                }
              }
            ]
          },
          "finish_reason": "tool_calls"
        }
      ]
    }
    
    // 3. Client follow-up with tool result
    {
      "role": "tool",
      "tool_call_id": "call_123",
      "content": "file1\nfile2\nfile3"
    }
  3. Use TurboQuant KV Cache compression

    master

    TurboQuant compresses the KV cache using Walsh-Hadamard transform to increase throughput and context length. It is supported on both CUDA (SM70+) and Metal (Apple Silicon) platforms. Note that MLA models (e.g., DeepSeek, GLM4/GLM-5.2) will automatically fallback to standard KV cache as TurboQuant is incompatible with their layout.

    ModeDescriptionKV Cache Compression
    turbo8FP8 K + 4-bit V~2.6x
    turbo44-bit K + 4-bit V~3.7x
    turbo33-bit K + 4-bit V~4.7x

    Use the --kvcache-dtype flag to select a mode.

    # Turbo4 (4-bit KV cache, ~3.7x compression)
    candle-vllm --w /data/Qwen3.5-27B-FP8/ --kvcache-dtype turbo4
  4. Configure TurboQuant KV Cache

    master

    TurboQuant uses the Walsh-Hadamard transform to compress the KV cache, enabling higher throughput and longer context windows. It supports CUDA (SM70+) and Metal (Apple Silicon). Note that MLA models (e.g., DeepSeek, GLM4/GLM-5.2) will automatically fallback to standard KV cache due to layout incompatibility.

    ModeDescriptionCompression RatioRecommended Use
    turbo8FP8 K + 4-bit V~2.6xBest quality-to-compression balance
    turbo44-bit K + 4-bit V~3.7xBalance of quality and memory savings
    turbo33-bit K + 4-bit V~4.7xMaximum memory savings
    fp8Standard FP8N/AStandard FP8 KV cache
    # Turbo4 (approx 3.7x compression)
    candle-vllm --w /data/Qwen3.5-27B-FP8/ --kvcache-dtype turbo4
    
    # Turbo8 (approx 2.6x compression)
    candle-vllm --w /data/Qwen3.5-27B-FP8/ --kvcache-dtype turbo8
  5. How streaming tool parsing works

    master

    Streaming tool parsing uses an internal state machine to handle partial outputs without dropping data:

    1. Normal Content: Streams through normally.
    2. Detection: When a tool-call start marker is detected, content is buffered.
    3. Incremental Parsing: Buffered content is parsed into tool call fragments.
    4. Finalization: On tool-call end detection, fragments are finalized into full tool_calls.
    5. Error Handling: If parsing fails, the buffered content is released as normal text rather than being discarded.

    To prevent false positives, the parser tracks reasoning (<think>...</think> blocks) and fenced code blocks to avoid attempting to parse tool calls inside them.

  6. How Prefix Cache (KV Reuse) works

    master

    Prefix cache allows candle-vllm to reuse KV cache blocks from previous requests when new prompts share a common prefix. This reduces computation time for repetitive prompt structures.

    Key Mechanics:

    • Block Granularity: The cache operates on a block-by-block basis. If a shared prefix ends in the middle of a block, the remainder of that block must be recomputed.
    • Prefill Behavior: Even if a prompt is fully cached at block boundaries, the last block is recomputed to ensure the request still undergoes a non-empty prefill step.
    • Memory Management: The prefix cache shares the same KV memory pool as active sequences. Increasing the cache size reduces the amount of memory available for concurrent live tokens.
    • Limitations: Sliding-window attention may limit the amount of cached context that can be effectively reused.
  7. Run models with candle-vllm

    master

    The candle-vllm CLI can be used to serve various model formats including FP8, FP4, GGUF, and Marlin-compatible GPTQ/AWQ. By default, it starts an OpenAI-compatible API service at http://localhost:2000. Adding the --ui-server flag starts a built-in ChatGPT-style Web UI.

    Common Usage Scenarios

    • FP8 Models: Use --m with the model ID.
    • GGUF Models: Use --m for local files or directories. For HuggingFace repositories, use --m <repo> --f <file_or_subdir>.
    • In-place Quantization (ISQ): Run unquantized models with the --isq flag.
    • Marlin/AWQ/GPTQ: Use --w to point to local weights after conversion.
    • Speculative Decoding: Use --mtp <n> for MTP draft tokens.
    # FP8 model + Web UI
    candle-vllm --m Qwen/Qwen3.6-27B-FP8 --ui-server
    
    # GGUF model from HuggingFace (specific file)
    candle-vllm --m unsloth/Qwen3-30B-A3B-Instruct-2507-GGUF --f Qwen3-30B-A3B-Instruct-2507-Q4_K_M.gguf --ui-server
    
    # In-place quantization (ISQ)
    candle-vllm --m Qwen/Qwen3.6-27B --isq q4k
    
    # Speculative decoding (2 draft tokens)
    candle-vllm --w /data/Qwen3.5-35B-A3B-FP8/ --mtp 2 --ui-server
  8. Configure Kilo Code to use candle-vLLM

    master

    First, install the Kilo Code CLI via npm:

    npm install -g @kilocode/cli

    Then, create a configuration file at ~/.config/kilo/config.json. You must define a provider using the @ai-sdk/openai-compatible npm package and point the baseURL to your candle-vLLM instance (e.g., http://localhost:8000/v1).

    Important: Ensure the model ID in the models section matches the exact model ID returned by the GET /v1/models endpoint of your running candle-vLLM server.

    {
      "$schema": "https://opencode.ai/config.json",
      "provider": {
        "local-candle-vllm": {
          "npm": "@ai-sdk/openai-compatible",
          "name": "Candle-vLLM Local",
          "options": {
            "baseURL": "http://localhost:8000/v1"
          },
          "models": {
            "qwen3-coder": {
              "name": "Qwen/Qwen3.6-27B-FP8"
            }
          }
        }
      },
      "model": "local-candle-vllm/qwen3-coder"
    }
  9. Run Candle-vLLM with HuggingFace or local models

    master

    Use the candle-vllm CLI to serve models. You can use HuggingFace Model IDs or local file paths.

    Using HuggingFace Model IDs

    Pass the model ID to the --m flag. You can also specify quantization formats with --f and device IDs with --d.

    # Standard HuggingFace model
    candle-vllm --m Qwen/Qwen3.6-27B-FP8 --ui-server
    
    # Model with specific quantization and multiple GPUs
    candle-vllm --m unsloth/Qwen3.5-122B-A10B-GGUF --f Q3_K_S --d 0,1 --ui-server
    
    # Model distributed across many GPUs
    candle-vllm --m zai-org/GLM-5.2-FP8 --d 0,1,2,3,4,5,6,7 --ui-server

    Using Local Model Paths

    Supported local formats include safetensors directories, single/split-shard GGUF files, or directories containing GGUF files.

    # Local safetensors directory
    candle-vllm --d 0,1,2,3,4,5,6,7 --m /home/data/GLM-5.2-FP8/ --ui-server
    
    # Local single GGUF file
    candle-vllm --d 0,1 --m /home/data/model-Q4_K_M.gguf --ui-server
    
    # Local directory containing GGUF files (auto-detected)
    candle-vllm --d 0,1 --m /home/data/Qwen3.5-35B-A3B-GGUF/ --ui-server

    Launching the Web UI

    Add the --ui-server flag to launch a built-in ChatGPT-style Web UI.

    Note on Ports: The UI server automatically uses the API port minus one. For example, if the API is running on port 2000, the UI will be available on port 1999.

    candle-vllm --m Qwen/Qwen3.6-27B-FP8 --ui-server
  10. Start the candle-vLLM server

    master

    Run the candle-vllm server using cargo run. Ensure you include the necessary features for your hardware (e.g., cuda, nccl, flashinfer, cutlass).

    Key Flags:

    • --m: Specify the model (e.g., Qwen/Qwen3.6-27B-FP8).
    • --d: Device index.
    • --p: Port number (default is often 8000).
    • --kv-fraction: Fraction of KV cache to use.
    • --enforce-parser: Use qwen_coder for reliable parsing with Qwen coder models.

    Note: If you prefer FlashAttention over FlashInfer, replace flashinfer with flashattn in the features list.

    cargo run --release --features cuda,nccl,flashinfer,cutlass -- \
      --m Qwen/Qwen3.6-27B-FP8 \
      --d 0 \
      --p 8000 \
      --kv-fraction 0.6 \
      --enforce-parser qwen_coder
  11. Integrate OpenCode with Candle-vLLM

    master

    You can connect OpenCode to candle-vllm using the built-in OpenAI-compatible /v1/chat/completions endpoint. The integration follows this flow:

    OpenCode -> Candle-vLLM (OpenAI-compatible)

    To set this up, you must start the candle-vllm server, identify the model ID being served, and then configure OpenCode to point to your local instance.