Знакът на КАГАМИ КАГАМИ
kagami.bg/academy · lesson · machine-readable viewVERIFIED 2026-10-01 · UPDATED 2026-10-01
IDENTITY
module
01-01a · vLLM: a local inference server for many users
series
KAGAMI Academy · Blocks (AI engineer) · Block 1 — Production inference · part 1/2
level
Intermediate → Advanced
duration
~3–4 h incl. lab
trust_label
VERIFIED 2026-10-01 (versions, commands, links checked against official sources) · UPDATED 2026-10-01 · NOT TESTED by KAGAMI on own hardware
language
human view: bg · english edition: /en/academy/blokove/moduli/01-01a_Блок_1_Част_1_vLLM_Inference.html
prerequisites
Block 0 (LLM basics, AI stack, lab)
next
01-01b · Docker Compose production stack
PURPOSE

Decide between Ollama (developer tool, easy start) and vLLM (serving engine for many concurrent requests), understand why vLLM is fast (PagedAttention + continuous batching), install it on x86 or ARM64 (Grace/GB10), serve an OpenAI-compatible API, and use pre-quantized AWQ checkpoints.

KEY CONCEPTS
COMMANDS / PATHS
CHECKLIST
NEXT MODULE

01-01b · Docker Compose production stack (vLLM + Nginx + Redis + Prometheus + Grafana) · offer: Quick experiment (kagami.bg/stalbata/)

SOURCES
TAGS
vllmollamapaged-attentioncontinuous-batchingopenai-apiawqarm64gb10
ПРОВЕРЕНО · 01.10.2026 ОБНОВЕНО · 01.10.2026

vLLM: локален inference сървър за много потребители

Ollama е за разработка и малък екип. Когато десетки хора питат модела едновременно, ти трябва vLLM. Тук разбираме двата механизма, които го правят бърз — PagedAttention и continuous batching — и вдигаме OpenAI-съвместим сървър на x86 и на ARM64 машина.

⏱ ~3–4 ч с лабораторията Средно → напреднало Блок 1 · Production inference vLLM · PagedAttention · AWQ
vLLM🔒 локално Ollama🔒 локално Docker🔒 локално Hugging Face Hub🌐 глобален (само сваляне на модели)
🔄
ОБНОВЕНО · 01.10.2026 — какво
ARM64: vLLM вече има официални aarch64 пакети в PyPI, а образът vllm/vllm-openai е за amd64 и arm64; NVIDIA пуска свой образ за GB10 (DGX Spark / ASUS Ascent GX10). Старото „ограничена поддръжка“ отпада.
Команди: vllm serve вместо python -m vllm.entrypoints.openai.api_server; Python 3.10–3.13 (беше 3.9–3.12); инсталация с uv.
AWQ: флагът --quantization awq иска AWQ модел — примерите вече ползват такъв; хранилището casperhansen/… вече не е достъпно; AutoAWQ е изоставен в полза на llm-compressor.
Факти: блокът на PagedAttention е фиксиран брой токени (не „~16 KB“); „24ד е спрямо HF Transformers, а статията дава 2–4× спрямо FasterTransformer и Orca; Ollama не е чист FIFO — има OLLAMA_NUM_PARALLEL; връзката към NGC е поправена.
Числата за скорост в примерите са илюстративни, не са мерени от нас — ⚠️ измери на своя хардуер.

01Какво ще научиш

02Преди да започнеш

