Naar de inhoud
NLEN
Illustratie: Tabby als lokale code-assistent met Docker installeren

Tabby als lokale code-assistent installeren met Docker

Door Ivo Donker — samengesteld met AI-ondersteuning (Claude & Gemini)

Systeemeisen (indicatief): Minimaal 16 GB systeem-RAM, een NVIDIA GPU met minimaal 8 GB VRAM (zoals een RTX 3060, 4060 of hoger) en een Linux-distributie met Docker en de NVIDIA Container Toolkit. Gangbare modelkeuzes als richtwaarde: StarCoder2-3B voor infilling en Qwen2.5-Coder-7B voor instruct/chat.

Binnen de route van het zelf hosten van taalmodellen bevindt deze handleiding zich in de fase toepassen en integreren. Nadat de onderliggende server en runtime zijn ingericht, richten we ons nu specifiek op het automatiseren van softwareontwikkeling. Wie al bekend is met de basisprincipes van containerisatie kan voor algemene achtergrond eerst de handleiding over een lokaal taalmodel in Docker draaien raadplegen om te zien hoe containerisolatie fundamenteel is opgebouwd.

Tabby is een opensource, zelfstandig te hosten AI-codeerassistent die fungeert als direct alternatief voor propriëtaire clouddiensten zoals GitHub Copilot. In tegenstelling tot generieke chatinterfaces draait Tabby om twee specifieke taken: realtime inline code-aanvulling (Fill-in-the-Middle) en contextbewuste interactie via een chatvenster in je editor. Door Tabby in te zetten behoud je het volledige beheer over je intellectuele eigendom en codebase, zonder concessies te doen aan latentie tijdens het typen.

Hardwarevereisten en VRAM-calculatie voor codegeneratie

Codegeneratie stelt wezenlijk andere eisen aan hardware dan een doorsnee chat-LLM. Voor inline autocomplete is latentie de allerbelangrijkste factor: een suggestie moet binnen 100 tot 250 milliseconden verschijnen om de typestroom van een ontwikkelaar niet te onderbreken. Wie wil begrijpen welke videokaart of geheugenconfiguratie hierbij past, kan de systeemeisen nalezen in de gids over hardware voor lokale LLM-opstellingen om een gefundeerde keuze te maken tussen dedicated VRAM en systeembandbreedte.

Bij Tabby splitsen we de werklast idealiter op in twee afzonderlijke modellen: een compact FIM-model (Fill-in-the-Middle) zoals StarCoder2-3B of DeepSeek-Coder-1.3B voor realtime aanvullingen, en een groter chatmodel zoals Qwen2.5-Coder-7B voor complexe refactoring of uitleg. Om te bepalen of beide modellen tegelijkertijd in het videogeheugen passen, biedt de onderstaande tabel een indicatief overzicht van het geschatte VRAM-beslag bij verschillende precisieniveaus.

Model Taak Formaat / Precisie Geschat VRAM-beslag (indicatief) GPU-richtlijn
StarCoder2-3B Autocomplete (FIM) FP16 / BF16 ~6,2 GB RTX 3060 (12 GB)
DeepSeek-Coder-1.3B Autocomplete (FIM) FP16 ~3,1 GB GTX 1660 Ti / RTX 3050 (6-8 GB)
Qwen2.5-Coder-7B Chat / Instruct Q4_K_M (GGUF/AWQ) ~5,8 GB RTX 4060 Ti (16 GB)
Qwen2.5-Coder-1.5B Autocomplete & Chat FP16 ~3,8 GB RTX 3060 / 4060 (8 GB)

Voor een gedetailleerde toelichting over hoe compressietechnieken de verhouding tussen precisie en modelomvang beïnvloeden, verwijst de documentatie naar het artikel waarin kwantisatie en bitreductie helder worden uiteengezet. In de praktijk geldt als richtwaarde dat een dedicated videokaart met minimaal 8 GB tot 12 GB VRAM raadzaam is om inline autocomplete vlot uit te serveren.

