feat(ui): require embedding model for semantic auto router (#33313)

Co-authored-by: shivam <shivam@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
devin-ai-integration[bot] 2026-07-16 15:13:38 -07:00 committed by GitHub
parent 111d447e1b
commit 5961c173e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 113 additions and 23 deletions

View file

@ -21,6 +21,7 @@ import {
getSemanticConfigError,
} from "./build_complexity_router_config";
import { buildAutoRouterTestTargets, AutoRouterTestTarget } from "./build_auto_router_test_targets";
import { getSemanticRouterError } from "./build_semantic_router_validation";
import AutoRouterConnectionTest from "./auto_router_connection_test";
import NotificationManager from "../molecules/notifications_manager";
@ -164,23 +165,13 @@ const AddAutoRouterTab: React.FC<AddAutoRouterTabProps> = ({ form, handleOk, acc
};
const submitSemanticRouter = (name: string) => {
if (!form.getFieldValue("auto_router_default_model")) {
NotificationManager.fromBackend("Please select a Default Model");
return;
}
if (!routerConfig || !routerConfig.routes || routerConfig.routes.length === 0) {
NotificationManager.fromBackend("Please configure at least one route for the auto router");
return;
}
const invalidRoutes = routerConfig.routes.filter(
(route: any) => !route.name || !route.description || route.utterances.length === 0,
);
if (invalidRoutes.length > 0) {
NotificationManager.fromBackend(
"Please ensure all routes have a target model, description, and at least one utterance",
);
const validationError = getSemanticRouterError({
defaultModel: form.getFieldValue("auto_router_default_model"),
embeddingModel: form.getFieldValue("auto_router_embedding_model"),
routerConfig,
});
if (validationError) {
NotificationManager.fromBackend(validationError);
return;
}
@ -358,18 +349,18 @@ const AddAutoRouterTab: React.FC<AddAutoRouterTabProps> = ({ form, handleOk, acc
</Form.Item>
<Form.Item
rules={[{ required: true, message: "Embedding model is required" }]}
label="Embedding Model"
name="auto_router_embedding_model"
tooltip="Optional: embedding model to use for semantic routing decisions"
tooltip="Embedding model to use for semantic routing decisions"
labelCol={{ span: 10 }}
labelAlign="left"
>
<AntdSelect
placeholder="Select an embedding model (optional)"
placeholder="Select an embedding model"
options={modelGroupOptions}
style={{ width: "100%" }}
showSearch
allowClear
/>
</Form.Item>
</>

View file

@ -0,0 +1,67 @@
import { getSemanticRouterError, SemanticRouterConfig } from "./build_semantic_router_validation";
const validRouterConfig: SemanticRouterConfig = {
routes: [{ name: "gpt-4o", description: "general chat", utterances: ["hello there"] }],
};
describe("getSemanticRouterError", () => {
it("requires an embedding model once the default model and routes are configured", () => {
expect(
getSemanticRouterError({
defaultModel: "gpt-4o",
embeddingModel: undefined,
routerConfig: validRouterConfig,
}),
).toBe("Please select an Embedding Model");
});
it("treats an empty embedding model string as missing", () => {
expect(
getSemanticRouterError({
defaultModel: "gpt-4o",
embeddingModel: "",
routerConfig: validRouterConfig,
}),
).toBe("Please select an Embedding Model");
});
it("passes when an embedding model is selected", () => {
expect(
getSemanticRouterError({
defaultModel: "gpt-4o",
embeddingModel: "text-embedding-3-large",
routerConfig: validRouterConfig,
}),
).toBeNull();
});
it("flags a missing default model before checking the embedding model", () => {
expect(
getSemanticRouterError({
defaultModel: undefined,
embeddingModel: undefined,
routerConfig: validRouterConfig,
}),
).toBe("Please select a Default Model");
});
it("flags missing routes before checking the embedding model", () => {
expect(
getSemanticRouterError({
defaultModel: "gpt-4o",
embeddingModel: undefined,
routerConfig: { routes: [] },
}),
).toBe("Please configure at least one route for the auto router");
});
it("validates route completeness after the embedding model is set", () => {
expect(
getSemanticRouterError({
defaultModel: "gpt-4o",
embeddingModel: "text-embedding-3-large",
routerConfig: { routes: [{ name: "gpt-4o", description: "", utterances: [] }] },
}),
).toBe("Please ensure all routes have a target model, description, and at least one utterance");
});
});

View file

@ -0,0 +1,29 @@
export interface SemanticRouterRoute {
name?: string;
description?: string;
utterances?: unknown[];
}
export interface SemanticRouterConfig {
routes?: SemanticRouterRoute[];
}
export interface SemanticRouterValidationParams {
defaultModel: string | undefined;
embeddingModel: string | undefined;
routerConfig: SemanticRouterConfig | null | undefined;
}
export const getSemanticRouterError = ({
defaultModel,
embeddingModel,
routerConfig,
}: SemanticRouterValidationParams): string | null => {
if (!defaultModel) return "Please select a Default Model";
if (!routerConfig?.routes || routerConfig.routes.length === 0)
return "Please configure at least one route for the auto router";
if (!embeddingModel) return "Please select an Embedding Model";
if (routerConfig.routes.some((route) => !route.name || !route.description || (route.utterances?.length ?? 0) === 0))
return "Please ensure all routes have a target model, description, and at least one utterance";
return null;
};

View file

@ -367,15 +367,18 @@ const EditAutoRouterModal: React.FC<EditAutoRouterModalProps> = ({
</Form.Item>
{/* Embedding Model */}
<Form.Item label="Embedding Model" name="auto_router_embedding_model">
<Form.Item
label="Embedding Model"
name="auto_router_embedding_model"
rules={[{ required: true, message: "Embedding model is required" }]}
>
<AntdSelect
placeholder="Select an embedding model (optional)"
placeholder="Select an embedding model"
onChange={(value) => {
setShowCustomEmbeddingModel(value === "custom");
}}
options={[...modelOptions, { value: "custom", label: "Enter custom model name" }]}
showSearch={true}
allowClear
/>
</Form.Item>
</>