### Packages impacted by this PR

@azure-rest/ai-content-safety

### Issues associated with this PR


### Describe the problem that is addressed by this PR


### What are the possible designs available to address the problem? If
there are more than one possible design, why was the one in this PR
chosen?


### Are there test cases added in this PR? _(If not, why?)_


### Provide a list of related PRs _(if any)_


### Command used to generate this PR:**_(Applicable only to SDK release
request PRs)_

### Checklists
- [ ] Added impacted package name to the issue description
- [ ] Does this PR needs any fixes in the SDK Generator?** _(If so,
create an Issue in the
[Autorest/typescript](https://github.com/Azure/autorest.typescript)
repository and link it here)_
- [ ] Added a changelog (if necessary)
This commit is contained in:
MinjueWu 2023-09-20 22:49:57 +08:00 коммит произвёл GitHub
Родитель 698d9fe109
Коммит e57e8a7a22
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
45 изменённых файлов: 3992 добавлений и 1 удалений

Просмотреть файл

@ -14,6 +14,9 @@ dependencies:
'@rush-temp/ai-anomaly-detector':
specifier: file:./projects/ai-anomaly-detector.tgz
version: file:projects/ai-anomaly-detector.tgz
'@rush-temp/ai-content-safety':
specifier: file:./projects/ai-content-safety.tgz
version: file:projects/ai-content-safety.tgz
'@rush-temp/ai-document-translator':
specifier: file:./projects/ai-document-translator.tgz
version: file:projects/ai-document-translator.tgz
@ -9880,6 +9883,47 @@ packages:
- utf-8-validate
dev: false
file:projects/ai-content-safety.tgz:
resolution: {integrity: sha512-ghhD0hitSl1yehkXY8937HiI0GIesBzqf10RHxOM3KYXo60elnspeGRfCd/ODPfDFrYwSROqNrKbSssvQ+ioPQ==, tarball: file:projects/ai-content-safety.tgz}
name: '@rush-temp/ai-content-safety'
version: 0.0.0
dependencies:
'@azure/identity': 2.1.0
'@microsoft/api-extractor': 7.36.2_@types+node@14.18.53
'@types/chai': 4.3.5
'@types/mocha': 7.0.2
'@types/node': 14.18.53
autorest: 3.6.3
chai: 4.3.7
cross-env: 7.0.3
dotenv: 16.3.1
eslint: 8.45.0
karma: 6.4.2
karma-chrome-launcher: 3.2.0
karma-coverage: 2.2.1
karma-env-preprocessor: 0.1.1
karma-firefox-launcher: 1.3.0
karma-junit-reporter: 2.0.1_karma@6.4.2
karma-mocha: 2.0.1
karma-mocha-reporter: 2.2.5_karma@6.4.2
karma-source-map-support: 1.4.0
karma-sourcemap-loader: 0.3.8
mkdirp: 2.1.6
mocha: 7.2.0
mocha-junit-reporter: 1.23.3_mocha@7.2.0
nyc: 15.1.0
prettier: 2.8.8
rimraf: 3.0.2
source-map-support: 0.5.21
tslib: 2.6.0
typescript: 5.0.4
transitivePeerDependencies:
- bufferutil
- debug
- supports-color
- utf-8-validate
dev: false
file:projects/ai-document-translator.tgz:
resolution: {integrity: sha512-/pBuuPQ7Gqwo6aMXE8Wx7HcFoP7lO0NOKVj66anxzCR0IHKTYwWYs70hS9CyF/wCbJw9BNbqd1D8mbb0TLQOsQ==, tarball: file:projects/ai-document-translator.tgz}
name: '@rush-temp/ai-document-translator'

Просмотреть файл

@ -4,3 +4,4 @@ https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/storage-blob-cha
https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/storage/storage-blob-changefeed/samples/typescript
https://docs.microsoft.com/javascript/api/@azure/arm-hybridconnectivity?view=azure-node-preview
https://docs.microsoft.com/javascript/api/@azure/arm-hybridconnectivity
https://docs.microsoft.com/javascript/api/@azure-rest/ai-content-safety?view=azure-node-preview

Просмотреть файл

@ -1,7 +1,7 @@
/**
* This is the main configuration file for Rush.
* For full documentation, please see https://rushjs.io
*/{
*/ {
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json",
/**
* (Required) This specifies the version of the Rush engine to be used in this repo.
@ -355,6 +355,11 @@
"projectFolder": "sdk/anomalydetector/ai-anomaly-detector-rest",
"versionPolicyName": "client"
},
{
"packageName": "@azure-rest/ai-content-safety",
"projectFolder": "sdk/contentsafety/ai-content-safety-rest",
"versionPolicyName": "client"
},
{
"packageName": "@azure/ai-form-recognizer",
"projectFolder": "sdk/formrecognizer/ai-form-recognizer",

Просмотреть файл

@ -0,0 +1,11 @@
{
"plugins": ["@azure/azure-sdk"],
"extends": ["plugin:@azure/azure-sdk/azure-sdk-base"],
"rules": {
"@azure/azure-sdk/ts-modules-only-named": "warn",
"@azure/azure-sdk/ts-apiextractor-json-types": "warn",
"@azure/azure-sdk/ts-package-json-types": "warn",
"@azure/azure-sdk/ts-package-json-engine-is-present": "warn",
"tsdoc/syntax": "warn"
}
}

Просмотреть файл

@ -0,0 +1,5 @@
# Release History
## 1.0.0-beta.1 (Unreleased)
- This is the initial beta release for Azure AI Content Safety, see README.md for details.

Просмотреть файл

@ -0,0 +1,465 @@
# Azure AI Content Safety REST client library for JavaScript/TypeScript
[Azure AI Content Safety](https://learn.microsoft.com/azure/ai-services/content-safety/overview) detects harmful user-generated and AI-generated content in applications and services. Content Safety includes text and image APIs that allow you to detect material that is harmful.
**Please rely on our [REST client docs](https://github.com/Azure/azure-sdk-for-js/blob/main/documentation/rest-clients.md) to use this library**
Key links:
- [Source code](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/contentsafety/ai-content-safety-rest)
- [Package (NPM)](https://www.npmjs.com/package/@azure-rest/ai-content-safety)
- [API reference documentation](https://docs.microsoft.com/javascript/api/@azure-rest/ai-content-safety?view=azure-node-preview)
- [Samples](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/contentsafety/ai-content-safety-rest/samples)
## Getting started
### Currently supported environments
- LTS versions of Node.js
### Prerequisites
- You need an [Azure subscription](https://azure.microsoft.com/free/) to use this package.
- An existing [Azure AI Content Safety](https://learn.microsoft.com/azure/ai-services/content-safety/overview) instance.
### Install the `@azure-rest/ai-content-safety` package
Install the Azure AI Content Safety REST client REST client library for JavaScript with `npm`:
```bash
npm install @azure-rest/ai-content-safety
```
### Create and authenticate a `ContentSafetyClient`
#### Get the endpoint
You can find the endpoint for your Azure AI Content Safety service resource using the [Azure Portal](https://ms.portal.azure.com/#home) or [Azure CLI](https://learn.microsoft.com/cli/azure/cognitiveservices/account?view=azure-cli-latest#az-cognitiveservices-account-show):
```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](https://ms.portal.azure.com/#home) or by running the following [Azure CLI](https://learn.microsoft.com/cli/azure/cognitiveservices/account?view=azure-cli-latest#az-cognitiveservices-account-show) command:
```bash
az cognitiveservices account keys list --name "<resource-name>" --resource-group "<resource-group-name>"
```
#### Create a ContentSafetyClient with AzureKeyCredential
To use an API key as the `credential` parameter, pass the key as a string into an instance of `AzureKeyCredential`.
```typescript
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
```
## Key concepts
### Available features
There are different types of analysis available from this service. The following table describes the currently available APIs.
| Feature | Description |
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 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. |
### 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 ones 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 ones 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:
- 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.
## Examples
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)
### Analyze text
#### Analyze text without blocklists
```typescript
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const text = "This is a sample text";
const analyzeTextOption: AnalyzeTextOptions = { text: text };
const analyzeTextParameters: AnalyzeTextParameters = { body: analyzeTextOption };
const result = await client.path("/text:analyze").post(analyzeTextParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Hate severity: ", result.body.hateResult?.severity);
console.log("SelfHarm severity: ", result.body.selfHarmResult?.severity);
console.log("Sexual severity: ", result.body.sexualResult?.severity);
console.log("Violence severity: ", result.body.violenceResult?.severity);
```
#### Analyze text with blocklists
```typescript
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const blocklistName = "TestBlocklist";
const inputText = "This is a sample to test text with blocklist.";
const analyzeTextParameters: AnalyzeTextParameters = {
body: {
text: inputText,
blocklistNames: [blocklistName],
breakByBlocklists: false
}
};
const result = await client.path("/text:analyze").post(analyzeTextParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Blocklist match results: ");
if (result.body.blocklistsMatchResults) {
for (const blocklistMatchResult of result.body.blocklistsMatchResults) {
console.log("Block item was hit in text, Offset=", blocklistMatchResult.offset, ", Length=", blocklistMatchResult.length);
console.log("BlocklistName: ", blocklistMatchResult.blocklistName, ", BlockItemId: ", blocklistMatchResult.blockItemId, ", BlockItemText: ", blocklistMatchResult.blockItemText);
}
}
```
### Analyze image
```typescript
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const image_path = path.resolve(__dirname, "./samples-dev/example-data/image.png");
const imageBuffer = fs.readFileSync(image_path);
const base64Image = imageBuffer.toString("base64");
const analyzeImageOption: AnalyzeImageOptions = { image: { content: base64Image } };
const analyzeImageParameters: AnalyzeImageParameters = { body: analyzeImageOption };
const result = await client.path("/image:analyze").post(analyzeImageParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Hate severity: ", result.body.hateResult?.severity);
console.log("SelfHarm severity: ", result.body.selfHarmResult?.severity);
console.log("Sexual severity: ", result.body.sexualResult?.severity);
console.log("Violence severity: ", result.body.violenceResult?.severity);
```
### Manage text blocklist
#### Create or update text blocklist
```typescript
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const blocklistName = "TestBlocklist";
const blocklistDescription = "Test blocklist management.";
const createOrUpdateTextBlocklistParameters: CreateOrUpdateTextBlocklistParameters = {
contentType: "application/merge-patch+json",
body: {
description: blocklistDescription,
}
}
const result = await client.path("/text/blocklists/{blocklistName}", blocklistName).patch(createOrUpdateTextBlocklistParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Blocklist created or updated: Name", result.body.blocklistName, ", Description: ", result.body.description);
```
#### List text blocklists
```typescript
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const result = await client.path("/text/blocklists").get();
if (isUnexpected(result)) {
throw result;
}
console.log("List blocklists: ");
if (result.body.value) {
for (const blocklist of result.body.value) {
console.log("BlocklistName: ", blocklist.blocklistName, ", Description: ", blocklist.description);
}
}
```
#### Get text blocklist
```typescript
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const blocklistName = "TestBlocklist";
const result = await client.path("/text/blocklists/{blocklistName}", blocklistName).get();
if (isUnexpected(result)) {
throw result;
}
console.log("Get blocklist: ");
console.log("Name: ", result.body.blocklistName, ", Description: ", result.body.description);
```
#### Delete text blocklist
```typescript
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const blocklistName = "TestBlocklist";
const result = await client.path("/text/blocklists/{blocklistName}", blocklistName).delete();
if (isUnexpected(result)) {
throw result;
}
console.log("Deleted blocklist: ", blocklistName);
```
#### Add blockItems
```typescript
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const blocklistName = "TestBlocklist";
const blockItemText1 = "sample";
const blockItemText2 = "text";
const addBlockItemsParameters: AddBlockItemsParameters = {
body: {
blockItems: [
{
description: "Test block item 1",
text: blockItemText1
},
{
description: "Test block item 2",
text: blockItemText2
}
]
}
};
const result = await client.path("/text/blocklists/{blocklistName}:addBlockItems", blocklistName).post(addBlockItemsParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Block items added: ");
if (result.body.value) {
for (const blockItem of result.body.value) {
console.log("BlockItemId: ", blockItem.blockItemId, ", Text: ", blockItem.text, ", Description: ", blockItem.description);
}
}
```
#### List blockItems
```typescript
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const blocklistName = "TestBlocklist";
const result = await client.path("/text/blocklists/{blocklistName}/blockItems", blocklistName).get();
if (isUnexpected(result)) {
throw result;
}
console.log("List block items: ");
if (result.body.value) {
for (const blockItem of result.body.value) {
console.log("BlockItemId: ", blockItem.blockItemId, ", Text: ", blockItem.text, ", Description: ", blockItem.description);
}
}
```
#### Get blockItem
```typescript
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const blocklistName = "TestBlocklist";
const blockItemText = "sample";
const addBlockItemsParameters: AddBlockItemsParameters = {
body: {
blockItems: [
{
description: "Test block item 1",
text: blockItemText
}
]
}
};
const result = await client.path("/text/blocklists/{blocklistName}:addBlockItems", blocklistName).post(addBlockItemsParameters);
if (isUnexpected(result) || result.body.value === undefined) {
throw new Error("Block item not added.");
}
const blockItemId = result.body.value[0].blockItemId;
const blockItem = await client.path("/text/blocklists/{blocklistName}/blockItems/{blockItemId}", blocklistName, blockItemId).get();
if (isUnexpected(blockItem)) {
throw blockItem;
}
console.log("Get blockitem: ");
console.log("BlockItemId: ", blockItem.body.blockItemId, ", Text: ", blockItem.body.text, ", Description: ", blockItem.body.description);
```
#### Remove blockItems
```typescript
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const blocklistName = "TestBlocklist";
const blockItemText = "sample";
const addBlockItemsParameters: AddBlockItemsParameters = {
body: {
blockItems: [
{
description: "Test block item 1",
text: blockItemText
}
]
}
};
const result = await client.path("/text/blocklists/{blocklistName}:addBlockItems", blocklistName).post(addBlockItemsParameters);
if (isUnexpected(result) || result.body.value === undefined) {
throw new Error("Block item not added.");
}
const blockItemId = result.body.value[0].blockItemId;
const removeBlockItemsParameters: RemoveBlockItemsParameters = {
body: {
blockItemIds: [blockItemId]
}
};
const removeBlockItem = await client.path("/text/blocklists/{blocklistName}:removeBlockItems", blocklistName).post(removeBlockItemsParameters);
if (isUnexpected(removeBlockItem)) {
throw removeBlockItem;
}
console.log("Removed blockItem: ", blockItemText);
```
## Troubleshooting
### Logging
Enabling logging may help uncover useful information about failures. In order to see a log of HTTP requests and responses, set the `AZURE_LOG_LEVEL` environment variable to `info`. Alternatively, logging can be enabled at runtime by calling `setLogLevel` in the `@azure/logger`:
```javascript
const { setLogLevel } = require("@azure/logger");
setLogLevel("info");
```
For more detailed instructions on how to enable logs, you can look at the [@azure/logger package docs](https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/logger).
## Next steps
### Additional documentation
For more extensive documentation on Azure Content Safety, see the [Azure AI Content Safety](https://learn.microsoft.com/azure/ai-services/content-safety/overview) on docs.microsoft.com.
## Contributing
If you'd like to contribute to this library, please read the [contributing guide](https://github.com/Azure/azure-sdk-for-js/blob/master/CONTRIBUTING.md) to learn more about how to build and test the code.

Просмотреть файл

@ -0,0 +1,18 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"mainEntryPointFilePath": "./types/src/index.d.ts",
"docModel": { "enabled": true },
"apiReport": { "enabled": true, "reportFolder": "./review" },
"dtsRollup": {
"enabled": true,
"untrimmedFilePath": "",
"publicTrimmedFilePath": "./types/ai-content-safety.d.ts"
},
"messages": {
"tsdocMessageReporting": { "default": { "logLevel": "none" } },
"extractorMessageReporting": {
"ae-missing-release-tag": { "logLevel": "none" },
"ae-unresolved-link": { "logLevel": "none" }
}
}
}

Просмотреть файл

@ -0,0 +1,6 @@
{
"AssetsRepo": "Azure/azure-sdk-assets",
"AssetsRepoPrefixPath": "js",
"TagPrefix": "js/contentsafety/ai-content-safety-rest",
"Tag": "js/contentsafety/ai-content-safety-rest_eda0fd342d"
}

Просмотреть файл

@ -0,0 +1,141 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// https://github.com/karma-runner/karma-chrome-launcher
process.env.CHROME_BIN = require("puppeteer").executablePath();
require("dotenv").config();
const { relativeRecordingsPath } = require("@azure-tools/test-recorder");
process.env.RECORDINGS_RELATIVE_PATH = relativeRecordingsPath();
module.exports = function (config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: "./",
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ["source-map-support", "mocha"],
plugins: [
"karma-mocha",
"karma-mocha-reporter",
"karma-chrome-launcher",
"karma-firefox-launcher",
"karma-env-preprocessor",
"karma-coverage",
"karma-sourcemap-loader",
"karma-junit-reporter",
"karma-source-map-support",
],
// list of files / patterns to load in the browser
files: [
"dist-test/index.browser.js",
{
pattern: "dist-test/index.browser.js.map",
type: "html",
included: false,
served: true,
},
{
pattern: "./samples-dev/example-data/*.png",
watched: false,
included: false,
served: true,
},
],
// list of files / patterns to exclude
exclude: [],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
"**/*.js": ["sourcemap", "env"],
// IMPORTANT: COMMENT following line if you want to debug in your browsers!!
// Preprocess source file to calculate code coverage, however this will make source file unreadable
// "dist-test/index.js": ["coverage"]
},
envPreprocessor: [
"TEST_MODE",
"ENDPOINT",
"AZURE_CLIENT_SECRET",
"AZURE_CLIENT_ID",
"AZURE_TENANT_ID",
"SUBSCRIPTION_ID",
"RECORDINGS_RELATIVE_PATH",
"CONTENT_SAFETY_ENDPOINT",
"CONTENT_SAFETY_API_KEY",
],
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ["mocha", "coverage", "junit"],
coverageReporter: {
// specify a common output directory
dir: "coverage-browser/",
reporters: [
{ type: "json", subdir: ".", file: "coverage.json" },
{ type: "lcovonly", subdir: ".", file: "lcov.info" },
{ type: "html", subdir: "html" },
{ type: "cobertura", subdir: ".", file: "cobertura-coverage.xml" },
],
},
junitReporter: {
outputDir: "", // results will be saved as $outputDir/$browserName.xml
outputFile: "test-results.browser.xml", // if included, results will be saved as $outputDir/$browserName/$outputFile
suite: "", // suite will become the package name attribute in xml testsuite element
useBrowserName: false, // add browser name to report and classes names
nameFormatter: undefined, // function (browser, result) to customize the name attribute in xml testcase element
classNameFormatter: undefined, // function (browser, result) to customize the classname attribute in xml testcase element
properties: {}, // key value pair of properties to add to the <properties> section of the report
},
// web server port
port: 9876,
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// --no-sandbox allows our tests to run in Linux without having to change the system.
// --disable-web-security allows us to authenticate from the browser without having to write tests using interactive auth, which would be far more complex.
browsers: ["ChromeHeadlessNoSandbox"],
customLaunchers: {
ChromeHeadlessNoSandbox: {
base: "ChromeHeadless",
flags: ["--no-sandbox", "--disable-web-security"],
},
},
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false,
// Concurrency level
// how many browser should be started simultaneous
concurrency: 1,
browserNoActivityTimeout: 60000000,
browserDisconnectTimeout: 10000,
browserDisconnectTolerance: 3,
client: {
mocha: {
// change Karma's debug.html to the mocha web reporter
reporter: "html",
timeout: "600000",
},
},
});
};

