Advanced NeMo Guardrails

NeMo Guardrails Architecture

3 min read

NVIDIA NeMo Guardrails is an open-source framework for adding programmable guardrails to LLM applications. Released in 2023, it provides a declarative approach to controlling LLM behavior using Colang, a domain-specific language for dialog flows.

Core Components

┌─────────────────────────────────────────────────────┐
│                 NeMo Guardrails                      │
├─────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  │
│  │  Input      │  │  Dialog     │  │  Output     │  │
│  │  Rails      │  │  Rails      │  │  Rails      │  │
│  └─────────────┘  └─────────────┘  └─────────────┘  │
├─────────────────────────────────────────────────────┤
│  ┌─────────────────────────────────────────────────┐│
│  │            Colang Runtime Engine                 ││
│  └─────────────────────────────────────────────────┘│
├─────────────────────────────────────────────────────┤
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  │
│  │  LLM        │  │  Actions    │  │  Knowledge  │  │
│  │  Provider   │  │  Library    │  │  Base       │  │
│  └─────────────┘  └─────────────┘  └─────────────┘  │
└─────────────────────────────────────────────────────┘

Installation and Setup

pip install nemoguardrails

Project Structure

my_guardrails_app/
├── config/
│   ├── config.yml          # Main configuration
│   ├── rails/
│   │   ├── input.co        # Input rails (Colang)
│   │   ├── output.co       # Output rails
│   │   └── dialog.co       # Dialog flows
│   ├── prompts/
│   │   └── prompts.yml     # Custom prompts
│   └── actions/
│       └── custom.py       # Python actions
└── main.py

Basic Configuration

# config.yml
models:
  - type: main
    engine: openai
    model: gpt-4o

rails:
  input:
    flows:
      - self check input      # Built-in input validation
      - check jailbreak       # Jailbreak detection

  output:
    flows:
      - self check output     # Built-in output validation
      - check hallucination   # Fact-checking

  dialog:
    user_messages:
      embeddings_only: true   # Use embeddings for matching

Basic Implementation

from nemoguardrails import LLMRails, RailsConfig

# Load configuration
config = RailsConfig.from_path("./config")

# Create rails instance
rails = LLMRails(config)

# Generate response with guardrails
async def chat(user_message: str) -> str:
    response = await rails.generate_async(
        messages=[{
            "role": "user",
            "content": user_message
        }]
    )
    return response["content"]

# Synchronous usage
def chat_sync(user_message: str) -> str:
    response = rails.generate(
        messages=[{
            "role": "user",
            "content": user_message
        }]
    )
    return response["content"]

Rail Types

Input Rails

Process and validate user input before LLM:

# input.co
define flow self check input
  $allowed = execute check_input_safety(user_message=$user_message)

  if not $allowed
    bot refuse to respond
    stop

Output Rails

Validate and modify LLM responses:

# output.co
define flow self check output
  $safe = execute check_output_safety(bot_message=$bot_message)

  if not $safe
    bot apologize and provide safe response

Dialog Rails

Control conversation flow:

# dialog.co
define user ask about pricing
  "How much does it cost?"
  "What's the price?"
  "Pricing information"

define flow handle pricing question
  user ask about pricing
  bot provide pricing info

Built-in Safety Rails

NeMo includes pre-built rails for common safety patterns:

# config.yml
rails:
  input:
    flows:
      - self check input
      - check jailbreak
      - mask sensitive data     # PII masking

  output:
    flows:
      - self check output
      - check facts             # Fact verification
      - check hallucination

Action Registration

from nemoguardrails.actions import action

@action(name="check_input_safety")
async def check_input_safety(user_message: str) -> bool:
    """Custom input safety check."""
    # Integrate with your safety classifier
    classifier = FastToxicityClassifier()
    result = classifier.classify(user_message)
    return result["toxic"] < 0.5

@action(name="get_user_context")
async def get_user_context(user_id: str) -> dict:
    """Retrieve user context for personalization."""
    # Fetch from database
    return {"tier": "premium", "region": "us"}

# Register with rails
rails.register_action(check_input_safety)
rails.register_action(get_user_context)

Streaming Support

from nemoguardrails import LLMRails

rails = LLMRails(config)

async def stream_response(user_message: str):
    """Stream response with guardrails."""
    async for chunk in rails.stream_async(
        messages=[{"role": "user", "content": user_message}]
    ):
        yield chunk["content"]

# Usage
async for token in stream_response("Tell me about Python"):
    print(token, end="", flush=True)

Performance Configuration

# config.yml
models:
  - type: main
    engine: openai
    model: gpt-4o

  # Faster model for safety checks
  - type: self_check
    engine: openai
    model: gpt-4o-mini

# Caching for repeated checks
cache:
  enabled: true
  type: redis
  url: redis://localhost:6379

# Parallel processing
streaming:
  enabled: true
  chunk_size: 20

Architecture Insight: NeMo Guardrails uses a dual-LLM approach by default—a main model for responses and a separate model for safety checks. Configure a faster model for checks to minimize latency overhead.

Next: Mastering Colang 2.0 for custom dialog flows. :::

Quiz

Module 4: Advanced NeMo Guardrails

Take Quiz