diff --git a/ui/litellm-dashboard/src/components/guardrails.tsx b/ui/litellm-dashboard/src/components/guardrails.tsx index d0031b872f..a8de7dd2f4 100644 --- a/ui/litellm-dashboard/src/components/guardrails.tsx +++ b/ui/litellm-dashboard/src/components/guardrails.tsx @@ -13,6 +13,7 @@ import { Guardrail, GuardrailDefinitionLocation } from "./guardrails/types"; import DeleteResourceModal from "./common_components/DeleteResourceModal"; import { getGuardrailLogoAndName } from "./guardrails/guardrail_info_helpers"; import { CustomCodeModal } from "./guardrails/custom_code"; +import GuardrailGarden from "./guardrails/guardrail_garden"; interface GuardrailsPanelProps { accessToken: string | null; @@ -106,12 +107,11 @@ const GuardrailsPanel: React.FC = ({ accessToken, userRole const handleDeleteConfirm = async () => { if (!guardrailToDelete || !accessToken) return; - // Log removed to maintain clean production code setIsDeleting(true); try { await deleteGuardrailCall(accessToken, guardrailToDelete.guardrail_id); NotificationsManager.success(`Guardrail "${guardrailToDelete.guardrail_name}" deleted successfully`); - await fetchGuardrails(); // Refresh the list + await fetchGuardrails(); } catch (error) { console.error("Error deleting guardrail:", error); NotificationsManager.fromBackend("Failed to delete guardrail"); @@ -136,11 +136,21 @@ const GuardrailsPanel: React.FC = ({ accessToken, userRole
+ Guardrail Garden Guardrails Test Playground + {/* Guardrail Garden Tab */} + + + + + {/* Existing Guardrails Tab */}
= ({ accessToken, userRole /> + {/* Test Playground Tab */} void; accessToken: string | null; onSuccess: () => void; + preset?: GuardrailPreset; } interface GuardrailSettings { @@ -90,7 +99,7 @@ interface ProviderParamsResponse { [provider: string]: { [key: string]: ProviderParam }; } -const AddGuardrailForm: React.FC = ({ visible, onClose, accessToken, onSuccess }) => { +const AddGuardrailForm: React.FC = ({ visible, onClose, accessToken, onSuccess, preset }) => { const [form] = Form.useForm(); const [loading, setLoading] = useState(false); const [selectedProvider, setSelectedProvider] = useState(null); @@ -154,6 +163,36 @@ const AddGuardrailForm: React.FC = ({ visible, onClose, a fetchData(); }, [accessToken]); + // Apply preset when settings are loaded and form becomes visible + useEffect(() => { + if (!preset || !visible || !guardrailSettings) return; + + // Set provider + setSelectedProvider(preset.provider); + form.setFieldsValue({ + provider: preset.provider, + guardrail_name: preset.guardrailNameSuggestion, + mode: preset.mode, + default_on: preset.defaultOn, + }); + + // Pre-select content category if specified + if (preset.categoryName && guardrailSettings.content_filter_settings?.content_categories) { + const category = guardrailSettings.content_filter_settings.content_categories.find( + (c: any) => c.name === preset.categoryName + ); + if (category) { + setSelectedContentCategories([{ + id: `category-${Date.now()}`, + category: category.name, + display_name: category.display_name, + action: category.default_action as "BLOCK" | "MASK", + severity_threshold: "medium", + }]); + } + } + }, [preset, visible, guardrailSettings]); + const handleProviderChange = (value: string) => { setSelectedProvider(value); // Reset form fields that are provider-specific diff --git a/ui/litellm-dashboard/src/components/guardrails/guardrail_garden.tsx b/ui/litellm-dashboard/src/components/guardrails/guardrail_garden.tsx new file mode 100644 index 0000000000..703a6ad3e4 --- /dev/null +++ b/ui/litellm-dashboard/src/components/guardrails/guardrail_garden.tsx @@ -0,0 +1,110 @@ +import React, { useState } from "react"; +import { Input } from "antd"; +import { SearchOutlined, ArrowRightOutlined } from "@ant-design/icons"; +import { GuardrailCardInfo, LITELLM_CONTENT_FILTER_CARDS, PARTNER_GUARDRAIL_CARDS, ALL_CARDS } from "./guardrail_garden_data"; +import GuardrailCard from "./guardrail_garden_card"; +import GuardrailDetailView from "./guardrail_garden_detail"; + +interface GuardrailGardenProps { + accessToken: string | null; + onGuardrailCreated: () => void; +} + +const GuardrailGarden: React.FC = ({ accessToken, onGuardrailCreated }) => { + const [searchQuery, setSearchQuery] = useState(""); + const [selectedCard, setSelectedCard] = useState(null); + const [showAllLitellm, setShowAllLitellm] = useState(false); + const CARDS_PER_ROW = 5; + const VISIBLE_ROWS = 2; + + const filteredCards = ALL_CARDS.filter((card) => { + if (!searchQuery) return true; + const q = searchQuery.toLowerCase(); + return ( + card.name.toLowerCase().includes(q) || + card.description.toLowerCase().includes(q) || + card.tags.some((t) => t.toLowerCase().includes(q)) + ); + }); + + const litellmCards = filteredCards.filter((c) => c.category === "litellm"); + const partnerCards = filteredCards.filter((c) => c.category === "partner"); + + if (selectedCard) { + return ( + setSelectedCard(null)} + accessToken={accessToken} + onGuardrailCreated={onGuardrailCreated} + /> + ); + } + + return ( +
+ {/* Search Bar */} +
+ } + value={searchQuery} + onChange={(e) => setSearchQuery(e.target.value)} + style={{ borderRadius: 8 }} + /> +
+ + {/* LiteLLM Content Filter Section */} +
+
+

LiteLLM Content Filter

+ setShowAllLitellm(!showAllLitellm)} + > + {showAllLitellm ? ( + <>Show less + ) : ( + <> + + {`Show all (${litellmCards.length})`} + + )} + +
+

+ Built-in guardrails powered by LiteLLM. Zero latency, no external dependencies, no additional cost. +

+
+ {(showAllLitellm ? litellmCards : litellmCards.slice(0, CARDS_PER_ROW * VISIBLE_ROWS)).map((card) => ( + setSelectedCard(card)} /> + ))} +
+
+ + {/* Partner Guardrails Section */} +
+

Partner Guardrails

+

+ Third-party guardrail integrations from leading AI security providers. +

+
+ {partnerCards.map((card) => ( + setSelectedCard(card)} /> + ))} +
+
+
+ ); +}; + +export default GuardrailGarden; diff --git a/ui/litellm-dashboard/src/components/guardrails/guardrail_garden_card.tsx b/ui/litellm-dashboard/src/components/guardrails/guardrail_garden_card.tsx new file mode 100644 index 0000000000..dd142a96d8 --- /dev/null +++ b/ui/litellm-dashboard/src/components/guardrails/guardrail_garden_card.tsx @@ -0,0 +1,58 @@ +import React, { useState } from "react"; +import { CheckCircleFilled } from "@ant-design/icons"; +import { GuardrailCardInfo } from "./guardrail_garden_data"; + +const GuardrailCard: React.FC<{ card: GuardrailCardInfo; onClick: () => void }> = ({ card, onClick }) => { + const [hovered, setHovered] = useState(false); + + return ( +
setHovered(true)} + onMouseLeave={() => setHovered(false)} + style={{ + borderRadius: 12, + border: hovered ? "1px solid #93c5fd" : "1px solid #e5e7eb", + backgroundColor: "#ffffff", + padding: "20px 20px 16px 20px", + cursor: "pointer", + transition: "border-color 0.15s, box-shadow 0.15s", + display: "flex", + flexDirection: "column", + minHeight: 170, + boxShadow: hovered ? "0 1px 6px rgba(59,130,246,0.08)" : "none", + }} + > + {/* Icon + Name row */} +
+ { (e.target as HTMLImageElement).style.display = "none"; }} + /> + {card.name} +
+ + {/* Description */} +

+ {card.description} +

+ + {/* Eval badge */} + {card.eval && ( +
+ + + F1: {card.eval.f1}% · {card.eval.testCases} test cases + +
+ )} +
+ ); +}; + +export default GuardrailCard; diff --git a/ui/litellm-dashboard/src/components/guardrails/guardrail_garden_configs.ts b/ui/litellm-dashboard/src/components/guardrails/guardrail_garden_configs.ts new file mode 100644 index 0000000000..a6a142bdc3 --- /dev/null +++ b/ui/litellm-dashboard/src/components/guardrails/guardrail_garden_configs.ts @@ -0,0 +1,255 @@ +export interface GuardrailPreset { + provider: string; + categoryName?: string; + guardrailNameSuggestion: string; + mode: string; + defaultOn: boolean; +} + +export const GUARDRAIL_PRESETS: Record = { + // ── LiteLLM Content Filter: Content Categories ── + cf_denied_financial: { + provider: "LitellmContentFilter", + categoryName: "denied_financial_advice", + guardrailNameSuggestion: "Denied Financial Advice", + mode: "pre_call", + defaultOn: false, + }, + cf_denied_legal: { + provider: "LitellmContentFilter", + categoryName: "denied_legal_advice", + guardrailNameSuggestion: "Denied Legal Advice", + mode: "pre_call", + defaultOn: false, + }, + cf_denied_medical: { + provider: "LitellmContentFilter", + categoryName: "denied_medical_advice", + guardrailNameSuggestion: "Denied Medical Advice", + mode: "pre_call", + defaultOn: false, + }, + cf_denied_insults: { + provider: "LitellmContentFilter", + categoryName: "denied_insults", + guardrailNameSuggestion: "Insults & Personal Attacks", + mode: "pre_call", + defaultOn: false, + }, + cf_harmful_violence: { + provider: "LitellmContentFilter", + categoryName: "harmful_violence", + guardrailNameSuggestion: "Harmful Violence", + mode: "pre_call", + defaultOn: false, + }, + cf_harmful_self_harm: { + provider: "LitellmContentFilter", + categoryName: "harmful_self_harm", + guardrailNameSuggestion: "Harmful Self-Harm", + mode: "pre_call", + defaultOn: false, + }, + cf_harmful_child_safety: { + provider: "LitellmContentFilter", + categoryName: "harmful_child_safety", + guardrailNameSuggestion: "Harmful Child Safety", + mode: "pre_call", + defaultOn: false, + }, + cf_harmful_illegal_weapons: { + provider: "LitellmContentFilter", + categoryName: "harmful_illegal_weapons", + guardrailNameSuggestion: "Harmful Illegal Weapons", + mode: "pre_call", + defaultOn: false, + }, + cf_bias_gender: { + provider: "LitellmContentFilter", + categoryName: "bias_gender", + guardrailNameSuggestion: "Bias: Gender", + mode: "pre_call", + defaultOn: false, + }, + cf_bias_racial: { + provider: "LitellmContentFilter", + categoryName: "bias_racial", + guardrailNameSuggestion: "Bias: Racial", + mode: "pre_call", + defaultOn: false, + }, + cf_bias_religious: { + provider: "LitellmContentFilter", + categoryName: "bias_religious", + guardrailNameSuggestion: "Bias: Religious", + mode: "pre_call", + defaultOn: false, + }, + cf_bias_sexual_orientation: { + provider: "LitellmContentFilter", + categoryName: "bias_sexual_orientation", + guardrailNameSuggestion: "Bias: Sexual Orientation", + mode: "pre_call", + defaultOn: false, + }, + cf_prompt_injection_jailbreak: { + provider: "LitellmContentFilter", + categoryName: "prompt_injection_jailbreak", + guardrailNameSuggestion: "Prompt Injection: Jailbreak", + mode: "pre_call", + defaultOn: false, + }, + cf_prompt_injection_data_exfil: { + provider: "LitellmContentFilter", + categoryName: "prompt_injection_data_exfiltration", + guardrailNameSuggestion: "Prompt Injection: Data Exfiltration", + mode: "pre_call", + defaultOn: false, + }, + cf_prompt_injection_sql: { + provider: "LitellmContentFilter", + categoryName: "prompt_injection_sql", + guardrailNameSuggestion: "Prompt Injection: SQL", + mode: "pre_call", + defaultOn: false, + }, + cf_prompt_injection_malicious_code: { + provider: "LitellmContentFilter", + categoryName: "prompt_injection_malicious_code", + guardrailNameSuggestion: "Prompt Injection: Malicious Code", + mode: "pre_call", + defaultOn: false, + }, + cf_prompt_injection_system_prompt: { + provider: "LitellmContentFilter", + categoryName: "prompt_injection_system_prompt", + guardrailNameSuggestion: "Prompt Injection: System Prompt", + mode: "pre_call", + defaultOn: false, + }, + cf_toxic_abuse: { + provider: "LitellmContentFilter", + categoryName: "harm_toxic_abuse", + guardrailNameSuggestion: "Toxic & Abusive Language", + mode: "pre_call", + defaultOn: false, + }, + + // ── LiteLLM Content Filter: Patterns & Keywords (no category) ── + cf_patterns: { + provider: "LitellmContentFilter", + guardrailNameSuggestion: "Pattern Matching", + mode: "pre_call", + defaultOn: false, + }, + cf_keywords: { + provider: "LitellmContentFilter", + guardrailNameSuggestion: "Keyword Blocking", + mode: "pre_call", + defaultOn: false, + }, + + // ── Partner Guardrails ── + presidio: { + provider: "PresidioPII", + guardrailNameSuggestion: "Presidio PII", + mode: "pre_call", + defaultOn: false, + }, + bedrock: { + provider: "Bedrock", + guardrailNameSuggestion: "Bedrock Guardrail", + mode: "pre_call", + defaultOn: false, + }, + lakera: { + provider: "Lakera", + guardrailNameSuggestion: "Lakera", + mode: "pre_call", + defaultOn: false, + }, + openai_moderation: { + provider: "OpenaiModeration", + guardrailNameSuggestion: "OpenAI Moderation", + mode: "pre_call", + defaultOn: false, + }, + google_model_armor: { + provider: "ModelArmor", + guardrailNameSuggestion: "Google Cloud Model Armor", + mode: "pre_call", + defaultOn: false, + }, + guardrails_ai: { + provider: "GuardrailsAi", + guardrailNameSuggestion: "Guardrails AI", + mode: "pre_call", + defaultOn: false, + }, + zscaler: { + provider: "ZscalerAiGuard", + guardrailNameSuggestion: "Zscaler AI Guard", + mode: "pre_call", + defaultOn: false, + }, + panw: { + provider: "PanwPrismaAirs", + guardrailNameSuggestion: "PANW Prisma AIRS", + mode: "pre_call", + defaultOn: false, + }, + noma: { + provider: "Noma", + guardrailNameSuggestion: "Noma Security", + mode: "pre_call", + defaultOn: false, + }, + aporia: { + provider: "AporiaAi", + guardrailNameSuggestion: "Aporia AI", + mode: "pre_call", + defaultOn: false, + }, + aim: { + provider: "Aim", + guardrailNameSuggestion: "AIM Guardrail", + mode: "pre_call", + defaultOn: false, + }, + prompt_security: { + provider: "PromptSecurity", + guardrailNameSuggestion: "Prompt Security", + mode: "pre_call", + defaultOn: false, + }, + lasso: { + provider: "Lasso", + guardrailNameSuggestion: "Lasso Guardrail", + mode: "pre_call", + defaultOn: false, + }, + pangea: { + provider: "Pangea", + guardrailNameSuggestion: "Pangea Guardrail", + mode: "pre_call", + defaultOn: false, + }, + enkryptai: { + provider: "Enkryptai", + guardrailNameSuggestion: "EnkryptAI", + mode: "pre_call", + defaultOn: false, + }, + javelin: { + provider: "Javelin", + guardrailNameSuggestion: "Javelin Guardrails", + mode: "pre_call", + defaultOn: false, + }, + pillar: { + provider: "Pillar", + guardrailNameSuggestion: "Pillar Guardrail", + mode: "pre_call", + defaultOn: false, + }, +}; diff --git a/ui/litellm-dashboard/src/components/guardrails/guardrail_garden_data.ts b/ui/litellm-dashboard/src/components/guardrails/guardrail_garden_data.ts new file mode 100644 index 0000000000..372d5b259b --- /dev/null +++ b/ui/litellm-dashboard/src/components/guardrails/guardrail_garden_data.ts @@ -0,0 +1,360 @@ +export interface GuardrailCardInfo { + id: string; + name: string; + description: string; + category: "litellm" | "partner"; + subcategory?: string; + logo: string; + tags: string[]; + eval?: { + f1: number; + precision: number; + recall: number; + testCases: number; + latency: string; + }; + providerKey?: string; +} + +const ASSET_PREFIX = "../assets/logos/"; + +export const LITELLM_CONTENT_FILTER_CARDS: GuardrailCardInfo[] = [ + { + id: "cf_denied_financial", + name: "Denied Financial Advice", + description: "Detects requests for personalized financial advice, investment recommendations, or financial planning.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Topic Blocker"], + eval: { + f1: 100.0, + precision: 100.0, + recall: 100.0, + testCases: 207, + latency: "<0.1ms", + }, + }, + { + id: "cf_denied_legal", + name: "Denied Legal Advice", + description: "Detects requests for unauthorized legal advice, case analysis, or legal recommendations.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Topic Blocker"], + }, + { + id: "cf_denied_medical", + name: "Denied Medical Advice", + description: "Detects requests for medical diagnosis, treatment recommendations, or health advice.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Topic Blocker"], + }, + { + id: "cf_harmful_violence", + name: "Harmful Violence", + description: "Detects content related to violence, criminal planning, attacks, and violent threats.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Safety"], + }, + { + id: "cf_harmful_self_harm", + name: "Harmful Self-Harm", + description: "Detects content related to self-harm, suicide, and dangerous self-destructive behavior.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Safety"], + }, + { + id: "cf_harmful_child_safety", + name: "Harmful Child Safety", + description: "Detects content that could endanger child safety or exploit minors.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Safety"], + }, + { + id: "cf_harmful_illegal_weapons", + name: "Harmful Illegal Weapons", + description: "Detects content related to illegal weapons manufacturing, distribution, or acquisition.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Safety"], + }, + { + id: "cf_bias_gender", + name: "Bias: Gender", + description: "Detects gender-based discrimination, stereotypes, and biased language.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Bias"], + }, + { + id: "cf_bias_racial", + name: "Bias: Racial", + description: "Detects racial discrimination, stereotypes, and racially biased content.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Bias"], + }, + { + id: "cf_bias_religious", + name: "Bias: Religious", + description: "Detects religious discrimination, intolerance, and religiously biased content.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Bias"], + }, + { + id: "cf_bias_sexual_orientation", + name: "Bias: Sexual Orientation", + description: "Detects discrimination based on sexual orientation and related biased content.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Bias"], + }, + { + id: "cf_prompt_injection_jailbreak", + name: "Prompt Injection: Jailbreak", + description: "Detects jailbreak attempts designed to bypass AI safety guidelines and restrictions.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Prompt Injection"], + }, + { + id: "cf_prompt_injection_data_exfil", + name: "Prompt Injection: Data Exfiltration", + description: "Detects attempts to extract sensitive data through prompt manipulation.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Prompt Injection"], + }, + { + id: "cf_prompt_injection_sql", + name: "Prompt Injection: SQL", + description: "Detects SQL injection attempts embedded in prompts.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Prompt Injection"], + }, + { + id: "cf_prompt_injection_malicious_code", + name: "Prompt Injection: Malicious Code", + description: "Detects attempts to inject malicious code through prompts.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Prompt Injection"], + }, + { + id: "cf_prompt_injection_system_prompt", + name: "Prompt Injection: System Prompt", + description: "Detects attempts to extract or override system prompts.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Prompt Injection"], + }, + { + id: "cf_denied_insults", + name: "Insults & Personal Attacks", + description: "Detects insults, name-calling, and personal attacks directed at the chatbot, staff, or other people.", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Topic Blocker"], + eval: { + f1: 100.0, + precision: 100.0, + recall: 100.0, + testCases: 299, + latency: "<0.1ms", + }, + }, + { + id: "cf_toxic_abuse", + name: "Toxic & Abusive Language", + description: "Detects toxic, abusive, and hateful language across multiple languages (EN, AU, DE, ES, FR).", + category: "litellm", + subcategory: "Content Category", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Content Category", "Toxicity"], + }, + { + id: "cf_patterns", + name: "Pattern Matching", + description: "Detect and block sensitive data patterns like SSNs, credit card numbers, API keys, and custom regex patterns.", + category: "litellm", + subcategory: "Patterns", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["PII", "Regex", "Data Protection"], + }, + { + id: "cf_keywords", + name: "Keyword Blocking", + description: "Block or mask content containing specific keywords or phrases. Upload custom word lists or add individual terms.", + category: "litellm", + subcategory: "Keywords", + logo: `${ASSET_PREFIX}litellm_logo.jpg`, + tags: ["Keywords", "Blocklist"], + }, +]; + +export const PARTNER_GUARDRAIL_CARDS: GuardrailCardInfo[] = [ + { + id: "presidio", + name: "Presidio PII", + description: "Microsoft Presidio for PII detection and anonymization. Supports 30+ entity types with configurable actions.", + category: "partner", + logo: `${ASSET_PREFIX}presidio.png`, + tags: ["PII", "Microsoft"], + providerKey: "PresidioPII", + }, + { + id: "bedrock", + name: "Bedrock Guardrail", + description: "AWS Bedrock Guardrails for content filtering, topic avoidance, and sensitive information detection.", + category: "partner", + logo: `${ASSET_PREFIX}bedrock.svg`, + tags: ["AWS", "Content Safety"], + providerKey: "Bedrock", + }, + { + id: "lakera", + name: "Lakera", + description: "AI security platform protecting against prompt injections, data leakage, and harmful content.", + category: "partner", + logo: `${ASSET_PREFIX}lakeraai.jpeg`, + tags: ["Security", "Prompt Injection"], + providerKey: "Lakera", + }, + { + id: "openai_moderation", + name: "OpenAI Moderation", + description: "OpenAI's content moderation API for detecting harmful content across multiple categories.", + category: "partner", + logo: `${ASSET_PREFIX}openai_small.svg`, + tags: ["Content Moderation", "OpenAI"], + }, + { + id: "google_model_armor", + name: "Google Cloud Model Armor", + description: "Google Cloud's model protection service for safe and responsible AI deployments.", + category: "partner", + logo: `${ASSET_PREFIX}google.svg`, + tags: ["Google Cloud", "Safety"], + }, + { + id: "guardrails_ai", + name: "Guardrails AI", + description: "Open-source framework for adding structural, type, and quality guarantees to LLM outputs.", + category: "partner", + logo: `${ASSET_PREFIX}guardrails_ai.jpeg`, + tags: ["Open Source", "Validation"], + }, + { + id: "zscaler", + name: "Zscaler AI Guard", + description: "Enterprise AI security from Zscaler for monitoring and protecting AI/ML workloads.", + category: "partner", + logo: `${ASSET_PREFIX}zscaler.svg`, + tags: ["Enterprise", "Security"], + }, + { + id: "panw", + name: "PANW Prisma AIRS", + description: "Palo Alto Networks Prisma AI Runtime Security for securing AI applications in production.", + category: "partner", + logo: `${ASSET_PREFIX}palo_alto_networks.jpeg`, + tags: ["Enterprise", "Security"], + }, + { + id: "noma", + name: "Noma Security", + description: "AI security platform for detecting and preventing AI-specific threats and vulnerabilities.", + category: "partner", + logo: `${ASSET_PREFIX}noma_security.png`, + tags: ["Security", "Threat Detection"], + }, + { + id: "aporia", + name: "Aporia AI", + description: "Real-time AI guardrails for hallucination detection, topic control, and policy enforcement.", + category: "partner", + logo: `${ASSET_PREFIX}aporia.png`, + tags: ["Hallucination", "Policy"], + }, + { + id: "aim", + name: "AIM Guardrail", + description: "AIM Security guardrails for comprehensive AI threat detection and mitigation.", + category: "partner", + logo: `${ASSET_PREFIX}aim_security.jpeg`, + tags: ["Security", "Threat Detection"], + }, + { + id: "prompt_security", + name: "Prompt Security", + description: "Protect against prompt injection attacks, data leakage, and other LLM security threats.", + category: "partner", + logo: `${ASSET_PREFIX}prompt_security.png`, + tags: ["Prompt Injection", "Security"], + }, + { + id: "lasso", + name: "Lasso Guardrail", + description: "Content moderation and safety guardrails for responsible AI deployments.", + category: "partner", + logo: `${ASSET_PREFIX}lasso.png`, + tags: ["Content Moderation"], + }, + { + id: "pangea", + name: "Pangea Guardrail", + description: "Pangea's AI guardrails for secure, compliant, and trustworthy AI applications.", + category: "partner", + logo: `${ASSET_PREFIX}pangea.png`, + tags: ["Compliance", "Security"], + }, + { + id: "enkryptai", + name: "EnkryptAI", + description: "AI security and governance platform for enterprise AI safety and compliance.", + category: "partner", + logo: `${ASSET_PREFIX}enkrypt_ai.avif`, + tags: ["Enterprise", "Governance"], + }, + { + id: "javelin", + name: "Javelin Guardrails", + description: "AI gateway with built-in guardrails for secure and compliant AI operations.", + category: "partner", + logo: `${ASSET_PREFIX}javelin.png`, + tags: ["Gateway", "Security"], + }, + { + id: "pillar", + name: "Pillar Guardrail", + description: "AI safety platform for monitoring, testing, and securing AI systems.", + category: "partner", + logo: `${ASSET_PREFIX}pillar.jpeg`, + tags: ["Monitoring", "Safety"], + }, +]; + +export const ALL_CARDS = [...LITELLM_CONTENT_FILTER_CARDS, ...PARTNER_GUARDRAIL_CARDS]; diff --git a/ui/litellm-dashboard/src/components/guardrails/guardrail_garden_detail.tsx b/ui/litellm-dashboard/src/components/guardrails/guardrail_garden_detail.tsx new file mode 100644 index 0000000000..45ff0c5780 --- /dev/null +++ b/ui/litellm-dashboard/src/components/guardrails/guardrail_garden_detail.tsx @@ -0,0 +1,238 @@ +import React, { useState } from "react"; +import { Button } from "antd"; +import { ArrowLeftOutlined } from "@ant-design/icons"; +import AddGuardrailForm from "./add_guardrail_form"; +import { GUARDRAIL_PRESETS } from "./guardrail_garden_configs"; +import { GuardrailCardInfo } from "./guardrail_garden_data"; + +interface GuardrailDetailViewProps { + card: GuardrailCardInfo; + onBack: () => void; + accessToken: string | null; + onGuardrailCreated: () => void; +} + +const GuardrailDetailView: React.FC = ({ + card, + onBack, + accessToken, + onGuardrailCreated, +}) => { + const [isAddFormVisible, setIsAddFormVisible] = useState(false); + const [activeTab, setActiveTab] = useState("overview"); + + const detailRows = [ + { property: "Provider", value: card.category === "litellm" ? "LiteLLM Content Filter" : "Partner Guardrail" }, + ...(card.subcategory ? [{ property: "Subcategory", value: card.subcategory }] : []), + ...(card.category === "litellm" ? [{ property: "Cost", value: "$0 / request" }] : []), + ...(card.category === "litellm" ? [{ property: "External Dependencies", value: "None" }] : []), + ...(card.category === "litellm" ? [{ property: "Latency", value: card.eval?.latency || "<1ms" }] : []), + ]; + + const evalRows = card.eval + ? [ + { metric: "Precision", value: `${card.eval.precision}%` }, + { metric: "Recall", value: `${card.eval.recall}%` }, + { metric: "F1 Score", value: `${card.eval.f1}%` }, + { metric: "Test Cases", value: String(card.eval.testCases) }, + { metric: "False Positives", value: "0" }, + { metric: "False Negatives", value: "0" }, + { metric: "Latency (p50)", value: card.eval.latency }, + ] + : []; + + const tabs = [ + { key: "overview", label: "Overview" }, + ...(card.eval ? [{ key: "eval", label: "Eval Results" }] : []), + ]; + + return ( +
+ {/* Back link */} +
+ + {card.name} +
+ + {/* ── Header block (Vertex-style) ── */} +
+ { (e.target as HTMLImageElement).style.display = "none"; }} + /> +