Просмотреть файл

@ -0,0 +1,126 @@
{
"name": "@azure-rest/ai-content-safety",
"sdk-type": "client",
"author": "Microsoft Corporation",
"version": "1.0.0-beta.1",
"description": "ContentSafety Service",
"keywords": [
"node",
"azure",
"cloud",
"typescript",
"browser",
"isomorphic"
],
"license": "MIT",
"main": "dist/index.js",
"module": "./dist-esm/src/index.js",
"types": "./types/ai-content-safety.d.ts",
"repository": "github:Azure/azure-sdk-for-js",
"bugs": {
"url": "https://github.com/Azure/azure-sdk-for-js/issues"
},
"files": [
"dist/",
"dist-esm/src/",
"types/ai-content-safety.d.ts",
"README.md",
"LICENSE",
"review/*"
],
"engines": {
"node": ">=14.0.0"
},
"scripts": {
"audit": "node ../../../common/scripts/rush-audit.js && rimraf node_modules package-lock.json && npm i --package-lock-only 2>&1 && npm audit",
"build:browser": "tsc -p . && cross-env ONLY_BROWSER=true rollup -c 2>&1",
"build:node": "tsc -p . && cross-env ONLY_NODE=true rollup -c 2>&1",
"build:samples": "echo skipped.",
"build:test": "tsc -p . && dev-tool run bundle",
"build:debug": "tsc -p . && dev-tool run bundle && api-extractor run --local",
"check-format": "prettier --list-different --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"*.{js,json}\" \"test/**/*.ts\"",
"clean": "rimraf dist dist-browser dist-esm test-dist temp types *.tgz *.log",
"execute:samples": "echo skipped",
"extract-api": "rimraf review && mkdirp ./review && api-extractor run --local",
"format": "prettier --write --config ../../../.prettierrc.json --ignore-path ../../../.prettierignore \"src/**/*.ts\" \"*.{js,json}\" \"test/**/*.ts\"",
"generate:client": "echo skipped",
"integration-test:browser": "dev-tool run test:browser",
"integration-test:node": "dev-tool run test:node-js-input -- --timeout 5000000 'dist-esm/test/**/*.spec.js'",
"integration-test": "npm run integration-test:node && npm run integration-test:browser",
"lint:fix": "eslint package.json api-extractor.json src test --ext .ts --fix --fix-type [problem,suggestion]",
"lint": "eslint package.json api-extractor.json src test --ext .ts",
"pack": "npm pack 2>&1",
"test:browser": "npm run clean && npm run build:test && npm run unit-test:browser",
"test:node": "npm run clean && npm run build:test && npm run unit-test:node",
"test": "npm run clean && npm run build:test && npm run unit-test",
"unit-test": "npm run unit-test:node && npm run unit-test:browser",
"unit-test:node": "dev-tool run test:node-ts-input -- --timeout 1200000 --exclude 'test/**/browser/*.spec.ts' 'test/**/*.spec.ts'",
"unit-test:browser": "dev-tool run test:browser",
"build": "npm run clean && tsc -p . && dev-tool run bundle && mkdirp ./review && api-extractor run --local"
},
"sideEffects": false,
"autoPublish": false,
"dependencies": {
"@azure/core-auth": "^1.3.0",
"@azure-rest/core-client": "^1.1.3",
"@azure/core-rest-pipeline": "^1.8.0",
"@azure/logger": "^1.0.0",
"tslib": "^2.2.0",
"@azure/core-paging": "^1.5.0"
},
"devDependencies": {
"@microsoft/api-extractor": "^7.31.1",
"autorest": "latest",
"@types/node": "^14.0.0",
"dotenv": "^16.0.0",
"eslint": "^8.0.0",
"mkdirp": "^2.1.2",
"prettier": "^2.5.1",
"rimraf": "^3.0.0",
"source-map-support": "^0.5.9",
"typescript": "~5.0.0",
"@azure/dev-tool": "^1.0.0",
"@azure/eslint-plugin-azure-sdk": "^3.0.0",
"@azure-tools/test-credential": "^1.0.0",
"@azure/identity": "^2.0.1",
"@azure-tools/test-recorder": "^3.0.0",
"mocha": "^7.1.1",
"@types/mocha": "^7.0.2",
"mocha-junit-reporter": "^1.18.0",
"cross-env": "^7.0.2",
"@types/chai": "^4.2.8",
"chai": "^4.2.0",
"karma-chrome-launcher": "^3.0.0",
"karma-coverage": "^2.0.0",
"karma-env-preprocessor": "^0.1.1",
"karma-firefox-launcher": "^1.1.0",
"karma-junit-reporter": "^2.0.1",
"karma-mocha-reporter": "^2.2.5",
"karma-mocha": "^2.0.1",
"karma-source-map-support": "~1.4.0",
"karma-sourcemap-loader": "^0.3.8",
"karma": "^6.2.0",
"nyc": "^15.0.0",
"@azure/core-util": "1.4.1"
},
"homepage": "https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/contentsafety/ai-content-safety-rest/README.md",
"//metadata": {
"constantPaths": [
{
"path": "src/contentSafetyClient.ts",
"prefix": "userAgentInfo"
}
]
},
"browser": {
"./dist-esm/test/public/utils/env.js": "./dist-esm/test/public/utils/env.browser.js"
},
"//sampleConfiguration": {
"productName": "ContentSafety",
"productSlugs": [
"azure"
],
"disableDocsMs": true,
"apiRefLink": "https://docs.microsoft.com/javascript/api/@azure-rest/ai-content-safety?view=azure-node-preview"
}
}

Просмотреть файл

