diff --git a/README.md b/README.md index 63caf26ca9..38cd565e87 100644 --- a/README.md +++ b/README.md @@ -314,6 +314,7 @@ Active: Unused: > openai > localai +> ollama > azureopenai > cohere > amazonbedrock diff --git a/go.mod b/go.mod index 1e23ce24dd..8c08970d2b 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/kedacore/keda/v2 v2.11.2 github.com/magiconair/properties v1.8.7 github.com/mittwald/go-helm-client v0.12.9 + github.com/ollama/ollama v0.1.48 github.com/sashabaranov/go-openai v1.23.0 github.com/schollz/progressbar/v3 v3.14.2 github.com/spf13/cobra v1.8.1 @@ -197,7 +198,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect - github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect diff --git a/go.sum b/go.sum index 5b04427000..8159465c82 100644 --- a/go.sum +++ b/go.sum @@ -1808,8 +1808,8 @@ github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ib github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= -github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= -github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b h1:udzkj9S/zlT5X367kqJis0QP7YMxobob6zhzq6Yre00= github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b/go.mod h1:pcaDhQK0/NJZEvtCO0qQPPropqV0sJOJ6YW7X+9kRwM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -1919,6 +1919,8 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/ollama/ollama v0.1.48 h1:6j9ziyqyAJD3NuTLYJlzZl/b/Q9PDvvYg02FGmREUmE= +github.com/ollama/ollama v0.1.48/go.mod h1:TvVa25PEZI6M0bosiW1sa2XJGq3Xw/OPlpUAkMEntTU= github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= @@ -1933,8 +1935,8 @@ github.com/ovh/go-ovh v1.4.3 h1:Gs3V823zwTFpzgGLZNI6ILS4rmxZgJwJCz54Er9LwD0= github.com/ovh/go-ovh v1.4.3/go.mod h1:AkPXVtgwB6xlKblMjRKJJmjRp+ogrE7fz2lVgcQY8SY= github.com/owenrumney/squealer v1.2.1 h1:4ryMMT59aaz8VMsqsD+FDkarADJz0F1dcq2fd0DRR+c= github.com/owenrumney/squealer v1.2.1/go.mod h1:7D0a/+Bouwy504YhaWsBYW73kyklSEq1MNf6zsNoTRg= -github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= diff --git a/pkg/ai/iai.go b/pkg/ai/iai.go index 3e2ee96bde..d158882b13 100644 --- a/pkg/ai/iai.go +++ b/pkg/ai/iai.go @@ -22,6 +22,7 @@ var ( &OpenAIClient{}, &AzureAIClient{}, &LocalAIClient{}, + &OllamaClient{}, &NoOpAIClient{}, &CohereClient{}, &AmazonBedRockClient{}, @@ -35,6 +36,7 @@ var ( Backends = []string{ openAIClientName, localAIClientName, + ollamaClientName, azureAIClientName, cohereAIClientName, amazonbedrockAIClientName, @@ -172,7 +174,7 @@ func (p *AIProvider) GetOrganizationId() string { return p.OrganizationId } -var passwordlessProviders = []string{"localai", "amazonsagemaker", "amazonbedrock", "googlevertexai", "oci", "watsonxai"} +var passwordlessProviders = []string{"localai", "ollama", "amazonsagemaker", "amazonbedrock", "googlevertexai", "oci", "watsonxai"} func NeedPassword(backend string) bool { for _, b := range passwordlessProviders { diff --git a/pkg/ai/ollama.go b/pkg/ai/ollama.go new file mode 100644 index 0000000000..098c455f22 --- /dev/null +++ b/pkg/ai/ollama.go @@ -0,0 +1,102 @@ +/* +Copyright 2023 The K8sGPT Authors. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package ai + +import ( + "context" + "errors" + "net/http" + "net/url" + + ollama "github.com/ollama/ollama/api" +) + +const ollamaClientName = "ollama" + +type OllamaClient struct { + nopCloser + + client *ollama.Client + model string + temperature float32 + topP float32 +} + +const ( + defaultBaseURL = "http://localhost:11434" + defaultModel = "llama3" +) + +func (c *OllamaClient) Configure(config IAIConfig) error { + baseURL := config.GetBaseURL() + if baseURL == "" { + baseURL = defaultBaseURL + } + baseClientURL, err := url.Parse(baseURL) + if err != nil { + return err + } + + proxyEndpoint := config.GetProxyEndpoint() + httpClient := http.DefaultClient + if proxyEndpoint != "" { + proxyUrl, err := url.Parse(proxyEndpoint) + if err != nil { + return err + } + transport := &http.Transport{ + Proxy: http.ProxyURL(proxyUrl), + } + + httpClient = &http.Client{ + Transport: transport, + } + } + + c.client = ollama.NewClient(baseClientURL, httpClient) + if c.client == nil { + return errors.New("error creating Ollama client") + } + c.model = config.GetModel() + if c.model == "" { + c.model = defaultModel + } + c.temperature = config.GetTemperature() + c.topP = config.GetTopP() + return nil +} +func (c *OllamaClient) GetCompletion(ctx context.Context, prompt string) (string, error) { + req := &ollama.GenerateRequest{ + Model: c.model, + Prompt: prompt, + Stream: new(bool), + Options: map[string]interface{}{ + "temperature": c.temperature, + "top_p": c.topP, + }, + } + completion := "" + respFunc := func(resp ollama.GenerateResponse) error { + completion = resp.Response + return nil + } + err := c.client.Generate(ctx, req, respFunc) + if err != nil { + return "", err + } + return completion, nil +} +func (a *OllamaClient) GetName() string { + return ollamaClientName +}