Skip to content

Commit

Permalink
[JS] fix: content safety public preview deprecation (#2133)
Browse files Browse the repository at this point in the history
## Linked issues

closes: #2121 

## Details

the version of azure content safety we are using was public preview and
is no longer supported, these changes update our code to work with the
official GA version of content safety
https://learn.microsoft.com/en-us/azure/ai-services/content-safety/how-to/migrate-to-general-availability
  • Loading branch information
aacebo authored Oct 22, 2024
1 parent eb10850 commit fea76d5
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 86 deletions.
13 changes: 7 additions & 6 deletions js/packages/teams-ai/src/internals/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ export interface ContentSafetyOptions {
* When set to false, all analyses of harmful content will be performed, whether or not blocklists are hit.
* Default value is false.
*/
breakByBlocklists?: boolean;
haltOnBlocklistHit?: boolean;
}

export interface CreateContentSafetyRequest extends ContentSafetyOptions {
Expand All @@ -399,9 +399,10 @@ export interface ContentSafetyHarmCategory {
}

export interface CreateContentSafetyResponse {
blocklistsMatchResults: Array<string>;
hateResult: ContentSafetyHarmCategory;
selfHarmResult: ContentSafetyHarmCategory;
sexualResult: ContentSafetyHarmCategory;
violenceResult: ContentSafetyHarmCategory;
blocklistsMatch: Array<{
blockListName: string;
blockListItemId: string;
blockListItemText: string;
}>;
categoriesAnalysis: Array<ContentSafetyHarmCategory>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,10 @@ describe('AzureContentSafetyModerator', () => {
status: '200',
statusText: 'OK',
data: {
hateResult: {
categoriesAnalysis: [{
category: 'Hate',
severity: 1
}
}]
}
})
);
Expand Down Expand Up @@ -170,10 +170,10 @@ describe('AzureContentSafetyModerator', () => {
status: '200',
statusText: 'OK',
data: {
hateResult: {
categoriesAnalysis: [{
category: 'Hate',
severity: 7
}
}]
}
})
);
Expand Down Expand Up @@ -221,18 +221,20 @@ describe('AzureContentSafetyModerator', () => {
status: '200',
statusText: 'OK',
data: {
selfHarmResult: {
category: 'SelfHarm',
severity: 1
},
violenceResult: {
category: 'Violence',
severity: 1
},
sexualResult: {
category: 'Sexual',
severity: 1
}
categoriesAnalysis: [
{
category: 'SelfHarm',
severity: 1
},
{
category: 'Violence',
severity: 1
},
{
category: 'Sexual',
severity: 1
}
]
}
})
);
Expand Down Expand Up @@ -292,18 +294,20 @@ describe('AzureContentSafetyModerator', () => {
status: '200',
statusText: 'OK',
data: {
selfHarmResult: {
category: 'SelfHarm',
severity: 7
},
violenceResult: {
category: 'Violence',
severity: 7
},
sexualResult: {
category: 'Sexual',
severity: 7
}
categoriesAnalysis: [
{
category: 'SelfHarm',
severity: 7
},
{
category: 'Violence',
severity: 7
},
{
category: 'Sexual',
severity: 7
}
]
}
})
);
Expand Down Expand Up @@ -373,18 +377,20 @@ describe('AzureContentSafetyModerator', () => {
status: '200',
statusText: 'OK',
data: {
selfHarmResult: {
category: 'SelfHarm',
severity: 1
},
violenceResult: {
category: 'Violence',
severity: 1
},
sexualResult: {
category: 'Sexual',
severity: 1
}
categoriesAnalysis: [
{
category: 'SelfHarm',
severity: 1
},
{
category: 'Violence',
severity: 1
},
{
category: 'Sexual',
severity: 1
}
]
}
})
);
Expand Down
79 changes: 44 additions & 35 deletions js/packages/teams-ai/src/moderators/AzureContentSafetyModerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
AzureOpenAIModeratorCategory,
CreateContentSafetyResponse,
OpenAIClientResponse,
ModerationResponse,
CreateContentSafetyRequest,
ContentSafetyHarmCategory,
ContentSafetyOptions,
Expand Down Expand Up @@ -44,11 +43,21 @@ export interface AzureOpenAIModeratorOptions extends OpenAIModeratorOptions {
blocklistNames?: string[];

/**
* @deprecated
* use `haltOnBlocklistHit`
*
* 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.
* Default value is false.
*/
breakByBlocklists?: boolean;

/**
* 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.
* Default value is false.
*/
haltOnBlocklistHit?: boolean;
}

const defaultHarmCategories: AzureOpenAIModeratorCategory[] = ['Hate', 'Sexual', 'SelfHarm', 'Violence'];
Expand Down Expand Up @@ -113,7 +122,7 @@ export class AzureContentSafetyModerator<TState extends TurnState = TurnState> e
this._contentSafetyOptions = {
categories: categories ?? defaultHarmCategories,
blocklistNames: options.blocklistNames ?? [],
breakByBlocklists: options.breakByBlocklists ?? false
haltOnBlocklistHit: options.haltOnBlocklistHit ?? options.breakByBlocklists ?? false
};
}