@ -0,0 +1,575 @@
## API Report File for "@azure-rest/ai-content-safety"
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
import { Client } from '@azure-rest/core-client';
import { ClientOptions } from '@azure-rest/core-client';
import { ErrorResponse } from '@azure-rest/core-client';
import { HttpResponse } from '@azure-rest/core-client';
import { KeyCredential } from '@azure/core-auth';
import { Paged } from '@azure/core-paging';
import { PagedAsyncIterableIterator } from '@azure/core-paging';
import { PathUncheckedResponse } from '@azure-rest/core-client';
import { RawHttpHeaders } from '@azure/core-rest-pipeline';
import { RequestParameters } from '@azure-rest/core-client';
import { StreamableMethod } from '@azure-rest/core-client';
// @public (undocumented)
export interface AddBlockItems {
post(options?: AddBlockItemsParameters): StreamableMethod<AddBlockItems200Response | AddBlockItemsDefaultResponse>;
}
// @public
export interface AddBlockItems200Response extends HttpResponse {
// (undocumented)
body: AddBlockItemsResultOutput;
// (undocumented)
status: "200";
}
// @public (undocumented)
export interface AddBlockItemsBodyParam {
// (undocumented)
body?: AddBlockItemsOptions;
}
// @public (undocumented)
export interface AddBlockItemsDefaultHeaders {
"x-ms-error-code"?: string;
}
// @public (undocumented)
export interface AddBlockItemsDefaultResponse extends HttpResponse {
// (undocumented)
body: ErrorResponse;
// (undocumented)
headers: RawHttpHeaders & AddBlockItemsDefaultHeaders;
// (undocumented)
status: string;
}
// @public
export interface AddBlockItemsOptions {
blockItems: Array<TextBlockItemInfo>;
}
// @public (undocumented)
export type AddBlockItemsParameters = AddBlockItemsBodyParam & RequestParameters;
// @public
export interface AddBlockItemsResultOutput {
value?: Array<TextBlockItemOutput>;
}
// @public (undocumented)
export interface AnalyzeImage {
post(options: AnalyzeImageParameters): StreamableMethod<AnalyzeImage200Response | AnalyzeImageDefaultResponse>;
}
// @public
export interface AnalyzeImage200Response extends HttpResponse {
// (undocumented)
body: AnalyzeImageResultOutput;
// (undocumented)
status: "200";
}
// @public (undocumented)
export interface AnalyzeImageBodyParam {
body: AnalyzeImageOptions;
}
// @public (undocumented)
export interface AnalyzeImageDefaultHeaders {
"x-ms-error-code"?: string;
}
// @public (undocumented)
export interface AnalyzeImageDefaultResponse extends HttpResponse {
// (undocumented)
body: ErrorResponse;
// (undocumented)
headers: RawHttpHeaders & AnalyzeImageDefaultHeaders;
// (undocumented)
status: string;
}
// @public
export interface AnalyzeImageOptions {
categories?: string[];
image: ImageData_2;
}
// @public
export interface AnalyzeImageOptionsOutput {
categories?: string[];
image: ImageDataOutput;
}
// @public (undocumented)
export type AnalyzeImageParameters = AnalyzeImageBodyParam & RequestParameters;
// @public
export interface AnalyzeImageResultOutput {
hateResult?: ImageAnalyzeSeverityResultOutput;
selfHarmResult?: ImageAnalyzeSeverityResultOutput;
sexualResult?: ImageAnalyzeSeverityResultOutput;
violenceResult?: ImageAnalyzeSeverityResultOutput;
}
// @public (undocumented)
export interface AnalyzeText {
post(options: AnalyzeTextParameters): StreamableMethod<AnalyzeText200Response | AnalyzeTextDefaultResponse>;
}
// @public
export interface AnalyzeText200Response extends HttpResponse {
// (undocumented)
body: AnalyzeTextResultOutput;
// (undocumented)
status: "200";
}
// @public (undocumented)
export interface AnalyzeTextBodyParam {
body: AnalyzeTextOptions;
}
// @public (undocumented)
export interface AnalyzeTextDefaultHeaders {
"x-ms-error-code"?: string;
}
// @public (undocumented)
export interface AnalyzeTextDefaultResponse extends HttpResponse {
// (undocumented)
body: ErrorResponse;
// (undocumented)
headers: RawHttpHeaders & AnalyzeTextDefaultHeaders;
// (undocumented)
status: string;
}
// @public
export interface AnalyzeTextOptions {
blocklistNames?: string[];
breakByBlocklists?: boolean;
categories?: string[];
text: string;
}
// @public
export interface AnalyzeTextOptionsOutput {
blocklistNames?: string[];
breakByBlocklists?: boolean;
categories?: string[];
text: string;
}
// @public (undocumented)
export type AnalyzeTextParameters = AnalyzeTextBodyParam & RequestParameters;
// @public
export interface AnalyzeTextResultOutput {
blocklistsMatchResults?: Array<TextBlocklistMatchResultOutput>;
hateResult?: TextAnalyzeSeverityResultOutput;
selfHarmResult?: TextAnalyzeSeverityResultOutput;
sexualResult?: TextAnalyzeSeverityResultOutput;
violenceResult?: TextAnalyzeSeverityResultOutput;
}
// @public (undocumented)
export type ContentSafetyClient = Client & {
path: Routes;
};
// @public
function createClient(endpoint: string, credentials: KeyCredential, options?: ClientOptions): ContentSafetyClient;
export default createClient;
// @public
export interface CreateOrUpdateTextBlocklist200Response extends HttpResponse {
// (undocumented)
body: TextBlocklistOutput;
// (undocumented)
status: "200";
}
// @public
export interface CreateOrUpdateTextBlocklist201Response extends HttpResponse {
// (undocumented)
body: TextBlocklistOutput;
// (undocumented)
status: "201";
}
// @public (undocumented)
export interface CreateOrUpdateTextBlocklistBodyParam {
body: TextBlocklistResourceMergeAndPatch;
}
// @public (undocumented)
export interface CreateOrUpdateTextBlocklistDefaultHeaders {
"x-ms-error-code"?: string;
}
// @public (undocumented)
export interface CreateOrUpdateTextBlocklistDefaultResponse extends HttpResponse {
// (undocumented)
body: ErrorResponse;
// (undocumented)
headers: RawHttpHeaders & CreateOrUpdateTextBlocklistDefaultHeaders;
// (undocumented)
status: string;
}
// @public (undocumented)
export interface CreateOrUpdateTextBlocklistMediaTypesParam {
contentType: "application/merge-patch+json";
}
// @public (undocumented)
export type CreateOrUpdateTextBlocklistParameters = CreateOrUpdateTextBlocklistMediaTypesParam & CreateOrUpdateTextBlocklistBodyParam & RequestParameters;
// @public
export interface DeleteTextBlocklist204Response extends HttpResponse {
// (undocumented)
status: "204";
}
// @public (undocumented)
export interface DeleteTextBlocklistDefaultHeaders {
"x-ms-error-code"?: string;
}
// @public (undocumented)
export interface DeleteTextBlocklistDefaultResponse extends HttpResponse {
// (undocumented)
body: ErrorResponse;
// (undocumented)
headers: RawHttpHeaders & DeleteTextBlocklistDefaultHeaders;
// (undocumented)
status: string;
}
// @public (undocumented)
export type DeleteTextBlocklistParameters = RequestParameters;
// @public
export type GetArrayType<T> = T extends Array<infer TData> ? TData : never;
// @public
export type GetPage<TPage> = (pageLink: string, maxPageSize?: number) => Promise<{
page: TPage;
nextPageLink?: string;
}>;
// @public (undocumented)
export interface GetTextBlocklist {
delete(options?: DeleteTextBlocklistParameters): StreamableMethod<DeleteTextBlocklist204Response | DeleteTextBlocklistDefaultResponse>;
get(options?: GetTextBlocklistParameters): StreamableMethod<GetTextBlocklist200Response | GetTextBlocklistDefaultResponse>;
patch(options: CreateOrUpdateTextBlocklistParameters): StreamableMethod<CreateOrUpdateTextBlocklist200Response | CreateOrUpdateTextBlocklist201Response | CreateOrUpdateTextBlocklistDefaultResponse>;
}
// @public
export interface GetTextBlocklist200Response extends HttpResponse {
// (undocumented)
body: TextBlocklistOutput;
// (undocumented)
status: "200";
}
// @public (undocumented)
export interface GetTextBlocklistDefaultHeaders {
"x-ms-error-code"?: string;
}
// @public (undocumented)
export interface GetTextBlocklistDefaultResponse extends HttpResponse {
// (undocumented)
body: ErrorResponse;
// (undocumented)
headers: RawHttpHeaders & GetTextBlocklistDefaultHeaders;
// (undocumented)
status: string;
}
// @public (undocumented)
export interface GetTextBlocklistItem {
get(options?: GetTextBlocklistItemParameters): StreamableMethod<GetTextBlocklistItem200Response | GetTextBlocklistItemDefaultResponse>;
}
// @public
export interface GetTextBlocklistItem200Response extends HttpResponse {
// (undocumented)
body: TextBlockItemOutput;
// (undocumented)
status: "200";
}
// @public (undocumented)
export interface GetTextBlocklistItemDefaultHeaders {
"x-ms-error-code"?: string;
}
// @public (undocumented)
export interface GetTextBlocklistItemDefaultResponse extends HttpResponse {
// (undocumented)
body: ErrorResponse;
// (undocumented)
headers: RawHttpHeaders & GetTextBlocklistItemDefaultHeaders;
// (undocumented)
status: string;
}
// @public (undocumented)
export type GetTextBlocklistItemParameters = RequestParameters;
// @public (undocumented)
export type GetTextBlocklistParameters = RequestParameters;
// @public
export interface ImageAnalyzeSeverityResultOutput {
category: string;
severity: number;
}
// @public
interface ImageData_2 {
blobUrl?: string;
content?: string;
}
export { ImageData_2 as ImageData }
// @public
export interface ImageDataOutput {
blobUrl?: string;
content?: string;
}
// @public (undocumented)
export function isUnexpected(response: AnalyzeText200Response | AnalyzeTextDefaultResponse): response is AnalyzeTextDefaultResponse;
// @public (undocumented)
export function isUnexpected(response: AnalyzeImage200Response | AnalyzeImageDefaultResponse): response is AnalyzeImageDefaultResponse;
// @public (undocumented)
export function isUnexpected(response: GetTextBlocklist200Response | GetTextBlocklistDefaultResponse): response is GetTextBlocklistDefaultResponse;
// @public (undocumented)
export function isUnexpected(response: CreateOrUpdateTextBlocklist200Response | CreateOrUpdateTextBlocklist201Response | CreateOrUpdateTextBlocklistDefaultResponse): response is CreateOrUpdateTextBlocklistDefaultResponse;
// @public (undocumented)
export function isUnexpected(response: DeleteTextBlocklist204Response | DeleteTextBlocklistDefaultResponse): response is DeleteTextBlocklistDefaultResponse;
// @public (undocumented)
export function isUnexpected(response: ListTextBlocklists200Response | ListTextBlocklistsDefaultResponse): response is ListTextBlocklistsDefaultResponse;
// @public (undocumented)
export function isUnexpected(response: AddBlockItems200Response | AddBlockItemsDefaultResponse): response is AddBlockItemsDefaultResponse;
// @public (undocumented)
export function isUnexpected(response: RemoveBlockItems204Response | RemoveBlockItemsDefaultResponse): response is RemoveBlockItemsDefaultResponse;
// @public (undocumented)
export function isUnexpected(response: GetTextBlocklistItem200Response | GetTextBlocklistItemDefaultResponse): response is GetTextBlocklistItemDefaultResponse;
// @public (undocumented)
export function isUnexpected(response: ListTextBlocklistItems200Response | ListTextBlocklistItemsDefaultResponse): response is ListTextBlocklistItemsDefaultResponse;
// @public (undocumented)
export interface ListTextBlocklistItems {
get(options?: ListTextBlocklistItemsParameters): StreamableMethod<ListTextBlocklistItems200Response | ListTextBlocklistItemsDefaultResponse>;
}
// @public
export interface ListTextBlocklistItems200Response extends HttpResponse {
// (undocumented)
body: TextBlockItemListOutput;
// (undocumented)
status: "200";
}
// @public (undocumented)
export interface ListTextBlocklistItemsDefaultHeaders {
"x-ms-error-code"?: string;
}
// @public (undocumented)
export interface ListTextBlocklistItemsDefaultResponse extends HttpResponse {
// (undocumented)
body: ErrorResponse;
// (undocumented)
headers: RawHttpHeaders & ListTextBlocklistItemsDefaultHeaders;
// (undocumented)
status: string;
}
// @public (undocumented)
export type ListTextBlocklistItemsParameters = ListTextBlocklistItemsQueryParam & RequestParameters;
// @public (undocumented)
export interface ListTextBlocklistItemsQueryParam {
// (undocumented)
queryParameters?: ListTextBlocklistItemsQueryParamProperties;
}
// @public (undocumented)
export interface ListTextBlocklistItemsQueryParamProperties {
maxpagesize?: number;
skip?: number;
top?: number;
}
// @public (undocumented)
export interface ListTextBlocklists {
get(options?: ListTextBlocklistsParameters): StreamableMethod<ListTextBlocklists200Response | ListTextBlocklistsDefaultResponse>;
}
// @public
export interface ListTextBlocklists200Response extends HttpResponse {
// (undocumented)
body: TextBlocklistListOutput;
// (undocumented)
status: "200";
}
// @public (undocumented)
export interface ListTextBlocklistsDefaultHeaders {
"x-ms-error-code"?: string;
}
// @public (undocumented)
export interface ListTextBlocklistsDefaultResponse extends HttpResponse {
// (undocumented)
body: ErrorResponse;
// (undocumented)
headers: RawHttpHeaders & ListTextBlocklistsDefaultHeaders;
// (undocumented)
status: string;
}
// @public (undocumented)
export type ListTextBlocklistsParameters = RequestParameters;
// @public
export function paginate<TResponse extends PathUncheckedResponse>(client: Client, initialResponse: TResponse, options?: PagingOptions<TResponse>): PagedAsyncIterableIterator<PaginateReturn<TResponse>>;
// @public
export type PaginateReturn<TResult> = TResult extends {
body: {
value?: infer TPage;
};
} ? GetArrayType<TPage> : Array<unknown>;
// @public
export interface PagingOptions<TResponse> {
customGetPage?: GetPage<PaginateReturn<TResponse>[]>;
}
// @public (undocumented)
export interface RemoveBlockItems {
post(options?: RemoveBlockItemsParameters): StreamableMethod<RemoveBlockItems204Response | RemoveBlockItemsDefaultResponse>;
}
// @public
export interface RemoveBlockItems204Response extends HttpResponse {
// (undocumented)
status: "204";
}
// @public (undocumented)
export interface RemoveBlockItemsBodyParam {
// (undocumented)
body?: RemoveBlockItemsOptions;
}
// @public (undocumented)
export interface RemoveBlockItemsDefaultHeaders {
"x-ms-error-code"?: string;
}
// @public (undocumented)
export interface RemoveBlockItemsDefaultResponse extends HttpResponse {
// (undocumented)
body: ErrorResponse;
// (undocumented)
headers: RawHttpHeaders & RemoveBlockItemsDefaultHeaders;
// (undocumented)
status: string;
}
// @public
export interface RemoveBlockItemsOptions {
blockItemIds: string[];
}
// @public (undocumented)
export type RemoveBlockItemsParameters = RemoveBlockItemsBodyParam & RequestParameters;
// @public (undocumented)
export interface Routes {
(path: "/text:analyze"): AnalyzeText;
(path: "/image:analyze"): AnalyzeImage;
(path: "/text/blocklists/{blocklistName}", blocklistName: string): GetTextBlocklist;
(path: "/text/blocklists"): ListTextBlocklists;
(path: "/text/blocklists/{blocklistName}:addBlockItems", blocklistName: string): AddBlockItems;
(path: "/text/blocklists/{blocklistName}:removeBlockItems", blocklistName: string): RemoveBlockItems;
(path: "/text/blocklists/{blocklistName}/blockItems/{blockItemId}", blocklistName: string, blockItemId: string): GetTextBlocklistItem;
(path: "/text/blocklists/{blocklistName}/blockItems", blocklistName: string): ListTextBlocklistItems;
}
// @public
export interface TextAnalyzeSeverityResultOutput {
category: string;
severity: number;
}
// @public
export interface TextBlockItemInfo {
description?: string;
text: string;
}
// @public
export type TextBlockItemListOutput = Paged<TextBlockItemOutput>;
// @public
export interface TextBlockItemOutput {
blockItemId: string;
description?: string;
text: string;
}
// @public
export interface TextBlocklist {
blocklistName: string;
description?: string;
}
// @public
export type TextBlocklistListOutput = Paged<TextBlocklistOutput>;
// @public
export interface TextBlocklistMatchResultOutput {
blockItemId: string;
blockItemText: string;
blocklistName: string;
length: number;
offset: number;
}
// @public
export interface TextBlocklistOutput {
blocklistName: string;
description?: string;
}
// @public
export type TextBlocklistResourceMergeAndPatch = Partial<TextBlocklist>;
// (No @packageDocumentation comment for this package)
```

Просмотреть файл

@ -0,0 +1,2 @@
CONTENT_SAFETY_ENDPOINT=
CONTENT_SAFETY_API_KEY=

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 338 KiB

Просмотреть файл

@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* @summary Demonstrates how to analyze image.
*/
import ContentSafetyClient, {
AnalyzeImageParameters,
AnalyzeImageOptions,
isUnexpected,
} from "@azure-rest/ai-content-safety";
import { AzureKeyCredential } from "@azure/core-auth";
import fs from "fs";
import path from "path";
// Load the .env file if it exists
import * as dotenv from "dotenv";
dotenv.config();
async function main() {
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const image_path = path.resolve(__dirname, "./samples-dev/example-data/image.png");
const imageBuffer = fs.readFileSync(image_path);
const base64Image = imageBuffer.toString("base64");
const analyzeImageOption: AnalyzeImageOptions = { image: { content: base64Image } };
const analyzeImageParameters: AnalyzeImageParameters = { body: analyzeImageOption };
const result = await client.path("/image:analyze").post(analyzeImageParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Hate severity: ", result.body.hateResult?.severity);
console.log("SelfHarm severity: ", result.body.selfHarmResult?.severity);
console.log("Sexual severity: ", result.body.sexualResult?.severity);
console.log("Violence severity: ", result.body.violenceResult?.severity);
}
main().catch((err) => {
console.error("The sample encountered an error:", err);
});

Просмотреть файл

@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* @summary Demonstrates how to analyze text.
*/
import ContentSafetyClient, {
AnalyzeTextParameters,
AnalyzeTextOptions,
isUnexpected
} from "@azure-rest/ai-content-safety";
import { AzureKeyCredential } from "@azure/core-auth";
// Load the .env file if it exists
import * as dotenv from "dotenv";
dotenv.config();
async function main() {
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const text = "This is a sample text";
const analyzeTextOption: AnalyzeTextOptions = { text: text };
const analyzeTextParameters: AnalyzeTextParameters = { body: analyzeTextOption };
const result = await client.path("/text:analyze").post(analyzeTextParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Hate severity: ", result.body.hateResult?.severity);
console.log("SelfHarm severity: ", result.body.selfHarmResult?.severity);
console.log("Sexual severity: ", result.body.sexualResult?.severity);
console.log("Violence severity: ", result.body.violenceResult?.severity);
}
main().catch((err) => {
console.error("The sample encountered an error:", err);
});

Просмотреть файл

@ -0,0 +1,236 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* @summary Demonstrates how to manage blocklist.
*/
import ContentSafetyClient, {
CreateOrUpdateTextBlocklistParameters,
AddBlockItemsParameters,
AnalyzeTextParameters,
RemoveBlockItemsParameters,
isUnexpected
} from "@azure-rest/ai-content-safety";
import { AzureKeyCredential } from "@azure/core-auth";
// Load the .env file if it exists
import * as dotenv from "dotenv";
dotenv.config();
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
async function createOrUpdateTextBlocklist() {
const blocklistName = "TestBlocklist";
const blocklistDescription = "Test blocklist management.";
const createOrUpdateTextBlocklistParameters: CreateOrUpdateTextBlocklistParameters = {
contentType: "application/merge-patch+json",
body: {
description: blocklistDescription,
}
}
const result = await client.path("/text/blocklists/{blocklistName}", blocklistName).patch(createOrUpdateTextBlocklistParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Blocklist created or updated: Name", result.body.blocklistName, ", Description: ", result.body.description);
}
async function addBlockItems() {
const blocklistName = "TestBlocklist";
const blockItemText1 = "sample";
const blockItemText2 = "text";
const addBlockItemsParameters: AddBlockItemsParameters = {
body: {
blockItems: [
{
description: "Test block item 1",
text: blockItemText1
},
{
description: "Test block item 2",
text: blockItemText2
}
]
}
};
const result = await client.path("/text/blocklists/{blocklistName}:addBlockItems", blocklistName).post(addBlockItemsParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Block items added: ");
if (result.body.value) {
for (const blockItem of result.body.value) {
console.log("BlockItemId: ", blockItem.blockItemId, ", Text: ", blockItem.text, ", Description: ", blockItem.description);
}
}
}
async function analyzeTextWithBlocklists() {
const blocklistName = "TestBlocklist";
const inputText = "This is a sample to test text with blocklist.";
const analyzeTextParameters: AnalyzeTextParameters = {
body: {
text: inputText,
blocklistNames: [blocklistName],
breakByBlocklists: false
}
};
const result = await client.path("/text:analyze").post(analyzeTextParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Blocklist match results: ");
if (result.body.blocklistsMatchResults) {
for (const blocklistMatchResult of result.body.blocklistsMatchResults) {
console.log("Block item was hit in text, Offset=", blocklistMatchResult.offset, ", Length=", blocklistMatchResult.length);
console.log("BlocklistName: ", blocklistMatchResult.blocklistName, ", BlockItemId: ", blocklistMatchResult.blockItemId, ", BlockItemText: ", blocklistMatchResult.blockItemText);
}
}
}
async function listTextBlocklists() {
const result = await client.path("/text/blocklists").get();
if (isUnexpected(result)) {
throw result;
}
console.log("List blocklists: ");
if (result.body.value) {
for (const blocklist of result.body.value) {
console.log("BlocklistName: ", blocklist.blocklistName, ", Description: ", blocklist.description);
}
}
}
async function getTextBlocklist() {
const blocklistName = "TestBlocklist";
const result = await client.path("/text/blocklists/{blocklistName}", blocklistName).get();
if (isUnexpected(result)) {
throw result;
}
console.log("Get blocklist: ");
console.log("Name: ", result.body.blocklistName, ", Description: ", result.body.description);
}
async function listBlockItems() {
const blocklistName = "TestBlocklist";
const result = await client.path("/text/blocklists/{blocklistName}/blockItems", blocklistName).get();
if (isUnexpected(result)) {
throw result;
}
console.log("List block items: ");
if (result.body.value) {
for (const blockItem of result.body.value) {
console.log("BlockItemId: ", blockItem.blockItemId, ", Text: ", blockItem.text, ", Description: ", blockItem.description);
}
}
}
async function getBlockItem() {
const blocklistName = "TestBlocklist";
const blockItemText = "sample";
const addBlockItemsParameters: AddBlockItemsParameters = {
body: {
blockItems: [
{
description: "Test block item 1",
text: blockItemText
}
]
}
};
const result = await client.path("/text/blocklists/{blocklistName}:addBlockItems", blocklistName).post(addBlockItemsParameters);
if (isUnexpected(result) || result.body.value === undefined) {
throw new Error("Block item not added.");
}
const blockItemId = result.body.value[0].blockItemId;
const blockItem = await client.path("/text/blocklists/{blocklistName}/blockItems/{blockItemId}", blocklistName, blockItemId).get();
if (isUnexpected(blockItem)) {
throw blockItem;
}
console.log("Get blockitem: ");
console.log("BlockItemId: ", blockItem.body.blockItemId, ", Text: ", blockItem.body.text, ", Description: ", blockItem.body.description);
}
async function removeBlockItems() {
const blocklistName = "TestBlocklist";
const blockItemText = "sample";
const addBlockItemsParameters: AddBlockItemsParameters = {
body: {
blockItems: [
{
description: "Test block item 1",
text: blockItemText
}
]
}
};
const result = await client.path("/text/blocklists/{blocklistName}:addBlockItems", blocklistName).post(addBlockItemsParameters);
if (isUnexpected(result) || result.body.value === undefined) {
throw new Error("Block item not added.");
}
const blockItemId = result.body.value[0].blockItemId;
const removeBlockItemsParameters: RemoveBlockItemsParameters = {
body: {
blockItemIds: [blockItemId]
}
};
const removeBlockItem = await client.path("/text/blocklists/{blocklistName}:removeBlockItems", blocklistName).post(removeBlockItemsParameters);
if (isUnexpected(removeBlockItem)) {
throw removeBlockItem;
}
console.log("Removed blockItem: ", blockItemText);
}
async function deleteBlocklist() {
const blocklistName = "TestBlocklist";
const result = await client.path("/text/blocklists/{blocklistName}", blocklistName).delete();
if (isUnexpected(result)) {
throw result;
}
console.log("Deleted blocklist: ", blocklistName);
}
(async () => {
await createOrUpdateTextBlocklist();
await addBlockItems();
await analyzeTextWithBlocklists();
await listTextBlocklists();
await getTextBlocklist();
await listBlockItems();
await getBlockItem();
await removeBlockItems();
await deleteBlocklist();
})().catch((err) => {
console.error("The sample encountered an error:", err);
});

Просмотреть файл

@ -0,0 +1,54 @@
# ContentSafety client library samples for JavaScript (Beta)
These sample programs show how to use the JavaScript client libraries for ContentSafety in some common scenarios.
| **File Name** | **Description** |
| ------------------------------------------------- | ------------------------------------- |
| [sampleAnalyzeImage.js][sampleanalyzeimage] | Demonstrates how to analyze image. |
| [sampleAnalyzeText.js][sampleanalyzetext] | Demonstrates how to analyze text. |
| [sampleManageBlocklist.js][samplemanageblocklist] | Demonstrates how to manage blocklist. |
## Prerequisites
The sample programs are compatible with [LTS versions of Node.js](https://github.com/nodejs/release#release-schedule).
You need [an Azure subscription][freesub] to run these sample programs.
Samples retrieve credentials to access the service endpoint from environment variables. Alternatively, edit the source code to include the appropriate credentials. See each individual sample for details on which environment variables/credentials it requires to function.
Adapting the samples to run in the browser may require some additional consideration. For details, please see the [package README][package].
## Setup
To run the samples using the published version of the package:
1. Install the dependencies using `npm`:
```bash
npm install
```
2. Edit the file `sample.env`, adding the correct credentials to access the Azure service and run the samples. Then rename the file from `sample.env` to just `.env`. The sample programs will read this file automatically.
3. Run whichever samples you like (note that some samples may require additional setup, see the table above):
```bash
node sampleAnalyzeImage.js
```
Alternatively, run a single sample with the correct environment variables set (setting up the `.env` file is not required if you do this), for example (cross-platform):
```bash
npx cross-env CONTENT_SAFETY_ENDPOINT="<content safety endpoint>" CONTENT_SAFETY_API_KEY="<content safety api key>" node sampleAnalyzeImage.js
```
## Next Steps
Take a look at our [API Documentation][apiref] for more information about the APIs that are available in the clients.
[sampleanalyzeimage]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/contentsafety/ai-content-safety-rest/samples/v1-beta/javascript/sampleAnalyzeImage.js
[sampleanalyzetext]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/contentsafety/ai-content-safety-rest/samples/v1-beta/javascript/sampleAnalyzeText.js
[samplemanageblocklist]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/contentsafety/ai-content-safety-rest/samples/v1-beta/javascript/sampleManageBlocklist.js
[apiref]: https://docs.microsoft.com/javascript/api/@azure-rest/ai-content-safety?view=azure-node-preview
[freesub]: https://azure.microsoft.com/free/
[package]: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/contentsafety/ai-content-safety-rest/README.md

Просмотреть файл

@ -0,0 +1,33 @@
{
"name": "@azure-samples/ai-content-safety-js-beta",
"private": true,
"version": "1.0.0",
"description": "ContentSafety client library samples for JavaScript (Beta)",
"engines": {
"node": ">=14.0.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Azure/azure-sdk-for-js.git",
"directory": "sdk/contentsafety/ai-content-safety-rest"
},
"keywords": [
"node",
"azure",
"cloud",
"typescript",
"browser",
"isomorphic"
],
"author": "Microsoft Corporation",
"license": "MIT",
"bugs": {
"url": "https://github.com/Azure/azure-sdk-for-js/issues"
},
"homepage": "https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/contentsafety/ai-content-safety-rest",
"dependencies": {
"@azure-rest/ai-content-safety": "next",
"dotenv": "latest",
"@azure/core-auth": "^1.3.0"
}
}

Просмотреть файл

@ -0,0 +1,2 @@
CONTENT_SAFETY_ENDPOINT=
CONTENT_SAFETY_API_KEY=

Просмотреть файл

@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* @summary Demonstrates how to analyze image.
*/
const ContentSafetyClient = require("@azure-rest/ai-content-safety").default,
{ isUnexpected } = require("@azure-rest/ai-content-safety");
const { AzureKeyCredential } = require("@azure/core-auth");
const fs = require("fs");
const path = require("path");
// Load the .env file if it exists
require("dotenv").config();
async function main() {
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const image_path = path.resolve(__dirname, "./samples-dev/example-data/image.png");
const imageBuffer = fs.readFileSync(image_path);
const base64Image = imageBuffer.toString("base64");
const analyzeImageOption = { image: { content: base64Image } };
const analyzeImageParameters = { body: analyzeImageOption };
const result = await client.path("/image:analyze").post(analyzeImageParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Hate severity: ", result.body.hateResult?.severity);
console.log("SelfHarm severity: ", result.body.selfHarmResult?.severity);
console.log("Sexual severity: ", result.body.sexualResult?.severity);
console.log("Violence severity: ", result.body.violenceResult?.severity);
}
main().catch((err) => {
console.error("The sample encountered an error:", err);
});

Просмотреть файл

@ -0,0 +1,40 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* @summary Demonstrates how to analyze text.
*/
const ContentSafetyClient = require("@azure-rest/ai-content-safety").default,
{ isUnexpected } = require("@azure-rest/ai-content-safety");
const { AzureKeyCredential } = require("@azure/core-auth");
// Load the .env file if it exists
require("dotenv").config();
async function main() {
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const text = "This is a sample text";
const analyzeTextOption = { text: text };
const analyzeTextParameters = { body: analyzeTextOption };
const result = await client.path("/text:analyze").post(analyzeTextParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Hate severity: ", result.body.hateResult?.severity);
console.log("SelfHarm severity: ", result.body.selfHarmResult?.severity);
console.log("Sexual severity: ", result.body.sexualResult?.severity);
console.log("Violence severity: ", result.body.violenceResult?.severity);
}
main().catch((err) => {
console.error("The sample encountered an error:", err);
});

Просмотреть файл

@ -0,0 +1,287 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* @summary Demonstrates how to manage blocklist.
*/
const ContentSafetyClient = require("@azure-rest/ai-content-safety").default,
{ isUnexpected } = require("@azure-rest/ai-content-safety");
const { AzureKeyCredential } = require("@azure/core-auth");
// Load the .env file if it exists
require("dotenv").config();
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
async function createOrUpdateTextBlocklist() {
const blocklistName = "TestBlocklist";
const blocklistDescription = "Test blocklist management.";
const createOrUpdateTextBlocklistParameters = {
contentType: "application/merge-patch+json",
body: {
description: blocklistDescription,
},
};
const result = await client
.path("/text/blocklists/{blocklistName}", blocklistName)
.patch(createOrUpdateTextBlocklistParameters);
if (isUnexpected(result)) {
throw result;
}
console.log(
"Blocklist created or updated: Name",
result.body.blocklistName,
", Description: ",
result.body.description
);
}
async function addBlockItems() {
const blocklistName = "TestBlocklist";
const blockItemText1 = "sample";
const blockItemText2 = "text";
const addBlockItemsParameters = {
body: {
blockItems: [
{
description: "Test block item 1",
text: blockItemText1,
},
{
description: "Test block item 2",
text: blockItemText2,
},
],
},
};
const result = await client
.path("/text/blocklists/{blocklistName}:addBlockItems", blocklistName)
.post(addBlockItemsParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Block items added: ");
if (result.body.value) {
for (const blockItem of result.body.value) {
console.log(
"BlockItemId: ",
blockItem.blockItemId,
", Text: ",
blockItem.text,
", Description: ",
blockItem.description
);
}
}
}
async function analyzeTextWithBlocklists() {
const blocklistName = "TestBlocklist";
const inputText = "This is a sample to test text with blocklist.";
const analyzeTextParameters = {
body: {
text: inputText,
blocklistNames: [blocklistName],
breakByBlocklists: false,
},
};
const result = await client.path("/text:analyze").post(analyzeTextParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Blocklist match results: ");
if (result.body.blocklistsMatchResults) {
for (const blocklistMatchResult of result.body.blocklistsMatchResults) {
console.log(
"Block item was hit in text, Offset=",
blocklistMatchResult.offset,
", Length=",
blocklistMatchResult.length
);
console.log(
"BlocklistName: ",
blocklistMatchResult.blocklistName,
", BlockItemId: ",
blocklistMatchResult.blockItemId,
", BlockItemText: ",
blocklistMatchResult.blockItemText
);
}
}
}
async function listTextBlocklists() {
const result = await client.path("/text/blocklists").get();
if (isUnexpected(result)) {
throw result;
}
console.log("List blocklists: ");
if (result.body.value) {
for (const blocklist of result.body.value) {
console.log(
"BlocklistName: ",
blocklist.blocklistName,
", Description: ",
blocklist.description
);
}
}
}
async function getTextBlocklist() {
const blocklistName = "TestBlocklist";
const result = await client.path("/text/blocklists/{blocklistName}", blocklistName).get();
if (isUnexpected(result)) {
throw result;
}
console.log("Get blocklist: ");
console.log("Name: ", result.body.blocklistName, ", Description: ", result.body.description);
}
async function listBlockItems() {
const blocklistName = "TestBlocklist";
const result = await client
.path("/text/blocklists/{blocklistName}/blockItems", blocklistName)
.get();
if (isUnexpected(result)) {
throw result;
}
console.log("List block items: ");
if (result.body.value) {
for (const blockItem of result.body.value) {
console.log(
"BlockItemId: ",
blockItem.blockItemId,
", Text: ",
blockItem.text,
", Description: ",
blockItem.description
);
}
}
}
async function getBlockItem() {
const blocklistName = "TestBlocklist";
const blockItemText = "sample";
const addBlockItemsParameters = {
body: {
blockItems: [
{
description: "Test block item 1",
text: blockItemText,
},
],
},
};
const result = await client
.path("/text/blocklists/{blocklistName}:addBlockItems", blocklistName)
.post(addBlockItemsParameters);
if (isUnexpected(result) || result.body.value === undefined) {
throw new Error("Block item not added.");
}
const blockItemId = result.body.value[0].blockItemId;
const blockItem = await client
.path("/text/blocklists/{blocklistName}/blockItems/{blockItemId}", blocklistName, blockItemId)
.get();
if (isUnexpected(blockItem)) {
throw blockItem;
}
console.log("Get blockitem: ");
console.log(
"BlockItemId: ",
blockItem.body.blockItemId,
", Text: ",
blockItem.body.text,
", Description: ",
blockItem.body.description
);
}
async function removeBlockItems() {
const blocklistName = "TestBlocklist";
const blockItemText = "sample";
const addBlockItemsParameters = {
body: {
blockItems: [
{
description: "Test block item 1",
text: blockItemText,
},
],
},
};
const result = await client
.path("/text/blocklists/{blocklistName}:addBlockItems", blocklistName)
.post(addBlockItemsParameters);
if (isUnexpected(result) || result.body.value === undefined) {
throw new Error("Block item not added.");
}
const blockItemId = result.body.value[0].blockItemId;
const removeBlockItemsParameters = {
body: {
blockItemIds: [blockItemId],
},
};
const removeBlockItem = await client
.path("/text/blocklists/{blocklistName}:removeBlockItems", blocklistName)
.post(removeBlockItemsParameters);
if (isUnexpected(removeBlockItem)) {
throw removeBlockItem;
}
console.log("Removed blockItem: ", blockItemText);
}
async function deleteBlocklist() {
const blocklistName = "TestBlocklist";
const result = await client.path("/text/blocklists/{blocklistName}", blocklistName).delete();
if (isUnexpected(result)) {
throw result;
}
console.log("Deleted blocklist: ", blocklistName);
}
(async () => {
await createOrUpdateTextBlocklist();
await addBlockItems();
await analyzeTextWithBlocklists();
await listTextBlocklists();
await getTextBlocklist();
await listBlockItems();
await getBlockItem();
await removeBlockItems();
await deleteBlocklist();
})().catch((err) => {
console.error("The sample encountered an error:", err);
});

Просмотреть файл

@ -0,0 +1,67 @@
# ContentSafety client library samples for TypeScript (Beta)
These sample programs show how to use the TypeScript client libraries for ContentSafety in some common scenarios.
| **File Name** | **Description** |
| ------------------------------------------------- | ------------------------------------- |
| [sampleAnalyzeImage.ts][sampleanalyzeimage] | Demonstrates how to analyze image. |
| [sampleAnalyzeText.ts][sampleanalyzetext] | Demonstrates how to analyze text. |
| [sampleManageBlocklist.ts][samplemanageblocklist] | Demonstrates how to manage blocklist. |
## Prerequisites
The sample programs are compatible with [LTS versions of Node.js](https://github.com/nodejs/release#release-schedule).
Before running the samples in Node, they must be compiled to JavaScript using the TypeScript compiler. For more information on TypeScript, see the [TypeScript documentation][typescript]. Install the TypeScript compiler using:
```bash
npm install -g typescript
```
You need [an Azure subscription][freesub] to run these sample programs.
Samples retrieve credentials to access the service endpoint from environment variables. Alternatively, edit the source code to include the appropriate credentials. See each individual sample for details on which environment variables/credentials it requires to function.
Adapting the samples to run in the browser may require some additional consideration. For details, please see the [package README][package].
## Setup
To run the samples using the published version of the package:
1. Install the dependencies using `npm`:
```bash
npm install
```
2. Compile the samples:
```bash
npm run build
```
3. Edit the file `sample.env`, adding the correct credentials to access the Azure service and run the samples. Then rename the file from `sample.env` to just `.env`. The sample programs will read this file automatically.
4. Run whichever samples you like (note that some samples may require additional setup, see the table above):
```bash
node dist/sampleAnalyzeImage.js
```
Alternatively, run a single sample with the correct environment variables set (setting up the `.env` file is not required if you do this), for example (cross-platform):
```bash
npx cross-env CONTENT_SAFETY_ENDPOINT="<content safety endpoint>" CONTENT_SAFETY_API_KEY="<content safety api key>" node dist/sampleAnalyzeImage.js
```
## Next Steps
Take a look at our [API Documentation][apiref] for more information about the APIs that are available in the clients.
[sampleanalyzeimage]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/contentsafety/ai-content-safety-rest/samples/v1-beta/typescript/src/sampleAnalyzeImage.ts
[sampleanalyzetext]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/contentsafety/ai-content-safety-rest/samples/v1-beta/typescript/src/sampleAnalyzeText.ts
[samplemanageblocklist]: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/contentsafety/ai-content-safety-rest/samples/v1-beta/typescript/src/sampleManageBlocklist.ts
[apiref]: https://docs.microsoft.com/javascript/api/@azure-rest/ai-content-safety?view=azure-node-preview
[freesub]: https://azure.microsoft.com/free/
[package]: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/contentsafety/ai-content-safety-rest/README.md
[typescript]: https://www.typescriptlang.org/docs/home.html

Просмотреть файл

@ -0,0 +1,42 @@
{
"name": "@azure-samples/ai-content-safety-ts-beta",
"private": true,
"version": "1.0.0",
"description": "ContentSafety client library samples for TypeScript (Beta)",
"engines": {
"node": ">=14.0.0"
},
"scripts": {
"build": "tsc",
"prebuild": "rimraf dist/"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Azure/azure-sdk-for-js.git",
"directory": "sdk/contentsafety/ai-content-safety-rest"
},
"keywords": [
"node",
"azure",
"cloud",
"typescript",
"browser",
"isomorphic"
],
"author": "Microsoft Corporation",
"license": "MIT",
"bugs": {
"url": "https://github.com/Azure/azure-sdk-for-js/issues"
},
"homepage": "https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/contentsafety/ai-content-safety-rest",
"dependencies": {
"@azure-rest/ai-content-safety": "next",
"dotenv": "latest",
"@azure/core-auth": "^1.3.0"
},
"devDependencies": {
"@types/node": "^14.0.0",
"typescript": "~5.0.0",
"rimraf": "latest"
}
}

Просмотреть файл

@ -0,0 +1,2 @@
CONTENT_SAFETY_ENDPOINT=
CONTENT_SAFETY_API_KEY=

Просмотреть файл

@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* @summary Demonstrates how to analyze image.
*/
import ContentSafetyClient, {
AnalyzeImageParameters,
AnalyzeImageOptions,
isUnexpected,
} from "@azure-rest/ai-content-safety";
import { AzureKeyCredential } from "@azure/core-auth";
import fs from "fs";
import path from "path";
// Load the .env file if it exists
import * as dotenv from "dotenv";
dotenv.config();
async function main() {
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const image_path = path.resolve(__dirname, "./samples-dev/example-data/image.png");
const imageBuffer = fs.readFileSync(image_path);
const base64Image = imageBuffer.toString("base64");
const analyzeImageOption: AnalyzeImageOptions = { image: { content: base64Image } };
const analyzeImageParameters: AnalyzeImageParameters = { body: analyzeImageOption };
const result = await client.path("/image:analyze").post(analyzeImageParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Hate severity: ", result.body.hateResult?.severity);
console.log("SelfHarm severity: ", result.body.selfHarmResult?.severity);
console.log("Sexual severity: ", result.body.sexualResult?.severity);
console.log("Violence severity: ", result.body.violenceResult?.severity);
}
main().catch((err) => {
console.error("The sample encountered an error:", err);
});

Просмотреть файл

@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* @summary Demonstrates how to analyze text.
*/
import ContentSafetyClient, {
AnalyzeTextParameters,
AnalyzeTextOptions,
isUnexpected
} from "@azure-rest/ai-content-safety";
import { AzureKeyCredential } from "@azure/core-auth";
// Load the .env file if it exists
import * as dotenv from "dotenv";
dotenv.config();
async function main() {
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
const text = "This is a sample text";
const analyzeTextOption: AnalyzeTextOptions = { text: text };
const analyzeTextParameters: AnalyzeTextParameters = { body: analyzeTextOption };
const result = await client.path("/text:analyze").post(analyzeTextParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Hate severity: ", result.body.hateResult?.severity);
console.log("SelfHarm severity: ", result.body.selfHarmResult?.severity);
console.log("Sexual severity: ", result.body.sexualResult?.severity);
console.log("Violence severity: ", result.body.violenceResult?.severity);
}
main().catch((err) => {
console.error("The sample encountered an error:", err);
});

Просмотреть файл

@ -0,0 +1,236 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* @summary Demonstrates how to manage blocklist.
*/
import ContentSafetyClient, {
CreateOrUpdateTextBlocklistParameters,
AddBlockItemsParameters,
AnalyzeTextParameters,
RemoveBlockItemsParameters,
isUnexpected
} from "@azure-rest/ai-content-safety";
import { AzureKeyCredential } from "@azure/core-auth";
// Load the .env file if it exists
import * as dotenv from "dotenv";
dotenv.config();
const endpoint = process.env["CONTENT_SAFETY_ENDPOINT"] || "<endpoint>";
const key = process.env["CONTENT_SAFETY_API_KEY"] || "<key>";
const credential = new AzureKeyCredential(key);
const client = ContentSafetyClient(endpoint, credential);
async function createOrUpdateTextBlocklist() {
const blocklistName = "TestBlocklist";
const blocklistDescription = "Test blocklist management.";
const createOrUpdateTextBlocklistParameters: CreateOrUpdateTextBlocklistParameters = {
contentType: "application/merge-patch+json",
body: {
description: blocklistDescription,
}
}
const result = await client.path("/text/blocklists/{blocklistName}", blocklistName).patch(createOrUpdateTextBlocklistParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Blocklist created or updated: Name", result.body.blocklistName, ", Description: ", result.body.description);
}
async function addBlockItems() {
const blocklistName = "TestBlocklist";
const blockItemText1 = "sample";
const blockItemText2 = "text";
const addBlockItemsParameters: AddBlockItemsParameters = {
body: {
blockItems: [
{
description: "Test block item 1",
text: blockItemText1
},
{
description: "Test block item 2",
text: blockItemText2
}
]
}
};
const result = await client.path("/text/blocklists/{blocklistName}:addBlockItems", blocklistName).post(addBlockItemsParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Block items added: ");
if (result.body.value) {
for (const blockItem of result.body.value) {
console.log("BlockItemId: ", blockItem.blockItemId, ", Text: ", blockItem.text, ", Description: ", blockItem.description);
}
}
}
async function analyzeTextWithBlocklists() {
const blocklistName = "TestBlocklist";
const inputText = "This is a sample to test text with blocklist.";
const analyzeTextParameters: AnalyzeTextParameters = {
body: {
text: inputText,
blocklistNames: [blocklistName],
breakByBlocklists: false
}
};
const result = await client.path("/text:analyze").post(analyzeTextParameters);
if (isUnexpected(result)) {
throw result;
}
console.log("Blocklist match results: ");
if (result.body.blocklistsMatchResults) {
for (const blocklistMatchResult of result.body.blocklistsMatchResults) {
console.log("Block item was hit in text, Offset=", blocklistMatchResult.offset, ", Length=", blocklistMatchResult.length);
console.log("BlocklistName: ", blocklistMatchResult.blocklistName, ", BlockItemId: ", blocklistMatchResult.blockItemId, ", BlockItemText: ", blocklistMatchResult.blockItemText);
}
}
}
async function listTextBlocklists() {
const result = await client.path("/text/blocklists").get();
if (isUnexpected(result)) {
throw result;
}
console.log("List blocklists: ");
if (result.body.value) {
for (const blocklist of result.body.value) {
console.log("BlocklistName: ", blocklist.blocklistName, ", Description: ", blocklist.description);
}
}
}
async function getTextBlocklist() {
const blocklistName = "TestBlocklist";
const result = await client.path("/text/blocklists/{blocklistName}", blocklistName).get();
if (isUnexpected(result)) {
throw result;
}
console.log("Get blocklist: ");
console.log("Name: ", result.body.blocklistName, ", Description: ", result.body.description);
}
async function listBlockItems() {
const blocklistName = "TestBlocklist";
const result = await client.path("/text/blocklists/{blocklistName}/blockItems", blocklistName).get();
if (isUnexpected(result)) {
throw result;
}
console.log("List block items: ");
if (result.body.value) {
for (const blockItem of result.body.value) {
console.log("BlockItemId: ", blockItem.blockItemId, ", Text: ", blockItem.text, ", Description: ", blockItem.description);
}
}
}
async function getBlockItem() {
const blocklistName = "TestBlocklist";
const blockItemText = "sample";
const addBlockItemsParameters: AddBlockItemsParameters = {
body: {
blockItems: [
{
description: "Test block item 1",
text: blockItemText
}
]
}
};
const result = await client.path("/text/blocklists/{blocklistName}:addBlockItems", blocklistName).post(addBlockItemsParameters);
if (isUnexpected(result) || result.body.value === undefined) {
throw new Error("Block item not added.");
}
const blockItemId = result.body.value[0].blockItemId;
const blockItem = await client.path("/text/blocklists/{blocklistName}/blockItems/{blockItemId}", blocklistName, blockItemId).get();
if (isUnexpected(blockItem)) {
throw blockItem;
}
console.log("Get blockitem: ");
console.log("BlockItemId: ", blockItem.body.blockItemId, ", Text: ", blockItem.body.text, ", Description: ", blockItem.body.description);
}
async function removeBlockItems() {
const blocklistName = "TestBlocklist";
const blockItemText = "sample";
const addBlockItemsParameters: AddBlockItemsParameters = {
body: {
blockItems: [
{
description: "Test block item 1",
text: blockItemText
}
]
}
};
const result = await client.path("/text/blocklists/{blocklistName}:addBlockItems", blocklistName).post(addBlockItemsParameters);
if (isUnexpected(result) || result.body.value === undefined) {
throw new Error("Block item not added.");
}
const blockItemId = result.body.value[0].blockItemId;
const removeBlockItemsParameters: RemoveBlockItemsParameters = {
body: {
blockItemIds: [blockItemId]
}
};
const removeBlockItem = await client.path("/text/blocklists/{blocklistName}:removeBlockItems", blocklistName).post(removeBlockItemsParameters);
if (isUnexpected(removeBlockItem)) {
throw removeBlockItem;
}
console.log("Removed blockItem: ", blockItemText);
}
async function deleteBlocklist() {
const blocklistName = "TestBlocklist";
const result = await client.path("/text/blocklists/{blocklistName}", blocklistName).delete();
if (isUnexpected(result)) {
throw result;
}
console.log("Deleted blocklist: ", blocklistName);
}
(async () => {
await createOrUpdateTextBlocklist();
await addBlockItems();
await analyzeTextWithBlocklists();
await listTextBlocklists();
await getTextBlocklist();
await listBlockItems();
await getBlockItem();
await removeBlockItems();
await deleteBlocklist();
})().catch((err) => {
console.error("The sample encountered an error:", err);
});

Просмотреть файл

@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"moduleResolution": "node",
"resolveJsonModule": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"alwaysStrict": true,
"outDir": "dist",
"rootDir": "src"
},
"include": [
"src/**.ts"
]
}

Просмотреть файл

@ -0,0 +1,140 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import {
AnalyzeTextParameters,
AnalyzeImageParameters,
GetTextBlocklistParameters,
CreateOrUpdateTextBlocklistParameters,
DeleteTextBlocklistParameters,
ListTextBlocklistsParameters,
AddBlockItemsParameters,
RemoveBlockItemsParameters,
GetTextBlocklistItemParameters,
ListTextBlocklistItemsParameters,
} from "./parameters";
import {
AnalyzeText200Response,
AnalyzeTextDefaultResponse,
AnalyzeImage200Response,
AnalyzeImageDefaultResponse,
GetTextBlocklist200Response,
GetTextBlocklistDefaultResponse,
CreateOrUpdateTextBlocklist200Response,
CreateOrUpdateTextBlocklist201Response,
CreateOrUpdateTextBlocklistDefaultResponse,
DeleteTextBlocklist204Response,
DeleteTextBlocklistDefaultResponse,
ListTextBlocklists200Response,
ListTextBlocklistsDefaultResponse,
AddBlockItems200Response,
AddBlockItemsDefaultResponse,
RemoveBlockItems204Response,
RemoveBlockItemsDefaultResponse,
GetTextBlocklistItem200Response,
GetTextBlocklistItemDefaultResponse,
ListTextBlocklistItems200Response,
ListTextBlocklistItemsDefaultResponse,
} from "./responses";
import { Client, StreamableMethod } from "@azure-rest/core-client";
export interface AnalyzeText {
/** A sync API for harmful content analysis for text. Currently, we support four categories: Hate, SelfHarm, Sexual, Violence. */
post(
options: AnalyzeTextParameters
): StreamableMethod<AnalyzeText200Response | AnalyzeTextDefaultResponse>;
}
export interface AnalyzeImage {
/** A sync API for harmful content analysis for image. Currently, we support four categories: Hate, SelfHarm, Sexual, Violence. */
post(
options: AnalyzeImageParameters
): StreamableMethod<AnalyzeImage200Response | AnalyzeImageDefaultResponse>;
}
export interface GetTextBlocklist {
/** Returns text blocklist details. */
get(
options?: GetTextBlocklistParameters
): StreamableMethod<GetTextBlocklist200Response | GetTextBlocklistDefaultResponse>;
/** Updates a text blocklist, if blocklistName does not exist, create a new blocklist. */
patch(
options: CreateOrUpdateTextBlocklistParameters
): StreamableMethod<
| CreateOrUpdateTextBlocklist200Response
| CreateOrUpdateTextBlocklist201Response
| CreateOrUpdateTextBlocklistDefaultResponse
>;
/** Deletes a text blocklist. */
delete(
options?: DeleteTextBlocklistParameters
): StreamableMethod<DeleteTextBlocklist204Response | DeleteTextBlocklistDefaultResponse>;
}
export interface ListTextBlocklists {
/** Get all text blocklists details. */
get(
options?: ListTextBlocklistsParameters
): StreamableMethod<ListTextBlocklists200Response | ListTextBlocklistsDefaultResponse>;
}
export interface AddBlockItems {
/** Add blockItems to a text blocklist. You can add at most 100 BlockItems in one request. */
post(
options?: AddBlockItemsParameters
): StreamableMethod<AddBlockItems200Response | AddBlockItemsDefaultResponse>;
}
export interface RemoveBlockItems {
/** Remove blockItems from a text blocklist. You can remove at most 100 BlockItems in one request. */
post(
options?: RemoveBlockItemsParameters
): StreamableMethod<RemoveBlockItems204Response | RemoveBlockItemsDefaultResponse>;
}
export interface GetTextBlocklistItem {
/** Get blockItem By blockItemId from a text blocklist. */
get(
options?: GetTextBlocklistItemParameters
): StreamableMethod<GetTextBlocklistItem200Response | GetTextBlocklistItemDefaultResponse>;
}
export interface ListTextBlocklistItems {
/** Get all blockItems in a text blocklist */
get(
options?: ListTextBlocklistItemsParameters
): StreamableMethod<ListTextBlocklistItems200Response | ListTextBlocklistItemsDefaultResponse>;
}
export interface Routes {
/** Resource for '/text:analyze' has methods for the following verbs: post */
(path: "/text:analyze"): AnalyzeText;
/** Resource for '/image:analyze' has methods for the following verbs: post */
(path: "/image:analyze"): AnalyzeImage;
/** Resource for '/text/blocklists/\{blocklistName\}' has methods for the following verbs: get, patch, delete */
(path: "/text/blocklists/{blocklistName}", blocklistName: string): GetTextBlocklist;
/** Resource for '/text/blocklists' has methods for the following verbs: get */
(path: "/text/blocklists"): ListTextBlocklists;
/** Resource for '/text/blocklists/\{blocklistName\}:addBlockItems' has methods for the following verbs: post */
(path: "/text/blocklists/{blocklistName}:addBlockItems", blocklistName: string): AddBlockItems;
/** Resource for '/text/blocklists/\{blocklistName\}:removeBlockItems' has methods for the following verbs: post */
(
path: "/text/blocklists/{blocklistName}:removeBlockItems",
blocklistName: string
): RemoveBlockItems;
/** Resource for '/text/blocklists/\{blocklistName\}/blockItems/\{blockItemId\}' has methods for the following verbs: get */
(
path: "/text/blocklists/{blocklistName}/blockItems/{blockItemId}",
blocklistName: string,
blockItemId: string
): GetTextBlocklistItem;
/** Resource for '/text/blocklists/\{blocklistName\}/blockItems' has methods for the following verbs: get */
(
path: "/text/blocklists/{blocklistName}/blockItems",
blocklistName: string
): ListTextBlocklistItems;
}
export type ContentSafetyClient = Client & {
path: Routes;
};

Просмотреть файл

@ -0,0 +1,48 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { getClient, ClientOptions } from "@azure-rest/core-client";
import { logger } from "./logger";
import { KeyCredential } from "@azure/core-auth";
import { ContentSafetyClient } from "./clientDefinitions";
/**
* Initialize a new instance of `ContentSafetyClient`
* @param endpoint - Supported Cognitive Services endpoints (protocol and hostname, for example:
* https://<resource-name>.cognitiveservices.azure.com).
* @param credentials - uniquely identify client credential
* @param options - the parameter for all optional parameters
*/
export default function createClient(
endpoint: string,
credentials: KeyCredential,
options: ClientOptions = {}
): ContentSafetyClient {
const baseUrl = options.baseUrl ?? `${endpoint}/contentsafety`;
options.apiVersion = options.apiVersion ?? "2023-04-30-preview";
options = {
...options,
credentials: {
apiKeyHeaderName: options.credentials?.apiKeyHeaderName ?? "Ocp-Apim-Subscription-Key",
},
};
const userAgentInfo = `azsdk-js-ai-content-safety-rest/1.0.0-beta.1`;
const userAgentPrefix =
options.userAgentOptions && options.userAgentOptions.userAgentPrefix
? `${options.userAgentOptions.userAgentPrefix} ${userAgentInfo}`
: `${userAgentInfo}`;
options = {
...options,
userAgentOptions: {
userAgentPrefix,
},
loggingOptions: {
logger: options.loggingOptions?.logger ?? logger.info,
},
};
const client = getClient(baseUrl, credentials, options) as ContentSafetyClient;
return client;
}

Просмотреть файл

@ -0,0 +1,15 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import ContentSafetyClient from "./contentSafetyClient";
export * from "./contentSafetyClient";
export * from "./parameters";
export * from "./responses";
export * from "./clientDefinitions";
export * from "./isUnexpected";
export * from "./models";
export * from "./outputModels";
export * from "./paginateHelper";
export default ContentSafetyClient;

Просмотреть файл

@ -0,0 +1,182 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import {
AnalyzeText200Response,
AnalyzeTextDefaultResponse,
AnalyzeImage200Response,
AnalyzeImageDefaultResponse,
GetTextBlocklist200Response,
GetTextBlocklistDefaultResponse,
CreateOrUpdateTextBlocklist200Response,
CreateOrUpdateTextBlocklist201Response,
CreateOrUpdateTextBlocklistDefaultResponse,
DeleteTextBlocklist204Response,
DeleteTextBlocklistDefaultResponse,
ListTextBlocklists200Response,
ListTextBlocklistsDefaultResponse,
AddBlockItems200Response,
AddBlockItemsDefaultResponse,
RemoveBlockItems204Response,
RemoveBlockItemsDefaultResponse,
GetTextBlocklistItem200Response,
GetTextBlocklistItemDefaultResponse,
ListTextBlocklistItems200Response,
ListTextBlocklistItemsDefaultResponse,
} from "./responses";
const responseMap: Record<string, string[]> = {
"POST /text:analyze": ["200"],
"POST /image:analyze": ["200"],
"GET /text/blocklists/{blocklistName}": ["200"],
"PATCH /text/blocklists/{blocklistName}": ["200", "201"],
"DELETE /text/blocklists/{blocklistName}": ["204"],
"GET /text/blocklists": ["200"],
"POST /text/blocklists/{blocklistName}:addBlockItems": ["200"],
"POST /text/blocklists/{blocklistName}:removeBlockItems": ["204"],
"GET /text/blocklists/{blocklistName}/blockItems/{blockItemId}": ["200"],
"GET /text/blocklists/{blocklistName}/blockItems": ["200"],
};
export function isUnexpected(
response: AnalyzeText200Response | AnalyzeTextDefaultResponse
): response is AnalyzeTextDefaultResponse;
export function isUnexpected(
response: AnalyzeImage200Response | AnalyzeImageDefaultResponse
): response is AnalyzeImageDefaultResponse;
export function isUnexpected(
response: GetTextBlocklist200Response | GetTextBlocklistDefaultResponse
): response is GetTextBlocklistDefaultResponse;
export function isUnexpected(
response:
| CreateOrUpdateTextBlocklist200Response
| CreateOrUpdateTextBlocklist201Response
| CreateOrUpdateTextBlocklistDefaultResponse
): response is CreateOrUpdateTextBlocklistDefaultResponse;
export function isUnexpected(
response: DeleteTextBlocklist204Response | DeleteTextBlocklistDefaultResponse
): response is DeleteTextBlocklistDefaultResponse;
export function isUnexpected(
response: ListTextBlocklists200Response | ListTextBlocklistsDefaultResponse
): response is ListTextBlocklistsDefaultResponse;
export function isUnexpected(
response: AddBlockItems200Response | AddBlockItemsDefaultResponse
): response is AddBlockItemsDefaultResponse;
export function isUnexpected(
response: RemoveBlockItems204Response | RemoveBlockItemsDefaultResponse
): response is RemoveBlockItemsDefaultResponse;
export function isUnexpected(
response: GetTextBlocklistItem200Response | GetTextBlocklistItemDefaultResponse
): response is GetTextBlocklistItemDefaultResponse;
export function isUnexpected(
response: ListTextBlocklistItems200Response | ListTextBlocklistItemsDefaultResponse
): response is ListTextBlocklistItemsDefaultResponse;
export function isUnexpected(
response:
| AnalyzeText200Response
| AnalyzeTextDefaultResponse
| AnalyzeImage200Response
| AnalyzeImageDefaultResponse
| GetTextBlocklist200Response
| GetTextBlocklistDefaultResponse
| CreateOrUpdateTextBlocklist200Response
| CreateOrUpdateTextBlocklist201Response
| CreateOrUpdateTextBlocklistDefaultResponse
| DeleteTextBlocklist204Response
| DeleteTextBlocklistDefaultResponse
| ListTextBlocklists200Response
| ListTextBlocklistsDefaultResponse
| AddBlockItems200Response
| AddBlockItemsDefaultResponse
| RemoveBlockItems204Response
| RemoveBlockItemsDefaultResponse
| GetTextBlocklistItem200Response
| GetTextBlocklistItemDefaultResponse
| ListTextBlocklistItems200Response
| ListTextBlocklistItemsDefaultResponse
): response is
| AnalyzeTextDefaultResponse
| AnalyzeImageDefaultResponse
| GetTextBlocklistDefaultResponse
| CreateOrUpdateTextBlocklistDefaultResponse
| DeleteTextBlocklistDefaultResponse
| ListTextBlocklistsDefaultResponse
| AddBlockItemsDefaultResponse
| RemoveBlockItemsDefaultResponse
| GetTextBlocklistItemDefaultResponse
| ListTextBlocklistItemsDefaultResponse {
const lroOriginal = response.headers["x-ms-original-url"];
const url = new URL(lroOriginal ?? response.request.url);
const method = response.request.method;
let pathDetails = responseMap[`${method} ${url.pathname}`];
if (!pathDetails) {
pathDetails = getParametrizedPathSuccess(method, url.pathname);
}
return !pathDetails.includes(response.status);
}
function getParametrizedPathSuccess(method: string, path: string): string[] {
const pathParts = path.split("/");
// Traverse list to match the longest candidate
// matchedLen: the length of candidate path
// matchedValue: the matched status code array
let matchedLen = -1,
matchedValue: string[] = [];
// Iterate the responseMap to find a match
for (const [key, value] of Object.entries(responseMap)) {
// Extracting the path from the map key which is in format
// GET /path/foo
if (!key.startsWith(method)) {
continue;
}
const candidatePath = getPathFromMapKey(key);
// Get each part of the url path
const candidateParts = candidatePath.split("/");
// track if we have found a match to return the values found.
let found = true;
for (let i = candidateParts.length - 1, j = pathParts.length - 1; i >= 1 && j >= 1; i--, j--) {
if (candidateParts[i]?.startsWith("{") && candidateParts[i]?.indexOf("}") !== -1) {
const start = candidateParts[i]!.indexOf("}") + 1,
end = candidateParts[i]?.length;
// If the current part of the candidate is a "template" part
// Try to use the suffix of pattern to match the path
// {guid} ==> $
// {guid}:export ==> :export$
const isMatched = new RegExp(`${candidateParts[i]?.slice(start, end)}`).test(
pathParts[j] || ""
);
if (!isMatched) {
found = false;
break;
}
continue;
}
// If the candidate part is not a template and
// the parts don't match mark the candidate as not found
// to move on with the next candidate path.
if (candidateParts[i] !== pathParts[j]) {
found = false;
break;
}
}
// We finished evaluating the current candidate parts
// Update the matched value if and only if we found the longer pattern
if (found && candidatePath.length > matchedLen) {
matchedLen = candidatePath.length;
matchedValue = value;
}
}
return matchedValue;
}
function getPathFromMapKey(mapKey: string): string {
const pathStart = mapKey.indexOf("/");
return mapKey.slice(pathStart);
}

Просмотреть файл

@ -0,0 +1,5 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { createClientLogger } from "@azure/logger";
export const logger = createClientLogger("ai-content-safety");

Просмотреть файл

@ -0,0 +1,58 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
/** The analysis request of the text. */
export interface AnalyzeTextOptions {
/** The text needs to be scanned. We support at most 1000 characters (unicode code points) in text of one request. */
text: string;
/** The categories will be analyzed. If not assigned, a default set of the categories' analysis results will be returned. */
categories?: string[];
/** The names of blocklists. */
blocklistNames?: string[];
/** When set to true, further analyses of harmful content will not be performed in cases where blocklists are hit. When set to false, all analyses of harmful content will be performed, whether or not blocklists are hit. */
breakByBlocklists?: boolean;
}
/** The analysis request of the image. */
export interface AnalyzeImageOptions {
/** The image needs to be analyzed. */
image: ImageData;
/** The categories will be analyzed. If not assigned, a default set of the categories' analysis results will be returned. */
categories?: string[];
}
/** The content or blob url of image, could be base64 encoding bytes or blob url. If both are given, the request will be refused. The maximum size of image is 2048 pixels * 2048 pixels, no larger than 4MB at the same time. The minimum size of image is 50 pixels * 50 pixels. */
export interface ImageData {
/** Base64 encoding of image. */
content?: string;
/** The blob url of image. */
blobUrl?: string;
}
/** Text Blocklist. */
export interface TextBlocklist {
/** Text blocklist name. */
blocklistName: string;
/** Text blocklist description. */
description?: string;
}
/** The request of adding blockItems to text blocklist. */
export interface AddBlockItemsOptions {
/** Array of blockItemInfo to add. */
blockItems: Array<TextBlockItemInfo>;
}
/** Block item info in text blocklist. */
export interface TextBlockItemInfo {
/** Block item description. */
description?: string;
/** Block item content. */
text: string;
}
/** The request of removing blockItems from text blocklist. */
export interface RemoveBlockItemsOptions {
/** Array of blockItemIds to remove. */
blockItemIds: string[];
}

Просмотреть файл

@ -0,0 +1,125 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { Paged } from "@azure/core-paging";
/** The analysis request of the text. */
export interface AnalyzeTextOptionsOutput {
/** The text needs to be scanned. We support at most 1000 characters (unicode code points) in text of one request. */
text: string;
/** The categories will be analyzed. If not assigned, a default set of the categories' analysis results will be returned. */
categories?: string[];
/** The names of blocklists. */
blocklistNames?: string[];
/** When set to true, further analyses of harmful content will not be performed in cases where blocklists are hit. When set to false, all analyses of harmful content will be performed, whether or not blocklists are hit. */
breakByBlocklists?: boolean;
}
/** The analysis response of the text */
export interface AnalyzeTextResultOutput {
/** The details of blocklist match. */
blocklistsMatchResults?: Array<TextBlocklistMatchResultOutput>;
/** Analysis result for Hate category. */
hateResult?: TextAnalyzeSeverityResultOutput;
/** Analysis result for SelfHarm category. */
selfHarmResult?: TextAnalyzeSeverityResultOutput;
/** Analysis result for Sexual category. */
sexualResult?: TextAnalyzeSeverityResultOutput;
/** Analysis result for Violence category. */
violenceResult?: TextAnalyzeSeverityResultOutput;
}
/** The result of blocklist match. */
export interface TextBlocklistMatchResultOutput {
/** The name of matched blocklist. */
blocklistName: string;
/** The id of matched item. */
blockItemId: string;
/** The content of matched item. */
blockItemText: string;
/** The character offset of matched text in original input. */
offset: number;
/** The length of matched text in original input. */
length: number;
}
/** Text analysis result. */
export interface TextAnalyzeSeverityResultOutput {
/**
* The text category.
*
* Possible values: Hate, SelfHarm, Sexual, Violence
*/
category: string;
/** The higher the severity of input content, the larger this value is. The values could be: 0,2,4,6. */
severity: number;
}
/** The analysis request of the image. */
export interface AnalyzeImageOptionsOutput {
/** The image needs to be analyzed. */
image: ImageDataOutput;
/** The categories will be analyzed. If not assigned, a default set of the categories' analysis results will be returned. */
categories?: string[];
}
/** The content or blob url of image, could be base64 encoding bytes or blob url. If both are given, the request will be refused. The maximum size of image is 2048 pixels * 2048 pixels, no larger than 4MB at the same time. The minimum size of image is 50 pixels * 50 pixels. */
export interface ImageDataOutput {
/** Base64 encoding of image. */
content?: string;
/** The blob url of image. */
blobUrl?: string;
}
/** The analysis response of the image. */
export interface AnalyzeImageResultOutput {
/** Analysis result for Hate category. */
hateResult?: ImageAnalyzeSeverityResultOutput;
/** Analysis result for SelfHarm category. */
selfHarmResult?: ImageAnalyzeSeverityResultOutput;
/** Analysis result for Sexual category. */
sexualResult?: ImageAnalyzeSeverityResultOutput;
/** Analysis result for Violence category. */
violenceResult?: ImageAnalyzeSeverityResultOutput;
}
/** Image analysis result. */
export interface ImageAnalyzeSeverityResultOutput {
/**
* The image category.
*
* Possible values: Hate, SelfHarm, Sexual, Violence
*/
category: string;
/** The higher the severity of input content, the larger this value, currently its value could be: 0,2,4,6. */
severity: number;
}
/** Text Blocklist. */
export interface TextBlocklistOutput {
/** Text blocklist name. */
blocklistName: string;
/** Text blocklist description. */
description?: string;
}
/** The response of adding blockItems to text blocklist. */
export interface AddBlockItemsResultOutput {
/** Array of blockItems added. */
value?: Array<TextBlockItemOutput>;
}
/** Item in TextBlocklist. */
export interface TextBlockItemOutput {
/** Block Item Id. It will be uuid. */
blockItemId: string;
/** Block item description. */
description?: string;
/** Block item content. */
text: string;
}
/** Paged collection of TextBlocklist items */
export type TextBlocklistListOutput = Paged<TextBlocklistOutput>;
/** Paged collection of TextBlockItem items */
export type TextBlockItemListOutput = Paged<TextBlockItemOutput>;

Просмотреть файл

@ -0,0 +1,131 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { getPagedAsyncIterator, PagedAsyncIterableIterator, PagedResult } from "@azure/core-paging";
import { Client, createRestError, PathUncheckedResponse } from "@azure-rest/core-client";
/**
* Helper type to extract the type of an array
*/
export type GetArrayType<T> = T extends Array<infer TData> ? TData : never;
/**
* The type of a custom function that defines how to get a page and a link to the next one if any.
*/
export type GetPage<TPage> = (
pageLink: string,
maxPageSize?: number
) => Promise<{
page: TPage;
nextPageLink?: string;
}>;
/**
* Options for the paging helper
*/
export interface PagingOptions<TResponse> {
/**
* Custom function to extract pagination details for crating the PagedAsyncIterableIterator
*/
customGetPage?: GetPage<PaginateReturn<TResponse>[]>;
}
/**
* Helper type to infer the Type of the paged elements from the response type
* This type is generated based on the swagger information for x-ms-pageable
* specifically on the itemName property which indicates the property of the response
* where the page items are found. The default value is `value`.
* This type will allow us to provide strongly typed Iterator based on the response we get as second parameter
*/
export type PaginateReturn<TResult> = TResult extends {
body: { value?: infer TPage };
}
? GetArrayType<TPage>
: Array<unknown>;
/**
* Helper to paginate results from an initial response that follows the specification of Autorest `x-ms-pageable` extension
* @param client - Client to use for sending the next page requests
* @param initialResponse - Initial response containing the nextLink and current page of elements
* @param customGetPage - Optional - Function to define how to extract the page and next link to be used to paginate the results
* @returns - PagedAsyncIterableIterator to iterate the elements
*/
export function paginate<TResponse extends PathUncheckedResponse>(
client: Client,
initialResponse: TResponse,
options: PagingOptions<TResponse> = {}
): PagedAsyncIterableIterator<PaginateReturn<TResponse>> {
// Extract element type from initial response
type TElement = PaginateReturn<TResponse>;
let firstRun = true;
const itemName = "value";
const nextLinkName = "nextLink";
const { customGetPage } = options;
const pagedResult: PagedResult<TElement[]> = {
firstPageLink: "",
getPage:
typeof customGetPage === "function"
? customGetPage
: async (pageLink: string) => {
const result = firstRun ? initialResponse : await client.pathUnchecked(pageLink).get();
firstRun = false;
checkPagingRequest(result);
const nextLink = getNextLink(result.body, nextLinkName);
const values = getElements<TElement>(result.body, itemName);
return {
page: values,
nextPageLink: nextLink,
};
},
};
return getPagedAsyncIterator(pagedResult);
}
/**
* Gets for the value of nextLink in the body
*/
function getNextLink(body: unknown, nextLinkName?: string): string | undefined {
if (!nextLinkName) {
return undefined;
}
const nextLink = (body as Record<string, unknown>)[nextLinkName];
if (typeof nextLink !== "string" && typeof nextLink !== "undefined") {
throw new Error(`Body Property ${nextLinkName} should be a string or undefined`);
}
return nextLink;
}
/**
* Gets the elements of the current request in the body.
*/
function getElements<T = unknown>(body: unknown, itemName: string): T[] {
const value = (body as Record<string, unknown>)[itemName] as T[];
// value has to be an array according to the x-ms-pageable extension.
// The fact that this must be an array is used above to calculate the
// type of elements in the page in PaginateReturn
if (!Array.isArray(value)) {
throw new Error(
`Couldn't paginate response\n Body doesn't contain an array property with name: ${itemName}`
);
}
return value ?? [];
}
/**
* Checks if a request failed
*/
function checkPagingRequest(response: PathUncheckedResponse): void {
const Http2xxStatusCodes = ["200", "201", "202", "203", "204", "205", "206", "207", "208", "226"];
if (!Http2xxStatusCodes.includes(response.status)) {
throw createRestError(
`Pagination failed with unexpected statusCode ${response.status}`,
response
);
}
}

Просмотреть файл

@ -0,0 +1,72 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { RequestParameters } from "@azure-rest/core-client";
import {
AnalyzeTextOptions,
AnalyzeImageOptions,
TextBlocklist,
AddBlockItemsOptions,
RemoveBlockItemsOptions,
} from "./models";
export interface AnalyzeTextBodyParam {
/** The request of text analysis. */
body: AnalyzeTextOptions;
}
export type AnalyzeTextParameters = AnalyzeTextBodyParam & RequestParameters;
export interface AnalyzeImageBodyParam {
/** The analysis request of the image. */
body: AnalyzeImageOptions;
}
export type AnalyzeImageParameters = AnalyzeImageBodyParam & RequestParameters;
export type GetTextBlocklistParameters = RequestParameters;
/** The resource instance. */
export type TextBlocklistResourceMergeAndPatch = Partial<TextBlocklist>;
export interface CreateOrUpdateTextBlocklistBodyParam {
/** The resource instance. */
body: TextBlocklistResourceMergeAndPatch;
}
export interface CreateOrUpdateTextBlocklistMediaTypesParam {
/** This request has a JSON Merge Patch body. */
contentType: "application/merge-patch+json";
}
export type CreateOrUpdateTextBlocklistParameters = CreateOrUpdateTextBlocklistMediaTypesParam &
CreateOrUpdateTextBlocklistBodyParam &
RequestParameters;
export type DeleteTextBlocklistParameters = RequestParameters;
export type ListTextBlocklistsParameters = RequestParameters;
export interface AddBlockItemsBodyParam {
body?: AddBlockItemsOptions;
}
export type AddBlockItemsParameters = AddBlockItemsBodyParam & RequestParameters;
export interface RemoveBlockItemsBodyParam {
body?: RemoveBlockItemsOptions;
}
export type RemoveBlockItemsParameters = RemoveBlockItemsBodyParam & RequestParameters;
export type GetTextBlocklistItemParameters = RequestParameters;
export interface ListTextBlocklistItemsQueryParamProperties {
/** The number of result items to return. */
top?: number;
/** The number of result items to skip. */
skip?: number;
/** The maximum number of result items per page. */
maxpagesize?: number;
}
export interface ListTextBlocklistItemsQueryParam {
queryParameters?: ListTextBlocklistItemsQueryParamProperties;
}
export type ListTextBlocklistItemsParameters = ListTextBlocklistItemsQueryParam & RequestParameters;

Просмотреть файл

@ -0,0 +1,188 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { RawHttpHeaders } from "@azure/core-rest-pipeline";
import { HttpResponse, ErrorResponse } from "@azure-rest/core-client";
import {
AnalyzeTextResultOutput,
AnalyzeImageResultOutput,
TextBlocklistOutput,
TextBlocklistListOutput,
AddBlockItemsResultOutput,
TextBlockItemOutput,
TextBlockItemListOutput,
} from "./outputModels";
/** The request has succeeded. */
export interface AnalyzeText200Response extends HttpResponse {
status: "200";
body: AnalyzeTextResultOutput;
}
export interface AnalyzeTextDefaultHeaders {
/** String error code indicating what went wrong. */
"x-ms-error-code"?: string;
}
export interface AnalyzeTextDefaultResponse extends HttpResponse {
status: string;
body: ErrorResponse;
headers: RawHttpHeaders & AnalyzeTextDefaultHeaders;
}
/** The request has succeeded. */
export interface AnalyzeImage200Response extends HttpResponse {
status: "200";
body: AnalyzeImageResultOutput;
}
export interface AnalyzeImageDefaultHeaders {
/** String error code indicating what went wrong. */
"x-ms-error-code"?: string;
}
export interface AnalyzeImageDefaultResponse extends HttpResponse {
status: string;
body: ErrorResponse;
headers: RawHttpHeaders & AnalyzeImageDefaultHeaders;
}
/** The request has succeeded. */
export interface GetTextBlocklist200Response extends HttpResponse {
status: "200";
body: TextBlocklistOutput;
}
export interface GetTextBlocklistDefaultHeaders {
/** String error code indicating what went wrong. */
"x-ms-error-code"?: string;
}
export interface GetTextBlocklistDefaultResponse extends HttpResponse {
status: string;
body: ErrorResponse;
headers: RawHttpHeaders & GetTextBlocklistDefaultHeaders;
}
/** The request has succeeded. */
export interface CreateOrUpdateTextBlocklist200Response extends HttpResponse {
status: "200";
body: TextBlocklistOutput;
}
/** The request has succeeded and a new resource has been created as a result. */
export interface CreateOrUpdateTextBlocklist201Response extends HttpResponse {
status: "201";
body: TextBlocklistOutput;
}
export interface CreateOrUpdateTextBlocklistDefaultHeaders {
/** String error code indicating what went wrong. */
"x-ms-error-code"?: string;
}
export interface CreateOrUpdateTextBlocklistDefaultResponse extends HttpResponse {
status: string;
body: ErrorResponse;
headers: RawHttpHeaders & CreateOrUpdateTextBlocklistDefaultHeaders;
}
/** There is no content to send for this request, but the headers may be useful. */
export interface DeleteTextBlocklist204Response extends HttpResponse {
status: "204";
}
export interface DeleteTextBlocklistDefaultHeaders {
/** String error code indicating what went wrong. */
"x-ms-error-code"?: string;
}
export interface DeleteTextBlocklistDefaultResponse extends HttpResponse {
status: string;
body: ErrorResponse;
headers: RawHttpHeaders & DeleteTextBlocklistDefaultHeaders;
}
/** The request has succeeded. */
export interface ListTextBlocklists200Response extends HttpResponse {
status: "200";
body: TextBlocklistListOutput;
}
export interface ListTextBlocklistsDefaultHeaders {
/** String error code indicating what went wrong. */
"x-ms-error-code"?: string;
}
export interface ListTextBlocklistsDefaultResponse extends HttpResponse {
status: string;
body: ErrorResponse;
headers: RawHttpHeaders & ListTextBlocklistsDefaultHeaders;
}
/** The request has succeeded. */
export interface AddBlockItems200Response extends HttpResponse {
status: "200";
body: AddBlockItemsResultOutput;
}
export interface AddBlockItemsDefaultHeaders {
/** String error code indicating what went wrong. */
"x-ms-error-code"?: string;
}
export interface AddBlockItemsDefaultResponse extends HttpResponse {
status: string;
body: ErrorResponse;
headers: RawHttpHeaders & AddBlockItemsDefaultHeaders;
}
/** There is no content to send for this request, but the headers may be useful. */
export interface RemoveBlockItems204Response extends HttpResponse {
status: "204";
}
export interface RemoveBlockItemsDefaultHeaders {
/** String error code indicating what went wrong. */
"x-ms-error-code"?: string;
}
export interface RemoveBlockItemsDefaultResponse extends HttpResponse {
status: string;
body: ErrorResponse;
headers: RawHttpHeaders & RemoveBlockItemsDefaultHeaders;
}
/** The request has succeeded. */
export interface GetTextBlocklistItem200Response extends HttpResponse {
status: "200";
body: TextBlockItemOutput;
}
export interface GetTextBlocklistItemDefaultHeaders {
/** String error code indicating what went wrong. */
"x-ms-error-code"?: string;
}
export interface GetTextBlocklistItemDefaultResponse extends HttpResponse {
status: string;
body: ErrorResponse;
headers: RawHttpHeaders & GetTextBlocklistItemDefaultHeaders;
}
/** The request has succeeded. */
export interface ListTextBlocklistItems200Response extends HttpResponse {
status: "200";
body: TextBlockItemListOutput;
}
export interface ListTextBlocklistItemsDefaultHeaders {
/** String error code indicating what went wrong. */
"x-ms-error-code"?: string;
}
export interface ListTextBlocklistItemsDefaultResponse extends HttpResponse {
status: string;
body: ErrorResponse;
headers: RawHttpHeaders & ListTextBlocklistItemsDefaultHeaders;
}

Просмотреть файл

@ -0,0 +1,291 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { Recorder, isPlaybackMode } from "@azure-tools/test-recorder";
import { assert } from "chai";
import { createRecorder, createClient } from "./utils/recordedClient";
import { Context } from "mocha";
import { ContentSafetyClient, isUnexpected, paginate, TextBlockItemOutput } from "../../src";
import { PagedAsyncIterableIterator, PageSettings } from "@azure/core-paging";
import fs from "fs";
import path from "path";
import { isBrowser } from "@azure/core-util";
describe("Content Safety Client Test", () => {
let recorder: Recorder;
let client: ContentSafetyClient;
function sleep(time: number): Promise<NodeJS.Timer> {
return new Promise((resolve) => setTimeout(resolve, time));
}
function uint8ArrayToBase64(binary: Uint8Array) {
let binaryString = "";
binary.forEach((byte) => {
binaryString += String.fromCharCode(byte);
});
return self.btoa(binaryString);
}
const blocklistName = "TestBlocklist";
const blockItemText1 = "sample";
const blockItemText2 = "text";
const blockItemText3 = "image";
let blockItemId: string;
beforeEach(async function (this: Context) {
recorder = await createRecorder(this);
client = await createClient(recorder);
});
afterEach(async function () {
await recorder.stop();
});
it("analyze text", async function () {
const response = await client.path("/text:analyze").post({
body: {
text: "This is a sample text",
categories: ["Hate"],
},
});
if (isUnexpected(response)) {
throw new Error(response.body?.error.message);
}
assert.strictEqual(response.status, "200");
assert.equal(response.body.hateResult?.category, "Hate");
assert.notExists(response.body.selfHarmResult);
});
it("analyze image", async function () {
let base64Image: string;
if (isBrowser) {
const imagePath = "/base/samples-dev/example-data/image.png";
const response = await fetch(imagePath);
const buffer = await response.arrayBuffer();
const binary = new Uint8Array(buffer);
base64Image = uint8ArrayToBase64(binary);
} else {
const imagePath = path.join("samples-dev", "example-data", "image.png");
const buffer = fs.readFileSync(imagePath);
base64Image = buffer.toString("base64");
}
const response = await client.path("/image:analyze").post({
body: {
image: {
content: base64Image,
},
categories: ["Sexual"],
},
});
if (isUnexpected(response)) {
throw new Error(response.body?.error.message);
}
assert.strictEqual(response.status, "200");
assert.equal(response.body.sexualResult?.category, "Sexual");
assert.notExists(response.body.violenceResult);
});
it("create blocklist", async function () {
const createBlockListResponse = await client
.path("/text/blocklists/{blocklistName}", blocklistName)
.patch({
contentType: "application/merge-patch+json",
body: {
description: "test",
},
});
if (isUnexpected(createBlockListResponse)) {
throw new Error(createBlockListResponse.body?.error.message);
}
assert.strictEqual(createBlockListResponse.status, "201");
assert.equal(createBlockListResponse.body.blocklistName, blocklistName);
});
it("add block items", async function () {
const addBlockItemsResponse = await client
.path("/text/blocklists/{blocklistName}:addBlockItems", blocklistName)
.post({
body: {
blockItems: [
{
description: "Test block item 1",
text: blockItemText1,
},
{
description: "Test block item 2",
text: blockItemText2,
},
{
description: "Test block item 3",
text: blockItemText3,
},
],
},
});
if (isUnexpected(addBlockItemsResponse)) {
throw new Error(addBlockItemsResponse.body?.error.message);
}
assert.strictEqual(addBlockItemsResponse.status, "200");
assert.isArray(addBlockItemsResponse.body.value);
if (!isPlaybackMode()) {
await sleep(30000);
}
});
it("analyze text with blocklist", async function () {
const analyzeTextResponse = await client.path("/text:analyze").post({
body: {
text: "This is a sample to test text with blocklist.",
blocklistNames: [blocklistName],
breakByBlocklists: false,
},
});
if (isUnexpected(analyzeTextResponse)) {
throw new Error(analyzeTextResponse.body?.error.message);
}
assert.strictEqual(analyzeTextResponse.status, "200");
});
it("list text blocklists", async function () {
const listTextBlocklistsResponse = await client.path("/text/blocklists").get();
if (isUnexpected(listTextBlocklistsResponse)) {
throw new Error(listTextBlocklistsResponse.body?.error.message);
}
assert.strictEqual(listTextBlocklistsResponse.status, "200");
assert.isArray(listTextBlocklistsResponse.body.value);
});
it("get text blocklist", async function () {
const getTextBlocklistResponse = await client
.path("/text/blocklists/{blocklistName}", blocklistName)
.get();
if (isUnexpected(getTextBlocklistResponse)) {
throw new Error(getTextBlocklistResponse.body?.error.message);
}
assert.strictEqual(getTextBlocklistResponse.status, "200");
assert.equal(getTextBlocklistResponse.body.blocklistName, blocklistName);
});
it("list block items", async function () {
const listBlockItemsResponse = await client
.path("/text/blocklists/{blocklistName}/blockItems", blocklistName)
.get();
if (isUnexpected(listBlockItemsResponse)) {
throw new Error(listBlockItemsResponse.body?.error.message);
}
assert.strictEqual(listBlockItemsResponse.status, "200");
assert.isArray(listBlockItemsResponse.body.value);
blockItemId = listBlockItemsResponse.body.value[1].blockItemId;
});
it("list block items with pagination helper", async function () {
const dataSources = await client
.path("/text/blocklists/{blocklistName}/blockItems", blocklistName)
.get();
if (isUnexpected(dataSources)) {
throw new Error(dataSources.body?.error.message);
}
const iter = paginate(client, dataSources);
const items: TextBlockItemOutput[] = [];
for await (const item of <
PagedAsyncIterableIterator<TextBlockItemOutput, TextBlockItemOutput[], PageSettings>
>iter) {
items.push(item);
}
assert.equal(items[1].blockItemId, blockItemId);
});
it("list block items with pagination 1", async function () {
const listBlockItemsResponse = await client
.path("/text/blocklists/{blocklistName}/blockItems", blocklistName)
.get({
queryParameters: {
top: 10,
skip: 0,
maxpagesize: 1,
},
});
if (isUnexpected(listBlockItemsResponse)) {
throw new Error(listBlockItemsResponse.body?.error.message);
}
assert.strictEqual(listBlockItemsResponse.status, "200");
assert.equal(listBlockItemsResponse.body.value.length, 1);
const nextLink = listBlockItemsResponse.body.nextLink;
const skip = nextLink?.split("skip=")[1].split("&")[0];
assert.equal(skip, "1");
});
it("list block items with pagination 2", async function () {
const listBlockItemsResponse = await client
.path("/text/blocklists/{blocklistName}/blockItems", blocklistName)
.get({
queryParameters: {
top: 10,
skip: 1,
maxpagesize: 1,
},
});
if (isUnexpected(listBlockItemsResponse)) {
throw new Error(listBlockItemsResponse.body?.error.message);
}
assert.strictEqual(listBlockItemsResponse.status, "200");
assert.equal(listBlockItemsResponse.body.value.length, 1);
assert.equal(listBlockItemsResponse.body.value[0].blockItemId, blockItemId);
const nextLink = listBlockItemsResponse.body.nextLink;
const skip = nextLink?.split("skip=")[1].split("&")[0];
assert.equal(skip, "2");
});
it("list block items with pagination 3", async function () {
const listBlockItemsResponse = await client
.path("/text/blocklists/{blocklistName}/blockItems", blocklistName)
.get({
queryParameters: {
top: 10,
skip: 0,
maxpagesize: 3,
},
});
if (isUnexpected(listBlockItemsResponse)) {
throw new Error(listBlockItemsResponse.body?.error.message);
}
assert.strictEqual(listBlockItemsResponse.status, "200");
assert.equal(listBlockItemsResponse.body.value.length, 3);
assert.equal(listBlockItemsResponse.body.value[1].blockItemId, blockItemId);
assert.notExists(listBlockItemsResponse.body.nextLink);
});
it("get block item", async function () {
const getBlockItemResponse = await client
.path("/text/blocklists/{blocklistName}/blockItems/{blockItemId}", blocklistName, blockItemId)
.get();
if (isUnexpected(getBlockItemResponse)) {
throw new Error(getBlockItemResponse.body?.error.message);
}
assert.strictEqual(getBlockItemResponse.status, "200");
assert.equal(getBlockItemResponse.body.blockItemId, blockItemId);
});
it("remove block item", async function () {
const removeBlockItemResponse = await client
.path("/text/blocklists/{blocklistName}:removeBlockItems", blocklistName)
.post({
body: {
blockItemIds: [blockItemId],
},
});
if (isUnexpected(removeBlockItemResponse)) {
throw new Error(removeBlockItemResponse.body?.error.message);
}
assert.strictEqual(removeBlockItemResponse.status, "204");
});
it("delete blocklist", async function () {
const deleteBlockListResponse = await client
.path("/text/blocklists/{blocklistName}", blocklistName)
.delete();
if (isUnexpected(deleteBlockListResponse)) {
throw new Error(deleteBlockListResponse.body?.error.message);
}
assert.strictEqual(deleteBlockListResponse.status, "204");
});
});

Просмотреть файл

@ -0,0 +1,2 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

Просмотреть файл

@ -0,0 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import * as dotenv from "dotenv";
dotenv.config();

Просмотреть файл

@ -0,0 +1,41 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { Context } from "mocha";
import {
Recorder,
RecorderStartOptions,
assertEnvironmentVariable,
} from "@azure-tools/test-recorder";
import "./env";
import ContentSafety, { ContentSafetyClient } from "../../../src";
import { AzureKeyCredential } from "@azure/core-auth";
// import { ClientOptions } from "@azure-rest/core-client";
const envSetupForPlayback: Record<string, string> = {
CONTENT_SAFETY_ENDPOINT: "https://endpoint",
CONTENT_SAFETY_API_KEY: "fake_key",
};
const recorderEnvSetup: RecorderStartOptions = {
envSetupForPlayback,
};
/**
* creates the recorder and reads the environment variables from the `.env` file.
* Should be called first in the test suite to make sure environment variables are
* read before they are being used.
*/
export async function createRecorder(context: Context): Promise<Recorder> {
const recorder = new Recorder(context.currentTest);
await recorder.start(recorderEnvSetup);
return recorder;
}
export function createClient(recorder: Recorder): ContentSafetyClient {
const endpoint = assertEnvironmentVariable("CONTENT_SAFETY_ENDPOINT");
const key = assertEnvironmentVariable("CONTENT_SAFETY_API_KEY");
const credential = new AzureKeyCredential(key);
const client = ContentSafety(endpoint, credential, recorder.configureClientOptions({}));
return client;
}

Просмотреть файл

@ -0,0 +1,12 @@
{
"extends": "../../../tsconfig.package",
"compilerOptions": {
"outDir": "./dist-esm",
"declarationDir": "./types",
"lib": ["es6", "dom"],
"paths": {
"@azure-rest/ai-content-safety": ["./src/index"]
}
},
"include": ["src/**/*.ts", "./test/**/*.ts", "samples-dev/**/*.ts"]
}

29
sdk/contentsafety/ci.yml Normal file
Просмотреть файл

@ -0,0 +1,29 @@
# NOTE: Please refer to https://aka.ms/azsdk/engsys/ci-yaml before editing this file.
trigger:
branches:
include:
- main
- release/*
- hotfix/*
paths:
include:
- sdk/contentsafety/
pr:
branches:
include:
- main
- feature/*
- release/*
- hotfix/*
exclude:
- feature/v4
paths:
include:
- sdk/contentsafety/
extends:
template: ../../eng/pipelines/templates/stages/archetype-sdk-client.yml
parameters:
ServiceDirectory: contentsafety
Artifacts:
- name: azure-rest-ai-content-safety
safeName: azurerestaicontentsafety