Ollama Go-klienter: SDK-jämförelse och Qwen3/GPT-OSS-exempel
Integrera Ollama med Go: SDK-guide, exempel och produktionsrekommendationer.
Den här guiden ger en omfattande översikt över tillgängliga Go SDK:er för Ollama och jämför deras funktionssätt.
Vi kommer utforska praktiska Go-exempel för att anropa Qwen3 och GPT-OSS-modeller som finns värd på Ollama—både via raw REST API-anrop och den officiella Go-klienten—inklusive detaljerad hantering av tänkande och icke-tänkande lägen i Qwen3.

Varför Ollama + Go?
Ollama exponerar en liten, pragmatisk HTTP-API (vanligtvis körande på http://localhost:11434) som är designad för generera och chatt-arbetsbelastningar, med inbyggd stöd för strömning och modellhantering. Den officiella dokumentationen täcker grundligt /api/generate och /api/chat-förfrågningar och svarsstrukturer samt strömningssemantik.
Go är ett utmärkt val för att bygga Ollama-klienter på grund av dess starka standardbibliotekssupport för HTTP, utmärkt JSON-hantering, inbyggda konkurrensprimitiver och statiskt typade gränssnitt som upptäcker fel vid kompileringsstadiet. För att se hur Ollama jämförs med vLLM, Docker Model Runner, LocalAI och molntillhandtagare — inklusive när du bör välja varje — se LLM Hosting: Lokal, självvärd och molninfrastruktur jämförd.
Upp till oktober 2025, här är de Go SDK-Alternativen du sannolikt kommer att överväga.
Go SDK:er för Ollama — vad finns tillgängligt?
| SDK / Paket | Status & “ägare” | Omfång (Generera/Chatt/Strömning) | Modellhantering (hämta/lista osv.) | Extra / Anteckningar |
|---|---|---|---|---|
github.com/ollama/ollama/api |
Officiell paket inom Ollama-repon; används av ollama CLI självt |
Full täckning mappad till REST; strömning stöds | Ja | Betraktas som den kanoniska Go-klienten; API speglar dokumentationen nära. |
LangChainGo (github.com/tmc/langchaingo/llms/ollama) |
Communityramverk (LangChainGo) med Ollama LLM-modul | Chatt/Slutförande + strömning via ramverksabstraktioner | Begränsad (modellhantering inte primärt mål) | Bra om du vill ha kedjor, verktyg, vektorlager i Go; mindre av en rå SDK. |
github.com/swdunlop/ollama-client |
Communityklient | Fokus på chatt; bra verktygsanrop experiment | Delvis | Byggd för att experimentera med verktygsanrop; inte en 1:1 full yta. |
Andra community SDK:er (t.ex., ollamaclient, tredjeparts “go-ollama-sdk”) |
Community | Varierar | Varierar | Kvalitet och täckning varierar; bedöm per repo. |
Rekommendation: För produktion, föredra github.com/ollama/ollama/api—det underhålls med det centrala projektet och speglar REST API:et.
Qwen3 & GPT-OSS på Ollama: tänkande vs icke-tänkande (vad du bör veta)
- Tänkande-läge i Ollama separerar modellens “resonemang” från slutresultatet när det är aktiverat. Ollama dokumenterar en första klass aktivera/avaktivera tänkande beteende över stödda modeller.
- (https://www.glukhov.org/sv/llm-performance/benchmarks/qwen3-30b-vs-gpt-oss-20b/ “Qwen3:30b vs GPT-OSS:20b: Tekniska detaljer, prestanda och hastighetsjämförelse”) stöder dynamiskt växling: lägg till
/thinkeller/no_thinki systembrukaremeddelanden för att växla lägen turn-by-turn; den senaste instruktionen vinner. - GPT-OSS: användare rapporterar att avaktivera tänkande (t.ex.,
/set nothinkeller--think=false) kan vara otrustvärt pågpt-oss:20b; planera att filtrera/dölja något resonemang din UI inte bör visa.
Del 1 — Anropa Ollama via rå REST (Go, net/http)
Delade typer
Först, definiera de gemensamma typerna och hjälpfunktionerna vi kommer använda i våra exempel:
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
// ---- Chatt API Typer ----
type ChatMessage struct {
Role string `json:"role"`
Content string `json:"content"`
}
type ChatRequest struct {
Model string `json:"model"`
Messages []ChatMessage `json:"messages"`
// Vissa servrar exponerar tänkande kontroll som en boolesk flagga.
// Även om den utelämnas, kan du fortfarande kontrollera Qwen3 via /think eller /no_think taggar.
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"` // närvarande när tänkande är på
} `json:"message"`
Done bool `json:"done"`
}
// ---- Generera API Typer ----
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"` // slutlig text för icke-ström
Thinking string `json:"thinking,omitempty"` // närvarande när tänkande är på
Done bool `json:"done"`
}
// ---- Hjälpfunktioner ----
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 returnerar en pekare till en boolesk värde
func bptr(b bool) *bool { return &b }
Chatt — Qwen3 med tänkande PÅ (och hur du stänger av)
func chatQwen3Thinking() error {
endpoint := "http://localhost:11434/api/chat"
req := ChatRequest{
Model: "qwen3:8b-thinking", // någon :*-thinking tagg du har hämtat
Think: bptr(true),
Stream: bptr(false),
Messages: []ChatMessage{
{Role: "system", Content: "Du är en exakt assistent."},
{Role: "user", Content: "Förklara rekursion med ett kort Go-exempel."},
},
}
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("🧠 tänkande:\n", out.Message.Thinking)
fmt.Println("\n💬 svar:\n", out.Message.Content)
return nil
}
// Stäng av tänkande för nästa omgång genom:
// (a) att ställa in Think=false, och/eller
// (b) lägga till "/no_think" i den senaste systembrukaremeddelandet (Qwen3 mjuk switch).
// Qwen3 följer den senaste /think eller /no_think instruktionen i flera omgångars chattar.
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: "Du är kort. /no_think"},
{Role: "user", Content: "Förklara rekursion i en mening."},
},
}
raw, err := httpPostJSON(endpoint, req)
if err != nil {
return err
}
var out ChatResponse
if err := json.Unmarshal(raw, &out); err != nil {
return err
}
// Förvänta dig att tänkande är tomt; hantera försiktigt ändå.
if out.Message.Thinking != "" {
fmt.Println("🧠 tänkande (förväntat):\n", out.Message.Thinking)
}
fmt.Println("\n💬 svar:\n", out.Message.Content)
return nil
}
(Qwen3s /think och /no_think mjuka switchar är dokumenterade av Qwen-teamet; den senaste instruktionen vinner i flera omgångars chattar.)
Chatt — GPT-OSS med tänkande (och en varning)
func chatGptOss() error {
endpoint := "http://localhost:11434/api/chat"
req := ChatRequest{
Model: "gpt-oss:20b",
Think: bptr(true), // begär separerat resonemang om det stöds
Stream: bptr(false),
Messages: []ChatMessage{
{Role: "user", Content: "Vad är dynamisk programmering? Förklara det centrala idet."},
},
}
raw, err := httpPostJSON(endpoint, req)
if err != nil {
return err
}
var out ChatResponse
if err := json.Unmarshal(raw, &out); err != nil {
return err
}
// Kända egenskaper: att avaktivera tänkande kan inte helt undertrycka resonemang på gpt-oss:20b.
// Filtrera alltid tänkande i UI om du inte vill visa det.
fmt.Println("🧠 tänkande:\n", out.Message.Thinking)
fmt.Println("\n💬 svar:\n", out.Message.Content)
return nil
}
Användare rapporterar att avaktivera tänkande på gpt-oss:20b (t.ex., /set nothink eller --think=false) kan ignoreras — planera för klientsidig filtrering om det behövs.
Generera — Qwen3 och GPT-OSS
func generateQwen3() error {
endpoint := "http://localhost:11434/api/generate"
req := GenerateRequest{
Model: "qwen3:4b-thinking",
Prompt: "I 2–3 meningar, vad används B-träd för i databaser?",
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("🧠 tänkande:\n", out.Thinking)
}
fmt.Println("\n💬 svar:\n", out.Response)
return nil
}
func generateGptOss() error {
endpoint := "http://localhost:11434/api/generate"
req := GenerateRequest{
Model: "gpt-oss:20b",
Prompt: "Förklara bakpropagering i neurala nätverk kort.",
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("🧠 tänkande:\n", out.Thinking)
}
fmt.Println("\n💬 svar:\n", out.Response)
return nil
}
REST-form och strömningsskede kommer direkt från Ollama API-referensen.
Del 2 — Anropa Ollama via den officiella Go SDK:n (github.com/ollama/ollama/api)
Den officiella paketet exponerar en Client med metoder som motsvarar REST API:et. Ollama CLI:et självt använder detta paket för att kommunicera med tjänsten, vilket gör det till den säkraste valen för kompatibilitet.
Installera
go get github.com/ollama/ollama/api
Chatt — Qwen3 (tänkande PÅ / AV)
package main
import (
"context"
"fmt"
"log"
"github.com/ollama/ollama/api"
)
func chatWithQwen3Thinking(ctx context.Context, thinking bool) error {
client, err := api.ClientFromEnvironment() // följer OLLAMA_HOST om inställt
if err != nil {
return err
}
req := &api.ChatRequest{
Model: "qwen3:8b-thinking",
// Många serverbyggare exponerar tänkande som en toppnivåflagga;
// dessutom kan du kontrollera Qwen3 via /think eller /no_think i meddelanden.
Think: api.Ptr(thinking),
Messages: []api.Message{
{Role: "system", Content: "Du är en exakt assistent."},
{Role: "user", Content: "Förklara mergesort med ett kort Go-snutt."},
},
}
var resp api.ChatResponse
if err := client.Chat(ctx, req, &resp); err != nil {
return err
}
if resp.Message.Thinking != "" {
fmt.Println("🧠 tänkande:\n", resp.Message.Thinking)
}
fmt.Println("\n💬 svar:\n", resp.Message.Content)
return nil
}
func main() {
ctx := context.Background()
if err := chatWithQwen3Thinking(ctx, true); err != nil {
log.Fatal(err)
}
// Exempel: icke-tänkande
if err := chatWithQwen3Thinking(ctx, false); err != nil {
log.Fatal(err)
}
}
Chatt — GPT-OSS (hantera resonemang försiktigt)
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: "Vad är memoisering och när är den användbar?"},
},
}
var resp api.ChatResponse
if err := client.Chat(ctx, req, &resp); err != nil {
return err
}
// Om du planerar att dölja resonemang, gör det här oavsett flaggor.
if resp.Message.Thinking != "" {
fmt.Println("🧠 tänkande:\n", resp.Message.Thinking)
}
fmt.Println("\n💬 svar:\n", resp.Message.Content)
return nil
}
Generera — 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: "Sammanfatta rollen av ett B-träd i 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("🧠 tänkande:\n", resp.Thinking)
}
fmt.Println("\n💬 svar:\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: "Förklara gradient descent i enkla termer.",
Think: api.Ptr(true),
}
var resp api.GenerateResponse
if err := client.Generate(ctx, req, &resp); err != nil {
return err
}
if resp.Thinking != "" {
fmt.Println("🧠 tänkande:\n", resp.Thinking)
}
fmt.Println("\n💬 svar:\n", resp.Response)
return nil
}
Den officiella paketets yta speglar REST-dokumentationen och uppdateras tillsammans med det centrala projektet.
Strömmande svar
För realtidsströmning, ställ in Stream: bptr(true) i din begäran. Svar kommer levereras som newline-delimited JSON-chunks:
func streamChatExample() error {
endpoint := "http://localhost:11434/api/chat"
req := ChatRequest{
Model: "qwen3:8b-thinking",
Think: bptr(true),
Stream: bptr(true), // Aktivera strömning
Messages: []ChatMessage{
{Role: "user", Content: "Förklara quicksort-algoritmen steg för steg."},
},
}
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
}
// Bearbeta tänkande och innehåll när de kommer
if chunk.Message.Thinking != "" {
fmt.Print(chunk.Message.Thinking)
}
fmt.Print(chunk.Message.Content)
if chunk.Done {
break
}
}
return nil
}
Med den officiella SDK:n, använd en callbackfunktion för att hantera strömmande chunks:
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: "Förklara binära sökträd."},
},
}
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
}
Arbeta med Qwen3 tänkande vs icke-tänkande (praktisk vägledning)
-
Två hävarter:
- En boolesk
tänkandeflagga som stöds av Ollamas tänkande funktion; och - Qwen3s mjuka switchkommandon
/thinkoch/no_thinki den senaste systembrukaremeddelandet. Den senaste instruktionen styr nästa omgång(ar).
- En boolesk
-
Standardposture: icke-tänkande för snabba svar; öka till tänkande för uppgifter som kräver steg-för-steg resonemang (matematik, planering, felsökning, komplex kodanalys).
-
Strömmande UI:er: när tänkande är aktiverat, kan du se sammanblandade resonemang/innehåll i strömmade ramar — buffra eller rendera dem separat och ge användarna en “visa resonemang” knapp. (Se API-dokumentation för strömmningsformat.)
-
Multi-turn konversationer: Qwen3 minns tänkandetillståndet från tidigare omgångar. Om du vill växla det mitt i en konversation, använd både flaggan och mjukswitchkommandot för pålitlighet.
Anteckningar för GPT-OSS
- Behandla resonemang som närvarande även om du försökte inaktivera det; filtrera på klienten om din UX inte ska visa det.
- För produktionsapplikationer som använder GPT-OSS, implementera klientsidig filtreringslogik som kan upptäcka och ta bort resonemangsmönster om det behövs.
- Testa din specifika GPT-OSS-modellvariant grundligt, eftersom beteendet kan variera mellan olika kvantiseringar och versioner.
Bästa praxis och produktionsförslag
Felhantering och timeout
Implementera alltid korrekt timeouthantering och felåterställning:
func robustChatRequest(ctx context.Context, model string, messages []api.Message) (*api.ChatResponse, error) {
// Sätt en rimlig timeout
ctx, cancel := context.WithTimeout(ctx, 2*time.Minute)
defer cancel()
client, err := api.ClientFromEnvironment()
if err != nil {
return nil, fmt.Errorf("skapa klient: %w", err)
}
req := &api.ChatRequest{
Model: model,
Messages: messages,
Options: map[string]interface{}{
"temperature": 0.7,
"num_ctx": 4096, // kontextfönsterstorlek
},
}
var resp api.ChatResponse
if err := client.Chat(ctx, req, &resp); err != nil {
return nil, fmt.Errorf("chatbegäran misslyckades: %w", err)
}
return &resp, nil
}
Anslutningspool och återanvändning
Återanvänd Ollama-klienten över flera begäranden istället för att skapa en ny varje gång:
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
}
Miljökonfiguration
Använd miljövariabler för flexibel distribution:
export OLLAMA_HOST=http://localhost:11434
export OLLAMA_NUM_PARALLEL=2
export OLLAMA_MAX_LOADED_MODELS=2
Den officiella SDK:n respekterar automatiskt OLLAMA_HOST via api.ClientFromEnvironment().
Övervakning och loggning
Implementera strukturerad loggning för produktionsystem:
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
}
Slutsats
-
För Go-projekt,
github.com/ollama/ollama/apiär den mest kompletta, produktionsklara valen. Den underhålls tillsammans med Ollama-core-projektet, används av den officiella CLI:n, och ger omfattande API-coverage med garanterad kompatibilitet. -
För högre abstraktioner, överväg LangChainGo när du behöver kedjor, verktyg, vektorlager och RAG-pipelines — även om du kommer att byta något lågnivåkontroll mot bekvämlighet.
-
Qwen3 ger dig ren, pålitlig kontroll över tänkande-läge med både flaggor och meddelandesnitt (
/think,/no_think), vilket gör det idealiskt för applikationer som behöver både snabba svar och djup resonemang. -
För GPT-OSS, planera alltid att rensning av resonemang utdata på klienten när det behövs, eftersom tänkande inaktiveringsflaggan kan inte vara konsekvent beaktad.
-
I produktion, implementera korrekt felhantering, anslutningspool, timeout och övervakning för att bygga robusta Ollama-drivna applikationer.
Kombinationen av Gös starka typning, utmärkt stöd för konkurrens och Ollamas enkel API gör det till ett idealiskt stack för att bygga AI-drivna applikationer — från enkla chattbotar till komplexa RAG-system.
Viktiga punkter
Här är en snabb referens för att välja din metod:
| Användningsscenarie | Rekommenderad metod | Varför |
|---|---|---|
| Produktionapplikation | github.com/ollama/ollama/api |
Officiell stöd, komplett API-coverage, underhålls tillsammans med core-projektet |
| RAG/kedjor/verktygspipeline | LangChainGo | Högre abstraktioner, integreringar med vektorlager |
| Lärande/experimentering | Rå REST med net/http | Full transparens, inga beroenden, pedagogisk |
| Snabb prototyp | Officiell SDK | Balans mellan enkelhet och kraft |
| Strömmande chatt UI | Officiell SDK med callbacks | Inbyggd strömningssupport, ren API |
Modellvalsinstruktioner:
- Qwen3: Bästa för applikationer som kräver kontrollerat tänkande-läge, pålitliga flera omgångars konversationer
- GPT-OSS: Stark prestanda men kräver försiktigt hantering av tänkande/resonemang utdata
- Andra modeller: Testa grundligt; tänkande beteende varierar per modellfamilj
Referenser & vidare läsning
Officiell dokumentation
- Ollama API-referens — Komplett REST API-dokumentation
- Officiell Ollama Go-paket — Go SDK-dokumentation
- Ollama GitHub-repo — Källkod och problem
Go SDK-alternativ
- LangChainGo Ollama-integrering — För kedjebaserade applikationer
- swdunlop/ollama-client — Communityklient med verktygsanrop
- xyproto/ollamaclient — En annan communityalternativ
Modellspecifika resurser
- Qwen-dokumentation — Officiell Qwen-modellinformation
- GPT-OSS-information — GPT-OSS-modellinformation
Relaterade ämnen
- Bygg RAG-applikationer med Go — LangChainGo-exempel
- Go context-paket — Essentiellt för timeout och avbrytning
- Go HTTP-klient bästa praxis — Standardbiblioteksdokumentation
Andra användbara länkar
För en bredare jämförelse av Ollama med andra lokala och molna LLM-infrastrukturer, kontrollera vår LLM Hosting: Lokal, självvärd och molninfrastruktur jämförd.