@paroicms/site-generator-plugin
Version:
ParoiCMS Site Generator Plugin
98 lines (97 loc) • 3.39 kB
JavaScript
import { type } from "arktype";
import { insertIssueEvent } from "../../db/db-write.queries.js";
import { invokeClaude } from "../lib/calling-llm-anthropic.js";
import { createPromptTemplate } from "../lib/create-prompt.js";
import { debugLlmOutput } from "../lib/debug-utils.js";
import { parseLlmResponseAsProperties } from "../lib/parse-llm-response.js";
const guardPrompt = await createPromptTemplate({
filename: "message-guard.md",
});
const MessageGuardReportAT = type({
"language?": "string|undefined",
valid: "boolean",
"causes?": '("rude"|"malicious"|"outOfScope"|"technicalLimits"|"noSense")[]|undefined',
"explanation?": "string|undefined",
"+": "reject",
});
export async function invokeMessageGuard(ctx, input, { skipOutOfScopeCheck = false } = {}) {
const llmTaskName = "guard";
const llmInput = {
message: input.prompt,
};
const debug = await debugLlmOutput(ctx, llmTaskName, ctx.anthropicModelName, undefined, {
message: llmInput.message,
});
let llmOutput = debug.stored;
if (!llmOutput) {
const { messageContent, report } = await invokeClaude(ctx, {
llmTaskName,
prompt: guardPrompt(llmInput),
maxTokens: 200,
temperature: 0.2,
systemInstruction: "beFast",
});
llmOutput = await debug.getMessageContent(messageContent, report);
}
const rawReport = parseLlmResponseAsProperties(llmOutput.output, [
{
tagName: "guard_json",
key: "guard",
format: "json",
},
]);
const report = MessageGuardReportAT.assert(rawReport.guard);
if (report.causes && skipOutOfScopeCheck) {
report.causes = report.causes.filter((cause) => cause !== "outOfScope");
if (report.causes.length === 0) {
report.valid = true;
}
}
if (report.valid)
return { detectedLanguage: report.language };
await insertIssueEvent(ctx, {
eventType: "blockedByGuard",
llmTaskName: "guard",
issueMessage: report.explanation,
});
return {
success: false,
language: report.language,
userMessage: report.explanation ?? toUserMessage(report.causes, report.language),
};
}
function toUserMessage(causes, language) {
if (!causes || causes.length === 0)
return "Invalid message";
return causes.map((cause) => getCauseLabel(cause, language)).join(", ");
}
function getCauseLabel(cause, language) {
if (language === "fr") {
switch (cause) {
case "rude":
case "malicious":
return "Nous ne pouvons pas répondre à cette demande";
case "outOfScope":
return "Hors sujet";
case "technicalLimits":
return "Limites techniques";
case "noSense":
return "Nous ne comprenons pas la demande";
default:
return cause;
}
}
switch (cause) {
case "rude":
case "malicious":
return "We cannot answer to this request";
case "outOfScope":
return "Out of scope";
case "technicalLimits":
return "Technical limits";
case "noSense":
return "We do not understand the request";
default:
return cause;
}
}