refactor(v2/ollama): drop openaicompat shim, use native provider
The Ollama provider now targets /api/chat directly via the native provider introduced in the previous commits. Public API is unchanged for callers that go through llm.Ollama() (and is extended by Task 5's OllamaCloud() constructor). DefaultBaseURL was renamed to DefaultLocalBaseURL (without the trailing /v1 segment used by the OpenAI-compat path). registry.go is updated correspondingly; no other callers referenced the old name. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+18
-32
@@ -1,36 +1,22 @@
|
|||||||
// Package ollama implements the go-llm v2 provider interface for Ollama
|
// Package ollama implements the go-llm v2 provider interface for Ollama,
|
||||||
// (https://ollama.com), a local model runner that exposes an OpenAI Chat
|
// targeting Ollama's native /api/chat endpoint. Supports both local Ollama
|
||||||
// Completions-compatible endpoint. No API key is required; capability depends
|
// instances (no API key) and Ollama Cloud (https://ollama.com, requires an
|
||||||
// on whichever model the user has pulled locally, so Rules are intentionally
|
// API key sent as a Bearer token).
|
||||||
// empty — we trust the local user.
|
|
||||||
package ollama
|
package ollama
|
||||||
|
|
||||||
import (
|
// New creates a new Ollama provider over the native /api/chat API. An empty
|
||||||
"gitea.stevedudenhoeffer.com/steve/go-llm/v2/openaicompat"
|
// apiKey means local-mode (no Authorization header is sent). A non-empty
|
||||||
)
|
// apiKey is sent as `Authorization: Bearer <key>` for Ollama Cloud.
|
||||||
|
|
||||||
// DefaultBaseURL points at a local Ollama instance with default port. Kept
|
|
||||||
// for the openaicompat-based shim; callers should migrate to
|
|
||||||
// DefaultLocalBaseURL (no /v1 suffix) which targets the native /api/chat
|
|
||||||
// endpoint.
|
|
||||||
const DefaultBaseURL = "http://localhost:11434/v1"
|
|
||||||
|
|
||||||
// shimNew is the legacy openaicompat-based constructor, retained until the
|
|
||||||
// native provider's Complete/Stream are fully implemented (Task 4 replaces
|
|
||||||
// the public New() with a native-backed constructor).
|
|
||||||
func shimNew(apiKey, baseURL string) *openaicompat.Provider {
|
|
||||||
if baseURL == "" {
|
|
||||||
baseURL = DefaultBaseURL
|
|
||||||
}
|
|
||||||
return openaicompat.New(apiKey, baseURL, openaicompat.Rules{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates a new Ollama provider. An empty baseURL uses DefaultBaseURL.
|
|
||||||
// Ollama ignores the API key; callers may pass "".
|
|
||||||
//
|
//
|
||||||
// Note: this constructor currently still routes through the openaicompat
|
// An empty baseURL defaults to DefaultLocalBaseURL when apiKey is empty, or
|
||||||
// shim. Subsequent commits replace the body with a native /api/chat
|
// DefaultCloudBaseURL when apiKey is set.
|
||||||
// implementation backed by the Provider type in native.go.
|
func New(apiKey, baseURL string) *Provider {
|
||||||
func New(apiKey, baseURL string) *openaicompat.Provider {
|
if baseURL == "" {
|
||||||
return shimNew(apiKey, baseURL)
|
if apiKey == "" {
|
||||||
|
baseURL = DefaultLocalBaseURL
|
||||||
|
} else {
|
||||||
|
baseURL = DefaultCloudBaseURL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newNative(apiKey, baseURL)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,35 @@
|
|||||||
package ollama_test
|
package ollama
|
||||||
|
|
||||||
import (
|
import "testing"
|
||||||
"testing"
|
|
||||||
|
|
||||||
"gitea.stevedudenhoeffer.com/steve/go-llm/v2/ollama"
|
func TestNew(t *testing.T) {
|
||||||
)
|
t.Run("local mode picks default local URL", func(t *testing.T) {
|
||||||
|
p := New("", "")
|
||||||
func TestNew_NoKeyNeeded(t *testing.T) {
|
if p == nil {
|
||||||
if p := ollama.New("", ""); p == nil {
|
|
||||||
t.Fatal("New returned nil")
|
t.Fatal("New returned nil")
|
||||||
}
|
}
|
||||||
|
if p.baseURL != DefaultLocalBaseURL {
|
||||||
|
t.Errorf("baseURL: want %q, got %q", DefaultLocalBaseURL, p.baseURL)
|
||||||
|
}
|
||||||
|
if p.apiKey != "" {
|
||||||
|
t.Errorf("apiKey: want empty, got %q", p.apiKey)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("cloud mode (apiKey set) picks cloud URL", func(t *testing.T) {
|
||||||
|
p := New("test-key", "")
|
||||||
|
if p.baseURL != DefaultCloudBaseURL {
|
||||||
|
t.Errorf("baseURL: want %q, got %q", DefaultCloudBaseURL, p.baseURL)
|
||||||
|
}
|
||||||
|
if p.apiKey != "test-key" {
|
||||||
|
t.Errorf("apiKey: want %q, got %q", "test-key", p.apiKey)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("explicit baseURL is preserved", func(t *testing.T) {
|
||||||
|
p := New("k", "http://example.test:9999")
|
||||||
|
if p.baseURL != "http://example.test:9999" {
|
||||||
|
t.Errorf("baseURL not preserved, got %q", p.baseURL)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -129,7 +129,7 @@ var providerRegistry = []ProviderInfo{
|
|||||||
Name: "ollama",
|
Name: "ollama",
|
||||||
DisplayName: "Ollama (local)",
|
DisplayName: "Ollama (local)",
|
||||||
EnvKey: "", // no key needed
|
EnvKey: "", // no key needed
|
||||||
DefaultURL: ollama.DefaultBaseURL,
|
DefaultURL: ollama.DefaultLocalBaseURL,
|
||||||
Models: []string{
|
Models: []string{
|
||||||
"llama3.2", "llama3.1", "qwen2.5", "mistral", "gemma2", "phi4",
|
"llama3.2", "llama3.1", "qwen2.5", "mistral", "gemma2", "phi4",
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user