Some checks failed
release-tag / Resolve release metadata (push) Successful in 30s
release-tag / Build knowledge (push) Failing after 4m51s
release-tag / Build control (push) Failing after 5m0s
release-tag / Build agent (push) Failing after 5m0s
release-tag / Build agent-data-init (push) Failing after 5m5s
release-tag / Build neuroforge-worker (push) Failing after 5m7s
release-tag / Build neuroforge (push) Failing after 5m9s
114 lines
3.0 KiB
Go
114 lines
3.0 KiB
Go
package provider
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"neuroforge/internal/core"
|
|
"neuroforge/internal/store"
|
|
)
|
|
|
|
func TestRouterHasNoGlobalInferenceTimeout(t *testing.T) {
|
|
s, err := store.New(t.TempDir())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer s.Close()
|
|
r := NewRouter(s)
|
|
if r.http.Timeout != 0 {
|
|
t.Fatalf("global http client timeout=%v, want 0", r.http.Timeout)
|
|
}
|
|
tr, ok := r.http.Transport.(*http.Transport)
|
|
if !ok {
|
|
t.Fatalf("transport type %T", r.http.Transport)
|
|
}
|
|
if tr.ResponseHeaderTimeout != 0 {
|
|
t.Fatalf("response header timeout=%v, want 0 for long non-streaming inference", tr.ResponseHeaderTimeout)
|
|
}
|
|
}
|
|
|
|
func TestOllamaRuntimeOptionsAreSent(t *testing.T) {
|
|
var got map[string]any
|
|
fake := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/api/chat" {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&got); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_ = json.NewEncoder(w).Encode(map[string]any{
|
|
"message": map[string]any{"content": "ok"},
|
|
"prompt_eval_count": 4,
|
|
"eval_count": 3,
|
|
})
|
|
}))
|
|
defer fake.Close()
|
|
|
|
s, err := store.New(t.TempDir())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer s.Close()
|
|
cfg := s.Config()
|
|
cfg.Routing.ChatProvider = "ollama"
|
|
cfg.Routing.ChatNodeID = "local"
|
|
cfg.Ollama = []core.OllamaServer{{
|
|
ID: "local", Name: "Local", BaseURL: fake.URL, ChatModel: "qwen-test", EmbeddingModel: "embed-test",
|
|
Weight: 1, Enabled: true, RequestTimeoutSeconds: 0, NumCtx: 8192, NumPredict: 512,
|
|
Think: "low", ChatKeepAlive: "30m", EmbeddingKeepAlive: "5m",
|
|
}}
|
|
if err := s.UpdateConfig(cfg); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
r := NewRouter(s)
|
|
if _, err := r.Chat(context.Background(), "ollama", "", "", "hello", 1400); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got["keep_alive"] != "30m" || got["think"] != "low" {
|
|
t.Fatalf("runtime body=%#v", got)
|
|
}
|
|
opts, ok := got["options"].(map[string]any)
|
|
if !ok {
|
|
t.Fatalf("options missing: %#v", got)
|
|
}
|
|
if opts["num_ctx"] != float64(8192) || opts["num_predict"] != float64(512) {
|
|
t.Fatalf("options=%#v", opts)
|
|
}
|
|
}
|
|
|
|
func TestOllamaExplicitRequestTimeoutStillWorks(t *testing.T) {
|
|
fake := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
time.Sleep(1200 * time.Millisecond)
|
|
_ = json.NewEncoder(w).Encode(map[string]any{"message": map[string]any{"content": "late"}})
|
|
}))
|
|
defer fake.Close()
|
|
|
|
s, err := store.New(t.TempDir())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer s.Close()
|
|
cfg := s.Config()
|
|
cfg.Ollama[0].BaseURL = fake.URL
|
|
cfg.Ollama[0].RequestTimeoutSeconds = 1
|
|
if err := s.UpdateConfig(cfg); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
r := NewRouter(s)
|
|
start := time.Now()
|
|
_, err = r.ChatOn(context.Background(), "ollama", "", "local", "", "hello", 32)
|
|
if err == nil {
|
|
t.Fatal("expected configured timeout")
|
|
}
|
|
if time.Since(start) > 2*time.Second {
|
|
t.Fatalf("configured timeout was not enforced promptly: %v", time.Since(start))
|
|
}
|
|
}
|