Architectuur van Tabby: FIM versus Chat

De architectuur van Tabby rust op een modulaire opzet die speciaal is geoptimaliseerd voor programmeertalen. Waar reguliere taalmodellen uitsluitend voorspellen wat er ná een bepaalde prompt volgt, vereist softwareontwikkeling context aan weerszijden van de cursor. Dit mechanisme staat bekend als Fill-in-the-Middle (FIM).

Het FIM-mechanisme splitst het geopende bronbestand op in een prefix (alles vóór de cursor) en een suffix (alles na de cursor). Het model leert de ontbrekende code daartussen in te vullen. Tabby beheert deze contextramen zelfstandig en combineert dit met Git-repository indexing. Hierdoor kan het systeem relevante definities en functies uit andere bestanden in je project als extra context meegeven aan de prompt, wat de accuraatheid van de voorgestelde code aanzienlijk verhoogt.

Naast de generatie-engine bevat Tabby een ingebouwde zoekindex op basis van Tree-sitter. Deze parser ontleedt broncodebestanden direct naar een abstracte syntaxboom (AST). Wanneer de ontwikkelaar een functie aanroept die elders in het project is gedefinieerd, herkent de indexeerder de relatie en injecteert hij de functiesignatuur automatisch in het contextvenster van het FIM-model. Hierdoor sluiten gegenereerde parameters naadloos aan op bestaande interfaces binnen de repository.

Docker Compose configuratie met GPU-passthrough

Om Tabby reproduceerbaar en geïsoleerd uit te rollen, maken we gebruik van Docker Compose in combinatie met de NVIDIA Container Toolkit. Zorg ervoor dat de officiële NVIDIA-stuurprogramma's en de container toolkit vooraf op het hostsysteem zijn geïnstalleerd en geconfigureerd.

Hieronder staat een complete docker-compose.yml waarin Tabby wordt geconfigureerd met CUDA-versnelling en persistente opslag voor gedownloade modellen en repository-indices:

services:
  tabby:
    image: registry.tabbyml.com/tabbyml/tabby:0.26.0
    container_name: tabby-server
    restart: unless-stopped
    ports:
      - "8080:8080"
    volumes:
      - ./data:/data
    environment:
      - TABBY_LOG_LEVEL=info
    command:
      - serve
      - --model
      - StarCoder2-3B
      - --chat-model
      - Qwen2.5-Coder-7B
      - --device
      - cuda
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]

Start de stack vervolgens op via de terminal:

docker compose up -d
docker compose logs -f tabby

Tijdens de eerste start downloadt de container automatisch de gewenste gewichten vanaf het modelregister naar het gekoppelde volume ./data. Zodra de initialisatie is voltooid, luistert de webinterface op poort 8080 van het hostsysteem.

Initialisatie en beheerdersaccount instellen

Na het starten van de container navigeer je in de browser naar http://localhost:8080 (of het IP-adres van je lokale server). De eerste stap bestaat uit het aanmaken van het primaire beheerdersaccount.

In het beheerpaneel configureer je de volgende essentiële parameters:

Koppeling met ontwikkelomgevingen: VS Code en JetBrains

Zodra de server draait en je over een token beschikt, kun je de client-extensies inrichten. Voor Microsoft Visual Studio Code verloopt dit via de officiële Tabby-extensie uit de marketplace. Wie liever alternatieve uitbreidingen onderzoekt, kan ook de gids over een lokale LLM koppelen aan VS Code doornemen voor bredere integratiemogelijkheden.

Open in VS Code de instellingen (settings.json) en voeg de serverconfiguratie toe:

{
  "tabby.server.endpoint": "http://127.0.0.1:8080",
  "tabby.server.token": "jouw_gegenereerde_auth_token_hier",
  "tabby.inlineCompletion.triggerMode": "automatic",
  "tabby.inlineCompletion.anonymousUsageTracking": false
}

