feat(ui): wire LLM-as-a-Judge into add guardrail form

This commit is contained in:
Ishaan Jaffer 2026-04-23 15:18:26 -07:00
parent 703e9e9130
commit e6ee14a249
No known key found for this signature in database
2 changed files with 52 additions and 4 deletions

View file

@ -1,7 +1,7 @@
import { Form, Input, Modal, Select, Tag, Typography, Button } from "antd";
import React, { useEffect, useMemo, useState } from "react";
import NotificationsManager from "../molecules/notifications_manager";
import { createGuardrailCall, getGuardrailProviderSpecificParams, getGuardrailUISettings } from "../networking";
import { createGuardrailCall, getGuardrailProviderSpecificParams, getGuardrailUISettings, modelAvailableCall } from "../networking";
import ContentFilterConfiguration from "./content_filter/ContentFilterConfiguration";
import {
choiceToSkipSystemForCreate,
@ -11,10 +11,12 @@ import {
populateGuardrailProviderMap,
populateGuardrailProviders,
shouldRenderContentFilterConfigSettings,
shouldRenderLLMJudgeFields,
shouldRenderPIIConfigSettings,
} from "./guardrail_info_helpers";
import GuardrailOptionalParams from "./guardrail_optional_params";
import GuardrailProviderFields from "./guardrail_provider_fields";
import LLMJudgeFields from "./llm_judge/LLMJudgeFields";
import PiiConfiguration from "./pii_configuration";
import ToolPermissionRulesEditor, { ToolPermissionConfig } from "./tool_permission/ToolPermissionRulesEditor";
@ -126,6 +128,7 @@ const AddGuardrailForm: React.FC<AddGuardrailFormProps> = ({ visible, onClose, a
const [onViolation, setOnViolation] = useState<"warn" | "end_session">("warn");
const [realtimeViolationMessage, setRealtimeViolationMessage] = useState<string>("");
const [endpointSettingsOpen, setEndpointSettingsOpen] = useState<boolean>(false);
const [availableModels, setAvailableModels] = useState<string[]>([]);
const [toolPermissionConfig, setToolPermissionConfig] = useState<ToolPermissionConfig>({
rules: [],
@ -149,13 +152,17 @@ const AddGuardrailForm: React.FC<AddGuardrailFormProps> = ({ visible, onClose, a
const fetchData = async () => {
try {
// Parallel requests for speed
const [uiSettings, providerParamsResp] = await Promise.all([
const [uiSettings, providerParamsResp, modelsResp] = await Promise.all([
getGuardrailUISettings(accessToken),
getGuardrailProviderSpecificParams(accessToken),
modelAvailableCall(accessToken, "", "").catch(() => null),
]);
setGuardrailSettings(uiSettings);
setProviderParams(providerParamsResp);
if (modelsResp?.data) {
setAvailableModels(modelsResp.data.map((m: any) => m.id));
}
// Populate dynamic providers from API response
populateGuardrailProviders(providerParamsResp);
@ -242,6 +249,11 @@ const AddGuardrailForm: React.FC<AddGuardrailFormProps> = ({ visible, onClose, a
on_disallowed_action: "block",
violation_message_template: "",
});
// Default LLM-as-a-Judge to post_call mode
if (value === "LlmAsAJudge") {
form.setFieldsValue({ mode: "post_call" });
}
};
const handleEntitySelect = (entity: string) => {
@ -510,6 +522,29 @@ const AddGuardrailForm: React.FC<AddGuardrailFormProps> = ({ visible, onClose, a
}
}
if (guardrailProvider === "llm_as_a_judge") {
const criteria: any[] = values.criteria || [];
if (criteria.length === 0) {
NotificationsManager.fromBackend("Add at least one evaluation criterion");
setLoading(false);
return;
}
const weightTotal = criteria.reduce((sum: number, c: any) => sum + (Number(c?.weight) || 0), 0);
if (weightTotal !== 100) {
NotificationsManager.fromBackend(`Criterion weights must sum to 100% (currently ${weightTotal}%)`);
setLoading(false);
return;
}
guardrailData.litellm_params.judge_model = values.judge_model;
guardrailData.litellm_params.overall_threshold = values.overall_threshold ?? 80;
guardrailData.litellm_params.on_failure = values.on_failure ?? "block";
guardrailData.litellm_params.criteria = criteria.map((c: any) => ({
name: c.name,
weight: Number(c.weight),
description: c.description || "",
}));
}
if (guardrailProvider === "tool_permission") {
if (toolPermissionConfig.rules.length === 0) {
NotificationsManager.fromBackend("Add at least one tool permission rule");
@ -549,7 +584,8 @@ const AddGuardrailForm: React.FC<AddGuardrailFormProps> = ({ visible, onClose, a
console.log("values: ", JSON.stringify(values));
// Use pre-fetched provider params to copy recognised params
if (providerParams && selectedProvider) {
// Skip for providers that handle their own litellm_params (llm_as_a_judge, tool_permission, content filter, PII)
if (providerParams && selectedProvider && guardrailProvider !== "llm_as_a_judge") {
const providerKey = guardrail_provider_map[selectedProvider]?.toLowerCase();
console.log("providerKey: ", providerKey);
const providerSpecificParams = providerParams[providerKey] || {};
@ -768,8 +804,13 @@ const AddGuardrailForm: React.FC<AddGuardrailFormProps> = ({ visible, onClose, a
</Select>
</Form.Item>
{/* LLM-as-a-Judge: dedicated criteria builder */}
{shouldRenderLLMJudgeFields(selectedProvider) && (
<LLMJudgeFields availableModels={availableModels} form={form} />
)}
{/* Use the GuardrailProviderFields component to render provider-specific fields */}
{!isToolPermissionProvider && !shouldRenderContentFilterConfigSettings(selectedProvider) && (
{!isToolPermissionProvider && !shouldRenderContentFilterConfigSettings(selectedProvider) && !shouldRenderLLMJudgeFields(selectedProvider) && (
<GuardrailProviderFields
selectedProvider={selectedProvider}
accessToken={accessToken}

View file

@ -16,6 +16,7 @@ export const populateGuardrailProviders = (providerParamsResponse: Record<string
providers.PresidioPII = "Presidio PII";
providers.Bedrock = "Bedrock Guardrail";
providers.Lakera = "Lakera";
providers.LlmAsAJudge = "LLM as a Judge";
// Add dynamic providers from API response
Object.entries(providerParamsResponse).forEach(([key, value]) => {
@ -49,6 +50,7 @@ export const guardrail_provider_map: Record<string, string> = {
ToolPermission: "tool_permission",
BlockCodeExecution: "block_code_execution",
Promptguard: "promptguard",
LlmAsAJudge: "llm_as_a_judge",
};
// Function to populate provider map from API response - updates the original map
@ -103,6 +105,11 @@ export const shouldRenderContentFilterConfigSettings = (provider: string | null)
return providerEnum === "LiteLLM Content Filter";
};
export const shouldRenderLLMJudgeFields = (provider: string | null) => {
if (!provider) return false;
return guardrail_provider_map[provider] === "llm_as_a_judge";
};
const asset_logos_folder = "../ui/assets/logos/";
export const guardrailLogoMap: Record<string, string> = {