📝 doc: Azure content safety Proxy usage

Signed-off-by: Lunik <lunik@tiwabbit.fr>
This commit is contained in:
Lunik
2024-05-04 10:39:43 +02:00
parent 9ba9b3891f
commit cb178723ca
3 changed files with 90 additions and 16 deletions
+85 -1
View File
@@ -17,6 +17,7 @@ Log Proxy Input, Output, Exceptions using Custom Callbacks, Langfuse, OpenTeleme
- [Logging to Sentry](#logging-proxy-inputoutput---sentry)
- [Logging to Traceloop (OpenTelemetry)](#logging-proxy-inputoutput-traceloop-opentelemetry)
- [Logging to Athina](#logging-proxy-inputoutput-athina)
- [Moderation with Azure Content-Safety](#moderation-with-azure-content-safety)
## Custom Callback Class [Async]
Use this when you want to run custom callbacks in `python`
@@ -1003,4 +1004,87 @@ curl --location 'http://0.0.0.0:4000/chat/completions' \
}
]
}'
```
```
## Moderation with Azure Content Safety
[Azure Content-Safety](https://azure.microsoft.com/en-us/products/ai-services/ai-content-safety) is a Microsoft Azure service that provides content moderation APIs to detect potential offensive, harmful, or risky content in text.
We will use the `--config` to set `litellm.success_callback = ["azure_content_safety"]` this will moderate all LLM calls using Azure Content Safety.
**Step 0** Deploy Azure Content Safety
Deploy an Azure Content-Safety instance from the Azure Portal and get the `endpoint` and `key`.
**Step 1** Set Athina API key
```shell
AZURE_CONTENT_SAFETY_KEU = "<your-azure-content-safety-key>"
```
**Step 2**: Create a `config.yaml` file and set `litellm_settings`: `success_callback`
```yaml
model_list:
- model_name: gpt-3.5-turbo
litellm_params:
model: gpt-3.5-turbo
litellm_settings:
callbacks: ["azure_content_safety"]
azure_content_safety_params:
endpoint: "<your-azure-content-safety-endpoint>"
key: "os.environ/AZURE_CONTENT_SAFETY_KEY"
```
**Step 3**: Start the proxy, make a test request
Start proxy
```shell
litellm --config config.yaml --debug
```
Test Request
```
curl --location 'http://0.0.0.0:4000/chat/completions' \
--header 'Content-Type: application/json' \
--data ' {
"model": "gpt-3.5-turbo",
"messages": [
{
"role": "user",
"content": "Hi, how are you?"
}
]
}'
```
An HTTP 400 error will be returned if the content is detected with a value greater than the threshold set in the `config.yaml`.
The details of the response will describe :
- The `source` : input text or llm generated text
- The `category` : the category of the content that triggered the moderation
- The `severity` : the severity from 0 to 10
**Step 4**: Customizing Azure Content Safety Thresholds
You can customize the thresholds for each category by setting the `thresholds` in the `config.yaml`
```yaml
model_list:
- model_name: gpt-3.5-turbo
litellm_params:
model: gpt-3.5-turbo
litellm_settings:
callbacks: ["azure_content_safety"]
azure_content_safety_params:
endpoint: "<your-azure-content-safety-endpoint>"
key: "os.environ/AZURE_CONTENT_SAFETY_KEY"
thresholds:
Hate: 6
SelfHarm: 8
Sexual: 6
Violence: 4
```
:::info
`thresholds` are not required by default, but you can tune the values to your needs.
Default values is `4` for all categories
:::
+3 -13
View File
@@ -59,16 +59,6 @@ class _PROXY_AzureContentSafety(
except:
pass
def _severity(self, severity):
if severity >= 6:
return "high"
elif severity >= 4:
return "medium"
elif severity >= 2:
return "low"
else:
return "safe"
def _compute_result(self, response):
result = {}
@@ -80,7 +70,7 @@ class _PROXY_AzureContentSafety(
if severity is not None:
result[category] = {
"filtered": severity >= self.thresholds[category],
"severity": self._severity(severity),
"severity": severity,
}
return result
@@ -148,10 +138,10 @@ class _PROXY_AzureContentSafety(
content=response.choices[0].message.content, source="output"
)
#async def async_post_call_streaming_hook(
# async def async_post_call_streaming_hook(
# self,
# user_api_key_dict: UserAPIKeyAuth,
# response: str,
#):
# ):
# self.print_verbose(f"Inside Azure Content-Safety Call-Stream Hook")
# await self.test_violation(content=response, source="output")
+2 -2
View File
@@ -50,7 +50,7 @@ async def test_strict_input_filtering_01():
assert exc_info.value.detail["source"] == "input"
assert exc_info.value.detail["category"] == "Hate"
assert exc_info.value.detail["severity"] == "low"
assert exc_info.value.detail["severity"] == 2
@pytest.mark.asyncio
@@ -168,7 +168,7 @@ async def test_strict_output_filtering_01():
assert exc_info.value.detail["source"] == "output"
assert exc_info.value.detail["category"] == "Hate"
assert exc_info.value.detail["severity"] == "low"
assert exc_info.value.detail["severity"] == 2
@pytest.mark.asyncio