Binnen JetBrains IDE's (zoals IntelliJ IDEA, PyCharm of WebStorm) installeer je de plugin Tabby via het Plugins-menu. Ga vervolgens naar Settings > Tools > Tabby, vul het server-endpoint in en plak het authenticatietoken. Na het opslaan toont de statusbalk rechtsonder direct een statusicoon zodra de verbinding actief is.

Vergelijking: Tabby versus Continue.dev

Ontwikkelaars die hun workflow willen verrijken met lokale AI twijfelen regelmatig tussen Tabby en Continue.dev. Hoewel beide oplossingen lokaal draaien, hanteren ze fundamenteel andere ontwerpkeuzes. Wie de werking van die andere populaire tool wil bestuderen, vindt alle details in het stappenplan voor Continue.dev instellen met lokale modellen in VS Code.

Eigenschap Tabby Continue.dev
Architectuur Client-server met centrale backend Client-side orchestrator (extensie-gedreven)
Inference-engine Geïntegreerd (C++ / Rust / llama.cpp) Extern (koppelt aan Ollama, LM Studio, vLLM)
Focusgebied Snelle FIM-autocomplete & indexering Geavanceerde chat, prompt-engineering & diff-bewerking
Teamfunctionaliteit Centraal serverbeheer en gezamenlijke API-keys Individuele configuratie per ontwikkelaar
Resourcebeslag client Zeer laag (dunne client-extensie) Gemiddeld (beheert context en extensie-runtime)

Meetmethode: latentie en generatiesnelheid valideren

De effectiviteit van een inline code-assistent hangt vrijwel geheel af van de reactietijd. Om te bepalen of je opstelling voldoet aan de praktische normen, meten we drie cruciale parameters: Time To First Token (TTFT), tokens per seconde tijdens generatie, en de acceptatieratio van suggesties.

Een betrouwbare meetmethode voert men direct uit via de HTTP-endpoints van Tabby met behulp van curl en een tijdmeting. Hiermee elimineren we eventuele netwerkoverhead van de IDE-extensie:

curl -w "\nTijd tot reactie: %{time_starttransfer}s\nTotale tijd: %{time_total}s\n" \
  -X POST http://localhost:8080/v1/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer jouw_gegenereerde_auth_token_hier" \
  -d '{
    "language": "python",
    "segments": {
      "prefix": "def bereken_gemiddelde(waarden: list[float]) -> float:\n    \"\"\"Bereken het gemiddelde van een lijst getallen.\"\"\"\n    ",
      "suffix": "\n    return resultaat"
    }
  }'

De interpretatie van de meetwaarden volgt strikte richtwaarden:

Beveiliging, isolatie en AVG-aspecten

Het voornaamste argument voor een lokale code-assistent is gegevenssoevereiniteit. Bij cloudgebaseerde alternatieven worden programmacode, interne functienamen, API-structuren en soms zelfs hardcoded configuraties naar externe verwerkers verstuurd. Door Tabby binnen een lokaal netwerk te draaien, blijft alle broncode binnen de eigen infrastructuur.

In het kader van dataminimalisatie en compliance sluit deze aanpak naadloos aan bij de richtlijnen voor privacyvriendelijk AI-gebruik op de werkvloer. Om de sandbox van de applicatie verder te versterken, is het raadzaam om netwerkisolatie toe te passen. In het artikel over sandboxing van LLM-tools via Docker-isolatie wordt uitgelegd hoe containers functioneel kunnen worden afgeschermd van het publieke internet door middel van strikte Docker-netwerkregels.

Om te voorkomen dat de Docker-container uitgaand verkeer initieert nadat de modellen zijn gedownload, kan men de container koppelen aan een intern bridge-netwerk zonder default gateway. Hierdoor is het technisch uitgesloten dat broncodefragmenten via een netwerkverbinding naar buiten lekken.

Prestaties meten en stroomverbruik

