Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions server/_core/embeddings/degradation-alert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,37 @@ export function alertSilentEmptyResult(detail: SilentEmptyDetail): void {
'error',
);
}

/** Drug/dosing keyword fallback for queries the intent classifier misses. */
const CLINICAL_DRUG_KEYWORDS = /\b(dose|doses|dosing|dosage|mg|mcg|administer|give|max|drug|medication)\b/i;

export interface ClinicalQuerySignal {
/** NormalizedQuery.intent */
intent: string;
/** NormalizedQuery.isEmergent — cardiac arrest, anaphylaxis, airway, etc. */
isEmergent: boolean;
/** NormalizedQuery.extractedMedications */
extractedMedications: string[];
/** NormalizedQuery.extractedConditions — chest pain, stroke, seizure, etc. */
extractedConditions: string[];
/** NormalizedQuery.normalized text */
normalizedText: string;
}

/**
* True if a query is clinically meaningful, so a zero-result on a resolved
* agency is worth alerting (the "blank screen mid-call" case). Broader than
* dosing alone: a paramedic searching "chest pain" / "stroke" / "cardiac arrest"
* and getting nothing is exactly the failure we must surface. Reuses the
* normalizer's intent / emergent / condition / medication signals.
*/
export function isClinicalQuery(s: ClinicalQuerySignal): boolean {
return (
s.intent === 'medication_dosing' ||
s.intent === 'contraindication_check' ||
s.isEmergent ||
s.extractedMedications.length > 0 ||
s.extractedConditions.length > 0 ||
CLINICAL_DRUG_KEYWORDS.test(s.normalizedText)
);
}
12 changes: 10 additions & 2 deletions server/routers/search/semantic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { validateSearchLimit, getUserTierFeatures } from "../../_core/tier-valid
import { toStateCode } from "../../lib/state-codes";
import { incrementAndCheckQueryLimit } from "../../db/users-usage";
import { logger } from "../../_core/logger";
import { alertSilentEmptyResult } from "../../_core/embeddings/degradation-alert";
import { alertSilentEmptyResult, isClinicalQuery } from "../../_core/embeddings/degradation-alert";
import { logQuery, createQueryLogEntry } from "../../_core/query-analytics";
import { getDrugByName } from "../../db/drugs";
import {
Expand Down Expand Up @@ -282,7 +282,15 @@ export const semanticRouter = router({
query: input.query,
agencyId,
agencyName,
isClinical: isDrugRelated || isMedicationQuery,
// Broadened beyond dosing: also alert on emergent / condition queries
// (chest pain, stroke, cardiac arrest) that blank-screen mid-call.
isClinical: isClinicalQuery({
intent: normalized.intent,
isEmergent: normalized.isEmergent,
extractedMedications: normalized.extractedMedications,
extractedConditions: normalized.extractedConditions,
normalizedText: normalized.normalized,
}),
});
}

Expand Down
32 changes: 32 additions & 0 deletions tests/embedding-degradation-alert.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as sentry from "../server/_core/sentry";
import {
alertEmbeddingDegraded,
alertSilentEmptyResult,
isClinicalQuery,
} from "../server/_core/embeddings/degradation-alert";

/**
Expand Down Expand Up @@ -49,3 +50,34 @@ describe("silent-degradation alerts", () => {
expect(spy).not.toHaveBeenCalled();
});
});

describe("isClinicalQuery (broadened clinical classification)", () => {
const base = {
intent: "general_search",
isEmergent: false,
extractedMedications: [] as string[],
extractedConditions: [] as string[],
normalizedText: "",
};

it("is true for an EMERGENT query with no drug term (chest pain / cardiac arrest)", () => {
expect(isClinicalQuery({ ...base, isEmergent: true, normalizedText: "cardiac arrest" })).toBe(true);
});

it("is true for a CONDITION query (stroke) even without dosing keywords", () => {
expect(isClinicalQuery({ ...base, extractedConditions: ["stroke"], normalizedText: "stroke" })).toBe(true);
});

it("is true for medication_dosing intent and for extracted medications", () => {
expect(isClinicalQuery({ ...base, intent: "medication_dosing", normalizedText: "epi dose" })).toBe(true);
expect(isClinicalQuery({ ...base, extractedMedications: ["epinephrine"], normalizedText: "epinephrine" })).toBe(true);
});

it("is true via the dosing-keyword fallback the intent classifier might miss", () => {
expect(isClinicalQuery({ ...base, normalizedText: "how much to administer" })).toBe(true);
});

it("is FALSE for a non-clinical / navigational query", () => {
expect(isClinicalQuery({ ...base, normalizedText: "about page settings" })).toBe(false);
});
});
Loading