| export const MODEL_ID = "Xenova/all-MiniLM-L6-v2"; |
|
|
| export const CONDITION_CARDS = [ |
| { |
| label: "common cold", |
| description: |
| "runny or stuffy nose, sneezing, sore throat, cough, mild headache, and usually little or no fever", |
| }, |
| { |
| label: "influenza", |
| description: |
| "sudden fever, dry cough, fatigue, body aches, headache, chills, and sometimes sore throat", |
| }, |
| { |
| label: "COVID-19", |
| description: |
| "fever, cough, fatigue, sore throat, congestion, headache, body aches, and possible loss of taste or smell", |
| }, |
| { |
| label: "seasonal allergies", |
| description: |
| "sneezing, itchy or watery eyes, clear runny nose, nasal congestion, and usually no fever", |
| }, |
| { |
| label: "strep throat", |
| description: |
| "sudden sore throat, pain when swallowing, fever, red swollen tonsils, and usually no cough", |
| }, |
| { |
| label: "migraine", |
| description: |
| "moderate or severe throbbing headache, often one-sided, nausea, and sensitivity to light or sound", |
| }, |
| { |
| label: "tension headache", |
| description: |
| "mild or moderate pressure or tightness around the head, scalp tenderness, and no nausea", |
| }, |
| { |
| label: "gastroenteritis", |
| description: |
| "watery diarrhea, abdominal cramps, nausea or vomiting, and sometimes fever", |
| }, |
| { |
| label: "urinary tract infection", |
| description: |
| "burning or pain during urination, frequent urination, urgent urination, and pelvic pressure", |
| }, |
| { |
| label: "pneumonia", |
| description: |
| "cough, fever, chills, difficulty breathing, chest pain with breathing or coughing, and fatigue", |
| }, |
| ]; |
|
|
| export const RED_FLAG_PHRASES = [ |
| "chest pain", |
| "difficulty breathing", |
| "trouble breathing", |
| "shortness of breath", |
| "fainting", |
| "confusion", |
| "blue lips", |
| "one-sided weakness", |
| "stiff neck", |
| "coughing blood", |
| ]; |
|
|
| export function normalizeInput(text) { |
| return text.trim().replace(/\s+/g, " "); |
| } |
|
|
| export function splitSymptoms(text) { |
| return text |
| .split(/\n|,|;|\.(?:\s|$)/) |
| .map(normalizeInput) |
| .filter(Boolean); |
| } |
|
|
| export function reorderSymptoms(text) { |
| return splitSymptoms(text).reverse().join(", "); |
| } |
|
|
| export function findRedFlags(text) { |
| const normalized = normalizeInput(text).toLowerCase(); |
| return RED_FLAG_PHRASES.filter((phrase) => normalized.includes(phrase)); |
| } |
|
|
| export function rankRows(result, limit = 5) { |
| return result.labels.slice(0, limit).map((label, index) => ({ |
| rank: index + 1, |
| label, |
| score: result.scores[index], |
| })); |
| } |
|
|
| export function compareRankings(first, second) { |
| const secondRanks = new Map(second.map((row) => [row.label, row.rank])); |
| return first.map((row) => ({ |
| label: row.label, |
| originalRank: row.rank, |
| reorderedRank: secondRanks.get(row.label) ?? null, |
| shift: |
| secondRanks.has(row.label) ? row.rank - secondRanks.get(row.label) : null, |
| })); |
| } |
|
|
| export function csvEscape(value) { |
| const text = String(value ?? ""); |
| return `"${text.replaceAll('"', '""')}"`; |
| } |
|
|
| export function runsToCsv(runs) { |
| const header = [ |
| "timestamp", |
| "input", |
| "variant", |
| "rank", |
| "condition", |
| "model_score", |
| "model_id", |
| "device", |
| "dtype", |
| "inference_ms", |
| ]; |
| const rows = runs.flatMap((run) => |
| run.results.map((result) => [ |
| run.timestamp, |
| run.input, |
| run.variant, |
| result.rank, |
| result.label, |
| result.score, |
| run.modelId, |
| run.device, |
| run.dtype, |
| run.inferenceMs, |
| ]), |
| ); |
| return [header, ...rows].map((row) => row.map(csvEscape).join(",")).join("\n"); |
| } |
|
|