Model AI na jednej karcie graficznej: faktury na własnym serwerze i do trzech razy szybciej
W sierpniu wyszły dwa otwarte modele, które zmieniają rachunek dla firm pilnujących swoich dokumentów: Muse Glimmer‑30B od Mety i Qwen3.8‑27B od zespołu Qwen, oba na licencji Apache 2.0. Faktura może zostać przeczytana na serwerze w Twojej serwerowni, bez wysyłania jej do zewnętrznego API. Poniżej cztery krótkie listingi: uruchomienie modelu, ekstrakcja z kontrolą sum, uruchomienie z drafterem i pomiar przyspieszenia.

Dwa modele, jedna licencja
Meta opublikowała Muse Glimmer 10 sierpnia. To gęsty model o około 29,6 mld parametrów, z czego około 1,8 mld to koder obrazu, więc czyta też skany. Okno kontekstu przekracza 131 tys. tokenów. Karta modelu podaje 76,0 w SWE‑Bench Verified i 83,5 w GPQA Diamond. W tym samym miesiącu pojawił się Qwen3.8‑27B: gęsty, 27 mld parametrów, 262 144 tokeny kontekstu, 89,2 w GPQA Diamond i 61,7 w SWE‑bench Pro.
Nie porównuj 76,0 z 61,7. SWE‑bench Verified i SWE‑bench Pro to różne zbiory zadań. Na SWE‑bench Pro karta Glimmera podaje 51,2, ale Qwen liczył swój wynik na wersji zbioru z poprawionymi zadaniami, więc i ta para nie jest w pełni porównywalna. Wynik GPQA dla Glimmera pochodzi według karty z pomiaru Artificial Analysis, nie z tego samego zestawu co wynik Qwena. Oba modele trzeba sprawdzić na własnych dokumentach, a poniższe listingi zadziałają z każdym z nich po zmianie nazwy modelu.
Apache 2.0 pozwala na użycie komercyjne, modyfikacje i uruchamianie na własnym sprzęcie bez opłat licencyjnych. Warunek jest jeden: przy dystrybucji zachowujesz tekst licencji i informacje o autorach. Zapisz licencję razem z datą pobrania i przypinaj konkretną rewizję repozytorium, bo pod tą samą nazwą może się pojawić inna wersja wag. W listingach poniżej każda rewizja jest przypięta skrótem commita.
Ile pamięci trzeba naprawdę
Meta pisze, że po kwantyzacji do około 4 bitów sam model językowy zajmuje poniżej 20 GB, a razem z koderem obrazu i pamięcią roboczą mieści się w budżecie 24 lub 32 GB. W vLLM liczba wygląda inaczej. Czterobitowa wersja NVFP4, której używa oficjalny przepis vLLM, waży 25,42 GB, bo osadzenia, warstwa wyjściowa i cały koder obrazu zostają w pełnej precyzji. Na karcie RTX 5090 przepis zmierzył 28,8 GB zajętych z 32,6 GB przy kontekście 131 072 tokenów i 68,8 tokena na sekundę. Kernele NVFP4 działają tylko na kartach z generacji Blackwell.
Praktyczne wymaganie to więc jedna karta z 32 GB pamięci, na przykład RTX 5090, która w dniu premiery kosztowała 1999 dolarów w cenie sugerowanej przez NVIDIĘ. Mniejsza liczba z ogłoszenia Mety dotyczy jej własnych kwantyzacji K‑Quant, nie wersji dla vLLM. Pomiary szybkości Meta zrobiła na K‑Quant‑17GB, a na RTX 5090 w llama.cpp.
Bash
pip install "vllm==0.28.0"
vllm serve Inferact/Muse-Glimmer-30B-NVFP4-W4A4 \
--revision d35cb79050f419c457611b1cee5c5d15b176f285 \
--tokenizer-revision d35cb79050f419c457611b1cee5c5d15b176f285 \
--served-model-name muse-glimmer \
--max-model-len 131072 \
--enable-auto-tool-choice --tool-call-parser muse_glimmer \
--reasoning-parser muse_glimmer \
--generation-config autoFaktura do JSON‑a, z kontrolą sum
Serwer mówi protokołem OpenAI, więc klientem jest zwykłe SDK openai wskazujące na localhost. Schemat faktury opisuje klasa pydantic: NIP sprzedawcy, numer, data wystawienia, netto, VAT, brutto i pozycje. Kwoty są typu Decimal, żeby porównanie odbywało się co do grosza, bez błędów zaokrągleń liczb zmiennoprzecinkowych.
Python
import re, sys
from datetime import date
from decimal import Decimal
from openai import OpenAI
from pydantic import BaseModel, ValidationError
class Line(BaseModel):
description: str
quantity: Decimal
net: Decimal
class Invoice(BaseModel):
seller_nip: str
number: str
issue_date: date
net: Decimal
vat: Decimal
gross: Decimal
lines: list[Line]
INVOICE = """FAKTURA VAT nr FV/2026/08/117, data wystawienia 28.08.2026
Sprzedawca: Przykładowa Firma sp. z o.o., NIP 123-456-00-20
1. Wdrożenie modułu, 1 szt., netto 4 000,00 zł, VAT 23%
2. Licencja roczna, 2 szt., netto 900,00 zł, VAT 23%
Razem netto 4 900,00 zł, VAT 1 127,00 zł, brutto 6 027,00 zł"""
client = OpenAI(base_url="http://localhost:8000/v1", api_key="local")
reply = client.chat.completions.create(
model="muse-glimmer",
messages=[{"role": "system", "content": "Reasoning strength: low"},
{"role": "user", "content": "Return this invoice as JSON only:\n" + INVOICE}],
response_format={"type": "json_schema", "json_schema": {
"name": "invoice", "schema": Invoice.model_json_schema()}},
temperature=1.0, top_p=0.95, extra_body={"top_k": 64}, max_tokens=4000)
text = reply.choices[0].message.content or ""
found = re.search(r"\{.*\}", text, re.DOTALL) # tolerate prose or a code fence around it
try:
invoice = Invoice.model_validate_json(found.group(0) if found else "")
except ValidationError as err:
sys.exit(f"Reply is not a valid invoice:\n{err}")
cents = Decimal("0.01")
if (invoice.net + invoice.vat).quantize(cents) != invoice.gross.quantize(cents):
sys.exit(f"Totals do not add up: {invoice.net} + {invoice.vat} != {invoice.gross}")
print(invoice.model_dump_json(indent=2))Skrypt wysyła response_format ze schematem, ale nie ufa mu. W vLLM 0.28.0 z parserem rozumowania muse_glimmer schemat jest pomijany bez żadnego ostrzeżenia: zapytanie kończy się sukcesem, ale model odpowiada swobodnym tekstem, który nie trzyma się schematu. Zgłoszenie 52594 opisuje to od 17 sierpnia i w chwili pisania pozostaje otwarte. Dlatego skrypt sam wyjmuje obiekt JSON z odpowiedzi, sprawdza go schematem i porównuje netto plus VAT z brutto. Każdy wynik, który nie przejdzie, trafia do człowieka, a nie do księgowości.
Parametry próbkowania pochodzą z przepisu vLLM: temperatura 1,0, top_p 0,95, top_k 64. Przepis odradza dekodowanie zachłanne dla tego modelu i zauważa, że nawet przy temperaturze 0 identyczne zapytania dawały różne długości odpowiedzi. Kolejne tanie kontrole to suma kontrolna NIP i zgodność sumy pozycji z kwotą netto.
Drafter: ten sam model, szybciej
Dekodowanie spekulacyjne dokłada mały model pomocniczy, drafter. Drafter proponuje kilka następnych tokenów, a duży model sprawdza je wszystkie w jednym przebiegu i przyjmuje te, które sam by wygenerował. DFlash, opisany w lutym przez Chena, Lianga i Liu, proponuje od razu cały blok tokenów w jednym przebiegu, metodą dyfuzji blokowej. Autorzy raportują ponad sześciokrotne przyspieszenie bez utraty jakości, a vLLM obsługuje DFlash od wersji 0.20.0.
Glimmer ma własny drafter DFlash, meta-models/Muse‑Glimmer‑30B‑assistant, o wadze 5,11 GB. Przewiduje bloki po 16 tokenów, więc liczba tokenów spekulacyjnych jest stała i wynosi 15. Przy dekodowaniu zachłannym wynik jest w teorii identyczny token w token. Przy próbkowaniu drafter zachowuje rozkład prawdopodobieństwa modelu, więc jakość jest ta sama, choć dwa uruchomienia nie dadzą tych samych znaków.
W vLLM drafter nie mieści się obok modelu na jednej karcie z 32 GB: przepis vLLM odnotowuje brak pamięci już przy starcie. Na dwóch kartach RTX 5090 ten sam przepis zmierzył wzrost z 68,8 do około 240 tokenów na sekundę. Zwróć uwagę, że to porównanie jednej karty z dwiema, a nie tylko wpływu draftera.
Bash
# Two 32 GB cards: the 5.11 GB drafter does not fit next to the model on one
vllm serve Inferact/Muse-Glimmer-30B-NVFP4-W4A4 \
--revision d35cb79050f419c457611b1cee5c5d15b176f285 \
--tokenizer-revision d35cb79050f419c457611b1cee5c5d15b176f285 \
--served-model-name muse-glimmer \
--tensor-parallel-size 2 \
--max-model-len 131072 --max-num-seqs 32 \
--enable-auto-tool-choice --tool-call-parser muse_glimmer \
--reasoning-parser muse_glimmer \
--generation-config auto \
--speculative-config '{"method": "dflash",
"model": "meta-models/Muse-Glimmer-30B-assistant",
"revision": "e8192f3a8f617f74be2ce220360c89ef4789f39f",
"num_speculative_tokens": 15}'Kiedy przyspieszenie przestaje pomagać
Drafter wykorzystuje moc obliczeniową, której karta nie używa, gdy obsługuje jedno zapytanie i czeka głównie na pamięć. Przy wielu równoległych zapytaniach tej wolnej mocy ubywa. W pracy o DFlash, na Qwen3‑8B i zadaniach HumanEval, przyspieszenie spada z 4,2 raza przy jednym zapytaniu do 2,4 raza przy 32 równoległych. Nagłówkowe liczby prawie zawsze dotyczą jednego zapytania: LMSYS podaje ponad 4,3 raza większą przepustowość dla dużego modelu Qwen 3.5 właśnie przy jednym zapytaniu.
- Rodzaj tekstu ma znaczenie. W tej samej pracy drafter trafia średnio 8,01 tokena naraz w zadaniach matematycznych i 6,50 w kodzie. Twoje faktury dadzą inną liczbę.
- Drafter zajmuje pamięć, która w przeciwnym razie poszłaby na pamięć podręczną kontekstu, czyli na liczbę obsługiwanych naraz zapytań.
- Liczby Mety opisują jeden strumień na maszynie dewelopera. Serwer obsługujący cały dział to inny profil obciążenia.
Python
import asyncio, time
from openai import AsyncOpenAI
client = AsyncOpenAI(base_url="http://localhost:8000/v1", api_key="local")
PROMPTS = [f"Opisz krok {i} zamknięcia miesiąca w małej firmie." for i in range(1, 17)]
async def ask(prompt: str, gate: asyncio.Semaphore) -> int:
async with gate:
reply = await client.chat.completions.create(
model="muse-glimmer", messages=[{"role": "user", "content": prompt}],
max_tokens=512, temperature=1.0, top_p=0.95, extra_body={"top_k": 64})
return reply.usage.completion_tokens
async def main() -> None:
await ask("Rozgrzewka.", asyncio.Semaphore(1)) # first request warms up the server
for concurrency in (1, 8):
gate = asyncio.Semaphore(concurrency)
start = time.perf_counter()
tokens = sum(await asyncio.gather(*(ask(p, gate) for p in PROMPTS)))
print(f"concurrency {concurrency}: {tokens / (time.perf_counter() - start):.1f} tok/s")
asyncio.run(main())Plan pomiaru na Twoim sprzęcie
Pięć kroków przed decyzją
- 01Punkt odniesienia: serwer z listingu 1, listing 4, zapisz tokeny na sekundę przy 1 i 8 równoległych zapytaniach.
- 02Uczciwe porównanie: jeśli drafter wymaga drugiej karty, zmierz też model bez draftera na dwóch kartach, z --tensor-parallel-size 2. Inaczej zmierzysz drugą kartę, a nie drafter.
- 03Z drafterem: serwer z listingu 3, ten sam skrypt. Podziel wyniki przez punkt odniesienia osobno dla 1 i dla 8 zapytań. W PROMPTS wstaw fragmenty własnych dokumentów, bo skuteczność draftera zależy od tekstu.
- 04Jakość: przepuść 50 do 100 prawdziwych faktur przez listing 2 z drafterem i bez niego. Liczba odrzuconych przez kontrolę sum powinna być taka sama w granicach losowości.
- 05Decyzja: przy kolejce dokumentów przetwarzanych jeden po drugim drafter zwykle się opłaca. Jeśli zysk przy 8 zapytaniach jest niewielki, a użytkowników przybywa, oddaj tę pamięć na obsługę większej liczby zapytań.
Źródła
- 01Meta AI Research, Introducing Muse Glimmeropublikowano 10 sierpnia 2026
- 02Hugging Face, model card meta-models/Muse‑Glimmer‑30Bopublikowano 10 sierpnia 2026
- 03Hugging Face, Meta is back with Muse Glimmeropublikowano 10 sierpnia 2026
- 04Hugging Face, model card Qwen/Qwen3.8‑27Bostatnia aktualizacja 14 sierpnia 2026
- 05vLLM recipes, Muse‑Glimmer‑30Bwersja z 31 sierpnia 2026
- 06vLLM, release v0.28.0opublikowano 26 sierpnia 2026
- 07vLLM issue 52594, muse_glimmer cannot combine reasoning with structured outputsotwarto 17 sierpnia 2026
- 08Chen, Liang, Liu, DFlash: Block Diffusion for Flash Speculative Decodingv1 5 lutego 2026, v2 28 maja 2026
- 09vLLM Blog, Speculators v0.5.0: DFlash Support and Online Trainingopublikowano 28 maja 2026
- 10LMSYS, The next generation of speculative decoding: DFlash and Spec V2opublikowano 15 czerwca 2026
- 11NVIDIA, GeForce RTX 50 Series announcementopublikowano 6 stycznia 2025
