diff --git a/sdk/contentsafety/Azure.AI.ContentSafety/CHANGELOG.md b/sdk/contentsafety/Azure.AI.ContentSafety/CHANGELOG.md index eb08e4a4d10ad..58a26dff66cd5 100644 --- a/sdk/contentsafety/Azure.AI.ContentSafety/CHANGELOG.md +++ b/sdk/contentsafety/Azure.AI.ContentSafety/CHANGELOG.md @@ -1,5 +1,5 @@ # Release History -## 1.0.0-beta.1 (2023-05-22) +## 1.0.0-beta.1 (2023-06-06) - Initial version diff --git a/sdk/contentsafety/Azure.AI.ContentSafety/README.md b/sdk/contentsafety/Azure.AI.ContentSafety/README.md index 1bf9c8a8fd7ed..36ed52989b015 100644 --- a/sdk/contentsafety/Azure.AI.ContentSafety/README.md +++ b/sdk/contentsafety/Azure.AI.ContentSafety/README.md @@ -1,43 +1,96 @@ -# Azure ContentSafety client library for .NET +# Azure AI Content Safety client library for .NET -This section should give out brief introduction of the client library. +[Azure AI Content Safety][contentsafety_overview] detects harmful user-generated and AI-generated content in applications and services. Content Safety includes several APIs that allow you to detect material that is harmful: -* First sentence: **Describe the service** briefly. You can usually use the first line of the service's docs landing page for this (Example: [Cosmos DB docs landing page](https://docs.microsoft.com/azure/cosmos-db/)). -* Next, add a **bulleted list** of the **most common tasks** supported by the package or library, prefaced with "Use the client library for [Product Name] to:". Then, provide code snippets for these tasks in the [Examples](#examples) section later in the document. Keep the task list short but include those tasks most developers need to perform with your package. +* Text Analysis API: Scans text for sexual content, violence, hate, and self harm with multi-severity levels. +* Image Analysis API: Scans images for sexual content, violence, hate, and self harm with multi-severity levels. +* Text Blocklist Management APIs: The default AI classifiers are sufficient for most content safety needs; however, you might need to screen for terms that are specific to your use case. You can create blocklists of terms to use with the Text API. - [Source code](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/contentsafety/Azure.AI.ContentSafety) | [Package (NuGet)](https://www.nuget.org) | [API reference documentation](https://azure.github.io/azure-sdk-for-net) | [Product documentation](https://docs.microsoft.com/azure) +[Source code](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/contentsafety/Azure.AI.ContentSafety) | [Package (NuGet)](https://www.nuget.org) | [API reference documentation](https://azure.github.io/azure-sdk-for-net) | [Product documentation](https://learn.microsoft.com/azure/cognitive-services/content-safety/) ## Getting started -This section should include everything a developer needs to do to install and create their first client connection *very quickly*. - ### Install the package -First, provide instruction for obtaining and installing the package or library. This section might include only a single line of code, like `dotnet add package package-name`, but should enable a developer to successfully install the package from NuGet, npm, or even cloning a GitHub repository. - Install the client library for .NET with [NuGet](https://www.nuget.org/ ): ```dotnetcli -dotnet add package Azure.AI --prerelease +dotnet add package Azure.AI.ContentSafety --prerelease ``` ### Prerequisites -Include a section after the install command that details any requirements that must be satisfied before a developer can [authenticate](#authenticate-the-client) and test all of the snippets in the [Examples](#examples) section. For example, for Cosmos DB: - -> You must have an [Azure subscription](https://azure.microsoft.com/free/dotnet/) and [Cosmos DB account](https://docs.microsoft.com/azure/cosmos-db/account-overview) (SQL API). In order to take advantage of the C# 8.0 syntax, it is recommended that you compile using the [.NET Core SDK](https://dotnet.microsoft.com/download) 3.0 or higher with a [language version](https://docs.microsoft.com/dotnet/csharp/language-reference/configure-language-version#override-a-default) of `latest`. It is also possible to compile with the .NET Core SDK 2.1.x using a language version of `preview`. +* You need an [Azure subscription][azure_sub] to use this package. +* An existing [Azure AI Content Safety][contentsafety_overview] instance. ### Authenticate the client -If your library requires authentication for use, such as for Azure services, include instructions and example code needed for initializing and authenticating. +#### Get the endpoint + +You can find the endpoint for your Azure AI Content Safety service resource using the [Azure Portal][azure_portal] or [Azure CLI][azure_cli_endpoint_lookup]: + +```bash +# Get the endpoint for the Azure AI Content Safety service resource +az cognitiveservices account show --name "resource-name" --resource-group "resource-group-name" --query "properties.endpoint" +``` + +#### Get the API key + +The API key can be found in the [Azure Portal][azure_portal] or by running the following [Azure CLI][azure_cli_key_lookup] command: + +```bash +az cognitiveservices account keys list --name "" --resource-group "" +``` + +#### Create a ContentSafetyClient with AzureKeyCredential + +Pass the API key as a string into an instance of `AzureKeyCredential`. -For example, include details on obtaining an account key and endpoint URI, setting environment variables for each, and initializing the client object. +```csharp +string endpoint = "https://.cognitiveservices.azure.com/"; +string key = ""; + +ContentSafetyClient client = new ContentSafetyClient(new Uri(endpoint), new AzureKeyCredential(key)); +``` ## Key concepts -The *Key concepts* section should describe the functionality of the main classes. Point out the most important and useful classes in the package (with links to their reference pages) and explain how those classes work together. Feel free to use bulleted lists, tables, code blocks, or even diagrams for clarity. +### Harm categories + +Content Safety recognizes four distinct categories of objectionable content. +|Category |Description | +|---------|---------| +|Hate |Hate refers to any content that attacks or uses pejorative or discriminatory language in reference to a person or identity group based on certain differentiating attributes of that group. This includes but is not limited to race, ethnicity, nationality, gender identity and expression, sexual orientation, religion, immigration status, ability status, personal appearance, and body size.| +|Sexual |Sexual describes content related to anatomical organs and genitals, romantic relationships, acts portrayed in erotic or affectionate terms, pregnancy, physical sexual acts—including those acts portrayed as an assault or a forced sexual violent act against one’s will—, prostitution, pornography, and abuse.| +|Violence |Violence describes content related to physical actions intended to hurt, injure, damage, or kill someone or something. It also includes weapons, guns and related entities, such as manufacturers, associations, legislation, and similar.| +|Self-harm |Self-harm describes content related to physical actions intended to purposely hurt, injure, or damage one’s body or kill oneself.| + +Classification can be multi-labeled. For example, when a text sample goes through the text moderation model, it could be classified as both Sexual content and Violence. + +### Severity levels + +Every harm category the service applies also comes with a severity level rating. The severity level is meant to indicate the severity of the consequences of showing the flagged content. +|Severity |Label | +|---------|---------| +|0 |Safe| +|2 |Low| +|4 |Medium| +|6 |High| + +### Text blocklist management + +Following operations are supported to manage your text blocklist: -Include the *Thread safety* and *Additional concepts* sections below at the end of your *Key concepts* section. You may remove or add links depending on what your library makes use of: +* Create or modify a blocklist +* List all blocklists +* Get a blocklist by blocklistName +* Add blockItems to a blocklist +* Remove blockItems from a blocklist +* List all blockItems in a blocklist by blocklistName +* Get a blockItem in a blocklist by blockItemId and blocklistName +* Delete a blocklist and all of its blockItems + +You can set the blocklists you want to use when analyze text, then you can get blocklist match result from returned response. ### Thread safety @@ -56,32 +109,277 @@ We guarantee that all client instance methods are thread-safe and independent of ## Examples -You can familiarize yourself with different APIs using [Samples](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples). +The following section provides several code snippets covering some of the most common Content Safety service tasks, including: + +* [Analyze text](#analyze-text) +* [Analyze image](#analyze-image) +* [Manage text blocklist](#manage-text-blocklist) + +Please refer to [sample data](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples/sample_data) for the data used here. For more samples, please refer to [Samples](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples). + +### Analyze text + +#### Analyze text without blocklists + +```C# Snippet:Azure_AI_ContentSafety_AnalyzeText +string datapath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Samples", "sample_data", "text.txt"); +string text = File.ReadAllText(datapath); + +var request = new AnalyzeTextOptions(text); + +Response response; +try +{ + response = client.AnalyzeText(request); +} +catch (RequestFailedException ex) +{ + Console.WriteLine("Analyze text failed.\nStatus code: {0}, Error code: {1}, Error message: {2}", ex.Status, ex.ErrorCode, ex.Message); + throw; +} + +Console.WriteLine("Hate severity: {0}", response.Value.HateResult?.Severity ?? 0); +Console.WriteLine("SelfHarm severity: {0}", response.Value.SelfHarmResult?.Severity ?? 0); +Console.WriteLine("Sexual severity: {0}", response.Value.SexualResult?.Severity ?? 0); +Console.WriteLine("Violence severity: {0}", response.Value.ViolenceResult?.Severity ?? 0); +``` -### +#### Analyze text with blocklists + +```C# Snippet:Azure_AI_ContentSafety_AnalyzeTextWithBlocklist +// After you edit your blocklist, it usually takes effect in 5 minutes, please wait some time before analyzing with blocklist after editing. +var request = new AnalyzeTextOptions("I h*te you and I want to k*ll you"); +request.BlocklistNames.Add(blocklistName); +request.BreakByBlocklists = true; + +Response response; +try +{ + response = client.AnalyzeText(request); +} +catch (RequestFailedException ex) +{ + Console.WriteLine("Analyze text failed.\nStatus code: {0}, Error code: {1}, Error message: {2}", ex.Status, ex.ErrorCode, ex.Message); + throw; +} + +if (response.Value.BlocklistsMatchResults != null) +{ + Console.WriteLine("\nBlocklist match result:"); + foreach (var matchResult in response.Value.BlocklistsMatchResults) + { + Console.WriteLine("Blockitem was hit in text: Offset: {0}, Length: {1}", matchResult.Offset, matchResult.Length); + Console.WriteLine("BlocklistName: {0}, BlockItemId: {1}, BlockItemText: {2}, ", matchResult.BlocklistName, matchResult.BlockItemId, matchResult.BlockItemText); + } +} +``` + +### Analyze image + +```C# Snippet:Azure_AI_ContentSafety_AnalyzeImage +string datapath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Samples", "sample_data", "image.jpg"); +ImageData image = new ImageData() { Content = BinaryData.FromBytes(File.ReadAllBytes(datapath)) }; + +var request = new AnalyzeImageOptions(image); + +Response response; +try +{ + response = client.AnalyzeImage(request); +} +catch (RequestFailedException ex) +{ + Console.WriteLine("Analyze image failed.\nStatus code: {0}, Error code: {1}, Error message: {2}", ex.Status, ex.ErrorCode, ex.Message); + throw; +} + +Console.WriteLine("Hate severity: {0}", response.Value.HateResult?.Severity ?? 0); +Console.WriteLine("SelfHarm severity: {0}", response.Value.SelfHarmResult?.Severity ?? 0); +Console.WriteLine("Sexual severity: {0}", response.Value.SexualResult?.Severity ?? 0); +Console.WriteLine("Violence severity: {0}", response.Value.ViolenceResult?.Severity ?? 0); +``` + +### Manage text blocklist + +#### Create or update text blocklist + +```C# Snippet:Azure_AI_ContentSafety_CreateNewBlocklist +var blocklistName = "TestBlocklist"; +var blocklistDescription = "Test blocklist management"; + +var data = new +{ + description = blocklistDescription, +}; + +var createResponse = client.CreateOrUpdateTextBlocklist(blocklistName, RequestContent.Create(data)); +if (createResponse.Status == 201) +{ + Console.WriteLine("\nBlocklist {0} created.", blocklistName); +} +else if (createResponse.Status == 200) +{ + Console.WriteLine("\nBlocklist {0} updated.", blocklistName); +} +``` -You can create a client and call the client's `` method. +#### Add blockItems + +```C# Snippet:Azure_AI_ContentSafety_AddBlockItems +string blockItemText1 = "k*ll"; +string blockItemText2 = "h*te"; + +var blockItems = new TextBlockItemInfo[] { new TextBlockItemInfo(blockItemText1), new TextBlockItemInfo(blockItemText2) }; +var addedBlockItems = client.AddBlockItems(blocklistName, new AddBlockItemsOptions(blockItems)); + +if (addedBlockItems != null && addedBlockItems.Value != null) +{ + Console.WriteLine("\nBlockItems added:"); + foreach (var addedBlockItem in addedBlockItems.Value.Value) + { + Console.WriteLine("BlockItemId: {0}, Text: {1}, Description: {2}", addedBlockItem.BlockItemId, addedBlockItem.Text, addedBlockItem.Description); + } +} +``` + +#### List text blocklists + +```C# Snippet:Azure_AI_ContentSafety_ListBlocklists +var blocklists = client.GetTextBlocklists(); +Console.WriteLine("\nList blocklists:"); +foreach (var blocklist in blocklists) +{ + Console.WriteLine("BlocklistName: {0}, Description: {1}", blocklist.BlocklistName, blocklist.Description); +} +``` + +#### Get text blocklist + +```C# Snippet:Azure_AI_ContentSafety_GetBlocklist +var getBlocklist = client.GetTextBlocklist(blocklistName); +if (getBlocklist != null && getBlocklist.Value != null) +{ + Console.WriteLine("\nGet blocklist:"); + Console.WriteLine("BlocklistName: {0}, Description: {1}", getBlocklist.Value.BlocklistName, getBlocklist.Value.Description); +} +``` + +#### List blockItems + +```C# Snippet:Azure_AI_ContentSafety_ListBlockItems +var allBlockitems = client.GetTextBlocklistItems(blocklistName); +Console.WriteLine("\nList BlockItems:"); +foreach (var blocklistItem in allBlockitems) +{ + Console.WriteLine("BlockItemId: {0}, Text: {1}, Description: {2}", blocklistItem.BlockItemId, blocklistItem.Text, blocklistItem.Description); +} +``` + +#### Get blockItem + +```C# Snippet:Azure_AI_ContentSafety_GetBlockItem +var getBlockItemId = addedBlockItems.Value.Value[0].BlockItemId; +var getBlockItem = client.GetTextBlocklistItem(blocklistName, getBlockItemId); +Console.WriteLine("\nGet BlockItem:"); +Console.WriteLine("BlockItemId: {0}, Text: {1}, Description: {2}", getBlockItem.Value.BlockItemId, getBlockItem.Value.Text, getBlockItem.Value.Description); +``` + +#### Remove blockItems + +```C# Snippet:Azure_AI_ContentSafety_RemoveBlockItems +var removeBlockItemId = addedBlockItems.Value.Value[0].BlockItemId; +var removeBlockItemIds = new List { removeBlockItemId }; +var removeResult = client.RemoveBlockItems(blocklistName, new RemoveBlockItemsOptions(removeBlockItemIds)); + +if (removeResult != null && removeResult.Status == 204) +{ + Console.WriteLine("\nBlockItem removed: {0}.", removeBlockItemId); +} +``` + +#### Delete text blocklist + +```C# Snippet:Azure_AI_ContentSafety_DeleteBlocklist +var deleteResult = client.DeleteTextBlocklist(blocklistName); +if (deleteResult != null && deleteResult.Status == 204) +{ + Console.WriteLine("\nDeleted blocklist."); +} +``` ## Troubleshooting -Describe common errors and exceptions, how to "unpack" them if necessary, and include guidance for graceful handling and recovery. +### General + +When you interact with the Azure AI Content Safety client library using the .NET SDK, errors returned by the service will result in a `RequestFailedException` with the same HTTP status code returned by the REST API request and error code defined by our service. You can parse the `RequestFailedException` like below: -Provide information to help developers avoid throttling or other service-enforced errors they might encounter. For example, provide guidance and examples for using retry or connection policies in the API. +```csharp +try +{ + response = client.AnalyzeText(request); +} +catch (RequestFailedException ex) +{ + Console.WriteLine("Analyze text failed.\nStatus code: {0}, Error code: {1}, Error message: {2}", ex.Status, ex.ErrorCode, ex.Message); + throw; +} +``` + +Example console output: + +``` +Analyze text failed. +Status code: 400, Error code: InvalidRequestBody, Error message: The length of given text 1158 exceeds the limit 1000. | Request Id: a04c7c32-ef27-4c23-8b18-07545b24765b, Timestamp: 2023-06-01T16:43:52Z. +``` -If the package or a related package supports it, include tips for logging or enabling instrumentation to help them debug their code. +Error codes are defined as below: + +|Error Code |Possible reasons |Suggestions| +|-----------|-------------------|-----------| +|InvalidRequestBody |One or more fields in the request body do not match the API definition. |1. Check the API version you specified in the API call.
2. Check the corresponding API definition for the API version you selected.| +|InvalidResourceName |The resource name you specified in the URL does not meet the requirements, like the blocklist name, blocklist term ID, etc. |1. Check the API version you specified in the API call.
2. Check whether the given name has invalid characters according to the API definition.| +|ResourceNotFound |The resource you specified in the URL may not exist, like the blocklist name. |1. Check the API version you specified in the API call.
2. Double check the existence of the resource specified in the URL.| +|InternalError |Some unexpected situations on the server side have been triggered. |1. You may want to retry a few times after a small period and see it the issue happens again.
2. Contact Azure Support if this issue persists.| +|ServerBusy |The server side cannot process the request temporarily. |1. You may want to retry a few times after a small period and see it the issue happens again.
2.Contact Azure Support if this issue persists.| +|TooManyRequests |The current RPS has exceeded the quota for your current SKU. |1. Check the pricing table to understand the RPS quota.
2.Contact Azure Support if you need more QPS.| + +### Setting up console logging + +The simplest way to see the logs is to enable the console logging. +To create an Azure SDK log listener that outputs messages to console use the AzureEventSourceListener.CreateConsoleLogger method. + +```C# +// Setup a listener to monitor logged events. +using AzureEventSourceListener listener = AzureEventSourceListener.CreateConsoleLogger(); +``` + +To learn more about other logging mechanisms see [Diagnostics Samples][logging]. ## Next steps -* Provide a link to additional code examples, ideally to those sitting alongside the README in the package's `/samples` directory. -* If appropriate, point users to other packages that might be useful. -* If you think there's a good chance that developers might stumble across your package in error (because they're searching for specific functionality and mistakenly think the package provides that functionality), point them to the packages they might be looking for. +### Additional documentation + +For more extensive documentation on Azure Content Safety, see the [Azure AI Content Safety][contentsafety_overview] on docs.microsoft.com. ## Contributing -This is a template, but your SDK readme should include details on how to contribute code to the repo/package. +This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit [cla.microsoft.com][cla]. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct][code_of_conduct]. For more information see the [Code of Conduct FAQ][coc_faq] or contact [opencode@microsoft.com][coc_contact] with any additional questions or comments. -[style-guide-msft]: https://docs.microsoft.com/style-guide/capitalization -[style-guide-cloud]: https://aka.ms/azsdk/cloud-style-guide +[azure_sub]: https://azure.microsoft.com/free/ +[contentsafety_overview]: https://aka.ms/acs-doc +[azure_portal]: https://ms.portal.azure.com/ +[azure_cli_endpoint_lookup]: https://docs.microsoft.com/cli/azure/cognitiveservices/account?view=azure-cli-latest#az-cognitiveservices-account-show +[azure_cli_key_lookup]: https://docs.microsoft.com/cli/azure/cognitiveservices/account/keys?view=azure-cli-latest#az-cognitiveservices-account-keys-list +[logging]: https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/core/Azure.Core/samples/Diagnostics.md + +[cla]: https://cla.microsoft.com +[code_of_conduct]: https://opensource.microsoft.com/codeofconduct/ +[coc_faq]: https://opensource.microsoft.com/codeofconduct/faq/ +[coc_contact]: mailto:opencode@microsoft.com ![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-net/sdk//Azure.AI/README.png) diff --git a/sdk/contentsafety/Azure.AI.ContentSafety/samples/README.md b/sdk/contentsafety/Azure.AI.ContentSafety/samples/README.md new file mode 100644 index 0000000000000..1fa817eef5f9b --- /dev/null +++ b/sdk/contentsafety/Azure.AI.ContentSafety/samples/README.md @@ -0,0 +1,20 @@ +--- +page_type: sample +languages: +- csharp +products: +- azure +- azure-cognitive-services +name: Azure AI Content Safety samples for .NET +description: Samples for the Azure.AI.ContentSafety client library +--- + +# Azure AI Content Safety client SDK Samples + +These code samples show common scenario operations with the Content Safety client library. + +|**Sample Name**|**Description**| +|----------------|-------------| +|[Sample1_AnalyzeText](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/contentsafety/Azure.AI.ContentSafety/samples/Sample1_AnalyzeText.md) |Scans text for sexual content, violence, hate, and self harm with multi-severity levels.| +|[Sample2_AnalyzeImage](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/contentsafety/Azure.AI.ContentSafety/samples/Sample2_AnalyzeImage.md) |Scans images for sexual content, violence, hate, and self harm with multi-severity levels.| +|[Sample3_ManageTextBlocklist](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/contentsafety/Azure.AI.ContentSafety/samples/Sample3_ManageTextBlocklist.md) |The default AI classifiers are sufficient for most content safety needs; however, you might need to screen for terms that are specific to your use case. You can create blocklists of terms to use with the Text API.| diff --git a/sdk/contentsafety/Azure.AI.ContentSafety/samples/Sample1_AnalyzeText.md b/sdk/contentsafety/Azure.AI.ContentSafety/samples/Sample1_AnalyzeText.md new file mode 100644 index 0000000000000..598ec48780aff --- /dev/null +++ b/sdk/contentsafety/Azure.AI.ContentSafety/samples/Sample1_AnalyzeText.md @@ -0,0 +1,46 @@ +# Analyze Text + +This sample shows how to analyze text using Azure AI Content Safety. +To get started, make sure you have satisfied all the prerequisites and got all the resources required by [README][README]. + +## Create a ContentSafetyClient + +To create a new `ContentSafetyClient` you need the endpoint and credentials from your resource. In the sample below you'll use a Content Safety API key credential by creating an `AzureKeyCredential` object. + +You can set `endpoint` and `key` based on an environment variable, a configuration setting, or any way that works for your application. + +```C# Snippet:Azure_AI_ContentSafety_CreateClient +string endpoint = TestEnvironment.Endpoint; +string key = TestEnvironment.Key; + +ContentSafetyClient client = new ContentSafetyClient(new Uri(endpoint), new AzureKeyCredential(key)); +``` + +## Load text and analyze text + +You can download our [sample data](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples/sample_data), read in the text and initialize `AnalyzeTextOptions` with it. Then call `AnalyzeText` to get analysis result. + +```C# Snippet:Azure_AI_ContentSafety_AnalyzeText +string datapath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Samples", "sample_data", "text.txt"); +string text = File.ReadAllText(datapath); + +var request = new AnalyzeTextOptions(text); + +Response response; +try +{ + response = client.AnalyzeText(request); +} +catch (RequestFailedException ex) +{ + Console.WriteLine("Analyze text failed.\nStatus code: {0}, Error code: {1}, Error message: {2}", ex.Status, ex.ErrorCode, ex.Message); + throw; +} + +Console.WriteLine("Hate severity: {0}", response.Value.HateResult?.Severity ?? 0); +Console.WriteLine("SelfHarm severity: {0}", response.Value.SelfHarmResult?.Severity ?? 0); +Console.WriteLine("Sexual severity: {0}", response.Value.SexualResult?.Severity ?? 0); +Console.WriteLine("Violence severity: {0}", response.Value.ViolenceResult?.Severity ?? 0); +``` + +[README]: https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/contentsafety/Azure.AI.ContentSafety/README.md diff --git a/sdk/contentsafety/Azure.AI.ContentSafety/samples/Sample2_AnalyzeImage.md b/sdk/contentsafety/Azure.AI.ContentSafety/samples/Sample2_AnalyzeImage.md new file mode 100644 index 0000000000000..9af9bf039cf41 --- /dev/null +++ b/sdk/contentsafety/Azure.AI.ContentSafety/samples/Sample2_AnalyzeImage.md @@ -0,0 +1,46 @@ +# Analyze Image + +This sample shows how to analyze image using Azure AI Content Safety. +To get started, make sure you have satisfied all the prerequisites and got all the resources required by [README][README]. + +## Create a ContentSafetyClient + +To create a new `ContentSafetyClient` you need the endpoint and credentials from your resource. In the sample below you'll use a Content Safety API key credential by creating an `AzureKeyCredential` object. + +You can set `endpoint` and `key` based on an environment variable, a configuration setting, or any way that works for your application. + +```C# Snippet:Azure_AI_ContentSafety_CreateClient +string endpoint = TestEnvironment.Endpoint; +string key = TestEnvironment.Key; + +ContentSafetyClient client = new ContentSafetyClient(new Uri(endpoint), new AzureKeyCredential(key)); +``` + +## Load image and analyze image + +You can download our [sample data](https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples/sample_data), read in the image and initialize `AnalyzeImageOptions` with it. Then call `AnalyzeImage` to get analysis result. + +```C# Snippet:Azure_AI_ContentSafety_AnalyzeImage +string datapath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Samples", "sample_data", "image.jpg"); +ImageData image = new ImageData() { Content = BinaryData.FromBytes(File.ReadAllBytes(datapath)) }; + +var request = new AnalyzeImageOptions(image); + +Response response; +try +{ + response = client.AnalyzeImage(request); +} +catch (RequestFailedException ex) +{ + Console.WriteLine("Analyze image failed.\nStatus code: {0}, Error code: {1}, Error message: {2}", ex.Status, ex.ErrorCode, ex.Message); + throw; +} + +Console.WriteLine("Hate severity: {0}", response.Value.HateResult?.Severity ?? 0); +Console.WriteLine("SelfHarm severity: {0}", response.Value.SelfHarmResult?.Severity ?? 0); +Console.WriteLine("Sexual severity: {0}", response.Value.SexualResult?.Severity ?? 0); +Console.WriteLine("Violence severity: {0}", response.Value.ViolenceResult?.Severity ?? 0); +``` + +[README]: https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/contentsafety/Azure.AI.ContentSafety/README.md diff --git a/sdk/contentsafety/Azure.AI.ContentSafety/samples/Sample3_ManageTextBlocklist.md b/sdk/contentsafety/Azure.AI.ContentSafety/samples/Sample3_ManageTextBlocklist.md new file mode 100644 index 0000000000000..c9cc3d9f4d41e --- /dev/null +++ b/sdk/contentsafety/Azure.AI.ContentSafety/samples/Sample3_ManageTextBlocklist.md @@ -0,0 +1,163 @@ +# Manage Text Blocklist + +This sample shows how to create a text blocklist and analyze text with blocklists using Azure AI Content Safety. +To get started, make sure you have satisfied all the prerequisites and got all the resources required by [README][README]. + +## Create a ContentSafetyClient + +To create a new `ContentSafetyClient` you need the endpoint and credentials from your resource. In the sample below you'll use a Content Safety API key credential by creating an `AzureKeyCredential` object. + +You can set `endpoint` and `key` based on an environment variable, a configuration setting, or any way that works for your application. + +```C# Snippet:Azure_AI_ContentSafety_CreateClient +string endpoint = TestEnvironment.Endpoint; +string key = TestEnvironment.Key; + +ContentSafetyClient client = new ContentSafetyClient(new Uri(endpoint), new AzureKeyCredential(key)); +``` + +## Create a text blocklist + +You can create or update a text blocklist by `CreateOrUpdateTextBlocklist`, the blocklist name is unique. If the new blocklist is created successfully it will return `201`, if an existed blocklist is updated successfully it will return `200`. + +```C# Snippet:Azure_AI_ContentSafety_CreateNewBlocklist +var blocklistName = "TestBlocklist"; +var blocklistDescription = "Test blocklist management"; + +var data = new +{ + description = blocklistDescription, +}; + +var createResponse = client.CreateOrUpdateTextBlocklist(blocklistName, RequestContent.Create(data)); +if (createResponse.Status == 201) +{ + Console.WriteLine("\nBlocklist {0} created.", blocklistName); +} +else if (createResponse.Status == 200) +{ + Console.WriteLine("\nBlocklist {0} updated.", blocklistName); +} +``` + +## Add blockItems to text blocklist + +You can add multiple blockItems once by calling `AddBlockItems`. There is a maximum limit of **10,000 items** in total across all lists. You can add at most **100 blockItems** in one request. + +```C# Snippet:Azure_AI_ContentSafety_AddBlockItems +string blockItemText1 = "k*ll"; +string blockItemText2 = "h*te"; + +var blockItems = new TextBlockItemInfo[] { new TextBlockItemInfo(blockItemText1), new TextBlockItemInfo(blockItemText2) }; +var addedBlockItems = client.AddBlockItems(blocklistName, new AddBlockItemsOptions(blockItems)); + +if (addedBlockItems != null && addedBlockItems.Value != null) +{ + Console.WriteLine("\nBlockItems added:"); + foreach (var addedBlockItem in addedBlockItems.Value.Value) + { + Console.WriteLine("BlockItemId: {0}, Text: {1}, Description: {2}", addedBlockItem.BlockItemId, addedBlockItem.Text, addedBlockItem.Description); + } +} +``` + +## Load text and analyze text with blocklists + +You can read in the text and initialize `AnalyzeTextOptions` with it. Then attach the blocklists you would like to use by adding their blocklist names, and call `AnalyzeText` to get analysis result. Note that after you edit your blocklist, it usually takes effect in **5 minutes**, please wait some time before analyzing with blocklist after editing. + +```C# Snippet:Azure_AI_ContentSafety_AnalyzeTextWithBlocklist +// After you edit your blocklist, it usually takes effect in 5 minutes, please wait some time before analyzing with blocklist after editing. +var request = new AnalyzeTextOptions("I h*te you and I want to k*ll you"); +request.BlocklistNames.Add(blocklistName); +request.BreakByBlocklists = true; + +Response response; +try +{ + response = client.AnalyzeText(request); +} +catch (RequestFailedException ex) +{ + Console.WriteLine("Analyze text failed.\nStatus code: {0}, Error code: {1}, Error message: {2}", ex.Status, ex.ErrorCode, ex.Message); + throw; +} + +if (response.Value.BlocklistsMatchResults != null) +{ + Console.WriteLine("\nBlocklist match result:"); + foreach (var matchResult in response.Value.BlocklistsMatchResults) + { + Console.WriteLine("Blockitem was hit in text: Offset: {0}, Length: {1}", matchResult.Offset, matchResult.Length); + Console.WriteLine("BlocklistName: {0}, BlockItemId: {1}, BlockItemText: {2}, ", matchResult.BlocklistName, matchResult.BlockItemId, matchResult.BlockItemText); + } +} +``` + +## Other text blocklist management samples + +### List text blocklists + +```C# Snippet:Azure_AI_ContentSafety_ListBlocklists +var blocklists = client.GetTextBlocklists(); +Console.WriteLine("\nList blocklists:"); +foreach (var blocklist in blocklists) +{ + Console.WriteLine("BlocklistName: {0}, Description: {1}", blocklist.BlocklistName, blocklist.Description); +} +``` + +### Get text blocklist + +```C# Snippet:Azure_AI_ContentSafety_GetBlocklist +var getBlocklist = client.GetTextBlocklist(blocklistName); +if (getBlocklist != null && getBlocklist.Value != null) +{ + Console.WriteLine("\nGet blocklist:"); + Console.WriteLine("BlocklistName: {0}, Description: {1}", getBlocklist.Value.BlocklistName, getBlocklist.Value.Description); +} +``` + +### List blockItems + +```C# Snippet:Azure_AI_ContentSafety_ListBlockItems +var allBlockitems = client.GetTextBlocklistItems(blocklistName); +Console.WriteLine("\nList BlockItems:"); +foreach (var blocklistItem in allBlockitems) +{ + Console.WriteLine("BlockItemId: {0}, Text: {1}, Description: {2}", blocklistItem.BlockItemId, blocklistItem.Text, blocklistItem.Description); +} +``` + +### Get blockItem + +```C# Snippet:Azure_AI_ContentSafety_GetBlockItem +var getBlockItemId = addedBlockItems.Value.Value[0].BlockItemId; +var getBlockItem = client.GetTextBlocklistItem(blocklistName, getBlockItemId); +Console.WriteLine("\nGet BlockItem:"); +Console.WriteLine("BlockItemId: {0}, Text: {1}, Description: {2}", getBlockItem.Value.BlockItemId, getBlockItem.Value.Text, getBlockItem.Value.Description); +``` + +### Remove blockItems + +```C# Snippet:Azure_AI_ContentSafety_RemoveBlockItems +var removeBlockItemId = addedBlockItems.Value.Value[0].BlockItemId; +var removeBlockItemIds = new List { removeBlockItemId }; +var removeResult = client.RemoveBlockItems(blocklistName, new RemoveBlockItemsOptions(removeBlockItemIds)); + +if (removeResult != null && removeResult.Status == 204) +{ + Console.WriteLine("\nBlockItem removed: {0}.", removeBlockItemId); +} +``` + +### Delete text blocklist + +```C# Snippet:Azure_AI_ContentSafety_DeleteBlocklist +var deleteResult = client.DeleteTextBlocklist(blocklistName); +if (deleteResult != null && deleteResult.Status == 204) +{ + Console.WriteLine("\nDeleted blocklist."); +} +``` + +[README]: https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/contentsafety/Azure.AI.ContentSafety/README.md diff --git a/sdk/contentsafety/Azure.AI.ContentSafety/tests/ContentSafetyLiveTests.cs b/sdk/contentsafety/Azure.AI.ContentSafety/tests/ContentSafetyLiveTests.cs index 2fe0af8e2e71b..c4cbec88ab2c0 100644 --- a/sdk/contentsafety/Azure.AI.ContentSafety/tests/ContentSafetyLiveTests.cs +++ b/sdk/contentsafety/Azure.AI.ContentSafety/tests/ContentSafetyLiveTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Threading.Tasks; +using Azure.Core; using Azure.Core.TestFramework; using NUnit.Framework; @@ -68,7 +69,30 @@ public async Task TestAnalyzeImage() var response = await client.AnalyzeImageAsync(request); Assert.IsNotNull(response); + Assert.IsNotNull(response.Value.ViolenceResult); Assert.Greater(response.Value.ViolenceResult.Severity, 0); + Assert.IsNotNull(response.Value.HateResult); + Assert.IsNotNull(response.Value.SexualResult); + Assert.IsNotNull(response.Value.SelfHarmResult); + } + + [RecordedTest] + public async Task TestCreateOrUpdateBlocklist() + { + var client = CreateContentSafetyClient(); + + var blocklistName = "TestBlocklist"; + var blocklistDescription = "Test blocklist management"; + + var data = new + { + description = blocklistDescription, + }; + + Response response = await client.CreateOrUpdateTextBlocklistAsync(blocklistName, RequestContent.Create(data)); + + Assert.IsNotNull(response); + Assert.GreaterOrEqual(response.Status, 200); } } } diff --git a/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples/Sample1_AnalyzeText.cs b/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples/Sample1_AnalyzeText.cs index 7cb338f430bf2..a182dd0f1d3d8 100644 --- a/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples/Sample1_AnalyzeText.cs +++ b/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples/Sample1_AnalyzeText.cs @@ -9,37 +9,28 @@ namespace Azure.AI.ContentSafety.Tests.Samples { - //TODO: Commenting unused snippets until they are used in readme public partial class ContentSafetySamples: SamplesBase { [Test] [SyncOnly] public void AnalyzeText() { - //#region Snippet:CreateContentSafetyClient + #region Snippet:Azure_AI_ContentSafety_CreateClient string endpoint = TestEnvironment.Endpoint; string key = TestEnvironment.Key; ContentSafetyClient client = new ContentSafetyClient(new Uri(endpoint), new AzureKeyCredential(key)); - //#endregion + #endregion Snippet:Azure_AI_ContentSafety_CreateClient - //#region Snippet:ReadTextData + #region Snippet:Azure_AI_ContentSafety_AnalyzeText string datapath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Samples", "sample_data", "text.txt"); string text = File.ReadAllText(datapath); - //#endregion - - //#region Snippet:CreateRequest - var request = new AnalyzeTextOptions(text); - //#endregion - - //#region Snippet:AnalyzeText - Response response; try { @@ -47,32 +38,16 @@ public void AnalyzeText() } catch (RequestFailedException ex) { - Console.WriteLine(String.Format("Analyze text failed: {0}", ex.Message)); - throw; - } - catch (Exception ex) - { - Console.WriteLine(String.Format("Analyze text error: {0}", ex.Message)); + Console.WriteLine("Analyze text failed.\nStatus code: {0}, Error code: {1}, Error message: {2}", ex.Status, ex.ErrorCode, ex.Message); throw; } - if (response.Value.HateResult != null) - { - Console.WriteLine(String.Format("Hate severity: {0}", response.Value.HateResult.Severity)); - } - if (response.Value.SelfHarmResult != null) - { - Console.WriteLine(String.Format("SelfHarm severity: {0}", response.Value.SelfHarmResult.Severity)); - } - if (response.Value.SexualResult != null) - { - Console.WriteLine(String.Format("Sexual severity: {0}", response.Value.SexualResult.Severity)); - } - if (response.Value.ViolenceResult != null) - { - Console.WriteLine(String.Format("Violence severity: {0}", response.Value.ViolenceResult.Severity)); - } - //#endregion + Console.WriteLine("Hate severity: {0}", response.Value.HateResult?.Severity ?? 0); + Console.WriteLine("SelfHarm severity: {0}", response.Value.SelfHarmResult?.Severity ?? 0); + Console.WriteLine("Sexual severity: {0}", response.Value.SexualResult?.Severity ?? 0); + Console.WriteLine("Violence severity: {0}", response.Value.ViolenceResult?.Severity ?? 0); + + #endregion Snippet:Azure_AI_ContentSafety_AnalyzeText } } } diff --git a/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples/Sample2_AnalyzeImage.cs b/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples/Sample2_AnalyzeImage.cs index 64e3954410203..00393c280a088 100644 --- a/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples/Sample2_AnalyzeImage.cs +++ b/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples/Sample2_AnalyzeImage.cs @@ -2,56 +2,31 @@ // Licensed under the MIT License. using System; -using System.Drawing; using System.IO; using System.Reflection; -using System.Security.Cryptography; using Azure.Core.TestFramework; using NUnit.Framework; -using static System.Net.Mime.MediaTypeNames; namespace Azure.AI.ContentSafety.Tests.Samples { - //TODO: Commenting unused snippets until they are used in readme public partial class ContentSafetySamples : SamplesBase { [Test] [SyncOnly] public void AnalyzeImage() { - //#region Snippet:CreateContentSafetyClient - string endpoint = TestEnvironment.Endpoint; string key = TestEnvironment.Key; ContentSafetyClient client = new ContentSafetyClient(new Uri(endpoint), new AzureKeyCredential(key)); - //#endregion - - //#region Snippet:ReadImageData + #region Snippet:Azure_AI_ContentSafety_AnalyzeImage string datapath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Samples", "sample_data", "image.jpg"); - byte[] b = File.ReadAllBytes(datapath); - //BinaryData binaryData = BinaryData.FromObjectAsJson(TestData.TestImageContent); - //BinaryData binaryData = BinaryData.FromString("\""+TestData.TestImageContent+"\""); - BinaryData binaryData = BinaryData.FromBytes(b); - ImageData image = new ImageData() { Content = binaryData }; - - //FileStream stream = new FileStream(datapath, FileMode.Open); - //byte[] buffer = new byte[stream.Length]; - //stream.Read(buffer, 0, (int)stream.Length); - //MemoryStream memoryStream = new MemoryStream(buffer); - - //#endregion - - //#region Snippet:CreateRequest + ImageData image = new ImageData() { Content = BinaryData.FromBytes(File.ReadAllBytes(datapath)) }; var request = new AnalyzeImageOptions(image); - //#endregion - - //#region Snippet:AnalyzeText - Response response; try { @@ -59,32 +34,16 @@ public void AnalyzeImage() } catch (RequestFailedException ex) { - Console.WriteLine(String.Format("Analyze image failed: {0}", ex.Message)); - throw; - } - catch (Exception ex) - { - Console.WriteLine(String.Format("Analyze image error: {0}", ex.Message)); + Console.WriteLine("Analyze image failed.\nStatus code: {0}, Error code: {1}, Error message: {2}", ex.Status, ex.ErrorCode, ex.Message); throw; } - if (response.Value.HateResult != null) - { - Console.WriteLine(String.Format("Hate severity: {0}", response.Value.HateResult.Severity)); - } - if (response.Value.SelfHarmResult != null) - { - Console.WriteLine(String.Format("SelfHarm severity: {0}", response.Value.SelfHarmResult.Severity)); - } - if (response.Value.SexualResult != null) - { - Console.WriteLine(String.Format("Sexual severity: {0}", response.Value.SexualResult.Severity)); - } - if (response.Value.ViolenceResult != null) - { - Console.WriteLine(String.Format("Violence severity: {0}", response.Value.ViolenceResult.Severity)); - } - //#endregion + Console.WriteLine("Hate severity: {0}", response.Value.HateResult?.Severity ?? 0); + Console.WriteLine("SelfHarm severity: {0}", response.Value.SelfHarmResult?.Severity ?? 0); + Console.WriteLine("Sexual severity: {0}", response.Value.SexualResult?.Severity ?? 0); + Console.WriteLine("Violence severity: {0}", response.Value.ViolenceResult?.Severity ?? 0); + + #endregion Snippet:Azure_AI_ContentSafety_AnalyzeImage } } } diff --git a/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples/Sample3_ManageBlocklist.cs b/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples/Sample3_ManageBlocklist.cs index 91b0e449fb55d..3fd895493b741 100644 --- a/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples/Sample3_ManageBlocklist.cs +++ b/sdk/contentsafety/Azure.AI.ContentSafety/tests/Samples/Sample3_ManageBlocklist.cs @@ -3,62 +3,47 @@ using System; using System.Collections.Generic; -using System.IO; -using System.Reflection; using System.Threading; +using Azure.Core; using Azure.Core.TestFramework; using NUnit.Framework; -using static System.Net.Mime.MediaTypeNames; namespace Azure.AI.ContentSafety.Tests.Samples { - //TODO: Commenting unused snippets until they are used in readme public partial class ContentSafetySamples : SamplesBase { [Test] [SyncOnly] public void ManageBlocklist() { - //#region Snippet:CreateContentSafetyClient - string endpoint = TestEnvironment.Endpoint; string key = TestEnvironment.Key; ContentSafetyClient client = new ContentSafetyClient(new Uri(endpoint), new AzureKeyCredential(key)); - //#endregion - - //#region Snippet:ListBlocklists - - var blocklists = client.GetTextBlocklists(); - Console.WriteLine("\nMy blocklists:"); - foreach (var blocklist in blocklists) - { - Console.WriteLine(String.Format("BlocklistName: {0}, Description: {1}", blocklist.BlocklistName, blocklist.Description)); - } - //#endregion - - //#region Snippet:CreateNewBlocklist + #region Snippet:Azure_AI_ContentSafety_CreateNewBlocklist var blocklistName = "TestBlocklist"; var blocklistDescription = "Test blocklist management"; - client.CreateOrUpdateTextBlocklist(blocklistName, blocklistDescription); - - //#endregion - - //#region Snippet:GetBlocklist + var data = new + { + description = blocklistDescription, + }; - var newBlocklist = client.GetTextBlocklist(blocklistName); - if (newBlocklist != null && newBlocklist.Value != null) + var createResponse = client.CreateOrUpdateTextBlocklist(blocklistName, RequestContent.Create(data)); + if (createResponse.Status == 201) + { + Console.WriteLine("\nBlocklist {0} created.", blocklistName); + } + else if (createResponse.Status == 200) { - Console.WriteLine("\nBlocklist created:"); - Console.WriteLine(String.Format("BlocklistName: {0}, Description: {1}", newBlocklist.Value.BlocklistName, newBlocklist.Value.Description)); + Console.WriteLine("\nBlocklist {0} updated.", blocklistName); } - //#endregion + #endregion Snippet:Azure_AI_ContentSafety_CreateNewBlocklist - //#region Snippet:AddBlockItems + #region Snippet:Azure_AI_ContentSafety_AddBlockItems string blockItemText1 = "k*ll"; string blockItemText2 = "h*te"; @@ -71,43 +56,19 @@ public void ManageBlocklist() Console.WriteLine("\nBlockItems added:"); foreach (var addedBlockItem in addedBlockItems.Value.Value) { - { - Console.WriteLine(String.Format("BlockItemId: {0}, Text: {1}, Description: {2}", addedBlockItem.BlockItemId, addedBlockItem.Text, addedBlockItem.Description)); - } + Console.WriteLine("BlockItemId: {0}, Text: {1}, Description: {2}", addedBlockItem.BlockItemId, addedBlockItem.Text, addedBlockItem.Description); } } - //#endregion - - //#region Snippet:RemoveBlockItems + #endregion Snippet:Azure_AI_ContentSafety_AddBlockItems - var removeBlockItemId = addedBlockItems.Value.Value[1].BlockItemId; - var removeBlockItemIds = new List { removeBlockItemId }; - var removeResult = client.RemoveBlockItems(blocklistName, new RemoveBlockItemsOptions(removeBlockItemIds)); + #region Snippet:Azure_AI_ContentSafety_AnalyzeTextWithBlocklist - if (removeResult != null && removeResult.Status == 204) - { - Console.WriteLine(String.Format("\nBlockItem {0} removed.", removeBlockItemId)); - } - - //#endregion - - //#region Snippet:ListBlockItems - - var remainingBlockItems = client.GetTextBlocklistItems(blocklistName); - Console.WriteLine("\nList BlockItems:"); - foreach (var blocklistItem in remainingBlockItems) - { - Console.WriteLine(String.Format("BlockItemId: {0}, Text: {1}, Description: {2}", blocklistItem.BlockItemId, blocklistItem.Text, blocklistItem.Description)); - } - - //#endregion - - //#region Snippet:AnalyzeTextWithBlocklist - Thread.Sleep(30000); + // After you edit your blocklist, it usually takes effect in 5 minutes, please wait some time before analyzing with blocklist after editing. var request = new AnalyzeTextOptions("I h*te you and I want to k*ll you"); request.BlocklistNames.Add(blocklistName); request.BreakByBlocklists = true; + Response response; try { @@ -115,35 +76,86 @@ public void ManageBlocklist() } catch (RequestFailedException ex) { - Console.WriteLine(String.Format("Analyze text failed: {0}", ex.Message)); - throw; - } - catch (Exception ex) - { - Console.WriteLine(String.Format("Analyze text error: {0}", ex.Message)); + Console.WriteLine("Analyze text failed.\nStatus code: {0}, Error code: {1}, Error message: {2}", ex.Status, ex.ErrorCode, ex.Message); throw; } if (response.Value.BlocklistsMatchResults != null) { - Console.WriteLine("\nMatched Blocklist:"); + Console.WriteLine("\nBlocklist match result:"); foreach (var matchResult in response.Value.BlocklistsMatchResults) { - Console.WriteLine(String.Format("BlocklistName: {0}, BlockItemId: {1}, BlockItemText: {2}, Offset: {3}, Length: {4}", matchResult.BlocklistName, matchResult.BlockItemId, matchResult.BlockItemText, matchResult.Offset, matchResult.Length)); + Console.WriteLine("Blockitem was hit in text: Offset: {0}, Length: {1}", matchResult.Offset, matchResult.Length); + Console.WriteLine("BlocklistName: {0}, BlockItemId: {1}, BlockItemText: {2}, ", matchResult.BlocklistName, matchResult.BlockItemId, matchResult.BlockItemText); } } - //#endregion + #endregion Snippet:Azure_AI_ContentSafety_AnalyzeTextWithBlocklist + + #region Snippet:Azure_AI_ContentSafety_ListBlocklists + + var blocklists = client.GetTextBlocklists(); + Console.WriteLine("\nList blocklists:"); + foreach (var blocklist in blocklists) + { + Console.WriteLine("BlocklistName: {0}, Description: {1}", blocklist.BlocklistName, blocklist.Description); + } + + #endregion Snippet:Azure_AI_ContentSafety_ListBlocklists + + #region Snippet:Azure_AI_ContentSafety_GetBlocklist + + var getBlocklist = client.GetTextBlocklist(blocklistName); + if (getBlocklist != null && getBlocklist.Value != null) + { + Console.WriteLine("\nGet blocklist:"); + Console.WriteLine("BlocklistName: {0}, Description: {1}", getBlocklist.Value.BlocklistName, getBlocklist.Value.Description); + } + + #endregion Snippet:Azure_AI_ContentSafety_GetBlocklist + + #region Snippet:Azure_AI_ContentSafety_ListBlockItems + + var allBlockitems = client.GetTextBlocklistItems(blocklistName); + Console.WriteLine("\nList BlockItems:"); + foreach (var blocklistItem in allBlockitems) + { + Console.WriteLine("BlockItemId: {0}, Text: {1}, Description: {2}", blocklistItem.BlockItemId, blocklistItem.Text, blocklistItem.Description); + } + + #endregion Snippet:Azure_AI_ContentSafety_ListBlockItems + + #region Snippet:Azure_AI_ContentSafety_GetBlockItem + + var getBlockItemId = addedBlockItems.Value.Value[0].BlockItemId; + var getBlockItem = client.GetTextBlocklistItem(blocklistName, getBlockItemId); + Console.WriteLine("\nGet BlockItem:"); + Console.WriteLine("BlockItemId: {0}, Text: {1}, Description: {2}", getBlockItem.Value.BlockItemId, getBlockItem.Value.Text, getBlockItem.Value.Description); + + #endregion Snippet:Azure_AI_ContentSafety_GetBlockItem + + #region Snippet:Azure_AI_ContentSafety_RemoveBlockItems + + var removeBlockItemId = addedBlockItems.Value.Value[0].BlockItemId; + var removeBlockItemIds = new List { removeBlockItemId }; + var removeResult = client.RemoveBlockItems(blocklistName, new RemoveBlockItemsOptions(removeBlockItemIds)); + + if (removeResult != null && removeResult.Status == 204) + { + Console.WriteLine("\nBlockItem removed: {0}.", removeBlockItemId); + } + + #endregion Snippet:Azure_AI_ContentSafety_RemoveBlockItems - //#region Snippet:DeleteBlocklist + #region Snippet:Azure_AI_ContentSafety_DeleteBlocklist var deleteResult = client.DeleteTextBlocklist(blocklistName); if (deleteResult != null && deleteResult.Status == 204) { - Console.WriteLine("\n Delete blocklist succeded."); + Console.WriteLine("\nDeleted blocklist."); } - //#endregion + #endregion Snippet:Azure_AI_ContentSafety_DeleteBlocklist } } } diff --git a/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestAnalyzeImage.json b/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestAnalyzeImage.json index 161e436491524..a53d81b7004c6 100644 --- a/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestAnalyzeImage.json +++ b/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestAnalyzeImage.json @@ -1,16 +1,16 @@ { "Entries": [ { - "RequestUri": "https://content-safety-canary-test.cognitiveservices.azure.com/contentsafety/image:analyze?api-version=2023-04-30-preview", + "RequestUri": "https://sdktest-contentsafety.cognitiveservices.azure.com/contentsafety/image:analyze?api-version=2023-04-30-preview", "RequestMethod": "POST", "RequestHeaders": { "Accept": "application/json", "Content-Length": "33592", "Content-Type": "application/json", "Ocp-Apim-Subscription-Key": "Sanitized", - "traceparent": "00-20f25e54496c5f79cf89bae440d68558-ded6163a5666075c-00", - "User-Agent": "azsdk-net-AI.ContentSafety/1.0.0-alpha.20230504.1 (.NET 7.0.5; Microsoft Windows 10.0.22621)", - "x-ms-client-request-id": "d4a1d4d60b970e17f64f12839b1b2332", + "traceparent": "00-2dae702325cc76c447f9f1831849ff73-f91d1077e8376d24-00", + "User-Agent": "azsdk-net-AI.ContentSafety/1.0.0-alpha.20230601.1 (.NET 7.0.5; Microsoft Windows 10.0.22621)", + "x-ms-client-request-id": "ccc222cdb0b00129745099d06a78a0e9", "x-ms-return-client-request-id": "true" }, "RequestBody": { @@ -21,15 +21,15 @@ "StatusCode": 200, "ResponseHeaders": { "api-supported-versions": "2022-12-30-preview,2023-04-30-preview", - "apim-request-id": "d83c93e8-5812-400c-8a81-0765d45292bf", - "apim-subscription-id": "973fda3f71b6448db2933f4e72c9d160", + "apim-request-id": "2e278a82-7b5a-4efd-89fd-72fa66986631", "Content-Type": "application/json; charset=utf-8", - "Date": "Thu, 04 May 2023 13:03:06 GMT", + "csp-billing-usage": "CognitiveServices.ContentSafety.Image:Analyze=1", + "Date": "Thu, 01 Jun 2023 15:08:24 GMT", "Server": "istio-envoy", "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", "Transfer-Encoding": "chunked", "X-Content-Type-Options": "nosniff", - "x-envoy-upstream-service-time": "78", + "x-envoy-upstream-service-time": "165", "x-ms-region": "Central US EUAP" }, "ResponseBody": { @@ -53,8 +53,8 @@ } ], "Variables": { - "CONTENT_SAFETY_ENDPOINT": "https://content-safety-canary-test.cognitiveservices.azure.com/", + "CONTENT_SAFETY_ENDPOINT": "https://sdktest-contentsafety.cognitiveservices.azure.com/", "CONTENT_SAFETY_KEY": "Sanitized", - "RandomSeed": "1110282065" + "RandomSeed": "1713768945" } } diff --git a/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestAnalyzeImageAsync.json b/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestAnalyzeImageAsync.json index ae7b9b90800f8..1923f13bb6345 100644 --- a/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestAnalyzeImageAsync.json +++ b/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestAnalyzeImageAsync.json @@ -1,16 +1,16 @@ { "Entries": [ { - "RequestUri": "https://content-safety-canary-test.cognitiveservices.azure.com/contentsafety/image:analyze?api-version=2023-04-30-preview", + "RequestUri": "https://sdktest-contentsafety.cognitiveservices.azure.com/contentsafety/image:analyze?api-version=2023-04-30-preview", "RequestMethod": "POST", "RequestHeaders": { "Accept": "application/json", "Content-Length": "33592", "Content-Type": "application/json", "Ocp-Apim-Subscription-Key": "Sanitized", - "traceparent": "00-4538a25e1d012278f387bc782ab29e52-61f6c31b921aeab8-00", - "User-Agent": "azsdk-net-AI.ContentSafety/1.0.0-alpha.20230504.1 (.NET 7.0.5; Microsoft Windows 10.0.22621)", - "x-ms-client-request-id": "0a020d85b5c2a98de891a8a1141c6b38", + "traceparent": "00-a6f2432ad08d6b1716ac911386b6e850-e30afe6f9b4198dd-00", + "User-Agent": "azsdk-net-AI.ContentSafety/1.0.0-alpha.20230601.1 (.NET 7.0.5; Microsoft Windows 10.0.22621)", + "x-ms-client-request-id": "08c078e388e37af945f757863d061111", "x-ms-return-client-request-id": "true" }, "RequestBody": { @@ -21,15 +21,15 @@ "StatusCode": 200, "ResponseHeaders": { "api-supported-versions": "2022-12-30-preview,2023-04-30-preview", - "apim-request-id": "3875a87c-ad13-4614-a79b-50d2c5b7dbb4", - "apim-subscription-id": "973fda3f71b6448db2933f4e72c9d160", + "apim-request-id": "68a89812-8b2d-470d-adfe-1328343eafea", "Content-Type": "application/json; charset=utf-8", - "Date": "Thu, 04 May 2023 13:03:07 GMT", + "csp-billing-usage": "CognitiveServices.ContentSafety.Image:Analyze=1", + "Date": "Thu, 01 Jun 2023 15:08:25 GMT", "Server": "istio-envoy", "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", "Transfer-Encoding": "chunked", "X-Content-Type-Options": "nosniff", - "x-envoy-upstream-service-time": "80", + "x-envoy-upstream-service-time": "85", "x-ms-region": "Central US EUAP" }, "ResponseBody": { @@ -53,8 +53,8 @@ } ], "Variables": { - "CONTENT_SAFETY_ENDPOINT": "https://content-safety-canary-test.cognitiveservices.azure.com/", + "CONTENT_SAFETY_ENDPOINT": "https://sdktest-contentsafety.cognitiveservices.azure.com/", "CONTENT_SAFETY_KEY": "Sanitized", - "RandomSeed": "1087195885" + "RandomSeed": "224723334" } } diff --git a/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestAnalyzeText.json b/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestAnalyzeText.json index 1ecd86a8957ef..1ead6e630355f 100644 --- a/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestAnalyzeText.json +++ b/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestAnalyzeText.json @@ -1,16 +1,16 @@ { "Entries": [ { - "RequestUri": "https://content-safety-canary-test.cognitiveservices.azure.com/contentsafety/text:analyze?api-version=2023-04-30-preview", + "RequestUri": "https://sdktest-contentsafety.cognitiveservices.azure.com/contentsafety/text:analyze?api-version=2023-04-30-preview", "RequestMethod": "POST", "RequestHeaders": { "Accept": "application/json", "Content-Length": "60", "Content-Type": "application/json", "Ocp-Apim-Subscription-Key": "Sanitized", - "traceparent": "00-1d8c2311edf7c3c1084f8064859420de-aaaa4552cb438553-00", - "User-Agent": "azsdk-net-AI.ContentSafety/1.0.0-alpha.20230504.1 (.NET 7.0.5; Microsoft Windows 10.0.22621)", - "x-ms-client-request-id": "f8f1e28b1c1a53b02d8a4d97e33d119e", + "traceparent": "00-00fe58e9876ed7e1d55b1b1a4b2185e7-196cc4d4d49ae929-00", + "User-Agent": "azsdk-net-AI.ContentSafety/1.0.0-alpha.20230601.1 (.NET 7.0.5; Microsoft Windows 10.0.22621)", + "x-ms-client-request-id": "a9f871fa2284c18ecbd7065b49dcf51c", "x-ms-return-client-request-id": "true" }, "RequestBody": { @@ -23,15 +23,15 @@ "StatusCode": 200, "ResponseHeaders": { "api-supported-versions": "2022-12-30-preview,2023-04-30-preview", - "apim-request-id": "36528636-49cf-4846-8980-07dac386ca8d", - "apim-subscription-id": "973fda3f71b6448db2933f4e72c9d160", + "apim-request-id": "d41b9bf7-2fcc-4073-bb03-b7f7c115f99d", "Content-Type": "application/json; charset=utf-8", - "Date": "Thu, 04 May 2023 13:03:07 GMT", + "csp-billing-usage": "CognitiveServices.ContentSafety.Text:Analyze=1", + "Date": "Thu, 01 Jun 2023 15:08:25 GMT", "Server": "istio-envoy", "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", "Transfer-Encoding": "chunked", "X-Content-Type-Options": "nosniff", - "x-envoy-upstream-service-time": "61", + "x-envoy-upstream-service-time": "66", "x-ms-region": "Central US EUAP" }, "ResponseBody": { @@ -48,8 +48,8 @@ } ], "Variables": { - "CONTENT_SAFETY_ENDPOINT": "https://content-safety-canary-test.cognitiveservices.azure.com/", + "CONTENT_SAFETY_ENDPOINT": "https://sdktest-contentsafety.cognitiveservices.azure.com/", "CONTENT_SAFETY_KEY": "Sanitized", - "RandomSeed": "352827987" + "RandomSeed": "1139492038" } } diff --git a/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestAnalyzeTextAsync.json b/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestAnalyzeTextAsync.json index 501b9d7760e20..1047b6c2d7282 100644 --- a/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestAnalyzeTextAsync.json +++ b/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestAnalyzeTextAsync.json @@ -1,16 +1,16 @@ { "Entries": [ { - "RequestUri": "https://content-safety-canary-test.cognitiveservices.azure.com/contentsafety/text:analyze?api-version=2023-04-30-preview", + "RequestUri": "https://sdktest-contentsafety.cognitiveservices.azure.com/contentsafety/text:analyze?api-version=2023-04-30-preview", "RequestMethod": "POST", "RequestHeaders": { "Accept": "application/json", "Content-Length": "60", "Content-Type": "application/json", "Ocp-Apim-Subscription-Key": "Sanitized", - "traceparent": "00-60270c9a37d94ae171123a8eeee1f23a-0f73e947d70e536b-00", - "User-Agent": "azsdk-net-AI.ContentSafety/1.0.0-alpha.20230504.1 (.NET 7.0.5; Microsoft Windows 10.0.22621)", - "x-ms-client-request-id": "c8a0ae96e570cb7fcf1b39f922fbe9d8", + "traceparent": "00-6de49372f7c9bb521a41684aeb0eadbc-8d6a55602aeb4b2e-00", + "User-Agent": "azsdk-net-AI.ContentSafety/1.0.0-alpha.20230601.1 (.NET 7.0.5; Microsoft Windows 10.0.22621)", + "x-ms-client-request-id": "965d15ad184ad613826229a0b2a08b26", "x-ms-return-client-request-id": "true" }, "RequestBody": { @@ -23,15 +23,15 @@ "StatusCode": 200, "ResponseHeaders": { "api-supported-versions": "2022-12-30-preview,2023-04-30-preview", - "apim-request-id": "bffaaf11-5c2d-4f46-8969-a57e94d746b7", - "apim-subscription-id": "973fda3f71b6448db2933f4e72c9d160", + "apim-request-id": "e966fe4d-81a9-4091-b1ba-8eba1f2e057b", "Content-Type": "application/json; charset=utf-8", - "Date": "Thu, 04 May 2023 13:03:08 GMT", + "csp-billing-usage": "CognitiveServices.ContentSafety.Text:Analyze=1", + "Date": "Thu, 01 Jun 2023 15:08:26 GMT", "Server": "istio-envoy", "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", "Transfer-Encoding": "chunked", "X-Content-Type-Options": "nosniff", - "x-envoy-upstream-service-time": "59", + "x-envoy-upstream-service-time": "57", "x-ms-region": "Central US EUAP" }, "ResponseBody": { @@ -48,8 +48,8 @@ } ], "Variables": { - "CONTENT_SAFETY_ENDPOINT": "https://content-safety-canary-test.cognitiveservices.azure.com/", + "CONTENT_SAFETY_ENDPOINT": "https://sdktest-contentsafety.cognitiveservices.azure.com/", "CONTENT_SAFETY_KEY": "Sanitized", - "RandomSeed": "322589143" + "RandomSeed": "251837957" } } diff --git a/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestCreateOrUpdateBlocklist.json b/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestCreateOrUpdateBlocklist.json new file mode 100644 index 0000000000000..dbc0a991d61ea --- /dev/null +++ b/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestCreateOrUpdateBlocklist.json @@ -0,0 +1,42 @@ +{ + "Entries": [ + { + "RequestUri": "https://sdktest-contentsafety.cognitiveservices.azure.com/contentsafety/text/blocklists/TestBlocklist?api-version=2023-04-30-preview", + "RequestMethod": "PATCH", + "RequestHeaders": { + "Accept": "application/json", + "Content-Length": "43", + "Content-Type": "application/merge-patch\u002Bjson", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-6c7db9038a36308624fa8e7a77643e8d-dcd3788013311e9c-00", + "User-Agent": "azsdk-net-AI.ContentSafety/1.0.0-alpha.20230601.1 (.NET 7.0.5; Microsoft Windows 10.0.22621)", + "x-ms-client-request-id": "29d6d5e2c300eef41ea5fb082fc4ae57", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "description": "Test blocklist management" + }, + "StatusCode": 200, + "ResponseHeaders": { + "apim-request-id": "4c37e6ea-e48d-479b-9eec-5a2df9f0a4a0", + "Content-Type": "application/json; charset=utf-8", + "Date": "Thu, 01 Jun 2023 15:08:25 GMT", + "Server": "istio-envoy", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "Transfer-Encoding": "chunked", + "X-Content-Type-Options": "nosniff", + "x-envoy-upstream-service-time": "48", + "x-ms-region": "Central US EUAP" + }, + "ResponseBody": { + "blocklistName": "TestBlocklist", + "description": "Test blocklist management" + } + } + ], + "Variables": { + "CONTENT_SAFETY_ENDPOINT": "https://sdktest-contentsafety.cognitiveservices.azure.com/", + "CONTENT_SAFETY_KEY": "Sanitized", + "RandomSeed": "924786438" + } +} diff --git a/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestCreateOrUpdateBlocklistAsync.json b/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestCreateOrUpdateBlocklistAsync.json new file mode 100644 index 0000000000000..ca5771032f348 --- /dev/null +++ b/sdk/contentsafety/Azure.AI.ContentSafety/tests/SessionRecords/ContentSafetyLiveTests/TestCreateOrUpdateBlocklistAsync.json @@ -0,0 +1,42 @@ +{ + "Entries": [ + { + "RequestUri": "https://sdktest-contentsafety.cognitiveservices.azure.com/contentsafety/text/blocklists/TestBlocklist?api-version=2023-04-30-preview", + "RequestMethod": "PATCH", + "RequestHeaders": { + "Accept": "application/json", + "Content-Length": "43", + "Content-Type": "application/merge-patch\u002Bjson", + "Ocp-Apim-Subscription-Key": "Sanitized", + "traceparent": "00-3e75aff5ba4c7103dba949f87f426ff4-8b253e0c34c26c0d-00", + "User-Agent": "azsdk-net-AI.ContentSafety/1.0.0-alpha.20230601.1 (.NET 7.0.5; Microsoft Windows 10.0.22621)", + "x-ms-client-request-id": "aeaf009c40204e6d744eece16a87fc3d", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "description": "Test blocklist management" + }, + "StatusCode": 200, + "ResponseHeaders": { + "apim-request-id": "48e89056-c03d-406a-b2fb-d2a65535e1db", + "Content-Type": "application/json; charset=utf-8", + "Date": "Thu, 01 Jun 2023 15:08:27 GMT", + "Server": "istio-envoy", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "Transfer-Encoding": "chunked", + "X-Content-Type-Options": "nosniff", + "x-envoy-upstream-service-time": "11", + "x-ms-region": "Central US EUAP" + }, + "ResponseBody": { + "blocklistName": "TestBlocklist", + "description": "Test blocklist management" + } + } + ], + "Variables": { + "CONTENT_SAFETY_ENDPOINT": "https://sdktest-contentsafety.cognitiveservices.azure.com/", + "CONTENT_SAFETY_KEY": "Sanitized", + "RandomSeed": "964674837" + } +}