03Стъпки

  1. Ollama или vLLM — кога кое

    Двата инструмента решават различни задачи. Ollama е инструмент за разработчика — лесен старт, добро управление на модели. vLLM е двигател за обслужване — направен да държи много заявки наведнъж. Олимпийски бегач срещу джип: всеки е най-добър на своя терен. Честа архитектурна грешка е да ползваш грешния за ситуацията.

    КритерийOllamavLLMКога кое
    Инсталация1 командаpip/uv или DockerOllama за старт
    Паралелни заявкиограничено — OLLAMA_NUM_PARALLEL (по подразбиране 1 на модел)continuous batching, стотици последователностиvLLM при много едновременни потребители
    Памет за контекстазаделя по NUM_PARALLEL × контекстPagedAttention — динамичноvLLM при много сесии
    OpenAI API✓ съвместим✓ съвместим (по-пълен)и двата работят с LangChain
    КвантизацияGGUF (llama.cpp)AWQ, GPTQ, FP8 и др.vLLM за AWQ/FP8
    ARM64 (GB10)✓✓ (aarch64 пакети и образи — вж. стъпка 3)и двата — обновено 01.10.2026
    Наблюдениеминималновградени Prometheus метрикиvLLM за production
    ✅
    Правило
    Разработка и малък екип → Ollama. Production API или RAG с много едновременни потребители → vLLM. Решавай по реалния товар (колко души наведнъж, колко дълъг контекст), не „по принцип“.
    🏥
    Примерен сценарий (илюстрация, не наш измерен случай)
    Болница пуска RAG за протоколи на НЗОК върху Ollama с настройки по подразбиране. Когато петима лекари питат наведнъж, заявките чакат една след друга и отговорът стига до десетки секунди. Със същия хардуер и модел, но на vLLM, заявките се обработват заедно и чакането пада многократно. Изводът: Ollama не е „виновен“ — направен е за друго.
  2. PagedAttention и continuous batching — защо vLLM е бърз

    Докато генерира, моделът пази KV кеш (ключове и стойности) за всеки токен от контекста. Наивният подход заделя място за целия възможен контекст на всяка заявка още в началото — дори отговорът да е кратък. Голяма част от паметта остава заделена, но празна, и нови заявки не се побират.

    PagedAttention (UC Berkeley, SOSP 2023) взима идеята за виртуалната памет от операционните системи: KV кешът се дели на блокове с фиксиран брой токени, които се заделят при нужда и не е нужно да са един до друг. Губи се място само в последния блок на всяка заявка — по данни на екипа на vLLM под 4%. Свободната памет отива за още едновременни заявки.

    Наивно заделянеPagedAttention
    Как се заделямаксималният контекст — предварителноблок по блок, докато заявката расте
    Загуба на паметголяма (заделено, но неизползвано)само в последния блок (<4%)
    Резултатмалко заявки се побиратмного повече заявки на същия хардуер

    Continuous batching е вторият механизъм. При статичен batch всички чакат най-дългата заявка: ако едната генерира 500 токена, а другата 10, втората седи без работа. С continuous batching завършилата заявка излиза и на нейно място влиза нова на всяка итерация — видеокартата не стои празна.

    📄
    Какво точно твърдят източниците
    Блогът на vLLM (2023): до 24× по-висок throughput спрямо HuggingFace Transformers и до 3,5× спрямо TGI. Научната статия (Kwon и съавт., SOSP 2023): 2–4× спрямо FasterTransformer и Orca при същото забавяне. Реалната печалба зависи от товара — мери при себе си.
  3. Инсталация: x86, ARM64 (GB10) и Docker

    x86 + NVIDIA. Официалният път днес е с uv — той сам избира правилния PyTorch за драйвера ти.

    bash · x86 или ARM64 Linux · инсталация
    # Проверки преди инсталация
    python3 --version     # 3.10–3.13
    nvidia-smi            # видеокартата и драйверът се виждат
    
    # Среда и инсталация (препоръчан път от документацията на vLLM)
    uv venv --python 3.12 --seed
    source .venv/bin/activate
    uv pip install vllm --torch-backend=auto
    
    python -c "import vllm; print(vllm.__version__)"

    ARM64 с GB10 (NVIDIA DGX Spark, ASUS Ascent GX10 и подобни). До скоро това беше слабото място. Към 01.10.2026 PyPI има aarch64 пакети на vLLM, а NVIDIA поддържа готов образ за тези машини — най-сигурният път, защото е сглобен за точната архитектура.

    bash · GB10 · образът на NVIDIA
    # Етикетът се сменя — вземи актуалния от NGC или от наръчника на NVIDIA за DGX Spark
    export VLLM_TAG=26.05.post1-py3   # етикетът в наръчника към 01.10.2026
    docker pull nvcr.io/nvidia/vllm:${VLLM_TAG}
    
    docker run -d --gpus all -p 8000:8000 --name vllm-server \
      nvcr.io/nvidia/vllm:${VLLM_TAG} \
      vllm serve Qwen/Qwen2.5-7B-Instruct-AWQ

    Docker, общият образ. vllm/vllm-openai:latest вече е и за amd64, и за arm64.

    bash · Docker · официалният образ на vLLM
    docker run --gpus all --ipc=host -p 8000:8000 \
      -v ~/.cache/huggingface:/root/.cache/huggingface \
      --name vllm-server \
      vllm/vllm-openai:latest \
      --model Qwen/Qwen2.5-7B-Instruct-AWQ \
      --max-model-len 16384 \
      --served-model-name qwen-7b
    
    # Тест веднага след старта
    curl http://localhost:8000/v1/models
    ⚠️
    Капан: заключени модели
    Моделите на Meta (Llama) в Hugging Face са заключени: трябва да приемеш лиценза и да подадеш токен (HF_TOKEN). Без това свалянето спира с грешка 401. Токенът не се пише в скриптове, които споделяш.
  4. Първи сървър — три начина на работа

    Начин 1 — OpenAI-съвместим HTTP сървър. Това е начинът за production: всяко приложение, което говори с OpenAI, говори и с него.

    bash · vllm serve с основните настройки
    # Моделът е AWQ — vLLM разпознава квантизацията от конфигурацията му
    vllm serve Qwen/Qwen2.5-7B-Instruct-AWQ \
      --port 8000 \
      --max-model-len 16384 \
      --max-num-seqs 128 \
      --gpu-memory-utilization 0.90 \
      --enable-prefix-caching \
      --served-model-name qwen-7b
    
    # --max-num-seqs      колко последователности наведнъж в една итерация
    # --enable-prefix-caching  преизползва общ начален текст (системния промпт)
    # --served-model-name      името, с което клиентите викат модела
    # --trust-remote-code      само за модели със собствен код и само ако им вярваш
    
    # Въпрос с curl
    curl http://localhost:8000/v1/chat/completions \
      -H "Content-Type: application/json" \
      -d '{
        "model": "qwen-7b",
        "messages": [
          {"role": "system", "content": "Ти си AI асистент на малка фирма."},
          {"role": "user",   "content": "Обясни PagedAttention в 3 изречения."}
        ],
        "temperature": 0.2,
        "max_tokens": 300
      }'
    
    # Поточно (за чат интерфейс): добави "stream": true

    Начин 2 — Python за пакетна обработка. Когато имаш списък с въпроси и не ти трябва сървър: даваш ги всички наведнъж и vLLM сам ги подрежда.

    python · batch_inference.py
    from vllm import LLM, SamplingParams
    import time
    
    llm = LLM(
        model="Qwen/Qwen2.5-7B-Instruct-AWQ",
        max_model_len=8192,
        enable_prefix_caching=True,
        gpu_memory_utilization=0.90,   # 10% резерв
    )
    params = SamplingParams(temperature=0.2, top_p=0.9, max_tokens=500,
                            repetition_penalty=1.05)
    
    PROMPTS = [
        "Обясни разликата между LoRA и пълно дообучение.",
        "Напиши пример за RAG верига с LangChain.",
        "Какво е PagedAttention и защо е важно?",
        "Как се изчислява косинусово сходство?",
    ]
    
    t0 = time.time()
    outputs = llm.generate(PROMPTS, params)
    elapsed = time.time() - t0
    tokens = sum(len(o.outputs[0].token_ids) for o in outputs)
    print(f"{len(PROMPTS)} заявки · {tokens} токена · {elapsed:.1f} s · {tokens/elapsed:.0f} tok/s")
    for p, o in zip(PROMPTS, outputs):
        print("\n?", p[:60]); print(o.outputs[0].text[:200])

    Начин 3 — смяна на Ollama в LangChain. vLLM говори OpenAI API, затова в RAG кода сменяш само адреса на модела. Embeddings могат да останат на Ollama.

    python · LangChain: Ollama → vLLM
    from langchain_openai import ChatOpenAI
    
    # ПРЕДИ: llm = ChatOllama(model="qwen2.5:7b", temperature=0.2)
    llm = ChatOpenAI(
        base_url="http://localhost:8000/v1",
        api_key="not-needed",        # vLLM не иска ключ, ако не си му задал
        model="qwen-7b",
        temperature=0.2,
        max_tokens=500,
    )
    # chain = ({"context": retriever, "question": RunnablePassthrough()}
    #          | prompt | llm | StrOutputParser())   ← смяна само тук
    
    # Бързо сравнение: едни и същи 10 заявки към двата сървъра
    import time, requests
    def bench(url, model, n=10):
        t0 = time.time()
        for _ in range(n):
            requests.post(url, json={"model": model, "max_tokens": 80,
                "messages": [{"role": "user", "content": "Обясни RAG в 50 думи."}]})
        return time.time() - t0
    print("Ollama:", bench("http://localhost:11434/v1/chat/completions", "qwen2.5:7b"))
    print("vLLM:  ", bench("http://localhost:8000/v1/chat/completions",  "qwen-7b"))
    ⚠️
    Числата не са наши измервания
    Старата версия на урока показваше „42 s срещу 14 s“ за 10 заявки — това е илюстрация, не резултат от наш тест. Последователните заявки почти не показват предимството на vLLM; то се вижда при паралелни заявки. Пусни сравнението с няколко нишки и запиши собствените си числа.
  5. Квантизация за production — AWQ, GPTQ, FP8

    AWQ (Lin и съавт., MIT, 2023) е 4-битова квантизация, която намира най-важните тегла (според реалните активации) и ги пази по-точно. Затова губи по-малко качество от обикновена 4-битова квантизация при същата памет.

    ФорматБитаПамет за 7B моделКога
    BF16 (без квантизация)16~14 GB само теглатамашини с много памет (напр. 128 GB обща)
    AWQ 4-bit4~4–5 GBвидеокарти с малко памет; добро качество
    GPTQ 4-bit4~4–5 GBалтернатива на AWQ
    FP88~7–8 GBнови видеокарти с хардуерна поддръжка на FP8
    GGUF Q4_K_M4~4–5 GBсамо Ollama / llama.cpp
    ⚠️
    Без общи проценти за качество
    Процентите „качество спрямо fp16“ и „по-бърз с 1,2–1,5ד от старата версия махнахме — не намерихме източник, който да ги потвърждава общо за всички модели. Паметта в таблицата е ориентировъчна. Качеството зависи от модела и задачата; сравнявай на своите данни.
    python · сваляне на готов AWQ модел и старт
    # Търси готови AWQ версии: huggingface.co/models?search=awq
    # Официални AWQ версии пускат напр. Qwen; за Llama 3.1 — hugging-quants
    from huggingface_hub import snapshot_download
    path = snapshot_download("Qwen/Qwen2.5-7B-Instruct-AWQ",
                             local_dir="./models/qwen2.5-7b-awq")
    
    from vllm import LLM
    llm = LLM(model=path,
              dtype="float16",            # AWQ ядрата работят с fp16
              max_model_len=32768,
              gpu_memory_utilization=0.85,
              enable_chunked_prefill=True)  # по-равно забавяне при дълги промптове
    
    # Същото от командния ред:
    # vllm serve ./models/qwen2.5-7b-awq --max-model-len 32768
    🔧
    Сам ли да квантизираш?
    Библиотеката AutoAWQ е изоставена; екипът на vLLM е поел функцията в llm-compressor. Ако няма готова AWQ версия на твоя модел, квантизирай с llm-compressor — но първо потърси готова.
  6. GB10 с 128 GB обща памет — стратегия

    Машини като DGX Spark и ASUS Ascent GX10 имат 128 GB памет, обща за процесора и видеокартата. Това позволява големи модели без квантизация, но паметта е по-бавна от тази на големите сървърни видеокарти. За малък екип или пилотен курс често стига добре настроен Ollama; vLLM (от образа на NVIDIA) е следващата стъпка, когато едновременните потребители растат.

    bash · Ollama за няколко паралелни заявки (systemd)
    sudo mkdir -p /etc/systemd/system/ollama.service.d/
    sudo tee /etc/systemd/system/ollama.service.d/override.conf >/dev/null <<'EOF'
    [Service]
    Environment="OLLAMA_NUM_PARALLEL=4"
    Environment="OLLAMA_MAX_LOADED_MODELS=2"
    Environment="OLLAMA_KEEP_ALIVE=30m"
    Environment="OLLAMA_FLASH_ATTENTION=1"
    EOF
    sudo systemctl daemon-reload && sudo systemctl restart ollama
    ollama ps   # кои модели са заредени
    
    # OLLAMA_NUM_PARALLEL  паралелни заявки на модел (по подразбиране 1)
    #                      паметта расте с NUM_PARALLEL × дължината на контекста
    # OLLAMA_FLASH_ATTENTION  Ollama го включва сам, където може; =1 го налага
    python · проверка: 8 паралелни заявки
    import requests, concurrent.futures, time
    URL = "http://localhost:11434/v1/chat/completions"   # или :8000 за vLLM
    MODEL = "qwen2.5:7b"
    def one(i):
        t0 = time.time()
        requests.post(URL, json={"model": MODEL, "max_tokens": 50,
            "messages": [{"role": "user", "content": f"Въпрос {i}: какво е AI?"}]})
        return time.time() - t0
    t0 = time.time()
    with concurrent.futures.ThreadPoolExecutor(max_workers=8) as ex:
        r = list(ex.map(one, range(8)))
    print(f"общо {time.time()-t0:.1f}s · средно {sum(r)/len(r):.1f}s · последователно би било ~{sum(r):.1f}s")
    ⛔
    Не пускай модела гол в интернет
    Нито Ollama, нито vLLM по подразбиране искат парола. Пред тях сложи обратен прокси (напр. nginx) с ограничение на заявките и вход — или ги дръж само във вътрешната мрежа. Как се сглобява това — в следващата част.
    🎯
    Кога да минеш от Ollama на vLLM
    Остани на Ollama: разработка, тестове, малък екип, няколко едновременни заявки.
    Мини на vLLM: много едновременни потребители, нужда от FP8/AWQ и метрики, договорени срокове за отговор. ⚠️ Точния праг измери на своя хардуер — старата версия даваше „8 потребители на 70B модел“, което не сме проверили.

