Skip to content

Commit

Permalink
make rating analyzer have a new format to increase modularity
Browse files Browse the repository at this point in the history
  • Loading branch information
mfish33 committed Aug 19, 2023
1 parent 9113ff9 commit 312e940
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 49 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,11 @@ jobs:
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
run: NX_CLOUD_DISTRIBUTED_EXECUTION=false npm run deploy:beta

# We will deploy to dev so that cloudflare preview urls will point to the backend
# This will be a problem with multiple PRs, but hey we at least tried :)
- name: Deploy Dev
if: github.ref != 'refs/heads/beta' && github.ref != 'refs/heads/master'
env:
CLOUDFLARE_API_TOKEN: ${{ secrets.CF_API_TOKEN }}
run: NX_CLOUD_DISTRIBUTED_EXECUTION=false npm run deploy:beta
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import { PendingRating, PerspectiveAttributeScore } from "@backend/types/schema"

const ANALYZE_COMMENT_URL = "https://commentanalyzer.googleapis.com/v1alpha1/comments:analyze";

export type AnalyzedRating = Record<string, number>;
export type RatingAnalyzer = {
analyzeRaring(rating: PendingRating): Promise<AnalyzeCommentResponse["attributeScores"]>;
analyzeRaring(rating: PendingRating): Promise<AnalyzedRating>;
};

export class PerspectiveDAO implements RatingAnalyzer {
constructor(private readonly apiKey: string) {}

async analyzeRaring(rating: PendingRating): Promise<AnalyzeCommentResponse["attributeScores"]> {
async analyzeRaring(rating: PendingRating): Promise<AnalyzedRating> {
// TODO: Perhaps we should define a default request?
const requestBody: AnalyzeCommentRequest = {
comment: {
Expand Down Expand Up @@ -38,43 +39,23 @@ export class PerspectiveDAO implements RatingAnalyzer {
}

const response = (await httpResponse.json()) as AnalyzeCommentResponse;
return response.attributeScores;
return Object.fromEntries(
Object.entries(response.attributeScores).map(
([
key,
{
summaryScore: { value },
},
]) => [key, value],
),
);
}
}

export class PassThroughRatingAnalyzer implements RatingAnalyzer {
// eslint-disable-next-line class-methods-use-this, @typescript-eslint/no-unused-vars
async analyzeRaring(rating: PendingRating): Promise<AnalyzeCommentResponse["attributeScores"]> {
return {
SEVERE_TOXICITY: {
summaryScore: {
type: "",
value: 0,
},
spanScores: null,
},
IDENTITY_ATTACK: {
summaryScore: {
type: "",
value: 0,
},
spanScores: null,
},
THREAT: {
summaryScore: {
type: "",
value: 0,
},
spanScores: null,
},
SEXUALLY_EXPLICIT: {
summaryScore: {
type: "",
value: 0,
},
spanScores: null,
},
};
async analyzeRaring(rating: PendingRating): Promise<AnalyzedRating> {
return {};
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
PassThroughRatingAnalyzer,
PerspectiveDAO,
RatingAnalyzer,
} from "@backend/dao/perspective-dao";
} from "@backend/dao/rating-analyzer-dao";
import { AuthStrategy } from "@backend/dao/auth-strategy";
import {
DiscordNotificationDAO,
Expand Down
13 changes: 5 additions & 8 deletions packages/backend/src/routers/rating.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,17 @@ export const ratingsRouter = t.router({
status: "Failed",
error: null,
sentimentResponse: null,
analyzedScores: null,
};

const attributeScores = await ctx.env.ratingAnalyzer.analyzeRaring(pendingRating);
pendingRating.sentimentResponse = attributeScores;
const analyzedScores = await ctx.env.ratingAnalyzer.analyzeRaring(pendingRating);
pendingRating.analyzedScores = analyzedScores;
console.log(analyzedScores);

// At least 50% of people would find the text offensive in category
const PERSPECTIVE_THRESHOLD = 0.5;

const passedAnalysis = [
attributeScores.SEVERE_TOXICITY?.summaryScore.value,
attributeScores.IDENTITY_ATTACK?.summaryScore?.value,
attributeScores.THREAT?.summaryScore?.value,
attributeScores.SEXUALLY_EXPLICIT?.summaryScore?.value,
].reduce((acc, num) => {
const passedAnalysis = Object.values(analyzedScores).reduce((acc, num) => {
if (num === undefined) {
throw new Error("Not all of perspective summery scores were received");
}
Expand Down
2 changes: 2 additions & 0 deletions packages/backend/src/types/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ export const pendingRatingParser = ratingParser.merge(
z.object({
status: z.enum(PENDING_RATING_STATUSES),
error: z.nullable(z.string()),
// TODO: Deprecate field completely
sentimentResponse: z.nullable(z.record(perspectiveAttributeScoreParser)),
analyzedScores: z.nullable(z.record(z.number())),
courseNum: z.number().min(100).max(599),
department: z.enum(DEPARTMENT_LIST),
}),
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"private": true,
"scripts": {
"start:dev": "vite",
"start:local": "vite --mode vite-local",
"start:local": "vite",
"build": "tsc && vite build",
"serve": "vite preview",
"test": "vitest run",
Expand Down
3 changes: 1 addition & 2 deletions packages/frontend/src/App.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ const cloudflareBranch = import.meta.env?.CF_PAGES_BRANCH ?? "";

// eslint-disable-next-line import/no-mutable-exports
let config: AppConfiguration;
// Have to use a prefix since "local" is not a valid MODE
if (import.meta.env.MODE === "vite-local") {
if (import.meta.env.DEV) {
config = localConfig;
} else if (branchToConfig[cloudflareBranch]) {
config = branchToConfig[cloudflareBranch];
Expand Down
11 changes: 8 additions & 3 deletions packages/frontend/src/pages/Admin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,11 @@ function ProcessedRatings() {
const { data: processedRatings } = useDbValues("rating-log");
type PendingRating = NonNullable<typeof processedRatings>[0];

const sortedProcessedRatings =
(processedRatings ?? []).sort(
(ratingA, ratingB) => Date.parse(ratingB.postDate) - Date.parse(ratingA.postDate),
) ?? [];

const columns = [
{
name: "Status",
Expand All @@ -211,9 +216,9 @@ function ProcessedRatings() {
grow: 1.5,
cell: (row: PendingRating) => (
<div className="flex flex-col">
{Object.entries(row.sentimentResponse ?? {}).map(([name, score]) => (
{Object.entries(row.analyzedScores ?? {}).map(([name, score]) => (
<div key={name}>
{name}: {score.summaryScore.value}
{name}: {score}
</div>
))}
</div>
Expand All @@ -230,7 +235,7 @@ function ProcessedRatings() {
return (
<div className="mt-4">
<h2 className="ml-1">Processed Ratings:</h2>
<DataTable columns={columns} data={processedRatings ?? []} pagination />
<DataTable columns={columns} data={sortedProcessedRatings} pagination />
</div>
);
}
Expand Down

0 comments on commit 312e940

Please sign in to comment.