agent build
This commit is contained in:
102
go-api/internal/runtime/embedder_test.go
Normal file
102
go-api/internal/runtime/embedder_test.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package runtime_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/krow/krow-backend/go-api/internal/config"
|
||||
"github.com/krow/krow-backend/go-api/internal/runtime"
|
||||
)
|
||||
|
||||
// Which embedder a deployment actually gets.
|
||||
//
|
||||
// The reason this is worth testing at all: all three providers return vectors,
|
||||
// and retrieval works with any of them. A deployment running the stand-in looks
|
||||
// exactly like one running a real model — same shape of result, same citations,
|
||||
// same confidence — until somebody phrases a question differently. There is no
|
||||
// symptom to notice, so the choice has to be asserted rather than observed.
|
||||
|
||||
func embedderFor(k config.KnowledgeConfig, env string) string {
|
||||
e := runtime.NewEmbedder(config.Config{AppEnv: env, Knowledge: k})
|
||||
if e == nil {
|
||||
return "none"
|
||||
}
|
||||
return e.Model()
|
||||
}
|
||||
|
||||
func TestTheNamedProviderWins(t *testing.T) {
|
||||
// Explicit beats inferred. A deployment that names ollama gets ollama even
|
||||
// with a Voyage key sitting in the environment — otherwise a leftover
|
||||
// credential silently decides where tenant text goes.
|
||||
got := embedderFor(config.KnowledgeConfig{
|
||||
EmbedProvider: "ollama",
|
||||
EmbedAPIKey: "pa-a-real-looking-key",
|
||||
}, "development")
|
||||
if !strings.HasPrefix(got, "ollama/") {
|
||||
t.Errorf("named ollama and got %q; a stray credential overrode an explicit choice", got)
|
||||
}
|
||||
|
||||
got = embedderFor(config.KnowledgeConfig{
|
||||
EmbedProvider: "voyage",
|
||||
EmbedAPIKey: "pa-key",
|
||||
EmbedBaseURL: "http://localhost:11434",
|
||||
}, "development")
|
||||
if strings.HasPrefix(got, "ollama/") {
|
||||
t.Errorf("named voyage and got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithNothingConfiguredThereIsNoEmbedder(t *testing.T) {
|
||||
// Nil, not a hosted client with an empty key. Both end up keyword-only, but
|
||||
// nil says so once at wiring time instead of failing one HTTP call per
|
||||
// query to learn the same thing.
|
||||
if got := embedderFor(config.KnowledgeConfig{}, "development"); got != "none" {
|
||||
t.Errorf("an unconfigured deployment got %q, want no embedder", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamingVoyageWithoutAKeyIsNotAnEmbedder(t *testing.T) {
|
||||
// Named but unusable. Degrading honestly beats failing a request per query
|
||||
// on a credential nobody set.
|
||||
if got := embedderFor(config.KnowledgeConfig{EmbedProvider: "voyage"}, "development"); got != "none" {
|
||||
t.Errorf("voyage with no key produced %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInferencePrefersTheLocalModel(t *testing.T) {
|
||||
// With nothing named, a configured local model wins over a hosted one: it
|
||||
// costs nothing and keeps tenant text on the host, and both are real
|
||||
// semantic embedders.
|
||||
got := embedderFor(config.KnowledgeConfig{
|
||||
EmbedBaseURL: "http://localhost:11434",
|
||||
EmbedAPIKey: "pa-key",
|
||||
}, "development")
|
||||
if !strings.HasPrefix(got, "ollama/") {
|
||||
t.Errorf("inferred %q; a local model should win when both are available", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTheStandInRefusesToRunInProduction(t *testing.T) {
|
||||
// It is not semantic. A production corpus indexed with it retrieves on word
|
||||
// overlap alone — which looks like working retrieval and is not, which is
|
||||
// exactly why the refusal is in the code and not in a comment.
|
||||
e := runtime.NewEmbedder(config.Config{
|
||||
AppEnv: "production",
|
||||
Knowledge: config.KnowledgeConfig{EmbedProvider: "lexical"},
|
||||
})
|
||||
if e == nil {
|
||||
t.Fatal("expected the stand-in, refusing at use rather than at wiring")
|
||||
}
|
||||
if _, err := e.Embed(t.Context(), []string{"x"}, "document"); err == nil {
|
||||
t.Error("the stand-in embedded text in production")
|
||||
}
|
||||
|
||||
// And in development it works, because that is what it is for.
|
||||
dev := runtime.NewEmbedder(config.Config{
|
||||
AppEnv: "development",
|
||||
Knowledge: config.KnowledgeConfig{EmbedProvider: "lexical"},
|
||||
})
|
||||
if _, err := dev.Embed(t.Context(), []string{"x"}, "document"); err != nil {
|
||||
t.Errorf("the stand-in refused in development: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user