ScuttleBot

scuttlebot / internal / llm / ollama.go
Source Blame History 94 lines
5ac549c… lmata 1 package llm
5ac549c… lmata 2
5ac549c… lmata 3 import (
5ac549c… lmata 4 "bytes"
5ac549c… lmata 5 "context"
5ac549c… lmata 6 "encoding/json"
5ac549c… lmata 7 "fmt"
5ac549c… lmata 8 "io"
5ac549c… lmata 9 "net/http"
5ac549c… lmata 10 )
5ac549c… lmata 11
5ac549c… lmata 12 type ollamaProvider struct {
5ac549c… lmata 13 baseURL string
5ac549c… lmata 14 model string
5ac549c… lmata 15 http *http.Client
5ac549c… lmata 16 }
5ac549c… lmata 17
5ac549c… lmata 18 func newOllamaProvider(cfg BackendConfig, baseURL string, hc *http.Client) *ollamaProvider {
5ac549c… lmata 19 model := cfg.Model
5ac549c… lmata 20 if model == "" {
5ac549c… lmata 21 model = "llama3.2"
5ac549c… lmata 22 }
5ac549c… lmata 23 return &ollamaProvider{
5ac549c… lmata 24 baseURL: baseURL,
5ac549c… lmata 25 model: model,
5ac549c… lmata 26 http: hc,
5ac549c… lmata 27 }
5ac549c… lmata 28 }
5ac549c… lmata 29
5ac549c… lmata 30 func (p *ollamaProvider) Summarize(ctx context.Context, prompt string) (string, error) {
5ac549c… lmata 31 body, _ := json.Marshal(map[string]any{
5ac549c… lmata 32 "model": p.model,
5ac549c… lmata 33 "prompt": prompt,
5ac549c… lmata 34 "stream": false,
5ac549c… lmata 35 })
5ac549c… lmata 36 req, err := http.NewRequestWithContext(ctx, "POST", p.baseURL+"/api/generate", bytes.NewReader(body))
5ac549c… lmata 37 if err != nil {
5ac549c… lmata 38 return "", err
5ac549c… lmata 39 }
5ac549c… lmata 40 req.Header.Set("Content-Type", "application/json")
5ac549c… lmata 41
5ac549c… lmata 42 resp, err := p.http.Do(req)
5ac549c… lmata 43 if err != nil {
5ac549c… lmata 44 return "", fmt.Errorf("ollama request: %w", err)
5ac549c… lmata 45 }
5ac549c… lmata 46 defer resp.Body.Close()
5ac549c… lmata 47
5ac549c… lmata 48 data, _ := io.ReadAll(resp.Body)
5ac549c… lmata 49 if resp.StatusCode != http.StatusOK {
5ac549c… lmata 50 return "", fmt.Errorf("ollama error %d: %s", resp.StatusCode, string(data))
5ac549c… lmata 51 }
5ac549c… lmata 52
5ac549c… lmata 53 var result struct {
5ac549c… lmata 54 Response string `json:"response"`
5ac549c… lmata 55 }
5ac549c… lmata 56 if err := json.Unmarshal(data, &result); err != nil {
5ac549c… lmata 57 return "", fmt.Errorf("ollama parse: %w", err)
5ac549c… lmata 58 }
5ac549c… lmata 59 return result.Response, nil
5ac549c… lmata 60 }
5ac549c… lmata 61
5ac549c… lmata 62 // DiscoverModels calls the Ollama /api/tags endpoint to list installed models.
5ac549c… lmata 63 func (p *ollamaProvider) DiscoverModels(ctx context.Context) ([]ModelInfo, error) {
5ac549c… lmata 64 req, err := http.NewRequestWithContext(ctx, "GET", p.baseURL+"/api/tags", nil)
5ac549c… lmata 65 if err != nil {
5ac549c… lmata 66 return nil, err
5ac549c… lmata 67 }
5ac549c… lmata 68
5ac549c… lmata 69 resp, err := p.http.Do(req)
5ac549c… lmata 70 if err != nil {
5ac549c… lmata 71 return nil, fmt.Errorf("ollama models request: %w", err)
5ac549c… lmata 72 }
5ac549c… lmata 73 defer resp.Body.Close()
5ac549c… lmata 74
5ac549c… lmata 75 data, _ := io.ReadAll(resp.Body)
5ac549c… lmata 76 if resp.StatusCode != http.StatusOK {
5ac549c… lmata 77 return nil, fmt.Errorf("ollama models error %d: %s", resp.StatusCode, string(data))
5ac549c… lmata 78 }
5ac549c… lmata 79
5ac549c… lmata 80 var result struct {
5ac549c… lmata 81 Models []struct {
5ac549c… lmata 82 Name string `json:"name"`
5ac549c… lmata 83 } `json:"models"`
5ac549c… lmata 84 }
5ac549c… lmata 85 if err := json.Unmarshal(data, &result); err != nil {
5ac549c… lmata 86 return nil, fmt.Errorf("ollama models parse: %w", err)
5ac549c… lmata 87 }
5ac549c… lmata 88
5ac549c… lmata 89 models := make([]ModelInfo, len(result.Models))
5ac549c… lmata 90 for i, m := range result.Models {
5ac549c… lmata 91 models[i] = ModelInfo{ID: m.Name, Name: m.Name}
5ac549c… lmata 92 }
5ac549c… lmata 93 return models, nil
5ac549c… lmata 94 }

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button