Mixed Content Moderation Examples

Examples of how to moderate both text and image content in a single request

Mixed Content Moderation

One of the key features of the Omni API is the ability to moderate both text and images in a single request. This is particularly useful for applications like social media posts, reviews, or comments that may contain both text and images.

Request

curl -X POST https://api.omnimoderate.com/v1/moderate \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your_api_key_here" \
  -d '{
    "input": [
      { "type": "text", "text": "This restaurant has amazing food!" },
      { "type": "text", "text": "The service was excellent and I highly recommend the steak." },
      { "type": "image", "base64": "data:image/jpeg;base64,/9j/4AAQSkZ..." },
      { "type": "image", "base64": "data:image/jpeg;base64,iVBORw0KGg..." }
    ],
    "analyze_images": true
  }'

Response

{
  "id": "modr-123462",
  "model": "text-moderation-latest",
  "results": [
    {
      "flagged": false,
      "categories": {
        "hate": false,
        "harassment": false,
        "self-harm": false,
        "sexual": false,
        "violence": false
      },
      "category_scores": {
        "hate": 0.0,
        "harassment": 0.0,
        "self-harm": 0.0,
        "sexual": 0.0,
        "violence": 0.0
      }
    },
    {
      "flagged": false,
      "categories": {
        "hate": false,
        "harassment": false,
        "self-harm": false,
        "sexual": false,
        "violence": false
      },
      "category_scores": {
        "hate": 0.0,
        "harassment": 0.0,
        "self-harm": 0.0,
        "sexual": 0.0,
        "violence": 0.0
      }
    },
    {
      "flagged": false,
      "categories": {
        "hate": false,
        "harassment": false,
        "self-harm": false,
        "sexual": false,
        "violence": false
      },
      "category_scores": {
        "hate": 0.0,
        "harassment": 0.0,
        "self-harm": 0.0,
        "sexual": 0.0,
        "violence": 0.0
      }
    },
    {
      "flagged": false,
      "categories": {
        "hate": false,
        "harassment": false,
        "self-harm": false,
        "sexual": false,
        "violence": false
      },
      "category_scores": {
        "hate": 0.0,
        "harassment": 0.0,
        "self-harm": 0.0,
        "sexual": 0.0,
        "violence": 0.0
      }
    }
  ],
  "combined_text_moderation": {
    "flagged": false,
    "categories": {
      "hate": false,
      "harassment": false,
      "self-harm": false,
      "sexual": false,
      "violence": false
    },
    "category_scores": {
      "hate": 0.0,
      "harassment": 0.0,
      "self-harm": 0.0,
      "sexual": 0.0,
      "violence": 0.0
    }
  },
  "vision_analysis": [
    {
      "image_index": 2,
      "analysis": "This image shows a plate of beautifully presented food in what appears to be a restaurant setting. The dish looks like a well-plated steak with garnishes and side dishes. The lighting is good, the food appears appetizing, and the image is of high quality. This is perfectly appropriate for a restaurant listing or review as it showcases the food offerings. VERDICT: APPROPRIATE",
      "flagged": false
    },
    {
      "image_index": 3,
      "analysis": "This image shows the interior of a restaurant with tables and chairs. The space appears clean, well-lit, and professionally designed. This is an appropriate image for a restaurant listing as it accurately represents the dining environment for potential customers. There are no inappropriate elements or overlays in the image. VERDICT: APPROPRIATE",
      "flagged": false
    }
  ],
  "flagged": false,
  "signature": "abcdef1234567896"
}

Code Examples

JavaScript

moderate-mixed-content.js
// Function to convert an image file to base64
function fileToBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = error => reject(error);
  });
}

async function moderateMixedContent(apiKey, textItems, imageFiles, analyzeImages = false) {
  // Convert all image files to base64
  const base64Promises = imageFiles.map(file => fileToBase64(file));
  const base64Images = await Promise.all(base64Promises);
  
  // Prepare the input array with both text and image items
  const input = [
    ...textItems.map(text => ({ type: 'text', text })),
    ...base64Images.map(base64 => ({ type: 'image', base64 }))
  ];
  
  const response = await fetch('https://api.omnimoderate.com/v1/moderate', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': apiKey
    },
    body: JSON.stringify({
      input,
      analyze_images: analyzeImages
    })
  });

  if (!response.ok) {
    const errorData = await response.json();
    throw new Error(errorData.error?.message || 'Moderation request failed');
  }

  return await response.json();
}

