Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions docs/user-guides/community/ai-defense.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Cisco AI Defense Integration

[Cisco AI Defense](https://www.cisco.com/site/us/en/products/security/ai-defense/index.html?utm_medium=github&utm_campaign=nemo-guardrails) allows you to protect LLM interactions. This integration enables NeMo Guardrails to use Cisco AI Defense to protect input and output flows.

You'll need to set the following env variables to work with Cisco AI Defense:

1. AI_DEFENSE_API_ENDPOINT - This is the URL for the Cisco AI Defense inspection API endpoint. This will look like https://[REGION].api.inspect.aidefense.security.cisco.com/api/v1/inspect/chat where REGION is us, ap, eu, etc.
2. AI_DEFENSE_API_KEY - This is the API key for Cisco AI Defense. It is used to authenticate the API request. It can be generated from the Cisco Security Cloud Control UI at https://security.cisco.com

## Setup

1. Ensure that you have access to the Cisco AI Defense endpoints (SaaS or in your private deployment)
2. Enable Cisco AI Defense flows in your `config.yml` file:

```yaml
rails:
input:
flows:
- ai defense inspect prompt

output:
flows:
- ai defense inspect response
```

Don't forget to set the `AI_DEFENSE_API_ENDPOINT` and `AI_DEFENSE_API_KEY` environment variables.

## Usage

Once configured, the Cisco AI Defense integration will automatically:

1. Protect prompts before they are processed by the LLM.
2. Protect LLM outputs before they are sent back to the user.

The `ai_defense_inspect` action in `nemoguardrails/library/ai_defense/actions.py` handles the protection process.

## Error Handling

If the Cisco AI Defense API request fails, it will operate in a fail-open mode (not blocking the prompt/response).

## Notes

For more information on Cisco AI Defense capabilities and configuration, please refer to the [Cisco AI Defense documentation](https://securitydocs.cisco.com/docs/scc/admin/108321.dita?utm_medium=github&utm_campaign=nemo-guardrails).
22 changes: 22 additions & 0 deletions docs/user-guides/guardrails-library.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ NeMo Guardrails comes with a library of built-in guardrails that you can easily
- [Pangea AI Guard](#pangea-ai-guard)
- [Trend Micro Vision One AI Application Security](#trend-micro-vision-one-ai-application-security)
- OpenAI Moderation API - *[COMING SOON]*
- [Cisco AI Defense](#cisco-ai-defense)

4. Other
- [Jailbreak Detection](#jailbreak-detection)
Expand Down Expand Up @@ -937,6 +938,27 @@ rails:

For more details, check out the [Trend Micro Vision One AI Application Security](./community/trend-micro.md) page.

### Cisco AI Defense Protection

NeMo Guardrails supports using [Cisco AI Defense Inspection](https://www.cisco.com/site/us/en/products/security/ai-defense/index.html?utm_medium=github&utm_campaign=nemo-guardrails) for protecting input and output flows.

To activate the protection, you need to set the `AI_DEFENSE_API_KEY` and `AI_DEFENSE_API_ENDPOINT` environment variables.

#### Example usage

```yaml
rails:
input:
flows:
- ai defense inspect prompt

output:
flows:
- ai defense inspect response
```

For more details, check out the [Cisco AI Defense Integration](./community/ai-defense.md) page.

## Other

### Jailbreak Detection
Expand Down
5 changes: 5 additions & 0 deletions examples/configs/ai_defense/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Cisco AI Defense Configuration Example

This example contains configuration files for using Cisco AI Defense in your NeMo Guardrails project.

For more details on the Cisco AI Defense integration, see [Cisco AI Defense Integration User Guide](../../../docs/user-guides/community/ai-defense.md).
13 changes: 13 additions & 0 deletions examples/configs/ai_defense/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
models:
- type: main
engine: openai
model: gpt-4o-mini

rails:
input:
flows:
- ai defense inspect prompt

output:
flows:
- ai defense inspect response
14 changes: 14 additions & 0 deletions nemoguardrails/library/ai_defense/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
116 changes: 116 additions & 0 deletions nemoguardrails/library/ai_defense/actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Prompt/Response protection using Cisco AI Defense."""

import logging
import os
from typing import Any, Dict, Optional

import httpx

from nemoguardrails.actions import action

log = logging.getLogger(__name__)


def ai_defense_text_mapping(result: dict) -> bool:
"""
Mapping for inspect API response
Expects result to be a dict with:
- "is_blocked": a boolean indicating if the prompt or response passed sent to AI Defense should be blocked.

Returns:
True if the response should be blocked (i.e. if "is_safe" is False),
False otherwise.
"""
# If the provider does not return "is_safe", default to safe (not blocked)
is_blocked = result.get("is_blocked", True)
return is_blocked


@action(is_system_action=True, output_mapping=ai_defense_text_mapping)
async def ai_defense_inspect(
user_prompt: Optional[str] = None, bot_response: Optional[str] = None, **kwargs
):
api_key = os.environ.get("AI_DEFENSE_API_KEY")
if api_key is None:
msg = "AI_DEFENSE_API_KEY environment variable not set."
log.error(msg)
raise ValueError(msg)

api_endpoint = os.environ.get("AI_DEFENSE_API_ENDPOINT")
if api_endpoint is None:
msg = "AI_DEFENSE_API_ENDPOINT environment variable not set."
log.error(msg)
raise ValueError(msg)

headers = {
"X-Cisco-AI-Defense-API-Key": api_key,
"Content-Type": "application/json",
"Accept": "application/json",
}

if bot_response is not None:
role = "assistant"
text = str(bot_response)
elif user_prompt is not None:
role = "user"
text = str(user_prompt)
else:
msg = "Either user_prompt or bot_response must be provided"
log.error(msg)
raise ValueError(msg)

messages = [{"role": role, "content": text}]

metadata = None
user = kwargs.get("user")
if user is not None:
metadata = {"user": user}

payload: Dict[str, Any] = {"messages": messages}
if metadata:
payload["metadata"] = metadata

async with httpx.AsyncClient() as client:
try:
resp = await client.post(api_endpoint, headers=headers, json=payload)
resp.raise_for_status()
data = resp.json()
except httpx.HTTPStatusError as e:
msg = f"Error calling AI Defense API: {e}"
log.error(msg)
raise ValueError(msg)

# Compose a consistent return structure for flows
is_safe = bool(data.get("is_safe", True))
rules = data.get("rules") or []
if not is_safe and rules:
entries = [
f"{r.get('rule_name')} ({r.get('classification')})"
for r in rules
if isinstance(r, dict)
]
if entries:
log.info("AI Defense matched rules: %s", ", ".join(entries))

# Ensure flows can check explicit block flag
result: Dict[str, Any] = {
"is_blocked": (not is_safe),
"is_safe": is_safe,
}

return result
24 changes: 24 additions & 0 deletions nemoguardrails/library/ai_defense/flows.co
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# INPUT RAILS

flow ai defense inspect prompt
"""Check if the prompt is safe according to AI Defense."""
$result = await AiDefenseInspectAction(user_prompt=$user_message)
if $result["is_blocked"]
if $system.config.enable_rails_exceptions
send AIDefenseRailException(message="Prompt not allowed. The prompt was blocked by the 'ai defense inspect prompt' flow.")
else
bot refuse to respond
abort


# OUTPUT RAILS

flow ai defense inspect response
"""Check if the response is safe according to AI Defense."""
$result = await AiDefenseInspectAction(bot_response=$bot_message)
if $result["is_blocked"]
if $system.config.enable_rails_exceptions
send AIDefenseRailException(message="Response not allowed. The response was blocked by the 'ai defense inspect response' flow.")
else
bot refuse to respond
abort
24 changes: 24 additions & 0 deletions nemoguardrails/library/ai_defense/flows.v1.co
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# INPUT RAILS

define subflow ai defense inspect prompt
"""Check if the prompt is safe according to AI Defense."""
$result = execute ai_defense_inspect(user_prompt=$user_message)
if $result["is_blocked"]
if $config.enable_rails_exceptions
create event AIDefenseRailException(message="Prompt not allowed. The prompt was blocked by the 'ai defense inspect prompt' flow.")
else
bot refuse to respond
stop


# OUTPUT RAILS

define subflow ai defense inspect response
"""Check if the response is safe according to AI Defense."""
$result = execute ai_defense_inspect(bot_response=$bot_message)
if $result["is_blocked"]
if $config.enable_rails_exceptions
create event AIDefenseRailException(message="Response not allowed. The response was blocked by the 'ai defense inspect response' flow.")
else
bot refuse to respond
stop
Loading