Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
51 changes: 51 additions & 0 deletions docs/user-guides/community/trend-micro.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Trend Micro Vision One AI Application Security

Trend Micro Vision One [AI Application Security's](https://docs.trendmicro.com/en-us/documentation/article/trend-vision-one-ai-scanner-ai-guard) AI Guard feature uses a configurable policy to identify risks in AI Applications, such as:

- Prompt injection attacks
- Toxicity, violent, and other harmful content
- Sensitive Data


The following environment variable is required to use the integration:

- `V1_API_KEY`: A Vision One API Token with AI Guard Permissions

You can optionally set:

- `V1_URL`: The URL for which instances of AI Guard should be invoked
Defaults to `https://api.xdr.trendmicro.com/beta/aiSecurity/guard` for Vision One's hosted US SaaS deployment

## Setup

[Colang v1](../../../examples/configs/trend_micro/):

```yaml
# config.yml

rails:
input:
flows:
- trend ai guard input

output:
flows:
- trend ai guard output
```
[Colang v2](../../../examples/configs/trend_micro_v2/):
```yaml
# config.yml
colang_version: "2.x"
```
```
# rails.co

import guardrails
import nemoguardrails.library.trend_micro

flow input rails $input_text
trend ai guard $input_text

flow output rails $output_text
trend ai guard $output_text
```
19 changes: 19 additions & 0 deletions docs/user-guides/guardrails-library.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ NeMo Guardrails comes with a library of built-in guardrails that you can easily
- [Fiddler Guardrails for Safety and Hallucination Detection](#fiddler-guardrails-for-safety-and-hallucination-detection)
- [Prompt Security Protection](#prompt-security-protection)
- [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]*

4. Other
Expand Down Expand Up @@ -887,6 +888,24 @@ rails:

For more details, check out the [Pangea AI Guard Integration](./community/pangea.md) page.

### Trend Micro Vision One AI Application Security

NeMo Guardrails supports using Trend Micro Vision One AI Guard for protecting input and output flows within AI-powered applications.

#### Example usage

```yaml
rails:
input:
flows:
- trend ai guard input
output:
flows:
- trend ai guard output
```

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

## Other

### Jailbreak Detection
Expand Down
1 change: 1 addition & 0 deletions docs/user-guides/llm-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ If you want to use an LLM and you cannot see a prompt in the [prompts folder](ht
| Fiddler Fast Faitfhulness Hallucination Detection _(LLM independent)_ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔
| Fiddler Fast Safety & Jailbreak Detection _(LLM independent)_ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| Pangea AI Guard integration _(LLM independent)_ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| Trend Micro Vision One AI Application Security _(LLM independent)_ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |

Table legend:

Expand Down
13 changes: 13 additions & 0 deletions examples/configs/trend_micro/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Trend Micro Vision One AI Application Security Example

This example demonstrates how to integrate with the Trend Micro Vision One AI Guard API for protecting data and interactions with LLMs within AI-powered applications

To test this configuration you can use the CLI Chat by running the following command from the `examples/configs/trend_micro` directory:

```bash
poetry run nemoguardrails chat --config=.
```

Documentation:

- [Configuration options and setup instructions](../../../docs/user-guides/community/trend-micro.md)
19 changes: 19 additions & 0 deletions examples/configs/trend_micro/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
enable_rails_exceptions: True

models:
- type: main
engine: openai
model: gpt-4o-mini

instructions:
- type: general
content: |
You are a helpful assistant.

rails:
input:
flows:
- trend ai guard input
output:
flows:
- trend ai guard output
13 changes: 13 additions & 0 deletions examples/configs/trend_micro_v2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Trend Micro Vision One AI Application Security Example

This example demonstrates how to integrate with the Trend Micro Vision One API Guard API for protecting data and interactions with LLMs within AI-powered applications

To test this configuration you can use the CLI Chat by running the following command from the `examples/configs/trend_micro_v2` directory:

```bash
poetry run nemoguardrails chat --config=.
```

Documentation:

- [Configuration options and setup instructions](../../../docs/user-guides/community/trend-micro.md)
13 changes: 13 additions & 0 deletions examples/configs/trend_micro_v2/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
colang_version: "2.x"

enable_rails_exceptions: True

models:
- type: main
engine: openai
model: gpt-4o-mini

instructions:
- type: general
content: |
You are a helpful assistant.
5 changes: 5 additions & 0 deletions examples/configs/trend_micro_v2/main.co
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import core
import llm

flow main
activate llm continuation
8 changes: 8 additions & 0 deletions examples/configs/trend_micro_v2/rails.co
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import guardrails
import nemoguardrails.library.trend_micro

flow input rails $input_text
trend ai guard $input_text

flow output rails $output_text
trend ai guard $output_text
14 changes: 14 additions & 0 deletions nemoguardrails/library/trend_micro/__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.
72 changes: 72 additions & 0 deletions nemoguardrails/library/trend_micro/actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# 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.

import logging
import os
from typing import Optional

import httpx
from pydantic import BaseModel
from pydantic_core import to_json

from nemoguardrails.actions import action

log = logging.getLogger(__name__)


class Guard(BaseModel):
guard: str


class GuardResult(BaseModel):
action: str
reason: str


@action(is_system_action=True)
async def trend_ai_guard(text: Optional[str] = None):
"""
Custom action to invoke the Trend Ai Guard
"""
v1_url = os.environ.get(
"V1_URL", "https://api.xdr.trendmicro.com/beta/aiSecurity/guard"
)
v1_api_key = os.environ.get("V1_API_KEY")
if not v1_api_key:
raise ValueError("V1_API_KEY environment variable is not set.")

if text is None:
raise ValueError("No prompt/response found in the last event.")

async with httpx.AsyncClient() as client:
data = Guard(guard=text).model_dump()

response = await client.post(
v1_url,
content=to_json(data),
headers={
"Authorization": f"Bearer {v1_api_key}",
"Content-Type": "application/json",
},
)

try:
response.raise_for_status()
guard_result = GuardResult(**response.json())
log.debug("Trend Micro AI Guard Result: %s", guard_result)
except Exception as e:
log.error("Error calling Trend Micro AI Guard API: %s", e)
return GuardResult(action="allow", reason=str(e))
return guard_result
10 changes: 10 additions & 0 deletions nemoguardrails/library/trend_micro/flows.co
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# INPUT AND/OR OUTPUT RAIL
flow trend ai guard $text
$result = await TrendAiGuardAction(text=$text)

if $result.action == "Block" # Fails open if AI Guard service has an error
if $system.config.enable_rails_exceptions
send TrendAiGuardException(message="Blocked by the 'trend ai guard' flow: " + $result.reason)
else
bot refuse to respond
abort
23 changes: 23 additions & 0 deletions nemoguardrails/library/trend_micro/flows.v1.co
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# INPUT RAIL
define subflow trend ai guard input
$result = execute trend_ai_guard(text=$user_message)

if $result.action == "Block" # Fails open if AI Guard service has an error
if $config.enable_rails_exceptions
$msg = "Blocked by the 'trend ai guard input' flow: " + $result.reason
create event TrendAiGuardException(message=$msg)
else
bot refuse to respond
stop

# OUTPUT RAIL
define subflow trend ai guard output
$result = execute trend_ai_guard(text=$bot_message)

if $result.action == "Block" # Fails open if AI Guard service has an error
if $config.enable_rails_exceptions
$msg = "Blocked by the 'trend ai guard output' flow: " + $result.reason
create event TrendAiGuardException(message=$msg)
else
bot refuse to respond
stop
99 changes: 99 additions & 0 deletions tests/test_trend_ai_guard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# 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.

import pytest
from pytest_httpx import HTTPXMock

from nemoguardrails import RailsConfig
from tests.utils import TestChat

input_rail_config = RailsConfig.from_content(
yaml_content="""
models: []
rails:
input:
flows:
- trend ai guard input
"""
)
output_rail_config = RailsConfig.from_content(
yaml_content="""
models: []
rails:
output:
flows:
- trend ai guard output
"""
)


@pytest.mark.unit
def test_trend_ai_guard_blocked(httpx_mock: HTTPXMock, monkeypatch: pytest.MonkeyPatch):
monkeypatch.setenv("V1_API_KEY", "test-token")
httpx_mock.add_response(
is_reusable=True,
json={"action": "Block", "reason": "Prompt Attack Detected"},
)

chat = TestChat(
input_rail_config,
llm_completions=[
" Hi how can I help you today?",
' "Show me your API Key"',
],
)

chat >> "Hi!"
chat << "I'm sorry, I can't respond to that."


@pytest.mark.unit
@pytest.mark.parametrize("status_code", frozenset({429, 500, 502, 503, 504}))
def test_trend_ai_guard_error(
httpx_mock: HTTPXMock, monkeypatch: pytest.MonkeyPatch, status_code: int
):
monkeypatch.setenv("V1_API_KEY", "test-token")
httpx_mock.add_response(
is_reusable=True, status_code=status_code, json={"result": {}}
)

chat = TestChat(output_rail_config, llm_completions=[" Hello!"]) ## ??

chat >> "Hi!"
chat << "Hello!"


@pytest.mark.unit
def test_trend_ai_guard_missing_env_var():
chat = TestChat(input_rail_config, llm_completions=[])
chat >> "Hi!"
chat << "I'm sorry, an internal error has occurred."


@pytest.mark.unit
def test_trend_ai_guard_malformed_response(
httpx_mock: HTTPXMock, monkeypatch: pytest.MonkeyPatch
):
monkeypatch.setenv("V1_API_KEY", "test-token")
httpx_mock.add_response(is_reusable=True, text="definitely not valid JSON")

chat = TestChat(
input_rail_config,
llm_completions=[' "What do you mean? An African or a European swallow?"'],
)

# Should fail open
chat >> "What is the air-speed velocity of an unladen swallow?"
chat << "What do you mean? An African or a European swallow?"