-
Notifications
You must be signed in to change notification settings - Fork 276
Make embedding server optional for vMCP optimizer #6106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -93,8 +93,10 @@ | |
| TelemetryConfigRef *MCPTelemetryConfigReference `json:"telemetryConfigRef,omitempty"` | ||
|
|
||
| // EmbeddingServerRef references an existing EmbeddingServer resource by name. | ||
| // When the optimizer is enabled, this field is required to point to a ready EmbeddingServer | ||
| // that provides embedding capabilities. | ||
| // It is optional even when the optimizer is enabled: without it (and without | ||
| // spec.config.optimizer.embeddingService), find_tool falls back to FTS5 | ||
| // keyword-only search with no semantic ranking. Set this field to point to a | ||
| // ready EmbeddingServer when semantic ranking is desired. | ||
| // The referenced EmbeddingServer must exist in the same namespace and be ready. | ||
| // +optional | ||
| EmbeddingServerRef *EmbeddingServerRef `json:"embeddingServerRef,omitempty"` | ||
|
|
@@ -598,8 +600,9 @@ | |
|
|
||
| // validateEmbeddingServer validates EmbeddingServerRef and Optimizer configuration. | ||
| // Rules: | ||
| // - embeddingServerRef.name must be non-empty when ref is provided | ||
| // - optimizer requires either embeddingServerRef or a manually set embeddingService | ||
| // - optimizer does not require an embedding source: with neither embeddingServerRef | ||
| // nor optimizer.embeddingService set, find_tool runs FTS5 keyword-only search | ||
| // - if embeddingServerRef is set without optimizer, auto-populate optimizer with defaults | ||
| // | ||
| // The controller handles the remaining cases at runtime (event emission, URL population). | ||
|
|
@@ -611,15 +614,6 @@ | |
|
|
||
| hasOptimizer := r.Spec.Config.Optimizer != nil | ||
| hasRef := r.Spec.EmbeddingServerRef != nil | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Worth thinking about what happens to With no embedding source those two fields stop meaning anything, so I agree there's no reason to reject the spec over them. What we should do is tell the user they're inert, so nobody sets One wrinkle to sort out first: today they aren't actually ignored. config:
optimizer:
embeddingProvider: openai
embeddingModel: text-embedding-3-small
# no embeddingService, no embeddingServerRefThe CEL rule at line 22 of this file doesn't catch it, since that one only blocks So "these fields are ignored" needs to become true before we can warn that it's true. That means short-circuiting on the absence of an embedding source before the provider switch: func resolveEmbeddingProvider(optCfg *Config) error {
if optCfg.EmbeddingService == "" {
// No embedding source: semantic search is disabled entirely, so the
// provider and model are inert. Skip provider validation rather than
// failing startup over fields that will never be read.
return nil
}
...
}With that in place the behavior matches the mental model (no embedding source means keyword-only, full stop, regardless of provider) and the warning is honest. Pair it with a line alongside the keyword-only event in the controller: if config.Optimizer.EmbeddingProvider != "" || config.Optimizer.EmbeddingModel != "" {
ctxLogger.Info("optimizer.embeddingProvider and optimizer.embeddingModel are ignored "+
"when no embedding source is configured; set embeddingServerRef or "+
"optimizer.embeddingService to enable semantic ranking",
"embeddingProvider", config.Optimizer.EmbeddingProvider,
"embeddingModel", config.Optimizer.EmbeddingModel)
}Note |
||
| hasManualService := hasOptimizer && r.Spec.Config.Optimizer.EmbeddingService != "" | ||
|
|
||
| // Optimizer configured without any embedding source is an error. | ||
| // The user must either set embeddingServerRef or manually set optimizer.embeddingService. | ||
| if hasOptimizer && !hasRef && !hasManualService { | ||
| return fmt.Errorf( | ||
| "spec.config.optimizer requires an embedding service: " + | ||
| "set spec.embeddingServerRef (recommended) or spec.config.optimizer.embeddingService") | ||
| } | ||
|
|
||
| // EmbeddingServerRef is set but optimizer is not configured: auto-populate | ||
| // optimizer with default values so the embedding server is actually used. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -422,7 +422,7 @@ func TestValidateEmbeddingServer(t *testing.T) { | |
| expectOptimizer: true, | ||
| }, | ||
| { | ||
| name: "optimizer_without_ref_or_service_errors", | ||
| name: "optimizer_without_ref_or_service_succeeds_keyword_only", | ||
| server: &VirtualMCPServer{ | ||
| Spec: VirtualMCPServerSpec{ | ||
| GroupRef: &MCPGroupRef{Name: "test-group"}, | ||
|
|
@@ -431,8 +431,7 @@ func TestValidateEmbeddingServer(t *testing.T) { | |
| }, | ||
| }, | ||
| }, | ||
| expectError: true, | ||
| errContains: "spec.config.optimizer requires an embedding service", | ||
| expectOptimizer: true, | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This asserts the check is gone, which is right, but nothing yet asserts the newly-legal config produces a working deployment. The keyword-only search path is well covered at the store layer (
Items 1 and 2 feel like they belong in this PR. 3 and 4 could be follow-ups, though 4 should land with whatever change introduces it. |
||
| }, | ||
| { | ||
| name: "empty_ref_name_errors", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gofmt rejects this. Go 1.19+ gofmt reformats doc comments, and a column-0
// -bullet with an indented continuation line isn't recognized as a list, so it gets rewritten to the canonical// -form:gofmt -lflags the file as it stands, so linting will fail.task lint-fixsorts it.