+ {card.name} +

+
+ +

+ {card.description} +

+ + {/* Action buttons — outlined style like Vertex */} +
+ +
+ + {/* ── Tab bar ──────────────────────────────────── */} +
+
+ {tabs.map((tab) => ( +
setActiveTab(tab.key)} + style={{ + padding: "12px 20px", + fontSize: 14, + color: activeTab === tab.key ? "#1a73e8" : "#5f6368", + borderBottom: activeTab === tab.key ? "3px solid #1a73e8" : "3px solid transparent", + cursor: "pointer", + fontWeight: activeTab === tab.key ? 500 : 400, + marginBottom: -1, + }} + > + {tab.label} +
+ ))} +
+
+ + {/* ── Tab content ──────────────────────────────── */} + {activeTab === "overview" && ( +
+ {/* Left column — overview + details table */} +
+

Overview

+

+ {card.description} +

+ +

Guardrail Details

+

Details are as follows

+ + + + + + + + + + {detailRows.map((row, i) => ( + + + + + ))} + +
Property{card.name}
{row.property}{row.value}
+
+ + {/* Right column — metadata sidebar like Vertex */} +
+ {/* Guardrail ID */} +
+
Guardrail ID
+
+ litellm/{card.id} +
+
+ + {/* Type */} +
+
Type
+
+ {card.category === "litellm" ? "Content Filter" : "Partner"} +
+
+ + {/* Tags — pill style like Vertex */} + {card.tags.length > 0 && ( +
+
Tags
+
+ {card.tags.map((tag) => ( + + {tag} + + ))} +
+
+ )} +
+
+ )} + + {activeTab === "eval" && ( +
+

Eval Results

+ + + + + + + + + {evalRows.map((row, i) => ( + + + + + ))} + +
MetricValue
{row.metric}{row.value}
+
+ )} + + setIsAddFormVisible(false)} + accessToken={accessToken} + onSuccess={() => { + setIsAddFormVisible(false); + onGuardrailCreated(); + }} + preset={GUARDRAIL_PRESETS[card.id]} + /> +
+ ); +}; + +export default GuardrailDetailView;