04Проверка

1. RAG система с 30 едновременни потребители отговаря бавно на Ollama с настройки по подразбиране. Кой механизъм на vLLM ще помогне най-много?

2. Защо AWQ губи по-малко качество от обикновена 4-битова квантизация?

3. На какво дели PagedAttention KV кеша?

4. Искаш vLLM на ARM64 машина с GB10 (към 01.10.2026). Кой е най-сигурният път?

05Какво следва

06Източници

  1. vLLM — Quickstart — инсталация с uv, vllm serve, OpenAI-съвместим сървър на порт 8000.
  2. vLLM — инсталация за GPU — изисквания (Linux, Python 3.10–3.13, compute capability ≥ 7.5), aarch64.
  3. vllm в PyPI — версия 0.30.0 към 01.10.2026, пакети за x86_64 и aarch64.
  4. NVIDIA DGX Spark playbooks — vLLM — образът nvcr.io/nvidia/vllm за GB10.
  5. NVIDIA NGC — vLLM контейнер — актуалните етикети.
  6. Kwon и съавт. — Efficient Memory Management for LLM Serving with PagedAttention (SOSP 2023) — раздели 3 и 4 са ядрото.
  7. Блогът на vLLM (2023) — 24× спрямо HF Transformers, загуба под 4%.
  8. Lin и съавт. — AWQ: Activation-aware Weight Quantization.
  9. vLLM — квантизация (AWQ, FP8 и др.) · llm-compressor.
  10. Qwen2.5-7B-Instruct-AWQ · Llama 3.1 8B AWQ (hugging-quants) — готови AWQ модели.
  11. Ollama FAQ — OLLAMA_NUM_PARALLEL, OLLAMA_MAX_LOADED_MODELS, Flash Attention.