feat: Users AI Chat multi-step workflows with CDT lookup and alias management
- Add eligibility_by_id and check_and_claim intents to internal chat - New cdt-lookup.ts: keyword search against fee schedule JSON (no LLM) - New internal-chat-workflow.ts: deterministic orchestration — patient resolution, insurance siteKey derivation, CDT code mapping - Custom CDT aliases stored per-user in DB (TwilioSettings JSON blob) with GET/PUT /api/ai/cdt-aliases endpoints - Chatbot UI: new steps for eligibility-id-ready, check-and-claim-ready, and need-insurance-clarification with insurance picker - Settings UI: CDT Aliases CRUD table with built-in alias reference Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
4274cd61dc
commit
ba2882957a
@@ -1,39 +1,70 @@
|
||||
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
|
||||
|
||||
// ─── Intent types ─────────────────────────────────────────────────────────────
|
||||
|
||||
export type InternalChatIntent =
|
||||
| "check_eligibility"
|
||||
| "find_patient"
|
||||
| "check_eligibility" // by patient name → look up in DB
|
||||
| "eligibility_by_id" // by explicit memberId + dob (no name)
|
||||
| "check_and_claim" // eligibility + claim procedures
|
||||
| "find_patient" // look up patient record only
|
||||
| "navigate_claims"
|
||||
| "navigate_schedule"
|
||||
| "general";
|
||||
|
||||
export interface ChatClassification {
|
||||
intent: InternalChatIntent;
|
||||
patientName?: string;
|
||||
// --- patient resolution (one of name OR id+dob) ---
|
||||
patientName?: string; // for check_eligibility / find_patient
|
||||
memberId?: string; // for eligibility_by_id / check_and_claim
|
||||
dob?: string; // for eligibility_by_id / check_and_claim (MM/DD/YYYY)
|
||||
// --- insurance hint (only if explicitly stated in the message) ---
|
||||
insuranceHint?: string; // raw text, e.g. "masshealth", "BCBS", "CCA"
|
||||
// --- procedures (raw text, NOT CDT codes — CDT lookup is done in workflow) ---
|
||||
procedureNames?: string[]; // for check_and_claim, e.g. ["perio exam", "adult cleaning"]
|
||||
fallbackReply: string;
|
||||
}
|
||||
|
||||
const BASE_SYSTEM_PROMPT = `You are an internal assistant for a dental office management system.
|
||||
Staff members type natural language commands and you classify what they want.
|
||||
// ─── System prompt ────────────────────────────────────────────────────────────
|
||||
|
||||
Respond ONLY with valid JSON (no markdown, no code fences) in this exact format:
|
||||
const BASE_SYSTEM_PROMPT = `You are an internal assistant for a dental office management app.
|
||||
Staff type natural language commands. Your ONLY job is to classify the intent and extract
|
||||
structured parameters. Do NOT map procedure names to CDT codes — return them as plain text.
|
||||
|
||||
Respond ONLY with valid JSON (no markdown fences):
|
||||
{
|
||||
"intent": "<one of the intents below>",
|
||||
"patientName": "<full name if patient is mentioned, otherwise omit>",
|
||||
"fallbackReply": "<a short, helpful reply to show the user>"
|
||||
"intent": "<intent>",
|
||||
"patientName": "<full name if mentioned by name>",
|
||||
"memberId": "<member/insurance ID if given explicitly>",
|
||||
"dob": "<date of birth in MM/DD/YYYY if given>",
|
||||
"insuranceHint": "<insurance name only if explicitly stated in the message, e.g. 'masshealth', 'BCBS MA', 'CCA'>",
|
||||
"procedureNames": ["<raw procedure name>", ...],
|
||||
"fallbackReply": "<1-2 sentence reply to show the user>"
|
||||
}
|
||||
|
||||
Omit any field that is not present in the message.
|
||||
|
||||
Intents:
|
||||
- check_eligibility: user wants to check insurance eligibility for a patient (e.g. "check MARIA", "verify insurance for John Smith", "eligibility GONZALES")
|
||||
- find_patient: user wants to look up a patient record only (e.g. "find patient John", "look up Smith", "show me GONZALES record")
|
||||
- navigate_claims: user wants to open the claims page
|
||||
- navigate_schedule: user wants to open the appointments/schedule page
|
||||
- general: anything else — answer helpfully based on dental office context
|
||||
- check_eligibility : user wants to check insurance for a patient identified by NAME only
|
||||
e.g. "check Maria Jesus", "verify insurance for John Smith"
|
||||
- eligibility_by_id : user provides a member ID and date of birth (no patient name)
|
||||
e.g. "check masshealth for 100xxxx, 10/10/1988"
|
||||
- check_and_claim : user wants to check eligibility AND submit procedures as claims
|
||||
e.g. "check masshealth for 100xxxx, 10/10/1988 and claim perio exam and adult cleaning"
|
||||
e.g. "check Maria Jesus and claim D0120 D1110"
|
||||
- find_patient : look up a patient record only, no eligibility
|
||||
e.g. "find patient John", "look up Smith"
|
||||
- navigate_claims : open the claims page
|
||||
- navigate_schedule : open the appointments/schedule page
|
||||
- general : anything else
|
||||
|
||||
Rules:
|
||||
- Extract the full patient name as-is from the message for check_eligibility and find_patient
|
||||
- Keep fallbackReply to 1-2 sentences max
|
||||
- For navigate intents, fallbackReply should say "Opening the [page] page..."`;
|
||||
- For check_and_claim, procedureNames should be the RAW user text
|
||||
(e.g. "perio exam", "adult cleaning", "D0120") — do NOT translate to codes
|
||||
- insuranceHint is only set when the user explicitly names an insurance in the message
|
||||
- Keep fallbackReply to 1-2 sentences
|
||||
- For navigate intents, fallbackReply = "Opening the [page] page..."`;
|
||||
|
||||
// ─── Classifier ───────────────────────────────────────────────────────────────
|
||||
|
||||
export async function classifyInternalChat(
|
||||
message: string,
|
||||
@@ -42,7 +73,8 @@ export async function classifyInternalChat(
|
||||
): Promise<ChatClassification> {
|
||||
const fallback: ChatClassification = {
|
||||
intent: "general",
|
||||
fallbackReply: "I can help you search for a patient, check eligibility, or navigate to claims or appointments.",
|
||||
fallbackReply:
|
||||
"I can search for a patient, check eligibility, run check & claim, or navigate to claims or appointments.",
|
||||
};
|
||||
|
||||
if (!apiKey) return fallback;
|
||||
|
||||
Reference in New Issue
Block a user