Go-clients voor Ollama: SDK-vergelijking en voorbeelden met Qwen3/GPT-OSS
Integreer Ollama met Go: SDK-gids, voorbeelden en productiebest practices.
Deze gids biedt een uitgebreid overzicht van beschikbare Go SDKs voor Ollama en vergelijkt hun functionaliteiten.
We zullen praktische Go-voorbeelden bespreken voor het aanroepen van Qwen3 en GPT-OSS-modellen die worden gehost op Ollama—zowel via raw REST API-aanroepen als de officiële Go-client—waaronder gedetailleerde behandeling van denk- en niet-denkmodi in Qwen3.

Waarom Ollama + Go?
Ollama biedt een klein, pragmatisch HTTP-API (meestal actief op http://localhost:11434) die is ontworpen voor genereren en chatten-taken, met ingebouwde ondersteuning voor streaming en modelbeheer. De officiële documentatie bespreekt uitgebreid de /api/generate en /api/chat aanvraag/antwoordstructuur en streamingsemantiek.
Go is een uitstekende keuze voor het bouwen van Ollama-clients vanwege de sterke standaardbibliotheekondersteuning voor HTTP, uitstekende JSON-verwerking, native concurrentieprimitieven en statisch getypeerde interfaces die fouten tijdens het compileren opvangen. Kijk hoe Ollama vergelijkt met vLLM, Docker Model Runner, LocalAI en cloudproviders—waaronder wanneer je elk van hen zou moeten kiezen—bij LLM Hosting: Lokale, Self-Hosted & Cloud-infrastructuur vergeleken.
Tot oktober 2025 zijn hier de Go SDK-opties die je waarschijnlijk overweegt.
Go SDKs voor Ollama — wat is beschikbaar?
| SDK / Pakket | Status & “eigenaar” | Scope (Genereren/Chat/Streaming) | Modelbeheer (pull/list/etc.) | Extra’s / Opmerkingen |
|---|---|---|---|---|
github.com/ollama/ollama/api |
Officiële pakket binnen de Ollama-repo; gebruikt door de ollama CLI zelf |
Volledige dekking gemapt op REST; streaming ondersteund | Ja | Wordt beschouwd als de kanonieke Go-client; API spiegelt documentatie nauwkeurig. |
LangChainGo (github.com/tmc/langchaingo/llms/ollama) |
Communityframework (LangChainGo) met Ollama LLM-module | Chat/Compleet + streaming via framework-abstrakties | Beperkt (modelbeheer is geen hoofddoel) | Prima als je ketens, tools, vectoropslag in Go wilt; minder van een raw SDK. |
github.com/swdunlop/ollama-client |
Communityclient | Focus op chat; goede tool-aanroep experimenten | Gedeeltelijk | Gemaakt voor het experimenteren met tool-aanroepen; geen 1:1 volledige oppervlakte. |
Andere community-SDKs (bijv. ollamaclient, derde partij “go-ollama-sdk”) |
Community | Varieert | Varieert | Kwaliteit en dekking varieert; beoordeel per repo. |
Aanbeveling: Voor productie, prefereer github.com/ollama/ollama/api—het wordt onderhouden met het kernproject en spiegelt de REST API nauwkeurig.
Qwen3 & GPT-OSS op Ollama: denken vs niet-denken (wat je moet weten)
- Denkmodus in Ollama scheidt het model’s “redeneren” van het eindresultaat wanneer het is ingeschakeld. Ollama documenteert een eerste klasse aanzetten/uitzetten van denken gedrag over de ondersteunde modellen.
- (https://www.glukhov.org/nl/llm-performance/benchmarks/qwen3-30b-vs-gpt-oss-20b/ “Qwen3:30b vs GPT-OSS:20b: Technische details, prestaties en snelheid vergelijking”) ondersteunt dynamisch schakelen: voeg
/thinkof/no_thinktoe in systeem/gebruikersberichten om modi te schakelen per beurt; de nieuwste instructie wint. - GPT-OSS: gebruikers melden dat uitzetten van denken (bijv.
/set nothinkof--think=false) onbetrouwbaar kan zijn opgpt-oss:20b; plan om filteren/verbergen van elke redenering die je UI niet moet tonen.
Deel 1 — Ollama aanroepen via raw REST (Go, net/http)
Gedeelde types
Eerst definiëren we de algemene types en helperfuncties die we overal in onze voorbeelden zullen gebruiken:
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
// ---- Chat API Types ----
type ChatMessage struct {
Role string `json:"role"`
Content string `json:"content"`
}
type ChatRequest struct {
Model string `json:"model"`
Messages []ChatMessage `json:"messages"`
// Sommige servers tonen denkcontrole als een booleanvlag.
// Zelfs als het wordt overgeslagen, kun je Qwen3 nog steeds beïnvloeden via /think of /no_think tags.
Think *bool `json:"think,omitempty"`
Stream *bool `json:"stream,omitempty"`
Options map[string]any `json:"options,omitempty"`
}
type ChatResponse struct {
Model string `json:"model"`
CreatedAt string `json:"created_at"`
Message struct {
Role string `json:"role"`
Content string `json:"content"`
Thinking string `json:"thinking,omitempty"` // aanwezig wanneer denken is ingeschakeld
} `json:"message"`
Done bool `json:"done"`
}
// ---- Generate API Types ----
type GenerateRequest struct {
Model string `json:"model"`
Prompt string `json:"prompt"`
Think *bool `json:"think,omitempty"`
Stream *bool `json:"stream,omitempty"`
Options map[string]any `json:"options,omitempty"`
}
type GenerateResponse struct {
Model string `json:"model"`
CreatedAt string `json:"created_at"`
Response string `json:"response"` // eindtekst voor niet-stream
Thinking string `json:"thinking,omitempty"` // aanwezig wanneer denken is ingeschakeld
Done bool `json:"done"`
}
// ---- Helperfuncties ----
func httpPostJSON(url string, payload any) ([]byte, error) {
body, err := json.Marshal(payload)
if err != nil {
return nil, err
}
c := &http.Client{Timeout: 60 * time.Second}
resp, err := c.Post(url, "application/json", bytes.NewReader(body))
if err != nil {
return nil, err
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}
// bptr retourneert een pointer naar een booleanwaarde
func bptr(b bool) *bool { return &b }
Chat — Qwen3 met denken AAN (en hoe je het UIT kan zetten)
func chatQwen3Thinking() error {
endpoint := "http://localhost:11434/api/chat"
req := ChatRequest{
Model: "qwen3:8b-thinking", // elke :*-thinking tag die je hebt getrokken
Think: bptr(true),
Stream: bptr(false),
Messages: []ChatMessage{
{Role: "system", Content: "Je bent een nauwkeurige assistent."},
{Role: "user", Content: "Leg recursie uit met een korte Go-voorbeeld."},
},
}
raw, err := httpPostJSON(endpoint, req)
if err != nil {
return err
}
var out ChatResponse
if err := json.Unmarshal(raw, &out); err != nil {
return err
}
fmt.Println("🧠 denken:\n", out.Message.Thinking)
fmt.Println("\n💬 antwoord:\n", out.Message.Content)
return nil
}
// Zet denken UIT voor de volgende beurt door:
// (a) Think=false instellen, en/of
// (b) "/no_think" toevoegen aan de meest recente systeem/gebruikersbericht (Qwen3 soft switch).
// Qwen3 respecteert de laatste /think of /no_think instructie in meervoudige chats.
func chatQwen3NoThinking() error {
endpoint := "http://localhost:11434/api/chat"
req := ChatRequest{
Model: "qwen3:8b-thinking",
Think: bptr(false),
Stream: bptr(false),
Messages: []ChatMessage{
{Role: "system", Content: "Je bent kort. /no_think"},
{Role: "user", Content: "Leg recursie in één zin uit."},
},
}
raw, err := httpPostJSON(endpoint, req)
if err != nil {
return err
}
var out ChatResponse
if err := json.Unmarshal(raw, &out); err != nil {
return err
}
// Verwacht dat denken leeg is; nog steeds verdedigend behandelen.
if out.Message.Thinking != "" {
fmt.Println("🧠 denken (onverwacht):\n", out.Message.Thinking)
}
fmt.Println("\n💬 antwoord:\n", out.Message.Content)
return nil
}
(Qwen3’s /think en /no_think soft switch is gedocumenteerd door de Qwen-team; de laatste instructie wint in meervoudige chats.)
Chat — GPT-OSS met denken (en een waarschuwing)
func chatGptOss() error {
endpoint := "http://localhost:11434/api/chat"
req := ChatRequest{
Model: "gpt-oss:20b",
Think: bptr(true), // vraag gescheiden redenering indien ondersteund
Stream: bptr(false),
Messages: []ChatMessage{
{Role: "user", Content: "Wat is dynamisch programmeren? Leg het kernidee uit."},
},
}
raw, err := httpPostJSON(endpoint, req)
if err != nil {
return err
}
var out ChatResponse
if err := json.Unmarshal(raw, &out); err != nil {
return err
}
// Bekende kwal: uitschakelen van denken kan redenering niet volledig onderdrukken op gpt-oss:20b.
// Filter altijd denken in UI als je het niet wilt tonen.
fmt.Println("🧠 denken:\n", out.Message.Thinking)
fmt.Println("\n💬 antwoord:\n", out.Message.Content)
return nil
}
Gebruikers melden dat uitschakelen van denken op gpt-oss:20b (bijv. /set nothink of --think=false) genegeerd kan worden—plan voor clientzijde filtering indien nodig.
Genereren — Qwen3 en GPT-OSS
func generateQwen3() error {
endpoint := "http://localhost:11434/api/generate"
req := GenerateRequest{
Model: "qwen3:4b-thinking",
Prompt: "In 2–3 zinnen, wat zijn B-Bomen gebruikt voor in databases?",
Think: bptr(true),
}
raw, err := httpPostJSON(endpoint, req)
if err != nil {
return err
}
var out GenerateResponse
if err := json.Unmarshal(raw, &out); err != nil {
return err
}
if out.Thinking != "" {
fmt.Println("🧠 denken:\n", out.Thinking)
}
fmt.Println("\n💬 antwoord:\n", out.Response)
return nil
}
func generateGptOss() error {
endpoint := "http://localhost:11434/api/generate"
req := GenerateRequest{
Model: "gpt-oss:20b",
Prompt: "Verkort uitleg van backpropagation in neurale netwerken.",
Think: bptr(true),
}
raw, err := httpPostJSON(endpoint, req)
if err != nil {
return err
}
var out GenerateResponse
if err := json.Unmarshal(raw, &out); err != nil {
return err
}
if out.Thinking != "" {
fmt.Println("🧠 denken:\n", out.Thinking)
}
fmt.Println("\n💬 antwoord:\n", out.Response)
return nil
}
REST vormen en streaminggedrag komen rechtstreeks van de Ollama API-verwijzing.
Deel 2 — Ollama aanroepen via de officiële Go SDK (github.com/ollama/ollama/api)
Het officiële pakket biedt een Client met methoden die overeenkomen met de REST API. De Ollama CLI zelf gebruikt dit pakket om met de service te communiceren, wat het veiligste keuze is voor compatibiliteit.
Installatie
go get github.com/ollama/ollama/api
Chat — Qwen3 (denken AAN / UIT)
package main
import (
"context"
"fmt"
"log"
"github.com/ollama/ollama/api"
)
func chatWithQwen3Thinking(ctx context.Context, thinking bool) error {
client, err := api.ClientFromEnvironment() // respecteert OLLAMA_HOST als ingesteld
if err != nil {
return err
}
req := &api.ChatRequest{
Model: "qwen3:8b-thinking",
// Veel serverbuilds tonen denken als een top-level vlag;
// daarnaast kun je Qwen3 beïnvloeden via /think of /no_think in berichten.
Think: api.Ptr(thinking),
Messages: []api.Message{
{Role: "system", Content: "Je bent een nauwkeurige assistent."},
{Role: "user", Content: "Leg mergesort uit met een korte Go-voorbeeld."},
},
}
var resp api.ChatResponse
if err := client.Chat(ctx, req, &resp); err != nil {
return err
}
if resp.Message.Thinking != "" {
fmt.Println("🧠 denken:\n", resp.Message.Thinking)
}
fmt.Println("\n💬 antwoord:\n", resp.Message.Content)
return nil
}
func main() {
ctx := context.Background()
if err := chatWithQwen3Thinking(ctx, true); err != nil {
log.Fatal(err)
}
// Voorbeeld: niet-denkend
if err := chatWithQwen3Thinking(ctx, false); err != nil {
log.Fatal(err)
}
}
Chat — GPT-OSS (redenering verdedigend behandelen)
func chatWithGptOss(ctx context.Context) error {
client, err := api.ClientFromEnvironment()
if err != nil {
return err
}
req := &api.ChatRequest{
Model: "gpt-oss:20b",
Think: api.Ptr(true),
Messages: []api.Message{
{Role: "user", Content: "Wat is memoisatie en wanneer is het nuttig?"},
},
}
var resp api.ChatResponse
if err := client.Chat(ctx, req, &resp); err != nil {
return err
}
// Als je redenering wilt verbergen, doe het hier ongeacht vlaggen.
if resp.Message.Thinking != "" {
fmt.Println("🧠 denken:\n", resp.Message.Thinking)
}
fmt.Println("\n💬 antwoord:\n", resp.Message.Content)
return nil
}
Genereren — Qwen3 & GPT-OSS
func generateWithQwen3(ctx context.Context) error {
client, err := api.ClientFromEnvironment()
if err != nil {
return err
}
req := &api.GenerateRequest{
Model: "qwen3:4b-thinking",
Prompt: "Samenvat de rol van een B-Boom in indexering.",
Think: api.Ptr(true),
}
var resp api.GenerateResponse
if err := client.Generate(ctx, req, &resp); err != nil {
return err
}
if resp.Thinking != "" {
fmt.Println("🧠 denken:\n", resp.Thinking)
}
fmt.Println("\n💬 antwoord:\n", resp.Response)
return nil
}
func generateWithGptOss(ctx context.Context) error {
client, err := api.ClientFromEnvironment()
if err != nil {
return err
}
req := &api.GenerateRequest{
Model: "gpt-oss:20b",
Prompt: "Leg gradient descent in eenvoudige termen uit.",
Think: api.Ptr(true),
}
var resp api.GenerateResponse
if err := client.Generate(ctx, req, &resp); err != nil {
return err
}
if resp.Thinking != "" {
fmt.Println("🧠 denken:\n", resp.Thinking)
}
fmt.Println("\n💬 antwoord:\n", resp.Response)
return nil
}
Het oppervlak van het officiële pakket spiegelt de REST-documentatie en wordt bijgewerkt met het kernproject.
Streaming-antwoorden
Voor real-time streaming, stel Stream: bptr(true) in je aanvraag. Het antwoord wordt geleverd als newline-delimited JSON-blokken:
func streamChatExample() error {
endpoint := "http://localhost:11434/api/chat"
req := ChatRequest{
Model: "qwen3:8b-thinking",
Think: bptr(true),
Stream: bptr(true), // Streaming inschakelen
Messages: []ChatMessage{
{Role: "user", Content: "Leg quicksort algoritme stap voor stap uit."},
},
}
body, _ := json.Marshal(req)
resp, err := http.Post(endpoint, "application/json", bytes.NewReader(body))
if err != nil {
return err
}
defer resp.Body.Close()
decoder := json.NewDecoder(resp.Body)
for {
var chunk ChatResponse
if err := decoder.Decode(&chunk); err == io.EOF {
break
} else if err != nil {
return err
}
// Verwerk denken en inhoud terwijl ze aankomen
if chunk.Message.Thinking != "" {
fmt.Print(chunk.Message.Thinking)
}
fmt.Print(chunk.Message.Content)
if chunk.Done {
break
}
}
return nil
}
Met de officiële SDK, gebruik een callbackfunctie om streamingblokken te verwerken:
func streamWithOfficialSDK(ctx context.Context) error {
client, _ := api.ClientFromEnvironment()
req := &api.ChatRequest{
Model: "qwen3:8b-thinking",
Think: api.Ptr(true),
Messages: []api.Message{
{Role: "user", Content: "Leg binaire zoekbomen uit."},
},
}
err := client.Chat(ctx, req, func(resp api.ChatResponse) error {
if resp.Message.Thinking != "" {
fmt.Print(resp.Message.Thinking)
}
fmt.Print(resp.Message.Content)
return nil
})
return err
}
Werken met Qwen3 denken vs niet-denken (praktische richtlijnen)
-
Twee koppels:
- Een boolean
denkenvlag ondersteund door Ollama’s denkfunctie; en - Qwen3’s soft switch commando’s
/thinken/no_thinkin de meest recente systeem/gebruikersbericht. De meest recente instructie beheerst de volgende beurt(s).
- Een boolean
-
Standaard houding: niet-denkend voor snelle antwoorden; verhoog naar denken voor taken die stap-voor-stap redenering vereisen (wiskunde, planning, debuggen, complexe codeanalyse).
-
Streaming UIs: wanneer denken is ingeschakeld, zie je mogelijk doorlopende redenering/inhoud in gestreamde frames—buffer of render ze apart en geef gebruikers een “toon redenering” schakelknop. (Zie API-documentatie voor streamingformaat.)
-
Meervoudige conversaties: Qwen3 herinnert zich de denkmodus van vorige beurten. Als je deze midden in een conversatie wilt schakelen, gebruik zowel de vlag als het soft-switchcommando voor betrouwbaarheid.
Opmerkingen voor GPT-OSS
- Behandel redenering als aanwezig zelfs als je het probeert uit te schakelen; filter op de client als je UX het niet moet tonen.
- Voor productietoepassingen met GPT-OSS, implementeer clientzijde filterlogica die kan detecteren en verwijderen van redeneringspatronen indien nodig.
- Test je specifieke GPT-OSS-modellvariant grondig, aangezien gedrag kan variëren tussen verschillende kwantificaties en versies.
Best practices en productietips
Foutafhandeling en time-outs
Implementeer altijd correcte time-outafhandeling en foutherstel:
func robustChatRequest(ctx context.Context, model string, messages []api.Message) (*api.ChatResponse, error) {
// Stel een redelijke time-out in
ctx, cancel := context.WithTimeout(ctx, 2*time.Minute)
defer cancel()
client, err := api.ClientFromEnvironment()
if err != nil {
return nil, fmt.Errorf("client aanmaken: %w", err)
}
req := &api.ChatRequest{
Model: model,
Messages: messages,
Options: map[string]interface{}{
"temperature": 0.7,
"num_ctx": 4096, // contextvensteromvang
},
}
var resp api.ChatResponse
if err := client.Chat(ctx, req, &resp); err != nil {
return nil, fmt.Errorf("chat-aanvraag is mislukt: %w", err)
}
return &resp, nil
}
Verbindingspooling en hergebruik
Hergebruik de Ollama-client over meerdere aanvragen in plaats van een nieuwe te maken bij elke aanvraag:
type OllamaService struct {
client *api.Client
}
func NewOllamaService() (*OllamaService, error) {
client, err := api.ClientFromEnvironment()
if err != nil {
return nil, err
}
return &OllamaService{client: client}, nil
}
func (s *OllamaService) Chat(ctx context.Context, req *api.ChatRequest) (*api.ChatResponse, error) {
var resp api.ChatResponse
if err := s.client.Chat(ctx, req, &resp); err != nil {
return nil, err
}
return &resp, nil
}
Omgevingsconfiguratie
Gebruik omgevingsvariabelen voor flexibele implementatie:
export OLLAMA_HOST=http://localhost:11434
export OLLAMA_NUM_PARALLEL=2
export OLLAMA_MAX_LOADED_MODELS=2
De officiële SDK respecteert automatisch OLLAMA_HOST via api.ClientFromEnvironment().
Monitoring en logboekregistratie
Implementeer gestructureerde logboekregistratie voor productiesystemen:
func loggedChat(ctx context.Context, logger *log.Logger, req *api.ChatRequest) error {
start := time.Now()
client, _ := api.ClientFromEnvironment()
var resp api.ChatResponse
err := client.Chat(ctx, req, &resp)
duration := time.Since(start)
logger.Printf("model=%s duration=%v error=%v tokens=%d",
req.Model, duration, err, len(resp.Message.Content))
return err
}
Conclusie
-
Voor Go-projecten,
github.com/ollama/ollama/apiis de meest volledige, productie-geoorloofde keuze. Het wordt onderhouden met het Ollama-kernproject, gebruikt door de officiële CLI en biedt uitgebreide API-dekking met gegarandeerde compatibiliteit. -
Voor hogere abstracties, overweeg LangChainGo wanneer je ketens, tools, vectoropslag en RAG-pijplijnen nodig hebt—hoewel je enige lage-niveaucontrole moet opgeven voor handigheid.
-
Qwen3 geeft je schone, betrouwbare controle over denkmodus met zowel vlaggen als berichtniveau schakelaars (
/think,/no_think), waardoor het ideaal is voor toepassingen die zowel snelle antwoorden als diepe redenering nodig hebben. -
Voor GPT-OSS, plan altijd om redenering uit te schakelen op clientzijde wanneer nodig, aangezien de denk-uitgeschakelde vlag mogelijk niet consistent wordt geëerbiedigd.
-
In productie, implementeer correcte foutafhandeling, verbindingspooling, time-outs en monitoring om robuuste Ollama-aangedreven toepassingen te bouwen.
De combinatie van Go’s sterke typen, uitstekende ondersteuning voor concurrentie en Ollama’s eenvoudige API maakt het een ideaal stack voor het bouwen van AI-aangedreven toepassingen—van eenvoudige chatbots tot complexe RAG-systemen.
Belangrijkste conclusies
Hier is een snelle verwijzing voor het kiezen van je aanpak:
| Gebruiksscenario | Aanbevolen aanpak | Waarom |
|---|---|---|
| Productietoepassing | github.com/ollama/ollama/api |
Officiële ondersteuning, volledige API-dekking, onderhouden met kernproject |
| RAG/kettingen/tools-pijplijn | LangChainGo | Hogere abstracties, integraties met vectoropslag |
| Leren/experimenteren | Raw REST met net/http | Volledige transparantie, geen afhankelijkheden, educatief |
| Snel prototyperen | Officiële SDK | Evenwicht tussen eenvoud en kracht |
| Streaming chat UI | Officiële SDK met callbacks | Ingebouwde streamingondersteuning, nette API |
Modelkeuze-richtlijnen:
- Qwen3: Beste voor toepassingen die controleerbaar denkenmodus nodig hebben, betrouwbare meervoudige conversaties
- GPT-OSS: Sterke prestaties maar vereist verdedigende behandeling van denken/redenering-uitvoer
- Andere modellen: Test grondig; denkgedrag varieert per modelfamilie
Referenties & verdere lezing
Officiële documentatie
- Ollama API-verwijzing — Volledige REST API-documentatie
- Officiële Ollama Go-pakket — Go-SDK-documentatie
- Ollama GitHub-repository — Broncode en problemen
Go-SDK-alternatieven
- LangChainGo Ollama-integratie — Voor keten-gebaseerde toepassingen
- swdunlop/ollama-client — Communityclient met tool-aanroep
- xyproto/ollamaclient — Een andere communityoptie
Modelspecifieke bronnen
- Qwen-documentatie — Officiële Qwen-modellinformatie
- GPT-OSS-informatie — GPT-OSS-modellinformatie
Gerelateerde onderwerpen
- RAG-toepassingen bouwen met Go — LangChainGo-voorbeelden
- Go context-pakket — Essentieel voor time-outs en annulering
- Go HTTP-client best practices — Standaardbibliotheekdocumentatie
Andere nuttige links
Voor een breder vergelijken van Ollama met andere lokale en cloud LLM-infrastructuur, zie onze LLM Hosting: Lokale, Self-Hosted & Cloud-infrastructuur vergeleken.