Add SystemOne classification support and release version 4.0.0
This commit is contained in:
parent
76195f9a92
commit
9a5404cb62
16 changed files with 923 additions and 579 deletions
81
modules/backends/chatCompletions.js
Normal file
81
modules/backends/chatCompletions.js
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
const SYSTEM_PREFIX = `You are an email-classification assistant.
|
||||
Read the email below and the classification criterion provided by the user.
|
||||
`;
|
||||
|
||||
const DEFAULT_CUSTOM_SYSTEM_PROMPT = "Determine whether the email satisfies the user's criterion.";
|
||||
|
||||
const SYSTEM_SUFFIX = `
|
||||
Return ONLY a JSON object on a single line of the form:
|
||||
{"match": true, "reason": "<short explanation>"} - if the email satisfies the criterion
|
||||
{"match": false, "reason": "<short explanation>"} - otherwise
|
||||
|
||||
Do not add any other keys, text, or formatting.`;
|
||||
|
||||
function extractLastJsonObject(text) {
|
||||
let last = null;
|
||||
let start = -1;
|
||||
let depth = 0;
|
||||
let inString = false;
|
||||
let escape = false;
|
||||
|
||||
for (let i = 0; i < text.length; i += 1) {
|
||||
const ch = text[i];
|
||||
if (inString) {
|
||||
if (escape) {
|
||||
escape = false;
|
||||
continue;
|
||||
}
|
||||
if (ch === "\\") {
|
||||
escape = true;
|
||||
continue;
|
||||
}
|
||||
if (ch === "\"") {
|
||||
inString = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (ch === "\"") {
|
||||
inString = true;
|
||||
continue;
|
||||
}
|
||||
if (ch === "{") {
|
||||
if (depth === 0) {
|
||||
start = i;
|
||||
}
|
||||
depth += 1;
|
||||
continue;
|
||||
}
|
||||
if (ch === "}" && depth > 0) {
|
||||
depth -= 1;
|
||||
if (depth === 0 && start !== -1) {
|
||||
last = text.slice(start, i + 1);
|
||||
start = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
export const path = '/v1/chat/completions';
|
||||
export function buildRequest(text, criterion, config) {
|
||||
const payload = {
|
||||
messages: [
|
||||
{ role: 'system', content: SYSTEM_PREFIX + (config.customSystemPrompt || DEFAULT_CUSTOM_SYSTEM_PROMPT) + SYSTEM_SUFFIX },
|
||||
{ role: 'user', content: `**Email Contents**\n\`\`\`\n${text}\n\`\`\`\nClassification Criterion: ${criterion}` }
|
||||
], ...config.aiParams
|
||||
};
|
||||
if (config.model) payload.model = config.model;
|
||||
return payload;
|
||||
}
|
||||
export function parseResponse(result) {
|
||||
const content = result?.choices?.[0]?.message?.content;
|
||||
if (typeof content !== 'string') throw new Error('Chat response missing text content.');
|
||||
const candidate = extractLastJsonObject(content);
|
||||
if (!candidate) throw new Error('No JSON object found in AI response.');
|
||||
const obj = JSON.parse(candidate);
|
||||
const matched = Object.hasOwn(obj, 'match') ? obj.match : obj.matched;
|
||||
if (typeof matched !== 'boolean') throw new Error('AI response missing valid match boolean.');
|
||||
const reason = obj.reason ?? obj.reasoning ?? obj.explaination;
|
||||
return { matched, reason: typeof reason === 'string' ? reason : null, probability: null };
|
||||
}
|
||||
17
modules/backends/systemOne.js
Normal file
17
modules/backends/systemOne.js
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
export const path = '/v1/systemone';
|
||||
export function buildRequest(text, criterion, config) {
|
||||
const payload = {
|
||||
state: text,
|
||||
questions: { match: { type: 'noul', instructions: `Does this email satisfy the following criterion: ${criterion}` } }
|
||||
};
|
||||
if (config.model) payload.model = config.model;
|
||||
return payload;
|
||||
}
|
||||
export function parseResponse(result) {
|
||||
const answer = result?.answers?.match;
|
||||
if (answer?.type !== 'noul' || typeof answer.noul !== 'number' ||
|
||||
!Number.isFinite(answer.noul) || answer.noul < 0 || answer.noul > 1) {
|
||||
throw new Error('SystemOne response must contain answers.match with type noul and a probability from 0 to 1.');
|
||||
}
|
||||
return { matched: null, reason: null, probability: answer.noul };
|
||||
}
|
||||
Loading…
Reference in a new issue