Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 72 additions & 4 deletions apps/api/src/api/llm/core/services/moderation.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,32 @@ export class ModerationService implements IModerationService {
async validateContent(content: string): Promise<boolean> {
if (!content) return true;

// Check if this appears to be legitimate educational/technical content
if (this.isEducationalContent(content)) {
this.logger.debug(
"Content appears to be educational/technical, allowing with less strict moderation",
);
return true;
}

try {
const moderation = new OpenAIModerationChain();

const { output: guardRailsResponse } = await moderation.invoke({
input: content,
});

return (
guardRailsResponse !==
"Text was found that violates OpenAI's content policy."
);
const isViolation =
guardRailsResponse ===
"Text was found that violates OpenAI's content policy.";

if (isViolation) {
this.logger.warn(
`Content flagged by moderation: ${content.slice(0, 200)}...`,
);
}

return !isViolation;
} catch (error) {
this.logger.error(
`Error validating content: ${
Expand All @@ -41,6 +56,59 @@ export class ModerationService implements IModerationService {
}
}

private isEducationalContent(content: string): boolean {
const educationalIndicators = [
// Security education keywords
"xss",
"cross-site scripting",
"security",
"vulnerability",
"penetration testing",
"cybersecurity",
"sql injection",
"csrf",
"owasp",
"security report",
"vulnerability assessment",
"security analysis",
"ethical hacking",

// Technical/programming education
"algorithm",
"data structure",
"programming",
"software development",
"computer science",
"technical documentation",
"code example",
"tutorial",
"documentation",
"technical report",
"analysis",
"implementation",

// Academic indicators
"research",
"study",
"analysis",
"conclusion",
"methodology",
"findings",
"bibliography",
"references",
"abstract",
"introduction",
];

const lowerContent = content.toLowerCase();
const matchCount = educationalIndicators.filter((indicator) =>
lowerContent.includes(indicator),
).length;

// If multiple educational indicators are present, likely educational content
return matchCount >= 2;
}

/**
* Sanitize the content by removing any potentially harmful or unnecessary elements.
* This method uses DOMPurify to remove scripts or other dangerous HTML content.
Expand Down