diff --git a/backend/app/models/llm/request.py b/backend/app/models/llm/request.py index fdc078d17..788a55810 100644 --- a/backend/app/models/llm/request.py +++ b/backend/app/models/llm/request.py @@ -477,10 +477,12 @@ class Validator(SQLModel): class InlineValidatorTypeEnum(str, Enum): + """Validator types productised for tenants; mirrors GET /guardrails.""" + GENDER_ASSUMPTION_BIAS = "gender_assumption_bias" PII_REMOVER = "pii_remover" - PROFANITY_FREE = "profanity_free" TOPIC_RELEVANCE_LLM = "topic_relevance_llm" + ULI_SLUR_MATCH = "uli_slur_match" class InlineValidator(SQLModel): diff --git a/backend/app/services/llm/guardrails.py b/backend/app/services/llm/guardrails.py index 1b22d083f..e84aa7d74 100644 --- a/backend/app/services/llm/guardrails.py +++ b/backend/app/services/llm/guardrails.py @@ -11,7 +11,7 @@ from opentelemetry import trace from app.core.config import settings -from app.models.llm.request import InlineValidator, Validator +from app.models.llm.request import InlineValidator, InlineValidatorTypeEnum, Validator logger = logging.getLogger(__name__) tracer = trace.get_tracer(__name__) @@ -25,7 +25,7 @@ # Upstream supports more; only these are productised for tenants. EXPOSED_VALIDATOR_TYPES = frozenset( - {"topic_relevance_llm", "uli_slur_match", "gender_assumption_bias", "pii_remover"} + validator_type.value for validator_type in InlineValidatorTypeEnum ) diff --git a/backend/app/tests/services/llm/test_guardrails.py b/backend/app/tests/services/llm/test_guardrails.py index 526beebce..2b0b7f07f 100644 --- a/backend/app/tests/services/llm/test_guardrails.py +++ b/backend/app/tests/services/llm/test_guardrails.py @@ -474,7 +474,7 @@ def test_disabled_entries_are_neither_fetched_nor_posted( [ disabled_ref, enabled_ref, - InlineValidator(type="profanity_free", is_enabled=False), + InlineValidator(type="uli_slur_match", is_enabled=False), ] ) diff --git a/docs/wiki/modules/llm-call.md b/docs/wiki/modules/llm-call.md index cc61df5d4..4d4249510 100644 --- a/docs/wiki/modules/llm-call.md +++ b/docs/wiki/modules/llm-call.md @@ -27,7 +27,7 @@ All paths relative to `backend/app/`. ## Key pydantic/SQLModel schemas (`models/llm/request.py`) - `LLMCallConfig` — one-of: saved reference (`id` + `version`) XOR ad-hoc `blob` (validator-enforced) -- `ConfigBlob` — `completion` + optional `prompt_template` (`PromptTemplate.template`, plain string; `{{input}}` interpolation is llm-chain-only) + `input_guardrails`/`output_guardrails`. Each guardrail entry is either a `Validator` reference (`{validator_config_id}`) or an `InlineValidator` spec (`{type, on_fail, ...per-type params}`, `type` limited to `InlineValidatorTypeEnum`: gender_assumption_bias, pii_remover, profanity_free, topic_relevance_llm); tagged union `GuardrailEntry`. Both carry `is_enabled` (default true). Disabled entries are never fetched or sent. `services/llm/guardrails.apply_guardrails` POSTs fetched reference rows plus inline specs (a blob is all-refs or all-inline), with `is_enabled` stripped and `stage` stamped on inline specs. +- `ConfigBlob` — `completion` + optional `prompt_template` (`PromptTemplate.template`, plain string; `{{input}}` interpolation is llm-chain-only) + `input_guardrails`/`output_guardrails`. Each guardrail entry is either a `Validator` reference (`{validator_config_id}`) or an `InlineValidator` spec (`{type, on_fail, ...per-type params}`, `type` limited to `InlineValidatorTypeEnum`: gender_assumption_bias, pii_remover, topic_relevance_llm, uli_slur_match — same set as `EXPOSED_VALIDATOR_TYPES`); tagged union `GuardrailEntry`. Both carry `is_enabled` (default true). Disabled entries are never fetched or sent. `services/llm/guardrails.apply_guardrails` POSTs fetched reference rows plus inline specs (a blob is all-refs or all-inline), with `is_enabled` stripped and `stage` stamped on inline specs. - `CompletionConfig` — discriminated union on `provider`: `KaapiCompletionConfig` (standardized params: `TextLLMParams`/`STTLLMParams`/`TTSLLMParams`), `NativeCompletionConfig` (pass-through), `ProxyCompletionConfig` (client's own endpoint) - `TextLLMParams` reasoning knobs: `reasoning` + `effort` (OpenAI-style), `thinking` (Anthropic adaptive-thinking container, forwarded as-is) and `thinking_level` (Gemini). A knob must be **declared here** to survive config save — pydantic's default extra policy is ignore, so an undeclared key is dropped silently at validation with no error. - `QueryParams` — per-call input + `ConversationConfig`