Expand All @@ -127,7 +136,7 @@ export class AzureContentSafetyModerator<TState extends TurnState = TurnState> e
return new AzureOpenAIClient({
apiKey: options.apiKey,
endpoint: options.endpoint!,
apiVersion: options.apiVersion ?? '2023-04-30-preview',
apiVersion: options.apiVersion ?? '2023-10-01',
headerKey: 'Ocp-Apim-Subscription-Key'
});
}
Expand All @@ -140,49 +149,49 @@ export class AzureContentSafetyModerator<TState extends TurnState = TurnState> e
* @template TState Optional. Type of the applications turn state.
*/
protected async createModeration(input: string): Promise<CreateModerationResponseResultsInner | undefined> {
const response = (await this._azureContentSafetyClient.createModeration({
const res = (await this._azureContentSafetyClient.createModeration({
text: input,
...this._contentSafetyOptions
} as CreateContentSafetyRequest)) as OpenAIClientResponse<ModerationResponse>;
const data = response.data as CreateContentSafetyResponse;
if (!data) {
} as CreateContentSafetyRequest)) as OpenAIClientResponse<CreateContentSafetyResponse>;

if (!res.data) {
return undefined;
}
// Check if the input is safe for each category
const hateResult: boolean =
data.hateResult?.severity > 0 &&
data.hateResult.severity <= this._azureContentSafetyCategories.Hate.severity;
const selfHarmResult: boolean =
data.selfHarmResult?.severity > 0 &&
data.selfHarmResult.severity <= this._azureContentSafetyCategories.SelfHarm.severity;
const sexualResult: boolean =
data.sexualResult?.severity > 0 &&
data.sexualResult.severity <= this._azureContentSafetyCategories.Sexual.severity;
const violenceResult: boolean =
data.violenceResult?.severity > 0 &&
data.violenceResult.severity <= this._azureContentSafetyCategories.Violence.severity;

const predicate = (category: AzureOpenAIModeratorCategory) => {
return (c: ContentSafetyHarmCategory) => {
return c.category === category &&
c.severity > 0 &&
c.severity <= this._azureContentSafetyCategories[category].severity
};
};

const hate = res.data.categoriesAnalysis.find(predicate('Hate'));
const selfHarm = res.data.categoriesAnalysis.find(predicate('SelfHarm'));
const sexual = res.data.categoriesAnalysis.find(predicate('Sexual'));
const violence = res.data.categoriesAnalysis.find(predicate('Violence'));

// Create the moderation results
const result: CreateModerationResponseResultsInner = {
flagged: hateResult || selfHarmResult || sexualResult || violenceResult,
flagged: !!hate || !!selfHarm || !!sexual || !!violence,
categories: {
hate: hateResult,
'hate/threatening': hateResult,
'self-harm': selfHarmResult,
sexual: sexualResult,
'sexual/minors': sexualResult,
violence: violenceResult,
'violence/graphic': violenceResult
hate: !!hate,
'hate/threatening': !!hate,
'self-harm': !!selfHarm,
sexual: !!sexual,
'sexual/minors': !!sexual,
violence: !!violence,
'violence/graphic': !!violence
},
category_scores: {
// Normalize the scores to be between 0 and 1
hate: (data.hateResult?.severity ?? 0) / ModerationSeverity.High,
'hate/threatening': (data.hateResult?.severity ?? 0) / ModerationSeverity.High,
'self-harm': (data.selfHarmResult?.severity ?? 0) / ModerationSeverity.High,
sexual: (data.sexualResult?.severity ?? 0) / ModerationSeverity.High,
'sexual/minors': (data.sexualResult?.severity ?? 0) / ModerationSeverity.High,
violence: (data.violenceResult?.severity ?? 0) / ModerationSeverity.High,
'violence/graphic': (data.violenceResult?.severity ?? 0) / ModerationSeverity.High
hate: (hate?.severity ?? 0) / ModerationSeverity.High,
'hate/threatening': (hate?.severity ?? 0) / ModerationSeverity.High,
'self-harm': (selfHarm?.severity ?? 0) / ModerationSeverity.High,
sexual: (sexual?.severity ?? 0) / ModerationSeverity.High,
'sexual/minors': (sexual?.severity ?? 0) / ModerationSeverity.High,
violence: (violence?.severity ?? 0) / ModerationSeverity.High,
'violence/graphic': (violence?.severity ?? 0) / ModerationSeverity.High
}
};
return result;
Expand Down
4 changes: 2 additions & 2 deletions js/samples/03.ai-concepts/f.chatModeration/src/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ if (process.env.OPENAI_KEY) {
category: 'Violence',
severity: ModerationSeverity.High
}
]
// breakByBlocklists: true,
],
// haltOnBlocklistHit: true,
// blocklistNames: [] // Text blocklist Name. Only support following characters: 0-9 A-Z a-z - . _ ~. You could attach multiple lists name here.
});
}
Expand Down
6 changes: 3 additions & 3 deletions js/samples/03.ai-concepts/f.chatModeration/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import { ConfigurationServiceClientCredentialFactory, TurnContext } from 'botbui

import { TeamsAdapter } from '@microsoft/teams-ai';

// Include the Teams AI custom component
import * as bot from './bot';

// Read botFilePath and botFileSecret from .env file.
const ENV_FILE = path.join(__dirname, '..', '.env');
config({ path: ENV_FILE });

// Include the Teams AI custom component
import * as bot from './bot';

// Create adapter.
// See https://aka.ms/about-bot-adapter to learn more about how bots work.
const adapter = new TeamsAdapter(
Expand Down

0 comments on commit fea76d5

Please sign in to comment.