Spaces:
Running
Running
File size: 4,384 Bytes
222e211 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | /**
* Intent parser: maps natural language to task types.
* Ported from hf_space/intent_parser.py.
*/
import { DEFAULT_DETECT_CLASSES, KEYWORD_FALLBACK, ROUTING_GROUP_MAP } from "./constants.js";
const INTERPRET_KW = ["interpret","analyze","analyse","describe","assessment","what do you see","what is this","clinical interpretation","examine","evaluate","tell me about"];
const DETECT_KW = ["detect","find","locate","where is","where are","bounding box","identify","show me","mark","highlight"];
const SEGMENT_KW = ["segment","outline","contour","mask","delineate","boundary","trace","polygon"];
const CLASSIFY_KW = ["classify","what type","what view","which plane","what kind","categorize","classification"];
const GREETING_KW = ["hello","hi ","hey","good morning","good afternoon","thanks","thank you"];
const ANATOMY_TO_GROUP = new Map([
["nt keypoint","nt_kp"],["nt kp","nt_kp"],["nuchal keypoint","nt_kp"],["ntkpoint","nt_kp"],
["brain keypoint","brain"],["cardiac keypoint","cardiac"],
["fetal head","pelvimetry"],["fetal_head","pelvimetry"],["angle of progression","pelvimetry"],
["keypoint","crl_kp"],["kpoint","crl_kp"],["scalebar","crl_kp"],["scale bar","crl_kp"],
["crl_kp","crl_kp"],["scalebarpoint","crl_kp"],
["brain","brain"],["cerebral","brain"],["cerebellum","brain"],["ventricle","brain"],
["thalami","brain"],["bpd","brain"],["head circumference","brain"],["csp","brain"],
["cavum","brain"],["septum pellucidum","brain"],["lv","brain"],["lateral ventricle","brain"],
["choroid plexus","brain"],["falx","brain"],
["heart","cardiac"],["cardiac","cardiac"],["thorax","cardiac"],["thoracic","cardiac"],
["aorta","cardiac"],["four chamber","cardiac"],["cardic","cardiac"],["cariac","cardiac"],
["nuchal","nt_nasal"],["nasal","nt_nasal"],["translucency","nt_nasal"],["nasal bone","nt_nasal"],
["nasal tip","nt_nasal"],["nasal skin","nt_nasal"],["nuchel","nt_nasal"],["translucen","nt_nasal"],
["crown-rump","crl"],["crown rump","crl"],["crl","crl"],
["doppler","doppler"],["flow","doppler"],["vessel","doppler"],["artery","doppler"],
["vein","doppler"],["umbilical","doppler"],
["cervix","pelvimetry"],["pelvimetry","pelvimetry"],["symphysis","pelvimetry"],
["pubic","pelvimetry"],["symphsis","pelvimetry"],["symphis","pelvimetry"],["pelvimtry","pelvimetry"],
["body","body_pose"],["abdomen","body_pose"],["arm","body_pose"],["legs","body_pose"],
["pose","body_pose"],["abdomin","body_pose"],
["femur","femur"],["thigh","femur"],["femor","femur"],
]);
export function parseIntent(userText, hasImage = false, hasInterpretation = false) {
const text = userText.trim().toLowerCase();
if (!text && hasImage) return { task: "interpret" };
for (const kw of GREETING_KW) {
if (text.startsWith(kw) || text.includes(` ${kw}`)) {
if (hasImage && !hasInterpretation) return { task: "interpret" };
return { task: "greeting" };
}
}
for (const kw of SEGMENT_KW) {
if (text.includes(kw)) {
const { det, seg } = extractClasses(text);
return { task: "segment", classes: det || seg, segClasses: seg };
}
}
for (const kw of DETECT_KW) {
if (text.includes(kw)) {
const { det } = extractClasses(text);
return { task: "detect", classes: det };
}
}
for (const kw of CLASSIFY_KW) {
if (text.includes(kw)) return { task: "classify" };
}
for (const kw of INTERPRET_KW) {
if (text.includes(kw)) return { task: "interpret" };
}
if (hasImage && !hasInterpretation) return { task: "interpret" };
if (hasInterpretation) {
const { det } = extractClasses(text);
if (det) return { task: "detect", classes: det };
}
return { task: "general" };
}
function extractClasses(text) {
const lower = text.toLowerCase();
for (const [name, groupKey] of ANATOMY_TO_GROUP) {
if (lower.includes(name) && ROUTING_GROUP_MAP[groupKey]) {
const [det, seg] = ROUTING_GROUP_MAP[groupKey];
return { det, seg };
}
}
for (const [keywords, det, seg] of KEYWORD_FALLBACK) {
for (const kw of keywords) {
if (lower.includes(kw)) return { det, seg };
}
}
if (/\bnt\b/.test(lower) && ROUTING_GROUP_MAP.nt_nasal) {
const [det, seg] = ROUTING_GROUP_MAP.nt_nasal;
return { det, seg };
}
if (/\b(all|every|everything)\b/.test(lower)) return { det: DEFAULT_DETECT_CLASSES, seg: null };
return { det: null, seg: null };
}
|