11# litellm/proxy/guardrails/guardrail_hooks/pangea.py
22import os
3- import sys
4-
5- # Adds the parent directory to the system path to allow importing litellm modules
6- sys .path .insert (
7- 0 , os .path .abspath ("../../.." )
8- )
9- import json
103from typing import Any , List , Literal , Optional , Union
114
125from fastapi import HTTPException
136
14- import litellm
157from litellm ._logging import verbose_proxy_logger
168from litellm .integrations .custom_guardrail import (
179 CustomGuardrail ,
@@ -50,7 +42,8 @@ class PangeaHandler(CustomGuardrail):
5042 def __init__ (
5143 self ,
5244 guardrail_name : str ,
53- pangea_recipe : str ,
45+ pangea_input_recipe : Optional [str ] = None ,
46+ pangea_output_recipe : Optional [str ] = None ,
5447 api_key : Optional [str ] = None ,
5548 api_base : Optional [str ] = None ,
5649 ** kwargs ,
@@ -80,20 +73,22 @@ def __init__(
8073 or os .environ .get ("PANGEA_API_BASE" )
8174 or "https://ai-guard.aws.us.pangea.cloud"
8275 )
83- self .pangea_recipe = pangea_recipe
76+ self .pangea_input_recipe = pangea_input_recipe
77+ self .pangea_output_recipe = pangea_output_recipe
8478 self .guardrail_endpoint = f"{ self .api_base } /v1/text/guard"
8579
8680 # Pass relevant kwargs to the parent class
8781 super ().__init__ (guardrail_name = guardrail_name , ** kwargs )
8882 verbose_proxy_logger .info (
89- f"Initialized Pangea Guardrail: name={ guardrail_name } , recipe={ pangea_recipe } , api_base={ self .api_base } "
83+ f"Initialized Pangea Guardrail: name={ guardrail_name } , recipe={ pangea_input_recipe } , api_base={ self .api_base } "
9084 )
9185
9286 def _prepare_payload (
9387 self ,
9488 messages : Optional [List [AllMessageValues ]] = None ,
9589 text_input : Optional [str ] = None ,
9690 request_data : Optional [dict ] = None ,
91+ recipe : Optional [str ] = None ,
9792 ) -> dict :
9893 """
9994 Prepares the payload for the Pangea AI Guard API request.
@@ -107,9 +102,12 @@ def _prepare_payload(
107102 dict: The payload dictionary for the API request.
108103 """
109104 payload : dict [str , Any ] = {
110- "recipe" : self .pangea_recipe ,
111105 "debug" : False , # Or make this configurable if needed
112106 }
107+
108+ if recipe :
109+ payload ["recipe" ] = recipe
110+
113111 if messages :
114112 # Ensure messages are in the format Pangea expects (list of dicts with 'role' and 'content')
115113 payload ["messages" ] = [
@@ -253,7 +251,7 @@ async def async_moderation_hook(
253251
254252 try :
255253 payload = self ._prepare_payload (
256- messages = messages , text_input = text_input , request_data = data
254+ messages = messages , text_input = text_input , request_data = data , recipe = self . pangea_input_recipe
257255 )
258256 await self ._call_pangea_guard (
259257 payload = payload , request_data = data , hook_name = "moderation_hook"
@@ -303,7 +301,7 @@ async def async_post_call_success_hook(
303301 try :
304302 # Scan only the output text in the post-call hook
305303 payload = self ._prepare_payload (
306- text_input = response_str , request_data = data
304+ text_input = response_str , request_data = data , recipe = self . pangea_output_recipe
307305 )
308306 await self ._call_pangea_guard (
309307 payload = payload ,
@@ -321,4 +319,4 @@ async def async_post_call_success_hook(
321319 "error" : f"Error preparing Pangea payload for response: { ve } " ,
322320 "guardrail_name" : self .guardrail_name ,
323321 },
324- )
322+ )
0 commit comments