Ollama-klienter: Jämförelse av SDK:er och exempel med Qwen3/GPT-OSS
Integrera Ollama med Go: SDK-guide, exempel och bästa praxis för produktion.
Den här guiden ger en omfattande översikt över tillgängliga Go SDKs för Ollama och jämför deras funktioner.
Vi kommer att utforska praktiska Go-exempel för att anropa Qwen3 och GPT-OSS-modeller som värdas på Ollama—både via råa 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 ett litet, pragmatiskt HTTP-API (vanligtvis körande på http://localhost:11434) som är utformat för generate och chat-arbetsbelastningar, med inbyggt strömningsstöd och modellhanteringsfunktioner. Den officiella dokumentationen täcker fullständigt /api/generate och /api/chat-begärande/svarsstrukturer och strömningssemantik.
Go är ett utmärkt val för byggande av Ollama-klienter tack vare dess starka standardbiblioteksstöd för HTTP, utmärkt JSON-hantering, naturliga konkurrensprimitiver och statiskt typade gränssnitt som fångar fel vid kompileringsstadiet.
Per oktober 2025 finns här de Go SDK-alternativ du mest sannolikt kommer att överväga.
Go SDKs för Ollama — vad finns tillgängligt?
| SDK / Paket | Status & “ägare” | Omfattning (Generate/Chat/Strömning) | Modellhantering (pull/list/etc.) | Extra / Anteckningar |
|---|---|---|---|---|
github.com/ollama/ollama/api |
Officiellt paket inom Ollama-repo; används av ollama CLI själv |
Fullständig 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) |
Community-ramverk (LangChainGo) med Ollama LLM-modul | Chat/Completion + strömning via ramverksabstraktioner | Begränsad (modellhantering inte primärt mål) | Bra om du vill ha kedjor, verktyg, vektorlagring i Go; mindre av en rå SDK. |
github.com/swdunlop/ollama-client |
Community-klient | Fokus på chat; bra verktygsanropsexperiment | Delvis | Byggd för experiment med verktygsanrop; inte en 1:1 full yta. |
Andra community-SDKs (t.ex., ollamaclient, tredje parts “go-ollama-sdk”) |
Community | Varierar | Varierar | Kvalitet och täckning varierar; utvärdera per repo. |
Rekommendation: För produktion, föredra github.com/ollama/ollama/api—det underhålls med huvudprojektet och speglar REST-API:n.
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 slutlig utgång när det är aktiverat. Ollama dokumenterar ett förstaklassigt aktivera/inaktivera tänkande beteende över stödda modeller.
- (https://www.glukhov.org/sv/post/2025/10/qwen3-30b-vs-gpt-oss-20b/ “Qwen3:30b vs GPT-OSS:20b: Tekniska detaljer, prestanda och hastighetsjämförelse”) stöder dynamisk växling: lägg till
/thinkeller/no_thinki system/användarmeddelanden för att byta läge tur för tur; den senaste instruktionen gäller. - GPT-OSS: användare rapporterar att inaktivering av tänkande (t.ex.,
/set nothinkeller--think=false) kan vara opålitligt pågpt-oss:20b; planera för filtrering/döljande av allt resonemang som ditt gränssnitt inte bör visa.
Del 1 — Anrop till Ollama via rå REST (Go, net/http)
Gemensamma typer
Först, låt oss definiera de gemensamma typerna och hjälpfunktioner vi kommer att använda i våra exempel:
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
// ---- Chat 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änkandekontroll som en boolsk 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åslaget
} `json:"message"`
Done bool `json:"done"`
}
// ---- Generate 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ömning
Thinking string `json:"thinking,omitempty"` // närvarande när tänkande är påslaget
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 pekar till en boolsk värde
func bptr(b bool) *bool { return &b }
Chat — Qwen3 med tänkande PÅ (och hur man stänger det AV)
func chatQwen3Thinking() error {
endpoint := "http://localhost:11434/api/chat"
req := ChatRequest{
Model: "qwen3:8b-thinking", // någon :*-thinking-tagg du har laddat ner
Think: bptr(true),
Stream: bptr(false),
Messages: []ChatMessage{
{Role: "system", Content: "Du är en precis 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 tänkande AV för nästa tur genom:
// (a) att ställa in Think=false, och/eller
// (b) att lägga till "/no_think" i det senaste system/användarmeddelandet (Qwen3 mjuk switch).
// Qwen3 följer den senaste /think eller /no_think-instruktionen i flervägs-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 kortfattad. /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 ska vara tomt; hantera ändå försiktigt.
if out.Message.Thinking != "" {
fmt.Println("🧠 tänkande (oförväntat):\n", out.Message.Thinking)
}
fmt.Println("\n💬 svar:\n", out.Message.Content)
return nil
}
(Qwen3:s /think och /no_think mjuk switch dokumenteras av Qwen-teamet; den senaste instruktionen gäller i flervägs-chattar.)
Chat — 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 kärnidén."},
},
}
raw, err := httpPostJSON(endpoint, req)
if err != nil {
return err
}
var out ChatResponse
if err := json.Unmarshal(raw, &out); err != nil {
return err
}
// Känd egendomlighet: inaktivering av tänkande kan inte fullständigt undertrycka resonemang på gpt-oss:20b.
// Filtrera/undanröj alltid tänkande i gränssnittet 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 inaktivering av tänkande på gpt-oss:20b (t.ex., /set nothink eller --think=false) kan ignoreras—planera för klientsidig filtrering om det behövs.
Generate — Qwen3 och GPT-OSS
func generateQwen3() error {
endpoint := "http://localhost:11434/api/generate"
req := GenerateRequest{
Model: "qwen3:4b-thinking",
Prompt: "På 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 kort bakpropagering i neurala nätverk.",
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-formatering och strömningsbeteende kommer direkt från Ollama API-referensen.
Del 2 — Anrop till Ollama via det officiella Go SDK (github.com/ollama/ollama/api)
Det officiella paketet exponerar en Client med metoder som motsvarar REST-API:t. Ollama CLI själv använder detta paket för att kommunicera med tjänsten, vilket gör det till det säkraste valet för kompatibilitet.
Installera
go get github.com/ollama/ollama/api
Chat — 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() // respektera OLLAMA_HOST om inställt
if err != nil {
return err
}
req := &api.ChatRequest{
Model: "qwen3:8b-thinking",
// Många serverbyggnader exponerar tänkande som en huvudflagga;
// 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 noggrann assistent."},
{Role: "user", Content: "Förklara merge sort med ett kort Go-snippet."},
},
}
var resp api.ChatResponse
if err := client.Chat(ctx, req, &resp); err != nil {
return err
}
if resp.Message.Thinking != "" {
fmt.Println("🧠 tänker:\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)
}
}
Chat — GPT-OSS (hantera resonemang defensivt)
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 det användbart?"},
},
}
var resp api.ChatResponse
if err := client.Chat(ctx, req, &resp); err != nil {
return err
}
// Om du avser att dölja resonemang, gör det här oavsett flaggor.
if resp.Message.Thinking != "" {
fmt.Println("🧠 tänker:\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 för en B-Tree 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änker:\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änker:\n", resp.Thinking)
}
fmt.Println("\n💬 svar:\n", resp.Response)
return nil
}
Det officiella paketets gränssnitt speglar REST-dokumentationen och uppdateras tillsammans med kärnprojektet.
Strömmande svar
För realtidströmning, ställ in Stream: bptr(true) i din begäran. Svaret kommer att levereras som newline-avgränsade JSON-kluster:
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 anländer
if chunk.Message.Thinking != "" {
fmt.Print(chunk.Message.Thinking)
}
fmt.Print(chunk.Message.Content)
if chunk.Done {
break
}
}
return nil
}
Med det officiella SDK använder du en callback-funktion för att hantera strömmande kluster:
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
}
Arbete med Qwen3 tänkande vs icke-tänkande (praktisk vägledning)
-
Två reglage:
- En boolean
thinking-flagga som stöds av Ollamas tänkandefunktion; och - Qwen3:s mjuk switch-kommandon
/thinkoch/no_thinki det senaste system/användarmeddelandet. Den senaste instruktionen styr nästa tur(er).
- En boolean
-
Standardinställning: icke-tänkande för snabba svar; eskalera till tänkande för uppgifter som kräver steg-för-steg-resonemang (matematik, planering, felsökning, komplex kodanalys).
-
Strömmande UIs: när tänkande är aktiverat, kan du se blandade resonemang/innehåll i strömmande ramar—buffra eller rendera dem separat och ge användarna en “visa resonemang”-knapp. (Se API-dokumentation för strömningsformat.)
-
Multi-turn-samtal: Qwen3 kommer ihåg tänkande-läget från tidigare turer. Om du vill byta det under samtalet, använd både flaggan OCH mjuk-switch-kommandot för pålitlighet.
Anteckningar för GPT-OSS
- Behandla resonemang som närvarande även om du försökt att stänga av det; filtrera på klientsidan om ditt UX inte ska visa det.
- För produktionsapplikationer som använder GPT-OSS, implementera klientsidans filtreringslogik som kan upptäcka och ta bort resonemangsmönster om det behövs.
- Testa din specifika GPT-OSS-modellvariant noggrant, eftersom beteendet kan variera mellan olika kvantiseringar och versioner.
Bästa praxis och produktionsråd
Felhantering och tidsgränser
Implementera alltid korrekt hantering av tidsgränser och felåterhämtning:
func robustChatRequest(ctx context.Context, model string, messages []api.Message) (*api.ChatResponse, error) {
// Ställ in en rimlig tidsgräns
ctx, cancel := context.WithTimeout(ctx, 2*time.Minute)
defer cancel()
client, err := api.ClientFromEnvironment()
if err != nil {
return nil, fmt.Errorf("skapande av 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("chat-begäran misslyckades: %w", err)
}
return &resp, nil
}
Anslutningspooling och återanvändning
Återanvänd Ollama-klienten över 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ökontroll
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
Det officiella SDK respekterar automatiskt OLLAMA_HOST via api.ClientFromEnvironment().
Övervakning och loggning
Implementera strukturerad loggning för produktionssystem:
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 är
github.com/ollama/ollama/apidet mest kompletta, produktionsklara valet. Det underhålls tillsammans med Ollama-kärnprojektet, används av den officiella CLI:n och erbjuder omfattande API-täckning med garanterad kompatibilitet. -
För högre nivåer av abstraktion, överväg LangChainGo när du behöver kedjor, verktyg, vektorlagring och RAG-pipelines—fast du kommer att byta ut viss låg nivå kontroll för bekvämlighet.
-
Qwen3 ger dig ren, pålitlig kontroll över tänkande-läge med både flaggor och meddelandenivå-växlingar (
/think,/no_think), vilket gör det idealiskt för applikationer som behöver både snabba svar och djupt resonemang. -
För GPT-OSS, planera alltid för att sanitera resonemang på klientsidan när det behövs, eftersom flaggan för att stänga av tänkande kanske inte alltid följs.
-
I produktion, implementera korrekt felhantering, anslutningspooling, tidsgränser och övervakning för att bygga robusta Ollama-drivna applikationer.
Kombinationen av Gos starka typning, utmärkt stöd för parallellitet och Ollamas enkla API gör det till en idealisk stack för att bygga AI-drivna applikationer - från enkla chattbotar till komplexa RAG-system.
Nyckelpunkter
Här är en snabb referens för att välja din tillvägagångssätt:
| Användningsområde | Rekommenderat tillvägagångssätt | Varför |
|---|---|---|
| Produktionsapplikation | github.com/ollama/ollama/api |
Officiellt stöd, fullständig API-täckning, underhålls med kärnprojektet |
| RAG/kedjor/verktygspipeline | LangChainGo | Högre nivåer av abstraktion, integrationer med vektorlagring |
| Inlärning/experimentering | Raw REST med net/http | Full transparens, inga beroenden, pedagogisk |
| Snabb prototypering | Officiellt SDK | Balans mellan enkelhet och kraft |
| Strömmande chat-UI | Officiellt SDK med callbacks | Inbyggt stöd för strömning, ren API |
Modellval vägledning:
- Qwen3: Bäst för applikationer som kräver kontrollerbart tänkande-läge, pålitliga multi-turn-samtal
- GPT-OSS: Stark prestanda men kräver defensiv hantering av tänkande/resonemang
- Andra modeller: Testa noggrant; tänkande-beteende varierar mellan modellfamiljer
Referenser och vidare läsning
Officiell dokumentation
- Ollama API referens — Fullständig REST API-dokumentation
- Officiell Ollama Go-paket — Go SDK-dokumentation
- Ollama GitHub-repository — Källkod och problem
Go SDK-alternativ
- LangChainGo Ollama-integration — För kedjebaserade applikationer
- swdunlop/ollama-client — Community-klient med verktygsanrop
- xyproto/ollamaclient — Ett annat community-alternativ
Modellspecifika resurser
- Qwen-dokumentation — Officiell information om Qwen-modellen
- GPT-OSS-information — Detaljer om GPT-OSS-modellen
Relaterade ämnen
- Att bygga RAG-applikationer med Go — LangChainGo-exempel
- Go context-paket — Väsentligt för tidsgränser och avbrytande
- Go HTTP-klient bästa praxis — Standardbiblioteksdokumentation
Andra användbara länkar
- Installera och konfigurera Ollama
- Ollama snabbreferens
- Go snabbreferens
- Hur Ollama hanterar parallella begäranden
- Omrankning av textdokument med Ollama och Qwen3 Embedding-modell - i Go
- Jämförelse av Go ORMs för PostgreSQL: GORM vs Ent vs Bun vs sqlc
- Begränsa LLMs med strukturerad utgång: Ollama, Qwen3 & Python eller Go
- Användning av Ollama i Python-kod
- LLM-jämförelse: Qwen3:30b vs GPT-OSS:20b
- Ollama GPT-OSS strukturerad utgångsproblem