azure-ai-contentsafety-ts
microsoft/skills
使用 Azure AI 內容安全服務分析文字和影象中的有害內容,並支援自定義黑名單和嚴重程度閾值。
...展開全部Azure AI 內容安全 TypeScript REST SDK
使用可自定義的遮蔽列表分析文字和影象中的有害內容。
安裝
npm install @azure-rest/ai-content-safety @azure/identity @azure/core-auth
環境變數
CONTENT_SAFETY_ENDPOINT=https://<resource>.cognitiveservices.azure.com
CONTENT_SAFETY_KEY=<api-key>
AZURE_TOKEN_CREDENTIALS=prod # 僅在生產環境中使用 DefaultAzureCredential 時需要
</api-key></resource>身份驗證
重要提示:這是一個 REST 客戶端。ContentSafetyClient 是一個函式,而不是類。
API 金鑰
import ContentSafetyClient from "@azure-rest/ai-content-safety";
import { AzureKeyCredential } from "@azure/core-auth";
const client = ContentSafetyClient(
process.env.CONTENT_SAFETY_ENDPOINT!,
new AzureKeyCredential(process.env.CONTENT_SAFETY_KEY!)
);
DefaultAzureCredential
import ContentSafetyClient from "@azure-rest/ai-content-safety";
import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";
// 本地開發:DefaultAzureCredential。生產環境:設定 AZURE_TOKEN_CREDENTIALS=prod 或 AZURE_TOKEN_CREDENTIALS=<specific_credential>
const credential = new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]});
// 或者在生產環境中直接使用特定的憑據:
// 請參閱 https://learn.microsoft.com/javascript/api/overview/azure/identity-readme?view=azure-node-latest#credential-classes
// const credential = new ManagedIdentityCredential();
const client = ContentSafetyClient(
process.env.CONTENT_SAFETY_ENDPOINT!,
credential
);
</specific_credential>分析文字
import ContentSafetyClient, { isUnexpected } from "@azure-rest/ai-content-safety";
const result = await client.path("/text:analyze").post({
body: {
text: "要分析的文字內容",
categories: ["Hate", "Sexual", "Violence", "SelfHarm"],
outputType: "FourSeverityLevels" // 或 "EightSeverityLevels"
}
});
if (isUnexpected(result)) {
throw result.body;
}
for (const analysis of result.body.categoriesAnalysis) {
console.log(`${analysis.category}: 嚴重程度 ${analysis.severity}`);
}
分析影象
Base64 內容
import { readFileSync } from "node:fs";
const imageBuffer = readFileSync("./image.png");
const base64Image = imageBuffer.toString("base64");
const result = await client.path("/image:analyze").post({
body: {
image: { content: base64Image }
}
});
if (isUnexpected(result)) {
throw result.body;
}
for (const analysis of result.body.categoriesAnalysis) {
console.log(`${analysis.category}: 嚴重程度 ${analysis.severity}`);
}
Blob URL
const result = await client.path("/image:analyze").post({
body: {
image: { blobUrl: "https://storage.blob.core.windows.net/container/image.png" }
}
});
遮蔽列表管理
建立遮蔽列表
const result = await client
.path("/text/blocklists/{blocklistName}", "my-blocklist")
.patch({
contentType: "application/merge-patch+json",
body: {
description: "禁止術語的自定義遮蔽列表"
}
});
if (isUnexpected(result)) {
throw result.body;
}
console.log(`已建立: ${result.body.blocklistName}`);
向遮蔽列表新增專案
const result = await client
.path("/text/blocklists/{blocklistName}:addOrUpdateBlocklistItems", "my-blocklist")
.post({
body: {
blocklistItems: [
{ text: "prohibited-term-1", description: "第一個被遮蔽的術語" },
{ text: "prohibited-term-2", description: "第二個被遮蔽的術語" }
]
}
});
if (isUnexpected(result)) {
throw result.body;
}
for (const item of result.body.blocklistItems ?? []) {
console.log(`已新增: ${item.blocklistItemId}`);
}
使用遮蔽列表進行分析
const result = await client.path("/text:analyze").post({
body: {
text: "可能包含遮蔽術語的文字",
blocklistNames: ["my-blocklist"],
haltOnBlocklistHit: false
}
});
if (isUnexpected(result)) {
throw result.body;
}
// 檢查遮蔽列表匹配項
if (result.body.blocklistsMatch) {
for (const match of result.body.blocklistsMatch) {
console.log(`已遮蔽: "${match.blocklistItemText}" 來自 ${match.blocklistName}`);
}
}
列出遮蔽列表
const result = await client.path("/text/blocklists").get();
if (isUnexpected(result)) {
throw result.body;
}
for (const blocklist of result.body.value ?? []) {
console.log(`${blocklist.blocklistName}: ${blocklist.description}`);
}
刪除遮蔽列表
await client.path("/text/blocklists/{blocklistName}", "my-blocklist").delete();
有害類別
| 類別 | API 術語 | 描述 |
|---|---|---|
| 仇恨與公平性 | `Hate` | 針對身份群體的歧視性語言 |
| 色情 | `Sexual` | 色情內容、裸體、淫穢物品 |
| 暴力 | `Violence` | 身體傷害、武器、恐怖主義 |
| 自殘 | `SelfHarm` | 自傷、自殺、飲食失調 |
嚴重程度級別
| 級別 | 風險 | 建議操作 |
|---|---|---|
| 0 | 安全 | 允許 |
| 2 | 低 | 審查或允許但帶有警告 |
| 4 | 中 | 遮蔽或要求人工審查 |
| 6 | 高 | 立即遮蔽 |
輸出型別:
FourSeverityLevels(預設):返回 0, 2, 4, 6EightSeverityLevels:返回 0-7
內容稽覈助手
import ContentSafetyClient, {
isUnexpected,
TextCategoriesAnalysisOutput
} from "@azure-rest/ai-content-safety";
interface ModerationResult {
isAllowed: boolean;
flaggedCategories: string[];
maxSeverity: number;
blocklistMatches: string[];
}
async function moderateContent(
client: ReturnType<typeof>,
text: string,
maxAllowedSeverity = 2,
blocklistNames: string[] = []
): Promise<moderationresult> {
const result = await client.path("/text:analyze").post({
body: { text, blocklistNames, haltOnBlocklistHit: false }
});
if (isUnexpected(result)) {
throw result.body;
}
const flaggedCategories = result.body.categoriesAnalysis
.filter(c => (c.severity ?? 0) > maxAllowedSeverity)
.map(c => c.category!);
const maxSeverity = Math.max(
...result.body.categoriesAnalysis.map(c => c.severity ?? 0)
);
const blocklistMatches = (result.body.blocklistsMatch ?? [])
.map(m => m.blocklistItemText!);
return {
isAllowed: flaggedCategories.length === 0 && blocklistMatches.length === 0,
flaggedCategories,
maxSeverity,
blocklistMatches
};
}
</moderationresult></typeof>API 端點
| 操作 | 方法 | 路徑 |
|---|---|---|
| 分析文字 | POST | `/text:analyze` |
| 分析影象 | POST | `/image:analyze` |
| 建立/更新遮蔽列表 | PATCH | `/text/blocklists/{blocklistName}` |
| 列出遮蔽列表 | GET | `/text/blocklists` |
| 刪除遮蔽列表 | DELETE | `/text/blocklists/{blocklistName}` |
| 新增遮蔽列表專案 | POST | `/text/blocklists/{blocklistName}:addOrUpdateBlocklistItems` |
| 列出遮蔽列表專案 | GET | `/text/blocklists/{blocklistName}/blocklistItems` |
| 移除遮蔽列表專案 | POST | `/text/blocklists/{blocklistName}:removeBlocklistItems` |
關鍵型別
import ContentSafetyClient, {
isUnexpected,
AnalyzeTextParameters,
AnalyzeImageParameters,
TextCategoriesAnalysisOutput,
ImageCategoriesAnalysisOutput,
TextBlocklist,
TextBlocklistItem
} from "@azure-rest/ai-content-safety";
最佳實踐
- 始終使用 isUnexpected() - 用於錯誤處理的型別守衛
- 設定適當的閾值 - 不同類別可能需要不同的嚴重程度閾值
- 使用遮蔽列表處理特定領域的術語 - 用自定義規則補充 AI 檢測
- 記錄稽覈決策 - 保留合規性的審計軌跡
- 處理邊緣情況 - 空文字、超長文字、不支援的影象格式
---
name: azure-ai-contentsafety-ts
description: Analyze text and images for harmful content using Azure AI Content Safety, with customizable blocklists and severity thresholds.
license: MIT
---
# Azure AI Content Safety REST SDK for TypeScript
Analyze text and images for harmful content with customizable blocklists.
## Installation
```bash
npm install @azure-rest/ai-content-safety @azure/identity @azure/core-auth
```
## Environment Variables
```bash
CONTENT_SAFETY_ENDPOINT=https://<resource>.cognitiveservices.azure.com
CONTENT_SAFETY_KEY=<api-key>
AZURE_TOKEN_CREDENTIALS=prod # Required only if DefaultAzureCredential is used in production
```
## Authentication
**Important**: This is a REST client. `ContentSafetyClient` is a **function**, not a class.
### API Key
```typescript
import ContentSafetyClient from "@azure-rest/ai-content-safety";
import { AzureKeyCredential } from "@azure/core-auth";
const client = ContentSafetyClient(
process.env.CONTENT_SAFETY_ENDPOINT!,
new AzureKeyCredential(process.env.CONTENT_SAFETY_KEY!)
);
```
### DefaultAzureCredential
```typescript
import ContentSafetyClient from "@azure-rest/ai-content-safety";
import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";
// Local dev: DefaultAzureCredential. Production: set AZURE_TOKEN_CREDENTIALS=prod or AZURE_TOKEN_CREDENTIALS=<specific_credential>
const credential = new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]});
// Or use a specific credential directly in production:
// See https://learn.microsoft.com/javascript/api/overview/azure/identity-readme?view=azure-node-latest#credential-classes
// const credential = new ManagedIdentityCredential();
const client = ContentSafetyClient(
process.env.CONTENT_SAFETY_ENDPOINT!,
credential
);
```
## Analyze Text
```typescript
import ContentSafetyClient, { isUnexpected } from "@azure-rest/ai-content-safety";
const result = await client.path("/text:analyze").post({
body: {
text: "Text content to analyze",
categories: ["Hate", "Sexual", "Violence", "SelfHarm"],
outputType: "FourSeverityLevels" // or "EightSeverityLevels"
}
});
if (isUnexpected(result)) {
throw result.body;
}
for (const analysis of result.body.categoriesAnalysis) {
console.log(`${analysis.category}: severity ${analysis.severity}`);
}
```
## Analyze Image
### Base64 Content
```typescript
import { readFileSync } from "node:fs";
const imageBuffer = readFileSync("./image.png");
const base64Image = imageBuffer.toString("base64");
const result = await client.path("/image:analyze").post({
body: {
image: { content: base64Image }
}
});
if (isUnexpected(result)) {
throw result.body;
}
for (const analysis of result.body.categoriesAnalysis) {
console.log(`${analysis.category}: severity ${analysis.severity}`);
}
```
### Blob URL
```typescript
const result = await client.path("/image:analyze").post({
body: {
image: { blobUrl: "https://storage.blob.core.windows.net/container/image.png" }
}
});
```
## Blocklist Management
### Create Blocklist
```typescript
const result = await client
.path("/text/blocklists/{blocklistName}", "my-blocklist")
.patch({
contentType: "application/merge-patch+json",
body: {
description: "Custom blocklist for prohibited terms"
}
});
if (isUnexpected(result)) {
throw result.body;
}
console.log(`Created: ${result.body.blocklistName}`);
```
### Add Items to Blocklist
```typescript
const result = await client
.path("/text/blocklists/{blocklistName}:addOrUpdateBlocklistItems", "my-blocklist")
.post({
body: {
blocklistItems: [
{ text: "prohibited-term-1", description: "First blocked term" },
{ text: "prohibited-term-2", description: "Second blocked term" }
]
}
});
if (isUnexpected(result)) {
throw result.body;
}
for (const item of result.body.blocklistItems ?? []) {
console.log(`Added: ${item.blocklistItemId}`);
}
```
### Analyze with Blocklist
```typescript
const result = await client.path("/text:analyze").post({
body: {
text: "Text that might contain blocked terms",
blocklistNames: ["my-blocklist"],
haltOnBlocklistHit: false
}
});
if (isUnexpected(result)) {
throw result.body;
}
// Check blocklist matches
if (result.body.blocklistsMatch) {
for (const match of result.body.blocklistsMatch) {
console.log(`Blocked: "${match.blocklistItemText}" from ${match.blocklistName}`);
}
}
```
### List Blocklists
```typescript
const result = await client.path("/text/blocklists").get();
if (isUnexpected(result)) {
throw result.body;
}
for (const blocklist of result.body.value ?? []) {
console.log(`${blocklist.blocklistName}: ${blocklist.description}`);
}
```
### Delete Blocklist
```typescript
await client.path("/text/blocklists/{blocklistName}", "my-blocklist").delete();
```
## Harm Categories
| Category | API Term | Description |
|----------|----------|-------------|
| Hate and Fairness | `Hate` | Discriminatory language targeting identity groups |
| Sexual | `Sexual` | Sexual content, nudity, pornography |
| Violence | `Violence` | Physical harm, weapons, terrorism |
| Self-Harm | `SelfHarm` | Self-injury, suicide, eating disorders |
## Severity Levels
| Level | Risk | Recommended Action |
|-------|------|-------------------|
| 0 | Safe | Allow |
| 2 | Low | Review or allow with warning |
| 4 | Medium | Block or require human review |
| 6 | High | Block immediately |
**Output Types**:
- `FourSeverityLevels` (default): Returns 0, 2, 4, 6
- `EightSeverityLevels`: Returns 0-7
## Content Moderation Helper
```typescript
import ContentSafetyClient, {
isUnexpected,
TextCategoriesAnalysisOutput
} from "@azure-rest/ai-content-safety";
interface ModerationResult {
isAllowed: boolean;
flaggedCategories: string[];
maxSeverity: number;
blocklistMatches: string[];
}
async function moderateContent(
client: ReturnType<typeof ContentSafetyClient>,
text: string,
maxAllowedSeverity = 2,
blocklistNames: string[] = []
): Promise<ModerationResult> {
const result = await client.path("/text:analyze").post({
body: { text, blocklistNames, haltOnBlocklistHit: false }
});
if (isUnexpected(result)) {
throw result.body;
}
const flaggedCategories = result.body.categoriesAnalysis
.filter(c => (c.severity ?? 0) > maxAllowedSeverity)
.map(c => c.category!);
const maxSeverity = Math.max(
...result.body.categoriesAnalysis.map(c => c.severity ?? 0)
);
const blocklistMatches = (result.body.blocklistsMatch ?? [])
.map(m => m.blocklistItemText!);
return {
isAllowed: flaggedCategories.length === 0 && blocklistMatches.length === 0,
flaggedCategories,
maxSeverity,
blocklistMatches
};
}
```
## API Endpoints
| Operation | Method | Path |
|-----------|--------|------|
| Analyze Text | POST | `/text:analyze` |
| Analyze Image | POST | `/image:analyze` |
| Create/Update Blocklist | PATCH | `/text/blocklists/{blocklistName}` |
| List Blocklists | GET | `/text/blocklists` |
| Delete Blocklist | DELETE | `/text/blocklists/{blocklistName}` |
| Add Blocklist Items | POST | `/text/blocklists/{blocklistName}:addOrUpdateBlocklistItems` |
| List Blocklist Items | GET | `/text/blocklists/{blocklistName}/blocklistItems` |
| Remove Blocklist Items | POST | `/text/blocklists/{blocklistName}:removeBlocklistItems` |
## Key Types
```typescript
import ContentSafetyClient, {
isUnexpected,
AnalyzeTextParameters,
AnalyzeImageParameters,
TextCategoriesAnalysisOutput,
ImageCategoriesAnalysisOutput,
TextBlocklist,
TextBlocklistItem
} from "@azure-rest/ai-content-safety";
```
## Best Practices
1. **Always use isUnexpected()** - Type guard for error handling
2. **Set appropriate thresholds** - Different categories may need different severity thresholds
3. **Use blocklists for domain-specific terms** - Supplement AI detection with custom rules
4. **Log moderation decisions** - Keep audit trail for compliance
5. **Handle edge cases** - Empty text, very long text, unsupported image formats
所有檔案
0 個檔案安裝 azure-ai-contentsafety-ts
將技能檔案下載並解壓到 .claude/skills/ 目錄。
下載 ZIP複製儲存庫並將技能檔案複製到您的專案中。
git clone https://github.com/microsoft/skills/tree/main/.github/plugins/azure-sdk-typescript/skills/azure-ai-contentsafety-ts # Copy SKILL.md to your .claude/skills/ directory
複製





首頁
