Skip to content

Commit

Permalink
Added deepseek support (#29)
Browse files Browse the repository at this point in the history
* Added deepseek support
* Added docs to readme and usage
  • Loading branch information
baalimago authored Jan 27, 2025
1 parent 40cd93c commit 5a3a39a
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Nag on me to implement modellabs and I'll do it.
- **OpenAI API Key:** Set the `OPENAI_API_KEY` env var to your [OpenAI API key](https://platform.openai.com/docs/quickstart/step-2-set-up-your-api-key). [Text models](https://platform.openai.com/docs/models/gpt-4-and-gpt-4-turbo), [photo models](https://platform.openai.com/docs/models/dall-e).
- **Anthropic API Key:** Set the `ANTHROPIC_API_KEY` env var to your [Anthropic API key](https://console.anthropic.com/login?returnTo=%2F). [Text models](https://docs.anthropic.com/claude/docs/models-overview#model-recommendations).
- **Mistral API Key:** Set the `MISTRAL_API_KEY` env var to your [Mistral API key](https://console.mistral.ai/). [Text models](https://docs.mistral.ai/getting-started/models/)
- **Deepseek:** Set the `DEEPSEEK_API_KEY` env var to your [Deepseek API key](https://api-docs.deepseek.com/). [Text models](https://api-docs.deepseek.com/quick_start/pricing)
- **Novita AI:** Set the `NOVITA_API_KEY` env var to your [Novita API key](https://novita.ai/settings?utm_source=github_clai&utm_medium=github_readme&utm_campaign=link#key-management). Target the model using novita prefix, like this: `novita:<target>`, where `<target>` is one of the [text models](https://novita.ai/model-api/product/llm-api?utm_source=github_clai&utm_medium=github_readme&utm_campaign=link).
- **Ollama:** Start your ollama server (defaults to localhost:11434). Target using model format `ollama:<target>`, where `<target>` is optional (defaults to llama3). Reconfigure url with `clai s -> 1 -> <ollama-model-conf>`
- **Glow**(Optional): Install [Glow](https://github.com/charmbracelet/glow) for formatted markdown output when querying text responses.
Expand Down
12 changes: 12 additions & 0 deletions internal/create_queriers.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/baalimago/clai/internal/photo"
"github.com/baalimago/clai/internal/text"
"github.com/baalimago/clai/internal/vendors/anthropic"
"github.com/baalimago/clai/internal/vendors/deepseek"
"github.com/baalimago/clai/internal/vendors/mistral"
"github.com/baalimago/clai/internal/vendors/novita"
"github.com/baalimago/clai/internal/vendors/ollama"
Expand Down Expand Up @@ -51,6 +52,17 @@ func CreateTextQuerier(conf text.Configurations) (models.Querier, error) {
q = &qTmp
}

if strings.Contains(conf.Model, "deepseek") {
found = true
defaultCpy := deepseek.DEEPSEEK_DEFAULT
defaultCpy.Model = conf.Model
qTmp, err := text.NewQuerier(conf, &defaultCpy)
if err != nil {
return nil, fmt.Errorf("failed to create text querier: %w", err)
}
q = &qTmp
}

// process before mistral, in case we want to use mistral for ollama
if strings.HasPrefix(conf.Model, "ollama:") || conf.Model == "ollama" {
found = true
Expand Down
4 changes: 4 additions & 0 deletions internal/text/querier_setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ func vendorType(fromModel string) (string, string, string) {
if strings.Contains(fromModel, "mistral") || strings.Contains(fromModel, "mixtral") {
return "mistral", "mistral", fromModel
}

if strings.Contains(fromModel, "deepseek") {
return "deepseek", "deepseek", fromModel
}
if strings.Contains(fromModel, "mock") {
return "mock", "mock", "mock"
}
Expand Down
23 changes: 23 additions & 0 deletions internal/vendors/deepseek/deepseek.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package deepseek

import (
"github.com/baalimago/clai/internal/text/generic"
)

var DEEPSEEK_DEFAULT = Deepseek{
Model: "deepseek-chat",
Temperature: 1.0,
TopP: 1.0,
Url: ChatURL,
}

type Deepseek struct {
generic.StreamCompleter
Model string `json:"model"`
FrequencyPenalty float64 `json:"frequency_penalty"`
MaxTokens *int `json:"max_tokens"` // Use a pointer to allow null value
PresencePenalty float64 `json:"presence_penalty"`
Temperature float64 `json:"temperature"`
TopP float64 `json:"top_p"`
Url string `json:"url"`
}
32 changes: 32 additions & 0 deletions internal/vendors/deepseek/deepseek_setup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package deepseek

import (
"fmt"
"os"

"github.com/baalimago/clai/internal/tools"
)

const ChatURL = "https://api.deepseek.com/chat/completions"

func (g *Deepseek) Setup() error {
if os.Getenv("DEEPSEEK_API_KEY") == "" {
os.Setenv("DEEPSEEK_API_KEY", "deepseek")
}
err := g.StreamCompleter.Setup("DEEPSEEK_API_KEY", ChatURL, "DEEPSEEK_DEBUG")
if err != nil {
return fmt.Errorf("failed to setup stream completer: %w", err)
}
g.StreamCompleter.Model = g.Model
g.StreamCompleter.FrequencyPenalty = &g.FrequencyPenalty
g.StreamCompleter.MaxTokens = g.MaxTokens
g.StreamCompleter.Temperature = &g.Temperature
g.StreamCompleter.TopP = &g.TopP
toolChoice := "auto"
g.ToolChoice = &toolChoice
return nil
}

func (g *Deepseek) RegisterTool(tool tools.AiTool) {
g.InternalRegisterTool(tool)
}
56 changes: 56 additions & 0 deletions internal/vendors/deepseek/models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package deepseek

import "github.com/baalimago/clai/internal/tools"

// Copy from novita, and openai
type ChatCompletion struct {
ID string `json:"id"`
Object string `json:"object"`
Created int64 `json:"created"`
Model string `json:"model"`
Choices []Choice `json:"choices"`
Usage Usage `json:"usage"`
SystemFingerprint string `json:"system_fingerprint"`
}

type Choice struct {
Index int `json:"index"`
Delta Delta `json:"delta"`
Logprobs interface{} `json:"logprobs"` // null or complex object, hence interface{}
FinishReason string `json:"finish_reason"`
}

type Usage struct {
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
TotalTokens int `json:"total_tokens"`
}

type Delta struct {
Content any `json:"content"`
Role string `json:"role"`
ToolCalls []ToolsCall `json:"tool_calls"`
}

type ToolsCall struct {
Function GptFunc `json:"function"`
ID string `json:"id"`
Index int `json:"index"`
Type string `json:"type"`
}

type GptFunc struct {
Arguments string `json:"arguments"`
Name string `json:"name"`
}

type GptTool struct {
Name string `json:"name"`
Description string `json:"description"`
Inputs tools.InputSchema `json:"parameters"`
}

type GptToolSuper struct {
Type string `json:"type"`
Function GptTool `json:"function"`
}
3 changes: 3 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ const usage = `clai - (c)ommand (l)ine (a)rtificial (i)ntelligence
Prerequisites:
- Set the OPENAI_API_KEY environment variable to your OpenAI API key
- Set the ANTHROPIC_API_KEY environment variable to your Anthropic API key
- Set the MISTRAL_API_KEY environment variable to your Mistral API key
- Set the DEEPSEEK_API_KEY environment variable to your Deepseek API key
- Set the NOVITA_API_KEY environment variable to your Novita API key
- (Optional) Set the NO_COLOR environment variable to disable ansi color output
- (Optional) Install glow - https://github.com/charmbracelet/glow for formated markdown output
Expand Down

0 comments on commit 5a3a39a

Please sign in to comment.