// Example usage with form inputs
document.getElementById('contentForm').addEventListener('submit', async (e) => {
  e.preventDefault();
  
  const apiKey = 'your_api_key_here';
  const textInput = document.getElementById('textInput').value;
  const textInput2 = document.getElementById('textInput2').value;
  const fileInput = document.getElementById('imageInput');
  const analyzeImages = document.getElementById('analyzeImages').checked;
  
  const textItems = [textInput, textInput2].filter(text => text.trim() !== '');
  const imageFiles = Array.from(fileInput.files);
  
  try {
    const result = await moderateMixedContent(apiKey, textItems, imageFiles, analyzeImages);
    
    console.log('Moderation result:', result);
    console.log('Overall flagged:', result.flagged);
    
    // Check text results
    if (textItems.length > 0) {
      console.log('Combined text flagged:', result.combined_text_moderation.flagged);
      
      textItems.forEach((_, index) => {
        console.log(`Text item ${index + 1} flagged: ${result.results[index].flagged}`);
      });
    }
    
    // Check image results and vision analysis
    if (imageFiles.length > 0 && analyzeImages && result.vision_analysis) {
      result.vision_analysis.forEach((analysis) => {
        console.log(`Image ${analysis.image_index - textItems.length + 1} analysis: ${analysis.analysis}`);
        console.log(`Image ${analysis.image_index - textItems.length + 1} flagged: ${analysis.flagged}`);
      });
    }
  } catch (error) {
    console.error('Error:', error.message);
  }
});

Python

moderate_mixed_content.py
import requests
import base64
from pathlib import Path

def encode_image_to_base64(image_path):
    """Convert an image file to base64 encoding with MIME type prefix"""
    image_path = Path(image_path)
    mime_type = f"image/{image_path.suffix[1:]}"  # Remove the dot from extension
    
    with open(image_path, "rb") as image_file:
        encoded_string = base64.b64encode(image_file.read()).decode('utf-8')
        return f"data:{mime_type};base64,{encoded_string}"

def moderate_mixed_content(api_key, text_items, image_paths, analyze_images=False):
    """Moderate both text and images using the Omni API"""
    url = "https://api.omnimoderate.com/v1/moderate"
    
    headers = {
        "Content-Type": "application/json",
        "X-API-Key": api_key
    }
    
    # Convert all images to base64
    base64_images = [encode_image_to_base64(path) for path in image_paths]
    
    # Prepare the input array with both text and image items
    input_data = [
        *[{"type": "text", "text": text} for text in text_items],
        *[{"type": "image", "base64": base64} for base64 in base64_images]
    ]
    
    payload = {
        "input": input_data,
        "analyze_images": analyze_images
    }
    
    response = requests.post(url, headers=headers, json=payload)
    
    if response.status_code != 200:
        error_data = response.json()
        raise Exception(error_data.get("error", {}).get("message", "Moderation request failed"))
    
    return response.json()

# Example usage
def example():
    api_key = "your_api_key_here"
    text_items = [
        "This restaurant has amazing food!",
        "The service was excellent and I highly recommend the steak."
    ]
    image_paths = ["path/to/image1.jpg", "path/to/image2.png"]
    
    try:
        # Moderate mixed content with vision analysis
        result = moderate_mixed_content(api_key, text_items, image_paths, analyze_images=True)
        
        print(f"Overall moderation result: {result['flagged']}")
        
        # Check text results
        if text_items:
            print(f"Combined text flagged: {result['combined_text_moderation']['flagged']}")
            
            for i in range(len(text_items)):
                print(f"Text item {i + 1} flagged: {result['results'][i]['flagged']}")
        
        # Check image results and vision analysis
        if image_paths and 'vision_analysis' in result:
            for analysis in result['vision_analysis']:
                image_index = analysis['image_index'] - len(text_items)
                print(f"Image {image_index + 1} analysis: {analysis['analysis']}")
                print(f"Image {image_index + 1} flagged: {analysis['flagged']}")
    
    except Exception as e:
        print(f"Error: {str(e)}")

if __name__ == "__main__":
    example()

Next Steps