go-deepseek is an unofficial Go client for DeepSeek-compatible APIs. It can be used with DeepSeek, Qwen3/QwQ via DashScope-compatible endpoints, OpenAI-compatible APIs, and local Ollama models.
- Chat completions
- Streaming chat completions
- Function calling / tool calling
- FIM (Fill-in-Middle) completions
- Embeddings through Ollama
- DeepSeek account balance query
- Configurable
BaseUrl, timeout, and customhttp.Client
go get github.com/p9966/go-deepseekRequires Go 1.23+.
This is the fastest way to call the default DeepSeek API:
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/p9966/go-deepseek"
)
func main() {
client := deepseek.NewClient(os.Getenv("DEEPSEEK_API_KEY"))
req := deepseek.ChatCompletionRequest{
Model: deepseek.DeepseekV4Pro,
Messages: []deepseek.ChatCompletionMessage{
{
Role: deepseek.ChatMessageRoleUser,
Content: "Explain why the sky is blue in one paragraph.",
},
},
}
resp, err := client.CreateChatCompletion(context.Background(), &req)
if err != nil {
log.Fatal(err)
}
if len(resp.Choices) == 0 {
log.Fatal("no response choices returned")
}
fmt.Println(resp.Choices[0].Message.Content)
}The client defaults to https://api.deepseek.com, but you can point it to any compatible endpoint.
client := deepseek.NewClient(
os.Getenv("QWEN3_AUTH_TOKEN"),
deepseek.WithBaseURL("https://dashscope.aliyuncs.com/compatible-mode/v1"),
)client := deepseek.NewClient(
os.Getenv("OPENAI_API_KEY"),
deepseek.WithBaseURL("https://api.openai.com/v1"),
)client := deepseek.NewClient(
os.Getenv("DEEPSEEK_API_KEY"),
deepseek.WithTimeout(30*time.Second),
)Or:
client := deepseek.NewClient(
os.Getenv("DEEPSEEK_API_KEY"),
deepseek.WithHTTPClient(myHTTPClient),
)Use CreateChatCompletionStream when you want tokens as they arrive:
package main
import (
"context"
"errors"
"fmt"
"io"
"log"
"os"
"github.com/p9966/go-deepseek"
)
func main() {
client := deepseek.NewClient(os.Getenv("DEEPSEEK_API_KEY"))
stream, err := client.CreateChatCompletionStream(context.Background(), deepseek.StreamChatCompletionRequest{
Model: deepseek.DeepseekV4Flash,
Messages: []deepseek.ChatCompletionMessage{
{
Role: deepseek.ChatMessageRoleUser,
Content: "Write a short haiku about Go concurrency.",
},
},
})
if err != nil {
log.Fatal(err)
}
defer stream.Close()
for {
resp, err := stream.Recv()
if errors.Is(err, io.EOF) {
break
}
if err != nil {
log.Fatal(err)
}
if len(resp.Choices) == 0 {
continue
}
fmt.Print(resp.Choices[0].Delta.Content)
}
}package main
import (
"context"
"fmt"
"log"
"os"
"github.com/p9966/go-deepseek"
)
func main() {
client := deepseek.NewClient(os.Getenv("DEEPSEEK_API_KEY"))
req := deepseek.ChatCompletionRequest{
Model: deepseek.DeepseekV4Pro,
Messages: []deepseek.ChatCompletionMessage{
{
Role: deepseek.ChatMessageRoleUser,
Content: "What's the weather in Hangzhou?",
},
},
Tools: []deepseek.Tools{
{
Type: "function",
Function: deepseek.Function{
Name: "get_weather",
Description: "Get weather for a city",
Parameters: &deepseek.Parameters{
Type: "object",
Properties: map[string]interface{}{
"location": map[string]interface{}{
"type": "string",
"description": "City name",
},
},
Required: []string{"location"},
},
},
},
},
}
resp, err := client.CreateChatCompletion(context.Background(), &req)
if err != nil {
log.Fatal(err)
}
if len(resp.Choices) == 0 || len(resp.Choices[0].Message.ToolCalls) == 0 {
log.Fatal("no tool call returned")
}
call := resp.Choices[0].Message.ToolCalls[0]
fmt.Printf("tool=%s args=%s\n", call.Function.Name, call.Function.Arguments)
}You can also use local models through Ollama:
package main
import (
"context"
"fmt"
"log"
"github.com/p9966/go-deepseek"
)
func main() {
client := deepseek.NewClient(
"",
deepseek.WithBaseURL("http://localhost:11434"),
)
req := deepseek.OllamaChatRequest{
Model: "deepseek-r1:7b",
Messages: []deepseek.OllamaChatMessage{
{
Role: "user",
Content: "Hello!",
},
},
}
resp, err := client.CreateOllamaChatCompletion(context.Background(), &req)
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.Message.Content)
}If you do not have Ollama installed yet:
ollama run deepseek-r1Runnable examples live in examples/:
| Scenario | Path |
|---|---|
| Chat completion | examples/chat |
| Stream chat completion | examples/chat_stream |
| Function calling | examples/function_calling |
| FIM completion | examples/fin |
| Balance query | examples/balance |
| Ollama chat | examples/ollama_chat |
| Ollama generate | examples/ollama_generate |
| Ollama embeddings | examples/ollama_embed |
| Ollama function calling | examples/ollama_function_calling |
| Qwen3 stream chat | examples/qwen3_chat_stream |
| Qwen3 function calling | examples/qwen3_function_calling |
| QwQ stream chat | examples/qwq_chat_stream |
| QwQ function calling | examples/qwq_function_calling |
NewClient(token)uses DeepSeek's default base URL automatically.- Plain tokens are sent as
Bearer <token>automatically. - For compatible providers, set a custom base URL with
WithBaseURL(...). - For local Ollama usage, no auth token is required.
Run tests with:
go test ./...This project is licensed under the MIT License.