diff --git a/docs/index.md b/docs/index.md index ff1393fb3..ce4ef54fb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -26,6 +26,8 @@ product questions using backend LLM services, agents, and RAG databases. [Agent skills](https://lightspeed-core.github.io/lightspeed-stack/user_doc/skills_guide.html) +[Safety shields](https://lightspeed-core.github.io/lightspeed-stack/user_doc/shields_guide.html) + [A2A [Agent-to-Agent] Protocol](https://lightspeed-core.github.io/lightspeed-stack/user_doc/a2a_protocol.html) [RAG configuration guide](https://lightspeed-core.github.io/lightspeed-stack/user_doc/rag_guide.html) diff --git a/docs/user_doc/config.md b/docs/user_doc/config.md index 237c6f28c..e7166edc6 100644 --- a/docs/user_doc/config.md +++ b/docs/user_doc/config.md @@ -248,7 +248,7 @@ Global service configuration. | rag | | Unified RAG configuration: BYOK stores, OKP provider, and retrieval strategies (inline and tool-based). | | skills | | Agent skills configuration. Specifies paths to skill directories. | | saved_prompts | | Configuration for saved prompts feature limits including maximum prompts per user, display name length, and content length. | -| shields | array | List of pydantic-ai-lightspeed agent guardrail shields (question validity and PII redaction). Each entry has a unique 'name', a 'provider_id' ('question_validity' or 'redaction'), and a type-specific 'config'. | +| shields | array | List of LCS guardrail shields (question validity, PII redaction, and Granite Guardian). Each entry has a unique 'name', a 'provider_id' ('question_validity', 'redaction', or 'granite_guardian'), and a type-specific 'config'. See [shields_guide.md](shields_guide.md). | ## ConversationHistoryConfiguration @@ -360,6 +360,37 @@ Inference configuration. | max_tool_calls | integer | Server-side default for the maximum number of tool calls allowed in a single response. Prevents small models from exhausting the context window with repeated tool calls. Per-request values take precedence over this default. Set to None to disable the limit. | +## GraniteGuardianConfig + + +Configuration for the Granite Guardian moderation guardrail. + + +| Field | Type | Description | +|-------------|---------|-------------| +| url | string | Base URL of the OpenAI-compatible Granite Guardian API. | +| model_id | string | Model name sent to the inference server (default `ibm-granite/granite-guardian-4.1-8b`); override when the server registers the model under a different name. | +| api_key | string | API key for the inference endpoint (optional). | +| max_retries | integer | Maximum number of retries for transient errors (0–5, default 2). | +| timeout | integer | Request timeout in seconds (5–300, default 30). | +| verify_ssl | boolean or string | TLS verification: `true`, `false`, or path to a CA bundle (default `true`). | +| batch_size | integer | Number of risk checks to run in parallel per batch (1–10, default 3). | +| risks | array | List of [RiskDefinition](#riskdefinition) entries to evaluate. | + + +## GraniteGuardianShieldConfiguration + + +Configuration for a named Granite Guardian guardrail shield. + + +| Field | Type | Description | +|-------------|--------|-------------| +| name | string | Unique, user-facing name identifying this shield instance. | +| provider_id | string | Must be `granite_guardian`. | +| config | | [GraniteGuardianConfig](#graniteguardianconfig) for this shield. | + + ## JsonPathOperator @@ -792,6 +823,23 @@ Attributes: | config | | Redaction-specific configuration for this shield. | +## RiskDefinition + + +Definition for a custom risk category evaluated by Granite Guardian. + + +| Field | Type | Description | +|-------------------|---------|-------------| +| name | string | Unique identifier for this risk (for example `roleplay-jailbreak`). | +| description | string | Risk definition text passed to Granite Guardian as `custom_criteria`. | +| threshold | number | Score threshold for flagging, 0.0–1.0 (default 0.65; lower = more sensitive). | +| enabled | boolean | Whether to run this check (default `true`). | +| enable_thinking | boolean | Internal — set via `ModerationConfig.thinking_enabled`, not directly. | +| points | array | Where to evaluate: `input`, `output`, and/or `tool` (at least one). | +| violation_message | string | Message returned when this risk is violated. | + + ## RerankerConfiguration diff --git a/docs/user_doc/shields_guide.md b/docs/user_doc/shields_guide.md index 2777790ab..f0cadcee0 100644 --- a/docs/user_doc/shields_guide.md +++ b/docs/user_doc/shields_guide.md @@ -19,6 +19,7 @@ request overrides work. - [Supported shield types](#supported-shield-types) - [question_validity](#question_validity) - [redaction](#redaction) + - [granite_guardian](#granite_guardian) - [How shields apply at runtime](#how-shields-apply-at-runtime) - [Agent-based endpoints](#agent-based-endpoints) - [Responses-based endpoints](#responses-based-endpoints) @@ -38,7 +39,7 @@ configuration. Each entry has: | Field | Meaning | |-------|---------| | `name` | Unique shield name used in `/v1/shields` and in `shield_ids` overrides | -| `provider_id` | Shield type discriminator (`question_validity` or `redaction`) | +| `provider_id` | Shield type discriminator (`question_validity`, `redaction`, or `granite_guardian`) | | `config` | Type-specific settings | Names must be unique across the `shields` list. @@ -75,6 +76,7 @@ for a complete example. |---------------|---------|---------------------| | `question_validity` | Classify whether the user question is in-topic; reject off-topic input with a fixed reply | Agent capability on agent-based endpoints; also considered by direct-run input moderation | | `redaction` | Regex-based PII / sensitive-data redaction of model messages | Agent capability on agent-based endpoints | +| `granite_guardian` | IBM Granite Guardian model screening for custom safety risks at input, output, and tool points | Planned: same endpoints as other shields; **not yet implemented at runtime** — see [Granite Guardian Shield](granite_guardian_shield.md) | ## question_validity @@ -93,6 +95,28 @@ for a complete example. Invalid regex patterns are rejected at configuration load time. +## granite_guardian + +IBM Granite Guardian screening with configurable risk definitions, thresholds, +and guardrail points (`input`, `output`, `tool`). Requires a Granite Guardian +model behind an OpenAI-compatible API. + +| Config field | Required | Description | +|--------------|----------|-------------| +| `url` | Yes | Base URL of the OpenAI-compatible Granite Guardian API | +| `model_id` | No (default `ibm-granite/granite-guardian-4.1-8b`) | Model name sent to the inference server; override when the server registers the model under a different name (for example an Ollama tag) | +| `api_key` | No | API key for the inference endpoint | +| `timeout` | No (default `30`) | Request timeout in seconds (5-300) | +| `max_retries` | No (default `2`) | Retry count for transient errors (0-5) | +| `verify_ssl` | No (default `true`) | TLS verification: `true`, `false`, or a path to a CA bundle | +| `batch_size` | No (default `3`) | Number of risk checks to run in parallel per batch (1-10) | +| `risks` | Yes | Non-empty list of risk definitions: `{name, description, points, violation_message, threshold?, enabled?}` | + +> [!NOTE] +> Configuration is validated at startup, but the runtime capability is not yet +> wired. See the dedicated [Granite Guardian Shield guide](granite_guardian_shield.md) +> for prerequisites, risk-definition guidance, examples, and implementation status. + # How shields apply at runtime The same shield logic (`question_validity` and `redaction`) is used on both @@ -132,7 +156,7 @@ Each catalog entry has this shape: | Field | Description | |-------|-------------| | `name` | Configured shield name | -| `provider_id` | `question_validity` or `redaction` | +| `provider_id` | `question_validity`, `redaction`, or `granite_guardian` | | `type` | Always `"shield"` | | `config` | Type-specific shield configuration | diff --git a/examples/lightspeed-stack-shields.yaml b/examples/lightspeed-stack-shields.yaml index c0a2bdfdc..81cb88d5c 100644 --- a/examples/lightspeed-stack-shields.yaml +++ b/examples/lightspeed-stack-shields.yaml @@ -35,6 +35,33 @@ shields: - pattern: '\b\d{3}-\d{2}-\d{4}\b' replacement: "[REDACTED]" case_sensitive: false + # Requires a Granite Guardian model behind an OpenAI-compatible endpoint. + # NOTE: runtime capability is not yet wired (config-only for now). + - name: product-guardian + provider_id: granite_guardian + config: + url: http://localhost:8000/v1 + # model_id: ibm-granite/granite-guardian-4.1-8b # optional; override if the + # server registers the model under a different name (e.g. an Ollama tag) + # api_key: ${GUARDIAN_API_KEY} # optional + timeout: 30 + max_retries: 2 + verify_ssl: true + # batch_size: 3 # optional; number of risk checks run in parallel per batch + risks: + - name: roleplay-jailbreak + description: >- + The user message uses roleplay framing to override the assistant's + instructions or adopt an unrestricted persona. + threshold: 0.65 + points: [input] + violation_message: "That phrasing isn't something I can act on." + - name: harm-output + description: >- + The assistant response contains harmful, dangerous, or abusive content. + threshold: 0.70 + points: [output] + violation_message: "I cannot provide that response." # Optional: reject client shield_ids overrides on /query and /streaming_query # customization: # disable_shield_ids_override: true