fix: match PDF-imported patients by member ID when DOB is missing on record
MassHealth eligibility lookups via the AI chatbot only matched existing patients on memberId+DOB, so patients imported from PDF extraction (which have a member ID but no stored birthday) were treated as new/unknown even though they already exist in the system. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -79,6 +79,9 @@ Intents:
|
||||
Insurance abbreviations are: mh, masshealth, bcbs, cca, dentaquest — anything else is a patient name
|
||||
- eligibility_by_id : user provides a SINGLE member ID and date of birth (no patient name)
|
||||
e.g. "check masshealth for 100xxxx, 10/10/1988"
|
||||
e.g. "100xxxx 10/10/1988" or "100xxxx, 10/10/1988" — a bare member ID + DOB with
|
||||
NO verb and NO insurance keyword is STILL eligibility_by_id (default to MassHealth,
|
||||
omit insuranceHint). Do NOT classify this as "general".
|
||||
ALSO use this when user wants to check eligibility AND schedule/add an appointment on a date
|
||||
e.g. "check mh for 100xxxx, 10/10/1988 and schedule on 4/10/2026"
|
||||
e.g. "check mh for 100xxxx, 10/10/1988 and make appointment on 5/1/2026"
|
||||
@@ -219,6 +222,20 @@ Rules:
|
||||
|
||||
// ─── Classifier ───────────────────────────────────────────────────────────────
|
||||
|
||||
// Deterministic fast-path for a bare "memberId DOB" (or "DOB memberId") message with
|
||||
// nothing else in it — e.g. "100232102531 4/27/1999" or "100232102531, 4/27/1999".
|
||||
// Bypasses the LLM entirely so this always resolves to eligibility_by_id, since some
|
||||
// providers hedge/refuse structured output on a bare digit string that looks like an SSN.
|
||||
function parseBareIdDob(message: string): { memberId: string; dob: string } | null {
|
||||
const text = message.trim();
|
||||
const dobPattern = /(\d{1,2}[\/\-]\d{1,2}[\/\-]\d{4})/;
|
||||
const idThenDob = text.match(new RegExp(`^([A-Za-z0-9]{3,})[\\s,]+${dobPattern.source}$`));
|
||||
if (idThenDob) return { memberId: idThenDob[1]!, dob: idThenDob[2]!.replace(/-/g, "/") };
|
||||
const dobThenId = text.match(new RegExp(`^${dobPattern.source}[\\s,]+([A-Za-z0-9]{3,})$`));
|
||||
if (dobThenId) return { memberId: dobThenId[2]!, dob: dobThenId[1]!.replace(/-/g, "/") };
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function classifyInternalChat(
|
||||
message: string,
|
||||
apiKey: string,
|
||||
@@ -234,6 +251,16 @@ export async function classifyInternalChat(
|
||||
"I can search for a patient, check eligibility, run check & claim, schedule appointments, or navigate to claims or appointments.",
|
||||
};
|
||||
|
||||
const bare = parseBareIdDob(message);
|
||||
if (bare) {
|
||||
return {
|
||||
intent: "eligibility_by_id",
|
||||
memberId: bare.memberId,
|
||||
dob: bare.dob,
|
||||
fallbackReply: `Checking eligibility for Member ID ${bare.memberId}...`,
|
||||
};
|
||||
}
|
||||
|
||||
if (!apiKey) return fallback;
|
||||
|
||||
// Prefer the client's local date (avoids UTC midnight rollover for US timezones)
|
||||
|
||||
Reference in New Issue
Block a user