Een continu draaiende modelserver verbruikt permanent energie, zelfs in ruststand. Een moderne videokaart uit het middensegment verbruikt in ruststand (idle) naar schatting 10 tot 20 watt. Zodra een ontwikkelaar actief code typt en Tabby per minuut tientallen FIM-verzoeken verwerkt, piekt het vermogen kortstondig naar 150 tot 250 watt.

Om inzicht te krijgen in de operationele kosten van een dergelijke machine, kan men de berekening maken via de gids over het stroomverbruik van lokale AI-systemen, waarin het verschil tussen piekbelasting en continuverbruik wordt gekwantificeerd. De kwaliteit van de geproduceerde syntax vereist eveneens systematische controle; raadpleeg het referentiekader voor het evalueren van gegenereerde code om regressies in modelkwaliteit tijdig te signaleren.

Praktijkvoorbeelden en taalspecifieke scenario's

Om het gedrag van het FIM-model in de praktijk te verduidelijken, bekijken we hoe Tabby omgaat met contextgevoelige aanvullingen in verschillende programmeertalen.

TypeScript: Interface-matching en objectaanvulling

Stel dat in een bestand types.ts de volgende datastructuur is gedefinieerd:

export interface GebruikerProfiel {
  id: string;
  volledigeNaam: string;
  email: string;
  actief: boolean;
  rollen: string[];
}

Wanneer de ontwikkelaar in een ander bestand mapper.ts begint met het schrijven van een transformatiefunctie, plaatst de editor de cursor direct na de toewijzing:

export function formatteerGebruiker(data: GebruikerProfiel) {
  return {
    label: /* CURSOR HIER */
  };
}

Dankzij de repository-index leest Tabby de definitie van GebruikerProfiel in. Het FIM-model vult de ontbrekende expressie direct aan tot:

    label: `${data.volledigeNaam} (${data.email})`,
    isAdmin: data.rollen.includes("admin")

Python: Foutafhandeling en typehints

Bij het schrijven van asynchrone API-aanroepen in Python vult Tabby ontbrekende uitzonderingen aan op basis van gangbare bibliotheekconventies:

async def fetch_json(url: str) -> dict:
    async with httpx.AsyncClient() as client:
        try:
            response = await client.get(url, timeout=5.0)
            response.raise_for_status()
            return response.json()
        except httpx.HTTPStatusError as exc:
            # Tabby FIM vult aan:
            logger.error(f"Fout bij ophalen {url}: {exc.response.status_code}")
            raise

Beperkingen en praktische valkuilen

Hoewel Tabby een doeltreffende oplossing biedt voor lokale autonomie, kent het platform enkele duidelijke beperkingen:

Onderhoud, updates en back-up van repository-indices

Omdat Tabby functioneert als een permanente achtergronddienst, vereist de database met repository-indices periodiek onderhoud. Alle configuraties, tokens en gegenereerde syntaxbomen worden opgeslagen in de map die aan de container is gekoppeld (in het Compose-voorbeeld ./data).

Bij het bijwerken van het model of de containerimage volstaat de volgende standaardprocedure:

# 1. Stop de actieve server
docker compose down

# 2. Haal de nieuwste image op
docker compose pull

# 3. Start de container opnieuw
docker compose up -d

Wanneer grote wijzigingen worden doorgevoerd in de broncodebestanden op de host, kan het voorkomen dat de Tree-sitter index verouderd raakt. Via de webinterface op http://localhost:8080/settings/repositories kan op elk gewenst moment een handmatige re-indexatie worden gestart om de consistentie tussen projectbestanden en FIM-suggesties te herstellen.

Conclusie

Met de installatie van Tabby via Docker realiseer je een zelfstandige, privacyvriendelijke en snelle codeerassistent op eigen hardware. Door FIM-modellen specifiek af te stemmen op lage latentie en chatmodellen in te zetten voor uitgebreide taken, ontstaat een robuuste ontwikkelomgeving zonder dat gevoelige code je netwerk verlaat.