如何為有時間限制的保險理賠受理設計檢索架構
How to Design Retrieval Architecture for Insurance Intake Under Time Limits
這篇指南為保險理賠受理設計符合延遲預算的檢索架構,目標是在來電者等待期間提供可用證據,並把整體請求限制在一秒內。建議先用 150 ms 做詞彙檢索及元資料篩選,再用 350 ms 做語義檢索和重排;逾時時返回已有的最佳引用匹配結果,不要阻塞受理流程等待第二次嘗試。詞彙與向量搜尋並行,合併後只對前 20 至 50 個候選項重排,並分開追蹤檢索品質與 p50、p95、p99 延遲。
Insurance claims intake has a hard product constraint: the adjuster needs useful evidence while the caller is still waiting. The practical choice is not “the most accurate search.” It is a retrieval architecture whose quality target fits a measured latency budget, with a safe answer when one stage times out.
Short answer: reserve the first 150 ms for a fast lexical and metadata filter, spend the next 350 ms on semantic retrieval and reranking, and stop at a one-second wall clock deadline; return the best cited matches you have rather than blocking intake on a second attempt.
A field guide to latency budgets
Start by writing the budget as a table. These are design targets, not promises; measure them with your claim mix and network topology.
| Path | Budget | Pick this when | Quality trade-off |
|---|---|---|---|
| Lexical plus metadata | 150 ms | You need an immediate policy or vehicle match | Misses paraphrases and OCR variants |
| Hybrid retrieval | 500 ms | Claims contain both identifiers and narrative text | More moving parts and index freshness work |
| Hybrid plus reranker | 850 ms | A reviewer can wait for stronger ordering | Tail latency rises under load |
| Asynchronous enrichment | No blocking budget | You can improve a draft after intake | The first result is less complete |
Keep the table close to the request path. In a marketplace-style claims flow, a claim may contain a policy number, a repair description, and a scanned receipt. Identifiers are excellent lexical keys; “water entered from the rear seal” is a semantic clue. Sending both through one search mode creates avoidable misses.
The catch is tail latency. A p50 of 300 ms can still feel broken when p99 reaches 2 seconds. Set a deadline on the whole request, then allocate child deadlines. A child must never be allowed to consume the parent’s entire budget.
How should retrieval architecture handle insurance claims intake latency budgets?
Think of the request as a small pipeline, drawn in words:
claim text -> normalize -> lexical filter || vector search -> merge -> rerank -> cited evidence
The double bar means the first searches run in parallel. Merge by a stable document ID, preserve the retrieval source for debugging, and rerank only the top 20 to 50 candidates. Reranking every indexed policy document is an expensive way to discover that the policy number was already an exact match.
Here is a TypeScript skeleton with an explicit deadline. The interfaces are deliberately generic so the same contract can sit over a hosted or self-managed index.
type Candidate = {
id: string;
score: number;
source: "lexical" | "semantic";
text: string;
};
type Searcher = {
lexical(query: string, signal: AbortSignal): Promise<Candidate[]>;
semantic(query: string, signal: AbortSignal): Promise<Candidate[]>;
rerank(query: string, items: Candidate[], signal: AbortSignal): Promise<Candidate[]>;
};
export async function retrieveEvidence(
query: string,
searcher: Searcher,
totalMs = 1_000,
): Promise<Candidate[]> {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), totalMs);
try {
const [lexical, semantic] = await Promise.allSettled([
searcher.lexical(query, controller.signal),
searcher.semantic(query, controller.signal),
]);
const merged = new Map<string, Candidate>();
for (const result of [lexical, semantic]) {
if (result.status !== "fulfilled") continue;
for (const item of result.value) {
const prior = merged.get(item.id);
if (!prior || item.score > prior.score) merged.set(item.id, item);
}
}
const top = [...merged.values()]
.sort((a, b) => b.score - a.score)
.slice(0, 40);
if (top.length < 2 || controller.signal.aborted) return top;
return await searcher.rerank(query, top, controller.signal);
} finally {
clearTimeout(timer);
}
}
The important behavior is the partial result. Promise.allSettled lets a lexical hit survive a slow semantic service. That is a product decision: an exact policy identifier with a clear source is better than a blank intake form. Log which branch settled, how many candidates it returned, and whether reranking was skipped.
Pick the right stage for each failure mode
Normalize OCR text before embedding. Keep the original span for citations, but strip repeated whitespace, standardize dates, and retain claim identifiers as separate fields. Do not embed a policy number as if it were prose; index it for exact filtering.
Then test adversarial pairs. “Rear seal leak” versus “water ingress at trunk gasket” should be near each other semantically. “Policy 4817” versus “Policy 4818” must stay apart even if every other token matches. A retrieval test that checks only top-k recall will miss this costly collision.
I once assumed a higher top-k would cover these cases. It did not. The reranker simply received more near-duplicates, and the p99 graph climbed past the caller’s patience. The fix was a field-aware filter and a smaller rerank set, not a larger number.
Measure twice.
For a concrete test, take one week of de-identified intake text and create pairs by changing exactly one field at a time: swap a digit in the policy number, replace a synonym in the loss description, or remove the receipt date. Run each pair through lexical-only, semantic-only, and hybrid paths. Record the first stage that separates the pair, then inspect the trace for the milliseconds spent before that separation. This exposes a common false win: a semantic index can improve recall on paraphrases while making exact identifiers less precise. Keep those dimensions separate in the report, and require a reviewer to sign off on the threshold used to merge candidates. A single aggregate score cannot tell you whether a missed duplicate came from tokenization, stale metadata, or an overloaded reranker.
Use a golden set of de-identified claims with labels for duplicate, related, and irrelevant. Track recall@k for the first stage, nDCG for ordering, and a separate identifier-precision check. Pair each quality metric with p50, p95, and p99 latency. Your mileage may vary because OCR language, index size, and concurrency change the curve; record those variables with every run.
Make observability part of the contract
Every intake request needs one correlation ID. Emit structured events for normalization, lexical search, semantic search, merge, rerank, and final response. Useful fields include elapsed milliseconds, candidate counts, timeout stage, index version, and evidence IDs. Avoid logging raw medical or financial text; hash stable identifiers and apply the retention policy required by your jurisdiction.
Alert on symptoms that affect the decision: p95 over its stage budget, a rising timeout ratio, sudden drops in candidate count, and disagreement between lexical and semantic results. A dashboard that shows only average latency hides the exact incident the adjuster experiences.
For tracing, make the parent span the one-second deadline and child spans carry their allocated budgets. This makes a slow vector call visible without blaming the reranker for time it never received. Sample enough slow traces to inspect them, while keeping ordinary claim content out of span attributes.
Limits and deliberate compromises
This architecture is not suitable when a claim must be decided synchronously from a complete, legally reviewed record; use a human review queue and an asynchronous enrichment path instead. It is also a poor fit for tiny datasets where a well-indexed relational query is faster and easier to audit.
Semantic retrieval can amplify stale or duplicated documents. Rebuild and validate indexes with a versioned job, then expose the active version in telemetry. If evidence freshness matters more than paraphrase recall, prefer a shorter lexical path and make semantic enrichment optional.
I’m not sure one universal 1,000 ms deadline exists. The right number comes from a usability study and an error budget agreed with claims operations. The durable rule is simpler: define the deadline, measure the tail, cite what was actually retrieved, and make every fallback visible.
Sources
來源:DEV Community · dev.to