med-pdf-nmo 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/med-pdf-nmo.browser.js +730 -88
- package/dist/med-pdf-nmo.browser.mjs +730 -88
- package/dist/predictor/config.d.ts +2 -0
- package/dist/predictor/config.js +2 -0
- package/dist/predictor/scorer-registry.d.ts +28 -0
- package/dist/predictor/scorer-registry.js +290 -0
- package/dist/predictor/scorers/direction.d.ts +22 -0
- package/dist/predictor/scorers/direction.js +134 -0
- package/dist/predictor/scorers/drug-dose.js +36 -3
- package/dist/predictor/scorers/option-family.d.ts +59 -0
- package/dist/predictor/scorers/option-family.js +201 -0
- package/dist/predictor/scorers/recommendation-item.d.ts +12 -0
- package/dist/predictor/scorers/recommendation-item.js +63 -1
- package/dist/predictor/selection.js +1 -44
- package/dist/predictor.js +350 -37
- package/package.json +1 -1
|
@@ -32401,6 +32401,8 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
32401
32401
|
singleTieSpecificityGap: 0.5,
|
|
32402
32402
|
sharedMultiSegmentBoost: true,
|
|
32403
32403
|
countRelationBoost: true,
|
|
32404
|
+
optionFamilyComparatorGuard: true,
|
|
32405
|
+
optionFamilyCompactComboGuard: true,
|
|
32404
32406
|
topQuestionChunks: 28,
|
|
32405
32407
|
evidenceLimit: 8
|
|
32406
32408
|
};
|
|
@@ -32581,6 +32583,100 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
32581
32583
|
keyedRuntimeCache.clear();
|
|
32582
32584
|
}
|
|
32583
32585
|
|
|
32586
|
+
// src/predictor/scorer-registry.ts
|
|
32587
|
+
var SELECTION_STRUCTURAL_EVIDENCE_WEIGHTS_RECORD = {
|
|
32588
|
+
coordinate_table_row: 1.25,
|
|
32589
|
+
coordinate_table_group: 1.25,
|
|
32590
|
+
coordinate_table_group_inverse: 1.25,
|
|
32591
|
+
coordinate_table_multicell_row: 1.25,
|
|
32592
|
+
coordinate_table_membership: 1.15,
|
|
32593
|
+
parenthetical_group_segment: 1.05,
|
|
32594
|
+
preceding_question_label: 1.05,
|
|
32595
|
+
question_continuation_list: 1.05,
|
|
32596
|
+
exact_numeric_option_segment: 1.05,
|
|
32597
|
+
exact_hour_alias_segment: 1.05,
|
|
32598
|
+
short_medical_alias_segment: 0.9,
|
|
32599
|
+
visual_table_column: 1.2,
|
|
32600
|
+
exact_short_label_visual_row: 1.15,
|
|
32601
|
+
short_label_visual_row: 1.05,
|
|
32602
|
+
answer_ordinal_row: 1.05,
|
|
32603
|
+
fibrosis_stage_row: 1.2,
|
|
32604
|
+
gene_sentence_segment: 1.1,
|
|
32605
|
+
clinical_feature_segment: 1,
|
|
32606
|
+
mkb_class_exclusion_absent: 1,
|
|
32607
|
+
classification_code_segment: 1.15,
|
|
32608
|
+
label_number_proximity: 1,
|
|
32609
|
+
label_definition_segment: 1,
|
|
32610
|
+
definition_exact_answer_segment: 1,
|
|
32611
|
+
definition_completion_specificity: 0.95,
|
|
32612
|
+
row_label_segment: 0.95,
|
|
32613
|
+
bounded_list_segment: 0.95,
|
|
32614
|
+
ordinal_list_segment: 0.9,
|
|
32615
|
+
drug_dose_segment: 0.9,
|
|
32616
|
+
frequency_polarity_segment: 0.9,
|
|
32617
|
+
frequency_polarity_list_item: 0.95,
|
|
32618
|
+
clinical_course_cue_segment: 0.9,
|
|
32619
|
+
recommendation_block_segment: 0.85,
|
|
32620
|
+
recommendation_item_segment: 0.85,
|
|
32621
|
+
explicit_recommendation_target_segment: 0.85,
|
|
32622
|
+
numeric_condition_less_than: 0.85,
|
|
32623
|
+
numeric_condition_more_than: 0.85,
|
|
32624
|
+
numeric_condition_equal: 0.85,
|
|
32625
|
+
conditioned_number_segment: 0.8,
|
|
32626
|
+
cloze_gap_local: 0.8
|
|
32627
|
+
};
|
|
32628
|
+
var SELECTION_STRUCTURAL_EVIDENCE_WEIGHTS = new Map(Object.entries(SELECTION_STRUCTURAL_EVIDENCE_WEIGHTS_RECORD));
|
|
32629
|
+
var CONFIDENCE_STRUCTURAL_EVIDENCE_KINDS = /* @__PURE__ */ new Set([
|
|
32630
|
+
"coordinate_table_row",
|
|
32631
|
+
"coordinate_table_group",
|
|
32632
|
+
"coordinate_table_group_inverse",
|
|
32633
|
+
"coordinate_table_multicell_row",
|
|
32634
|
+
"coordinate_table_membership",
|
|
32635
|
+
"parenthetical_group_segment",
|
|
32636
|
+
"preceding_question_label",
|
|
32637
|
+
"question_continuation_list",
|
|
32638
|
+
"exact_numeric_option_segment",
|
|
32639
|
+
"exact_hour_alias_segment",
|
|
32640
|
+
"visual_table_column",
|
|
32641
|
+
"exact_short_label_visual_row",
|
|
32642
|
+
"short_label_visual_row",
|
|
32643
|
+
"answer_ordinal_row",
|
|
32644
|
+
"fibrosis_stage_row",
|
|
32645
|
+
"gene_sentence_segment",
|
|
32646
|
+
"clinical_feature_segment",
|
|
32647
|
+
"mkb_class_exclusion_absent",
|
|
32648
|
+
"classification_code_segment",
|
|
32649
|
+
"label_number_proximity",
|
|
32650
|
+
"label_definition_segment",
|
|
32651
|
+
"definition_exact_answer_segment",
|
|
32652
|
+
"definition_completion_specificity",
|
|
32653
|
+
"row_label_segment",
|
|
32654
|
+
"bounded_list_segment",
|
|
32655
|
+
"ordinal_list_segment",
|
|
32656
|
+
"drug_dose_segment",
|
|
32657
|
+
"frequency_polarity_segment",
|
|
32658
|
+
"frequency_polarity_list_item",
|
|
32659
|
+
"clinical_course_cue_segment",
|
|
32660
|
+
"recommendation_block_segment",
|
|
32661
|
+
"recommendation_item_segment",
|
|
32662
|
+
"explicit_recommendation_target_segment",
|
|
32663
|
+
"numeric_condition_less_than",
|
|
32664
|
+
"numeric_condition_more_than",
|
|
32665
|
+
"numeric_condition_equal",
|
|
32666
|
+
"conditioned_number_segment",
|
|
32667
|
+
"cloze_gap_local"
|
|
32668
|
+
]);
|
|
32669
|
+
var BROAD_EVIDENCE_KINDS = /* @__PURE__ */ new Set([
|
|
32670
|
+
"bm25_question_answer",
|
|
32671
|
+
"question_chunk_answer",
|
|
32672
|
+
"answer_chunk_question",
|
|
32673
|
+
"answer_window",
|
|
32674
|
+
"focused_answer_window",
|
|
32675
|
+
"shared_multi_segment"
|
|
32676
|
+
]);
|
|
32677
|
+
var DIAGNOSTIC_BROAD_EVIDENCE_KINDS = /* @__PURE__ */ new Set([...BROAD_EVIDENCE_KINDS, "answer_directional_window"]);
|
|
32678
|
+
var NOISY_SHARED_EVIDENCE_KINDS = /* @__PURE__ */ new Set(["question_chunk_answer", "bm25_question_answer", "shared_multi_segment"]);
|
|
32679
|
+
|
|
32584
32680
|
// src/predictor/text-utils.ts
|
|
32585
32681
|
function nearestCueName(local, entries) {
|
|
32586
32682
|
const center = Math.floor(local.length / 2);
|
|
@@ -32996,6 +33092,11 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
32996
33092
|
"\u0434\u043E\u0437\u0430",
|
|
32997
33093
|
"\u0434\u043E\u0437\u044B",
|
|
32998
33094
|
"\u0434\u043E\u0437\u0435",
|
|
33095
|
+
"\u0440\u0435\u043A\u043E\u043C\u0435\u043D\u0434\u0443\u0435\u043C\u0430\u044F",
|
|
33096
|
+
"\u0440\u0435\u043A\u043E\u043C\u0435\u043D\u0434\u0443\u0435\u043C\u044B\u0439",
|
|
33097
|
+
"\u0440\u0435\u043A\u043E\u043C\u0435\u043D\u0434\u0443\u0435\u0442\u0441\u044F",
|
|
33098
|
+
"\u043D\u0430\u0437\u043D\u0430\u0447\u0430\u0435\u0442\u0441\u044F",
|
|
33099
|
+
"\u043D\u0430\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435",
|
|
32999
33100
|
"\u043F\u0440\u0438",
|
|
33000
33101
|
"\u043B\u0435\u0447\u0435\u043D\u0438\u0438",
|
|
33001
33102
|
"\u043B\u0435\u0447\u0435\u043D\u0438\u044F",
|
|
@@ -33059,7 +33160,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33059
33160
|
}
|
|
33060
33161
|
function doseSlashNumbers(sourceText, drugTokens) {
|
|
33061
33162
|
const out = [];
|
|
33062
|
-
const slashPattern = /(\d+(?:[.,]\d+)?)\s*\/\s*(\d+(?:[.,]\d+)?)\s
|
|
33163
|
+
const slashPattern = /(\d+(?:[.,]\d+)?)\s*\/\s*(\d+(?:[.,]\d+)?)\s*[\u006d\u043c]\u0433/giu;
|
|
33063
33164
|
for (const match of sourceText.matchAll(slashPattern)) {
|
|
33064
33165
|
const rawIndex = match.index ?? 0;
|
|
33065
33166
|
const beforeText = sourceText.slice(Math.max(0, rawIndex - 150), rawIndex);
|
|
@@ -33088,7 +33189,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33088
33189
|
if (drugIndex < 0) return [];
|
|
33089
33190
|
const local = normalized.slice(drugIndex, Math.min(normalized.length, drugIndex + 95));
|
|
33090
33191
|
if (!containsNormalizedPhrase(local, "\u043C\u0433")) return [];
|
|
33091
|
-
if (/\d+(?:[.,]\d+)?\s*\/\s*\d+(?:[.,]\d+)?\s*
|
|
33192
|
+
if (/\d+(?:[.,]\d+)?\s*\/\s*\d+(?:[.,]\d+)?\s*[\u006d\u043c][\u0433g]/iu.test(local)) return [];
|
|
33092
33193
|
const firstNumber = local.match(/\d+(?:[.,]\d+)?/u);
|
|
33093
33194
|
if (!firstNumber || (firstNumber.index ?? 0) > 55) return [];
|
|
33094
33195
|
if (local.slice(0, firstNumber.index ?? 0).includes("+")) return [];
|
|
@@ -33102,6 +33203,21 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33102
33203
|
if (hasOtherDrugMarker) return [];
|
|
33103
33204
|
return extractNumbers(local).slice(0, 2).map((number) => String(number).replace(",", "."));
|
|
33104
33205
|
}
|
|
33206
|
+
function doseAssignedToDrugNumbers(sourceText, drugTokens) {
|
|
33207
|
+
const normalized = normalizeForSearch(sourceText);
|
|
33208
|
+
const out = [];
|
|
33209
|
+
const dosePattern = /(\d+(?:[.,]\d+)?)\s*[\u006d\u043c]\u0433/giu;
|
|
33210
|
+
for (const match of normalized.matchAll(dosePattern)) {
|
|
33211
|
+
const index = match.index ?? 0;
|
|
33212
|
+
if (normalized.slice(Math.max(0, index - 2), index).includes("/")) continue;
|
|
33213
|
+
const afterWindow = normalized.slice(index + match[0].length, Math.min(normalized.length, index + match[0].length + 70));
|
|
33214
|
+
const boundary = afterWindow.search(/[+.]|(?:^|\s)o\s|\s\d+(?:[.,]\d+)?\s*[\u0440p]\s*\/?\s*\u0434/u);
|
|
33215
|
+
const after = boundary >= 0 ? afterWindow.slice(0, boundary) : afterWindow;
|
|
33216
|
+
if (softCoverage(drugTokens, tokenizeNormalized(after)) < 0.8) continue;
|
|
33217
|
+
out.push(normalizeDoseNumber(match[1]));
|
|
33218
|
+
}
|
|
33219
|
+
return out;
|
|
33220
|
+
}
|
|
33105
33221
|
function normalizeDoseNumber(value) {
|
|
33106
33222
|
return String(value ?? "").replace(",", ".").replace(/\.0$/u, "");
|
|
33107
33223
|
}
|
|
@@ -33120,12 +33236,22 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33120
33236
|
const normalized = normalizeForSearch(sourceText);
|
|
33121
33237
|
const drugIndex = drugTokenIndex(normalized, drugTokens);
|
|
33122
33238
|
if (drugIndex < 0) return [];
|
|
33239
|
+
const assignedNumbers = doseAssignedToDrugNumbers(sourceText, drugTokens);
|
|
33240
|
+
if (assignedNumbers.length) {
|
|
33241
|
+
return assignedNumbers.map((number) => ({ dose: number, doseRange: null, frequency: null }));
|
|
33242
|
+
}
|
|
33123
33243
|
const local = normalized.slice(drugIndex, Math.min(normalized.length, drugIndex + 125));
|
|
33124
33244
|
const facts = [];
|
|
33245
|
+
const slashNumbers = doseSlashNumbers(sourceText, drugTokens);
|
|
33246
|
+
if (slashNumbers.length) {
|
|
33247
|
+
return slashNumbers.map((number) => ({ dose: normalizeDoseNumber(number), doseRange: null, frequency: null }));
|
|
33248
|
+
}
|
|
33125
33249
|
const dosePattern = /(\d+(?:[.,]\d+)?)(?:\s*-\s*(\d+(?:[.,]\d+)?))?\s*[\u006d\u043c]\u0433(?:\s*[\u0078\u0445]\s*(\d+(?:[.,]\d+)?))?/giu;
|
|
33126
33250
|
for (const match of local.matchAll(dosePattern)) {
|
|
33127
33251
|
const index = match.index ?? 0;
|
|
33128
33252
|
if (index > 80) continue;
|
|
33253
|
+
const beforeNumber = local.slice(0, index).replace(/\s+$/u, "");
|
|
33254
|
+
if (beforeNumber.endsWith("/")) continue;
|
|
33129
33255
|
facts.push({
|
|
33130
33256
|
dose: normalizeDoseNumber(match[2] ?? match[1]),
|
|
33131
33257
|
doseRange: match[2] ? [normalizeDoseNumber(match[1]), normalizeDoseNumber(match[2])] : null,
|
|
@@ -33133,7 +33259,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
33133
33259
|
});
|
|
33134
33260
|
break;
|
|
33135
33261
|
}
|
|
33136
|
-
for (const number of
|
|
33262
|
+
for (const number of doseNearDrugNumbers(sourceText, drugTokens)) {
|
|
33137
33263
|
facts.push({ dose: normalizeDoseNumber(number), doseRange: null, frequency: null });
|
|
33138
33264
|
}
|
|
33139
33265
|
return facts;
|
|
@@ -35272,6 +35398,220 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
35272
35398
|
}
|
|
35273
35399
|
return best;
|
|
35274
35400
|
}
|
|
35401
|
+
function broadRecommendationQuestion(question) {
|
|
35402
|
+
const normalized = normalizeForSearch(question);
|
|
35403
|
+
return containsNormalizedPhrase(normalized, "\u0440\u0435\u043A\u043E\u043C\u0435\u043D\u0434") || containsNormalizedPhrase(normalized, "\u043D\u0430\u0437\u043D\u0430\u0447") || containsNormalizedPhrase(normalized, "\u043F\u0440\u043E\u0432\u043E\u0434") || containsNormalizedPhrase(normalized, "\u043B\u0435\u0447\u0435\u043D") || containsNormalizedPhrase(normalized, "\u0442\u0435\u0440\u0430\u043F") || containsNormalizedPhrase(normalized, "\u043F\u0440\u043E\u0444\u0438\u043B\u0430\u043A\u0442");
|
|
35404
|
+
}
|
|
35405
|
+
function recommendationCueSegment(segmentNorm) {
|
|
35406
|
+
return containsNormalizedPhrase(segmentNorm, "\u0440\u0435\u043A\u043E\u043C\u0435\u043D\u0434") || containsNormalizedPhrase(segmentNorm, "\u043D\u0430\u0437\u043D\u0430\u0447") || containsNormalizedPhrase(segmentNorm, "\u043F\u0440\u043E\u0432\u043E\u0434") || containsNormalizedPhrase(segmentNorm, "\u043F\u0440\u0438\u043C\u0435\u043D");
|
|
35407
|
+
}
|
|
35408
|
+
function bestRecommendationBlockSupport({ mode, pages, topQuestionPages, question, answer, answerTokens }) {
|
|
35409
|
+
if (mode !== "multi") return null;
|
|
35410
|
+
if (!broadRecommendationQuestion(question)) return null;
|
|
35411
|
+
const questionNorm = normalizeForSearch(question);
|
|
35412
|
+
if (containsNormalizedPhrase(questionNorm, "\u043D\u0430\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435")) return null;
|
|
35413
|
+
const qTokens = recommendationQuestionTokens(question);
|
|
35414
|
+
if (qTokens.length < 3) return null;
|
|
35415
|
+
let best = null;
|
|
35416
|
+
for (const segment of recommendationSegments(pages)) {
|
|
35417
|
+
if (topQuestionPages?.size && !topQuestionPages.has(segment.page)) continue;
|
|
35418
|
+
if (!recommendationCueSegment(segment.normalized)) continue;
|
|
35419
|
+
if (recommendationPresenceMismatch(answer.text, segment.normalized)) continue;
|
|
35420
|
+
const segmentTokens = tokenizeNormalized(segment.normalized);
|
|
35421
|
+
const qCoverage = recommendationQuestionCoverage(questionNorm, qTokens, segment.normalized);
|
|
35422
|
+
const qHits = tokenHitCount(qTokens, segmentTokens);
|
|
35423
|
+
if (qCoverage < 0.54 || qHits < Math.min(4, qTokens.length)) continue;
|
|
35424
|
+
const answerHit = recommendationSegmentAnswerHit(answer, answerTokens, segment.normalized, segmentTokens);
|
|
35425
|
+
if (!answerHit.supportHit) continue;
|
|
35426
|
+
const score = 12.4 + Math.min(1, qCoverage) * 4.6 + Math.min(5, qHits) * 0.7 + answerHit.answerCoverage * 4.8 + answerHit.numericCoverage * 1.8 + (answerHit.strongPhraseHit ? 2.4 : answerHit.phraseHit ? 1.2 : 0);
|
|
35427
|
+
best = betterEvidence(best, {
|
|
35428
|
+
answerId: answer.id,
|
|
35429
|
+
page: segment.page,
|
|
35430
|
+
text: segment.text,
|
|
35431
|
+
score,
|
|
35432
|
+
kind: "recommendation_block_segment"
|
|
35433
|
+
});
|
|
35434
|
+
}
|
|
35435
|
+
return best;
|
|
35436
|
+
}
|
|
35437
|
+
|
|
35438
|
+
// src/predictor/scorers/option-family.ts
|
|
35439
|
+
var LESS_CUES = ["\u0434\u043E", "\u043C\u0435\u043D\u0435\u0435", "\u043C\u0435\u043D\u044C\u0448\u0435", "\u043D\u0438\u0436\u0435", "\u043C\u043E\u043B\u043E\u0436\u0435"].map(
|
|
35440
|
+
(item) => normalizeForSearch(item)
|
|
35441
|
+
);
|
|
35442
|
+
var GREATER_CUES = ["\u0431\u043E\u043B\u0435\u0435", "\u0431\u043E\u043B\u044C\u0448\u0435", "\u0432\u044B\u0448\u0435", "\u0441\u0432\u044B\u0448\u0435", "\u0441\u0442\u0430\u0440\u0448\u0435"].map(
|
|
35443
|
+
(item) => normalizeForSearch(item)
|
|
35444
|
+
);
|
|
35445
|
+
var COMBO_QUESTION_CUES = [
|
|
35446
|
+
"\u0440\u0435\u043A\u043E\u043C\u0435\u043D\u0434",
|
|
35447
|
+
"\u043D\u0430\u0437\u043D\u0430\u0447",
|
|
35448
|
+
"\u043F\u0440\u0438\u043C\u0435\u043D",
|
|
35449
|
+
"\u0442\u0435\u0440\u0430\u043F",
|
|
35450
|
+
"\u043B\u0435\u0447\u0435\u043D"
|
|
35451
|
+
].map((item) => normalizeForSearch(item));
|
|
35452
|
+
var COMBO_GENERIC_TOKENS = new Set(
|
|
35453
|
+
[
|
|
35454
|
+
"\u043C\u043E\u043D\u043E\u0442\u0435\u0440\u0430\u043F\u0438\u044F",
|
|
35455
|
+
"\u043C\u043E\u043D\u043E\u0442\u0435\u0440\u0430\u043F\u0438\u044E",
|
|
35456
|
+
"\u043A\u043E\u043C\u0431\u0438\u043D\u0430\u0446\u0438\u044F",
|
|
35457
|
+
"\u043A\u043E\u043C\u0431\u0438\u043D\u0430\u0446\u0438\u044E",
|
|
35458
|
+
"\u0438\u043B\u0438",
|
|
35459
|
+
"\u0433\u0440\u0443\u043F\u043F",
|
|
35460
|
+
"\u043F\u0440\u0435\u043F\u0430\u0440\u0430\u0442",
|
|
35461
|
+
"\u043D\u0430\u0437\u043D\u0430\u0447",
|
|
35462
|
+
"\u043F\u0440\u0438\u043C\u0435\u043D"
|
|
35463
|
+
].flatMap((item) => uniqueTokens(item))
|
|
35464
|
+
);
|
|
35465
|
+
var COMBO_UNIT_PARTS = /* @__PURE__ */ new Set(["m\u0433", "m\u043B", "k\u0433", "me", "mm", "m\u0438h", "cyt", "\u0434h", "pa\u0437", "mg", "ml", "kg"]);
|
|
35466
|
+
function answerComparatorSpecs(answerText) {
|
|
35467
|
+
const normalized = normalizeForSearch(answerText);
|
|
35468
|
+
const numbers = extractNumbers(answerText).map((number) => number.replace(",", "."));
|
|
35469
|
+
const specs = [];
|
|
35470
|
+
for (const number of numbers) {
|
|
35471
|
+
const escaped = number.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
35472
|
+
const lessPattern = new RegExp(`(?:<|\\b(?:${LESS_CUES.join("|")})\\b\\s*)${escaped}(?:\\b|\\s|%|$)`, "iu");
|
|
35473
|
+
const greaterPattern = new RegExp(`(?:>|\\b(?:${GREATER_CUES.join("|")})\\b\\s*)${escaped}(?:\\b|\\s|%|$)`, "iu");
|
|
35474
|
+
if (lessPattern.test(normalized)) specs.push({ number, direction: "less" });
|
|
35475
|
+
if (greaterPattern.test(normalized)) specs.push({ number, direction: "greater" });
|
|
35476
|
+
}
|
|
35477
|
+
return specs;
|
|
35478
|
+
}
|
|
35479
|
+
function opposite(direction) {
|
|
35480
|
+
return direction === "less" ? "greater" : "less";
|
|
35481
|
+
}
|
|
35482
|
+
function answerFamilyHasOppositeComparator(answer, answers, spec) {
|
|
35483
|
+
return answers.some((candidate) => {
|
|
35484
|
+
if (candidate.id === answer.id) return false;
|
|
35485
|
+
return answerComparatorSpecs(candidate.text).some((candidateSpec) => candidateSpec.number === spec.number && candidateSpec.direction === opposite(spec.direction));
|
|
35486
|
+
});
|
|
35487
|
+
}
|
|
35488
|
+
function sourceDirectionsForNumber(text, number) {
|
|
35489
|
+
const normalized = normalizeForSearch(text).replace(/\u2264/gu, "<").replace(/\u2265/gu, ">");
|
|
35490
|
+
const escaped = number.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
35491
|
+
const directions = /* @__PURE__ */ new Set();
|
|
35492
|
+
const pattern = new RegExp(escaped, "giu");
|
|
35493
|
+
for (const match of normalized.matchAll(pattern)) {
|
|
35494
|
+
const index = match.index ?? 0;
|
|
35495
|
+
const before = normalized.slice(Math.max(0, index - 26), index).trim();
|
|
35496
|
+
const after = normalized.slice(index + match[0].length, Math.min(normalized.length, index + match[0].length + 12));
|
|
35497
|
+
const local = `${before} ${match[0]} ${after}`;
|
|
35498
|
+
const previous = before.split(/\s+/u).filter(Boolean).slice(-3).join(" ");
|
|
35499
|
+
if (/[<]\s*$/u.test(before) || LESS_CUES.some((cue) => containsNormalizedPhrase(previous, cue))) directions.add("less");
|
|
35500
|
+
if (/[>]\s*$/u.test(before) || GREATER_CUES.some((cue) => containsNormalizedPhrase(previous, cue))) directions.add("greater");
|
|
35501
|
+
if (containsNormalizedPhrase(local, normalizeForSearch(`\u043D\u0435 \u043C\u0435\u043D\u0435\u0435 ${number}`))) directions.add("greater");
|
|
35502
|
+
if (containsNormalizedPhrase(local, normalizeForSearch(`\u043D\u0435 \u0431\u043E\u043B\u0435\u0435 ${number}`))) directions.add("less");
|
|
35503
|
+
}
|
|
35504
|
+
return directions;
|
|
35505
|
+
}
|
|
35506
|
+
function optionFamilyComparatorAdjustment({
|
|
35507
|
+
answer,
|
|
35508
|
+
answers,
|
|
35509
|
+
evidence
|
|
35510
|
+
}) {
|
|
35511
|
+
const answerSpecs = answerComparatorSpecs(answer.text);
|
|
35512
|
+
if (answerSpecs.length !== 1) return { adjustment: 0, evidence: null };
|
|
35513
|
+
const specs = answerSpecs.filter((spec) => answerFamilyHasOppositeComparator(answer, answers, spec));
|
|
35514
|
+
if (!specs.length) return { adjustment: 0, evidence: null };
|
|
35515
|
+
for (const item of evidence) {
|
|
35516
|
+
if ((item.score ?? 0) < 5.5 || !item.text) continue;
|
|
35517
|
+
for (const spec of specs) {
|
|
35518
|
+
const sourceDirections = sourceDirectionsForNumber(item.text, spec.number);
|
|
35519
|
+
if (!sourceDirections.size || sourceDirections.has(spec.direction)) continue;
|
|
35520
|
+
if (!sourceDirections.has(opposite(spec.direction))) continue;
|
|
35521
|
+
return {
|
|
35522
|
+
adjustment: -4.2,
|
|
35523
|
+
evidence: {
|
|
35524
|
+
answerId: answer.id,
|
|
35525
|
+
page: item.page,
|
|
35526
|
+
text: item.text,
|
|
35527
|
+
score: Math.max(6.8, Math.min(12.5, item.score)),
|
|
35528
|
+
kind: "option_family_comparator_mismatch"
|
|
35529
|
+
}
|
|
35530
|
+
};
|
|
35531
|
+
}
|
|
35532
|
+
}
|
|
35533
|
+
return { adjustment: 0, evidence: null };
|
|
35534
|
+
}
|
|
35535
|
+
function compactComboPhrases(answerText) {
|
|
35536
|
+
const normalized = normalizeForSearch(answerText);
|
|
35537
|
+
const phrases = /* @__PURE__ */ new Set();
|
|
35538
|
+
for (const match of normalized.matchAll(/[a-z\u0430-\u044f0-9]{2,}(?:[+/][a-z\u0430-\u044f0-9]{2,})+/giu)) {
|
|
35539
|
+
if (validCompactComboPhrase(match[0])) phrases.add(match[0]);
|
|
35540
|
+
}
|
|
35541
|
+
return [...phrases].filter((phrase) => phrase.length >= 5);
|
|
35542
|
+
}
|
|
35543
|
+
function validCompactComboPhrase(phrase) {
|
|
35544
|
+
const parts = phrase.split(/[+/]/u).filter(Boolean);
|
|
35545
|
+
if (parts.length < 2) return false;
|
|
35546
|
+
return parts.every((part) => part.length >= 3 && part.length <= 10 && !COMBO_UNIT_PARTS.has(part) && !/^\d/u.test(part));
|
|
35547
|
+
}
|
|
35548
|
+
function comboQuestion(question) {
|
|
35549
|
+
const normalized = normalizeForSearch(question);
|
|
35550
|
+
return COMBO_QUESTION_CUES.some((cue) => normalized.includes(cue));
|
|
35551
|
+
}
|
|
35552
|
+
function alternativeComboTokens(answerText) {
|
|
35553
|
+
const normalized = normalizeForSearch(answerText);
|
|
35554
|
+
const alternative = containsNormalizedPhrase(normalized, "\u0438\u043B\u0438") || containsNormalizedPhrase(normalized, "\u043C\u043E\u043D\u043E\u0442\u0435\u0440\u0430\u043F");
|
|
35555
|
+
if (!alternative) return [];
|
|
35556
|
+
return uniqueTokens(answerText).filter((token) => token.length >= 3 && !/^\d/u.test(token) && !COMBO_GENERIC_TOKENS.has(token)).slice(0, 8);
|
|
35557
|
+
}
|
|
35558
|
+
function evidenceHasCompactTokenPair(text, tokens) {
|
|
35559
|
+
const normalized = normalizeForSearch(text);
|
|
35560
|
+
if (!/[+/]/u.test(normalized)) return false;
|
|
35561
|
+
for (let leftIndex = 0; leftIndex < tokens.length - 1; leftIndex += 1) {
|
|
35562
|
+
for (let rightIndex = leftIndex + 1; rightIndex < tokens.length; rightIndex += 1) {
|
|
35563
|
+
const left = tokens[leftIndex];
|
|
35564
|
+
const right = tokens[rightIndex];
|
|
35565
|
+
const leftHit = normalized.indexOf(left);
|
|
35566
|
+
const rightHit = normalized.indexOf(right);
|
|
35567
|
+
if (leftHit < 0 || rightHit < 0) continue;
|
|
35568
|
+
const start = Math.min(leftHit, rightHit);
|
|
35569
|
+
const end = Math.max(leftHit + left.length, rightHit + right.length);
|
|
35570
|
+
if (end - start > 56) continue;
|
|
35571
|
+
const local = normalized.slice(start, end);
|
|
35572
|
+
if (/[+/]/u.test(local) && !containsNormalizedPhrase(local, "\u0438\u043B\u0438")) return true;
|
|
35573
|
+
}
|
|
35574
|
+
}
|
|
35575
|
+
return false;
|
|
35576
|
+
}
|
|
35577
|
+
function optionFamilyCompactComboAdjustment({
|
|
35578
|
+
question,
|
|
35579
|
+
answer,
|
|
35580
|
+
evidence
|
|
35581
|
+
}) {
|
|
35582
|
+
if (!comboQuestion(question)) return { adjustment: 0, evidence: null };
|
|
35583
|
+
const comboPhrases = compactComboPhrases(answer.text);
|
|
35584
|
+
const alternativeTokens = alternativeComboTokens(answer.text);
|
|
35585
|
+
for (const item of evidence) {
|
|
35586
|
+
if ((item.score ?? 0) < 5.5 || !item.text) continue;
|
|
35587
|
+
const normalizedEvidence = normalizeForSearch(item.text);
|
|
35588
|
+
if (comboPhrases.some((phrase) => normalizedEvidence.includes(phrase))) {
|
|
35589
|
+
return {
|
|
35590
|
+
adjustment: 6.8,
|
|
35591
|
+
evidence: {
|
|
35592
|
+
answerId: answer.id,
|
|
35593
|
+
page: item.page,
|
|
35594
|
+
text: item.text,
|
|
35595
|
+
score: Math.max(9.2, Math.min(14.5, item.score + 1.1)),
|
|
35596
|
+
kind: "option_family_compact_combo_match"
|
|
35597
|
+
}
|
|
35598
|
+
};
|
|
35599
|
+
}
|
|
35600
|
+
if (alternativeTokens.length >= 2 && evidenceHasCompactTokenPair(item.text, alternativeTokens)) {
|
|
35601
|
+
return {
|
|
35602
|
+
adjustment: -6.4,
|
|
35603
|
+
evidence: {
|
|
35604
|
+
answerId: answer.id,
|
|
35605
|
+
page: item.page,
|
|
35606
|
+
text: item.text,
|
|
35607
|
+
score: Math.max(7.2, Math.min(13, item.score)),
|
|
35608
|
+
kind: "option_family_compact_combo_mismatch"
|
|
35609
|
+
}
|
|
35610
|
+
};
|
|
35611
|
+
}
|
|
35612
|
+
}
|
|
35613
|
+
return { adjustment: 0, evidence: null };
|
|
35614
|
+
}
|
|
35275
35615
|
|
|
35276
35616
|
// src/predictor/scorers/direction.ts
|
|
35277
35617
|
var POLARITY_UP_CUES = ["\u043F\u043E\u0432\u044B\u0448", "\u0443\u0432\u0435\u043B\u0438\u0447", "\u0432\u043E\u0437\u0440\u0430\u0441\u0442\u0430", "\u0440\u043E\u0441\u0442", "\u0432\u044B\u0441\u043E\u043A", "\u0431\u043E\u043B\u0435\u0435", "\u0432\u044B\u0448\u0435"].map((item) => normalizeForSearch(item));
|
|
@@ -35383,6 +35723,117 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
35383
35723
|
if (bestMismatch && (!bestMatch || bestMismatch.score > bestMatch.score + 0.4)) return { support: null, adjustment: -4.8, evidence: bestMismatch };
|
|
35384
35724
|
return { support: null, adjustment: 0, evidence: null };
|
|
35385
35725
|
}
|
|
35726
|
+
var CLINICAL_COURSE_CUE_GROUPS = [
|
|
35727
|
+
{
|
|
35728
|
+
target: "\u043E\u0441\u0442\u0440",
|
|
35729
|
+
opposite: ["\u0445\u0440\u043E\u043D", "\u0445\u0440\u043E\u043D\u0438\u0447"]
|
|
35730
|
+
},
|
|
35731
|
+
{
|
|
35732
|
+
target: "\u0445\u0440\u043E\u043D",
|
|
35733
|
+
opposite: ["\u043E\u0441\u0442\u0440"]
|
|
35734
|
+
}
|
|
35735
|
+
].map((group) => ({
|
|
35736
|
+
target: normalizeForSearch(group.target),
|
|
35737
|
+
opposite: group.opposite.map((item) => normalizeForSearch(item))
|
|
35738
|
+
}));
|
|
35739
|
+
function clinicalCourseCue(question) {
|
|
35740
|
+
const tokens = tokenize(question);
|
|
35741
|
+
for (const group of CLINICAL_COURSE_CUE_GROUPS) {
|
|
35742
|
+
if (tokens.some((token) => token.startsWith(group.target))) return group;
|
|
35743
|
+
}
|
|
35744
|
+
return null;
|
|
35745
|
+
}
|
|
35746
|
+
function clinicalCourseRelationQuestion(question) {
|
|
35747
|
+
const normalized = normalizeForSearch(question);
|
|
35748
|
+
if (containsNormalizedPhrase(normalized, "\u0440\u0435\u043A\u043E\u043C\u0435\u043D\u0434") || containsNormalizedPhrase(normalized, "\u043D\u0430\u0437\u043D\u0430\u0447")) {
|
|
35749
|
+
return false;
|
|
35750
|
+
}
|
|
35751
|
+
return [
|
|
35752
|
+
"\u043F\u0440\u043E\u044F\u0432\u043B",
|
|
35753
|
+
"\u0445\u0430\u0440\u0430\u043A\u0442\u0435\u0440",
|
|
35754
|
+
"\u0442\u0438\u043F\u0438\u0447",
|
|
35755
|
+
"\u043F\u0440\u0438\u0437\u043D\u0430\u043A",
|
|
35756
|
+
"\u0441\u0438\u043C\u043F\u0442\u043E\u043C"
|
|
35757
|
+
].some((cue) => normalized.includes(normalizeForSearch(cue)));
|
|
35758
|
+
}
|
|
35759
|
+
var CLINICAL_COURSE_GENERIC_BINDING_TOKENS = new Set(
|
|
35760
|
+
[
|
|
35761
|
+
"\u0442\u0435\u0447\u0435\u043D\u0438\u0435",
|
|
35762
|
+
"\u0442\u0435\u0447\u0435\u043D\u0438\u044F",
|
|
35763
|
+
"\u0444\u043E\u0440\u043C\u0430",
|
|
35764
|
+
"\u0444\u043E\u0440\u043C\u044B",
|
|
35765
|
+
"\u0431\u043E\u043B\u0435\u0437\u043D\u044C",
|
|
35766
|
+
"\u0431\u043E\u043B\u0435\u0437\u043D\u0438",
|
|
35767
|
+
"\u0433\u0435\u043F\u0430\u0442\u0438\u0442",
|
|
35768
|
+
"\u0441\u0438\u043C\u043F\u0442\u043E\u043C",
|
|
35769
|
+
"\u043F\u0440\u0438\u0437\u043D\u0430\u043A",
|
|
35770
|
+
"\u043F\u0440\u043E\u044F\u0432\u043B\u0435\u043D\u0438\u0435",
|
|
35771
|
+
"\u043F\u0440\u043E\u044F\u0432\u043B\u044F\u0442\u044C"
|
|
35772
|
+
].flatMap((item) => tokenize(item))
|
|
35773
|
+
);
|
|
35774
|
+
function clinicalCourseBindingTokens(answerTokens, questionTokens) {
|
|
35775
|
+
const questionSet = new Set(questionTokens);
|
|
35776
|
+
return answerTokens.filter(
|
|
35777
|
+
(token) => token.length >= 4 && /[а-яё]/u.test(token) && !FOCUS_STOPWORDS.has(token) && !questionSet.has(token) && !CLINICAL_COURSE_GENERIC_BINDING_TOKENS.has(token)
|
|
35778
|
+
);
|
|
35779
|
+
}
|
|
35780
|
+
function nearestClinicalCourseCueBeforeAnswer(tokens, bindingTokens, cueGroup) {
|
|
35781
|
+
let best = null;
|
|
35782
|
+
if (!bindingTokens.length) return null;
|
|
35783
|
+
for (let index = 0; index < tokens.length; index += 1) {
|
|
35784
|
+
const token = tokens[index];
|
|
35785
|
+
if (!bindingTokens.some((answerToken) => token === answerToken || token.startsWith(answerToken) || answerToken.startsWith(token))) continue;
|
|
35786
|
+
const start = Math.max(0, index - 10);
|
|
35787
|
+
for (let cursor = index - 1; cursor >= start; cursor -= 1) {
|
|
35788
|
+
const beforeToken = tokens[cursor];
|
|
35789
|
+
const distance = index - cursor;
|
|
35790
|
+
let type = null;
|
|
35791
|
+
if (beforeToken.startsWith(cueGroup.target)) type = "target";
|
|
35792
|
+
else if (cueGroup.opposite.some((opposite2) => beforeToken.startsWith(opposite2))) type = "opposite";
|
|
35793
|
+
if (!type) continue;
|
|
35794
|
+
if (!best || distance < best.distance) best = { type, distance };
|
|
35795
|
+
break;
|
|
35796
|
+
}
|
|
35797
|
+
}
|
|
35798
|
+
return best;
|
|
35799
|
+
}
|
|
35800
|
+
function clinicalCourseCueAdjustment({ mode, pages, topQuestionPages, question, questionTokens, focusTokens, answer, answerTokens }) {
|
|
35801
|
+
if (mode !== "single") return { support: null, adjustment: 0, evidence: null };
|
|
35802
|
+
if (!clinicalCourseRelationQuestion(question)) return { support: null, adjustment: 0, evidence: null };
|
|
35803
|
+
const cueGroup = clinicalCourseCue(question);
|
|
35804
|
+
if (!cueGroup) return { support: null, adjustment: 0, evidence: null };
|
|
35805
|
+
const bindingTokens = clinicalCourseBindingTokens(answerTokens, questionTokens);
|
|
35806
|
+
if (!bindingTokens.length) return { support: null, adjustment: 0, evidence: null };
|
|
35807
|
+
const usefulFocus = focusTokens?.length ? focusTokens : questionTokens;
|
|
35808
|
+
let bestMatch = null;
|
|
35809
|
+
let bestMismatch = null;
|
|
35810
|
+
for (const page of pages) {
|
|
35811
|
+
const topPage = topQuestionPages?.has(page.page);
|
|
35812
|
+
const adjacentTopPage = topQuestionPages?.has(page.page - 1) || topQuestionPages?.has(page.page + 1);
|
|
35813
|
+
if (topQuestionPages?.size && !topPage && !adjacentTopPage) continue;
|
|
35814
|
+
for (const segment of cachedLineWindowSegments(page)) {
|
|
35815
|
+
const focusCoverage = coverage(usefulFocus, segment.tokens);
|
|
35816
|
+
if (focusCoverage < 0.12) continue;
|
|
35817
|
+
const binding = nearestClinicalCourseCueBeforeAnswer(segment.tokens, bindingTokens, cueGroup);
|
|
35818
|
+
if (!binding) continue;
|
|
35819
|
+
const answerHits = tokenHitCount(bindingTokens, segment.tokens);
|
|
35820
|
+
if (answerHits < Math.min(2, bindingTokens.length)) continue;
|
|
35821
|
+
const score = 9.2 + Math.min(0.5, focusCoverage) * 5 + Math.min(3, answerHits) * 0.7 + Math.max(0, 10 - binding.distance) * 0.12;
|
|
35822
|
+
const evidence = {
|
|
35823
|
+
answerId: answer.id,
|
|
35824
|
+
page: page.page,
|
|
35825
|
+
text: segment.text,
|
|
35826
|
+
score,
|
|
35827
|
+
kind: binding.type === "target" ? "clinical_course_cue_segment" : "clinical_course_cue_mismatch"
|
|
35828
|
+
};
|
|
35829
|
+
if (binding.type === "target") bestMatch = betterEvidence(bestMatch, evidence);
|
|
35830
|
+
else bestMismatch = betterEvidence(bestMismatch, evidence);
|
|
35831
|
+
}
|
|
35832
|
+
}
|
|
35833
|
+
if (bestMatch && (!bestMismatch || bestMatch.score >= bestMismatch.score - 0.6)) return { support: bestMatch, adjustment: 0, evidence: null };
|
|
35834
|
+
if (bestMismatch && (!bestMatch || bestMismatch.score > bestMatch.score + 0.6)) return { support: null, adjustment: -6.8, evidence: bestMismatch };
|
|
35835
|
+
return { support: null, adjustment: 0, evidence: null };
|
|
35836
|
+
}
|
|
35386
35837
|
var CONTRAST_CUE_GROUPS = [
|
|
35387
35838
|
{
|
|
35388
35839
|
answer: ["\u0432\u0435\u0440\u0445\u043D"],
|
|
@@ -36885,52 +37336,6 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
36885
37336
|
}
|
|
36886
37337
|
|
|
36887
37338
|
// src/predictor/selection.ts
|
|
36888
|
-
var STRUCTURAL_EVIDENCE_WEIGHTS = new Map(
|
|
36889
|
-
Object.entries({
|
|
36890
|
-
coordinate_table_row: 1.25,
|
|
36891
|
-
coordinate_table_group: 1.25,
|
|
36892
|
-
coordinate_table_group_inverse: 1.25,
|
|
36893
|
-
coordinate_table_multicell_row: 1.25,
|
|
36894
|
-
coordinate_table_membership: 1.15,
|
|
36895
|
-
parenthetical_group_segment: 1.05,
|
|
36896
|
-
preceding_question_label: 1.05,
|
|
36897
|
-
question_continuation_list: 1.05,
|
|
36898
|
-
exact_numeric_option_segment: 1.05,
|
|
36899
|
-
exact_hour_alias_segment: 1.05,
|
|
36900
|
-
short_medical_alias_segment: 0.9,
|
|
36901
|
-
visual_table_column: 1.2,
|
|
36902
|
-
exact_short_label_visual_row: 1.15,
|
|
36903
|
-
short_label_visual_row: 1.05,
|
|
36904
|
-
answer_ordinal_row: 1.05,
|
|
36905
|
-
fibrosis_stage_row: 1.2,
|
|
36906
|
-
gene_sentence_segment: 1.1,
|
|
36907
|
-
clinical_feature_segment: 1,
|
|
36908
|
-
mkb_class_exclusion_absent: 1,
|
|
36909
|
-
classification_code_segment: 1.15,
|
|
36910
|
-
label_number_proximity: 1,
|
|
36911
|
-
label_definition_segment: 1,
|
|
36912
|
-
row_label_segment: 0.95,
|
|
36913
|
-
bounded_list_segment: 0.95,
|
|
36914
|
-
ordinal_list_segment: 0.9,
|
|
36915
|
-
drug_dose_segment: 0.9,
|
|
36916
|
-
recommendation_item_segment: 0.85,
|
|
36917
|
-
explicit_recommendation_target_segment: 0.85,
|
|
36918
|
-
numeric_condition_less_than: 0.85,
|
|
36919
|
-
numeric_condition_more_than: 0.85,
|
|
36920
|
-
numeric_condition_equal: 0.85,
|
|
36921
|
-
conditioned_number_segment: 0.8,
|
|
36922
|
-
cloze_gap_local: 0.8
|
|
36923
|
-
})
|
|
36924
|
-
);
|
|
36925
|
-
var BROAD_EVIDENCE_KINDS = /* @__PURE__ */ new Set([
|
|
36926
|
-
"bm25_question_answer",
|
|
36927
|
-
"question_chunk_answer",
|
|
36928
|
-
"answer_chunk_question",
|
|
36929
|
-
"answer_window",
|
|
36930
|
-
"focused_answer_window",
|
|
36931
|
-
"shared_multi_segment"
|
|
36932
|
-
]);
|
|
36933
|
-
var NOISY_SHARED_EVIDENCE_KINDS = /* @__PURE__ */ new Set(["question_chunk_answer", "bm25_question_answer", "shared_multi_segment"]);
|
|
36934
37339
|
function calibrateScores(answerScores) {
|
|
36935
37340
|
const rawValues = answerScores.map((item) => item.raw);
|
|
36936
37341
|
const max = Math.max(...rawValues, 1e-4);
|
|
@@ -37031,7 +37436,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
37031
37436
|
bestScore = score;
|
|
37032
37437
|
bestKind = evidence.kind;
|
|
37033
37438
|
}
|
|
37034
|
-
const weight =
|
|
37439
|
+
const weight = SELECTION_STRUCTURAL_EVIDENCE_WEIGHTS.get(evidence.kind) ?? 0;
|
|
37035
37440
|
if (weight > 0) {
|
|
37036
37441
|
bestStructuralScore = Math.max(bestStructuralScore, score);
|
|
37037
37442
|
structuralWeight = Math.max(structuralWeight, weight);
|
|
@@ -38963,6 +39368,256 @@ ${nextPage.text}`;
|
|
|
38963
39368
|
}
|
|
38964
39369
|
return best;
|
|
38965
39370
|
}
|
|
39371
|
+
function definitionQuestionLike(question) {
|
|
39372
|
+
const normalized = normalizeForSearch(question);
|
|
39373
|
+
return questionDefinitionTerm(question) || containsNormalizedPhrase(normalized, "\u044D\u0442\u043E") || containsNormalizedPhrase(normalized, "\u043F\u043E\u043D\u0438\u043C\u0430") || containsNormalizedPhrase(normalized, "\u043D\u0430\u0437\u044B\u0432\u0430");
|
|
39374
|
+
}
|
|
39375
|
+
function definitionCueWindow(normalized) {
|
|
39376
|
+
return containsNormalizedPhrase(normalized, "\u044D\u0442\u043E") || containsNormalizedPhrase(normalized, "\u043F\u043E\u043D\u0438\u043C\u0430") || containsNormalizedPhrase(normalized, "\u043D\u0430\u0437\u044B\u0432\u0430") || /(?:^|\s)[a-z\u0430-\u044f]{4,}\s+[-\u2013\u2014]\s+/iu.test(normalized);
|
|
39377
|
+
}
|
|
39378
|
+
function definitionExactFragments(text) {
|
|
39379
|
+
const fragments = String(text ?? "").split(/(?<=[.!?;])\s+/u).map((item) => item.trim()).filter((item) => item.length >= 20);
|
|
39380
|
+
return fragments.length ? fragments : [String(text ?? "")];
|
|
39381
|
+
}
|
|
39382
|
+
var DEFINITION_TERM_GENERIC_TOKENS = new Set(
|
|
39383
|
+
[
|
|
39384
|
+
"\u043F\u043E\u0434",
|
|
39385
|
+
"\u043F\u043E\u043D\u0438\u043C\u0430\u044E\u0442",
|
|
39386
|
+
"\u043F\u043E\u043D\u0438\u043C\u0430\u0435\u0442\u0441\u044F",
|
|
39387
|
+
"\u044D\u0442\u043E",
|
|
39388
|
+
"\u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044F",
|
|
39389
|
+
"\u043F\u0440\u0438\u0437\u043D\u0430\u043A"
|
|
39390
|
+
].flatMap((item) => uniqueTokens(item))
|
|
39391
|
+
);
|
|
39392
|
+
function primaryDefinitionTermToken(question) {
|
|
39393
|
+
const term = questionDefinitionTerm(question);
|
|
39394
|
+
const tokens = uniqueTokens(term ?? question).filter((token) => token.length >= 4 && !DEFINITION_TERM_GENERIC_TOKENS.has(token));
|
|
39395
|
+
return tokens[0] ?? "";
|
|
39396
|
+
}
|
|
39397
|
+
function editDistanceAtMostOne(left, right) {
|
|
39398
|
+
if (left === right) return true;
|
|
39399
|
+
if (Math.abs(left.length - right.length) > 1) return false;
|
|
39400
|
+
let edits = 0;
|
|
39401
|
+
let i = 0;
|
|
39402
|
+
let j = 0;
|
|
39403
|
+
while (i < left.length && j < right.length) {
|
|
39404
|
+
if (left[i] === right[j]) {
|
|
39405
|
+
i += 1;
|
|
39406
|
+
j += 1;
|
|
39407
|
+
continue;
|
|
39408
|
+
}
|
|
39409
|
+
edits += 1;
|
|
39410
|
+
if (edits > 1) return false;
|
|
39411
|
+
if (left.length > right.length) i += 1;
|
|
39412
|
+
else if (right.length > left.length) j += 1;
|
|
39413
|
+
else {
|
|
39414
|
+
i += 1;
|
|
39415
|
+
j += 1;
|
|
39416
|
+
}
|
|
39417
|
+
}
|
|
39418
|
+
return edits + (left.length - i) + (right.length - j) <= 1;
|
|
39419
|
+
}
|
|
39420
|
+
function definitionFragmentMatchesQuestionTerm(fragmentTokens, primaryTerm) {
|
|
39421
|
+
if (!primaryTerm) return true;
|
|
39422
|
+
const cueIndex = fragmentTokens.findIndex((token) => token === normalizeForSearch("\u044D\u0442\u043E"));
|
|
39423
|
+
const labelTokens = fragmentTokens.slice(0, cueIndex >= 0 ? cueIndex : Math.min(3, fragmentTokens.length));
|
|
39424
|
+
return labelTokens.some((token) => token.length >= 4 && editDistanceAtMostOne(token, primaryTerm));
|
|
39425
|
+
}
|
|
39426
|
+
function bestDefinitionExactAnswerSupport({ mode, pages, topQuestionPages, question, answer, answerTokens }) {
|
|
39427
|
+
if (mode !== "single" || !definitionQuestionLike(question)) return null;
|
|
39428
|
+
const answerPhrases = answerSearchPhrases(answer.text).slice(0, 12);
|
|
39429
|
+
const primaryTerm = primaryDefinitionTermToken(question);
|
|
39430
|
+
let best = null;
|
|
39431
|
+
for (const page of pages) {
|
|
39432
|
+
if (topQuestionPages?.size && !topQuestionPages.has(page.page) && !topQuestionPages.has(page.page - 1) && !topQuestionPages.has(page.page + 1)) {
|
|
39433
|
+
continue;
|
|
39434
|
+
}
|
|
39435
|
+
for (const source of cachedLineWindowSegments(page)) {
|
|
39436
|
+
for (const fragment of definitionExactFragments(source.text)) {
|
|
39437
|
+
const normalized = normalizeForSearch(fragment);
|
|
39438
|
+
if (!definitionCueWindow(normalized)) continue;
|
|
39439
|
+
const fragmentTokens = tokenizeNormalized(normalized);
|
|
39440
|
+
if (!definitionFragmentMatchesQuestionTerm(fragmentTokens, primaryTerm)) continue;
|
|
39441
|
+
const phraseHit = answerPhrases.some((phrase) => containsNormalizedPhrase(normalized, phrase));
|
|
39442
|
+
const answerCoverage = strictSoftCoverage(answerTokens, fragmentTokens);
|
|
39443
|
+
if (!phraseHit || answerCoverage < 0.72) continue;
|
|
39444
|
+
const score = 15.2 + answerCoverage * 6 + numberCoverage(answer.text, normalized) * 0.8;
|
|
39445
|
+
best = betterEvidence(best, {
|
|
39446
|
+
answerId: answer.id,
|
|
39447
|
+
page: page.page,
|
|
39448
|
+
text: fragment,
|
|
39449
|
+
score,
|
|
39450
|
+
kind: "definition_exact_answer_segment"
|
|
39451
|
+
});
|
|
39452
|
+
}
|
|
39453
|
+
}
|
|
39454
|
+
}
|
|
39455
|
+
return best;
|
|
39456
|
+
}
|
|
39457
|
+
var DEFINITION_COMPLETION_EVIDENCE = /* @__PURE__ */ new Set(["definition_exact_answer_segment", "term_definition_segment", "label_definition_segment"]);
|
|
39458
|
+
function definitionCompletionAdjustment({ mode, question, answer, answers, answerTokens }, evidence) {
|
|
39459
|
+
if (mode !== "single" || !definitionQuestionLike(question)) return { adjustment: 0, evidence: null };
|
|
39460
|
+
const definitionEvidence = evidence.find((item) => DEFINITION_COMPLETION_EVIDENCE.has(item.kind) && (item.score ?? 0) >= 18);
|
|
39461
|
+
if (!definitionEvidence) return { adjustment: 0, evidence: null };
|
|
39462
|
+
const answerNorm = normalizeForSearch(answer.text);
|
|
39463
|
+
if (answerTokens.length < 5 || answerNorm.length < 32) return { adjustment: 0, evidence: null };
|
|
39464
|
+
let contained = 0;
|
|
39465
|
+
for (const candidate of answers) {
|
|
39466
|
+
if (candidate.id === answer.id) continue;
|
|
39467
|
+
const candidateNorm = normalizeForSearch(candidate.text);
|
|
39468
|
+
if (candidateNorm.length < 18 || candidateNorm === answerNorm) continue;
|
|
39469
|
+
const candidateTokens = uniqueTokens(candidate.text);
|
|
39470
|
+
if (candidateTokens.length < 3 || candidateTokens.length >= answerTokens.length) continue;
|
|
39471
|
+
if (answerNorm.includes(candidateNorm)) contained += 1;
|
|
39472
|
+
}
|
|
39473
|
+
if (!contained) return { adjustment: 0, evidence: null };
|
|
39474
|
+
const adjustment = Math.min(5, contained * 2.4);
|
|
39475
|
+
return {
|
|
39476
|
+
adjustment,
|
|
39477
|
+
evidence: {
|
|
39478
|
+
answerId: answer.id,
|
|
39479
|
+
page: definitionEvidence.page,
|
|
39480
|
+
text: definitionEvidence.text,
|
|
39481
|
+
score: Math.max(8.5, Math.min(14.5, definitionEvidence.score)),
|
|
39482
|
+
kind: "definition_completion_specificity"
|
|
39483
|
+
}
|
|
39484
|
+
};
|
|
39485
|
+
}
|
|
39486
|
+
var FREQUENCY_POLARITY_HIGH_CUES = [
|
|
39487
|
+
"\u043D\u0430\u0438\u0431\u043E\u043B\u0435\u0435 \u0447\u0430\u0441\u0442",
|
|
39488
|
+
"\u0441\u0430\u043C\u043E\u0439 \u0447\u0430\u0441\u0442",
|
|
39489
|
+
"\u0441\u0430\u043C\u044B\u043C \u0447\u0430\u0441\u0442",
|
|
39490
|
+
"\u0447\u0430\u0441\u0442\u043E \u0432\u0441\u0442\u0440\u0435\u0447",
|
|
39491
|
+
"\u0447\u0430\u0449\u0435",
|
|
39492
|
+
"\u0432\u0435\u0434\u0443\u0449"
|
|
39493
|
+
];
|
|
39494
|
+
var FREQUENCY_POLARITY_LOW_CUES = [
|
|
39495
|
+
"\u0440\u0435\u0434\u043A",
|
|
39496
|
+
"\u0440\u0435\u0436\u0435"
|
|
39497
|
+
];
|
|
39498
|
+
var FREQUENCY_POLARITY_GENERIC_FOCUS = new Set(
|
|
39499
|
+
[
|
|
39500
|
+
"\u043D\u0430\u0438\u0431\u043E\u043B\u0435\u0435",
|
|
39501
|
+
"\u0447\u0430\u0441\u0442\u044B\u0439",
|
|
39502
|
+
"\u0447\u0430\u0441\u0442\u0430\u044F",
|
|
39503
|
+
"\u0447\u0430\u0441\u0442\u043E\u0439",
|
|
39504
|
+
"\u0447\u0430\u0441\u0442\u043E\u0435",
|
|
39505
|
+
"\u0440\u0435\u0434\u043A\u0438\u0439",
|
|
39506
|
+
"\u0440\u0435\u0434\u043A\u0430\u044F",
|
|
39507
|
+
"\u0440\u0435\u0434\u043A\u043E\u0439",
|
|
39508
|
+
"\u0444\u043E\u0440\u043C\u0430",
|
|
39509
|
+
"\u0444\u043E\u0440\u043C\u043E\u0439",
|
|
39510
|
+
"\u0432\u0430\u0440\u0438\u0430\u043D\u0442",
|
|
39511
|
+
"\u0432\u0430\u0440\u0438\u0430\u043D\u0442\u043E\u043C",
|
|
39512
|
+
"\u0440\u043E\u043B\u044C",
|
|
39513
|
+
"\u043E\u0442\u0432\u043E\u0434\u0438\u0442\u0441\u044F",
|
|
39514
|
+
"\u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044F"
|
|
39515
|
+
].flatMap((item) => uniqueTokens(item))
|
|
39516
|
+
);
|
|
39517
|
+
function frequencyPolarity(normalized) {
|
|
39518
|
+
if (FREQUENCY_POLARITY_LOW_CUES.some((cue) => containsNormalizedPhrase(normalized, cue))) return "low";
|
|
39519
|
+
if (FREQUENCY_POLARITY_HIGH_CUES.some((cue) => containsNormalizedPhrase(normalized, cue))) return "high";
|
|
39520
|
+
return null;
|
|
39521
|
+
}
|
|
39522
|
+
function frequencyPolarityFocusTokens(focusTokens, answerTokens) {
|
|
39523
|
+
const answerSet = new Set(answerTokens ?? []);
|
|
39524
|
+
return (focusTokens ?? []).filter((token) => token.length >= 4 && !answerSet.has(token) && !FREQUENCY_POLARITY_GENERIC_FOCUS.has(token));
|
|
39525
|
+
}
|
|
39526
|
+
function containsPhraseOutsideParentheses(text, phrases) {
|
|
39527
|
+
const normalized = normalizeForSearch(String(text ?? "").replace(/\([^)]*\)/gu, " "));
|
|
39528
|
+
for (const phrase of phrases) {
|
|
39529
|
+
const normalizedPhrase = normalizeForSearch(phrase);
|
|
39530
|
+
if (!normalizedPhrase) continue;
|
|
39531
|
+
if (normalized.includes(normalizedPhrase)) return true;
|
|
39532
|
+
}
|
|
39533
|
+
return false;
|
|
39534
|
+
}
|
|
39535
|
+
function frequencyPolarityFragments(text) {
|
|
39536
|
+
const fragments = String(text ?? "").split(/(?<=[.!?;])\s+/u).map((item) => item.trim()).filter((item) => item.length >= 20);
|
|
39537
|
+
return fragments.length ? fragments : [String(text ?? "")];
|
|
39538
|
+
}
|
|
39539
|
+
function frequencyListItemLine(line) {
|
|
39540
|
+
return /^\s*(?:[•*\-]|\d+[.)]|[IVX]+[.)])\s+/iu.test(String(line ?? ""));
|
|
39541
|
+
}
|
|
39542
|
+
function frequencyPolarityListItems(pages, pageIndex, lineIndex) {
|
|
39543
|
+
const items = [];
|
|
39544
|
+
for (let offset = 0; offset <= 1; offset += 1) {
|
|
39545
|
+
const page = pages[pageIndex + offset];
|
|
39546
|
+
if (!page) continue;
|
|
39547
|
+
const start = offset === 0 ? lineIndex + 1 : 0;
|
|
39548
|
+
for (let index = start; index < (page.lines?.length ?? 0); index += 1) {
|
|
39549
|
+
const line = page.lines[index];
|
|
39550
|
+
if (!frequencyListItemLine(line)) {
|
|
39551
|
+
if (items.length) return items;
|
|
39552
|
+
continue;
|
|
39553
|
+
}
|
|
39554
|
+
items.push({ text: line, page: page.page });
|
|
39555
|
+
if (items.length >= 10) return items;
|
|
39556
|
+
}
|
|
39557
|
+
}
|
|
39558
|
+
return items;
|
|
39559
|
+
}
|
|
39560
|
+
function betterFrequencyListSupport(best, { pages, pageIndex, lineIndex, answer, answerPhrases, answerTokens, specificTokens, target }) {
|
|
39561
|
+
const page = pages[pageIndex];
|
|
39562
|
+
const heading = page.lines?.[lineIndex] ?? "";
|
|
39563
|
+
const headingNorm = normalizeForSearch(heading);
|
|
39564
|
+
if (frequencyPolarity(headingNorm) !== target) return best;
|
|
39565
|
+
const headingTokens = tokenizeNormalized(headingNorm);
|
|
39566
|
+
const headingFocusHits = tokenHitCount(specificTokens, headingTokens);
|
|
39567
|
+
if (specificTokens.length >= 2 && headingFocusHits <= 0) return best;
|
|
39568
|
+
for (const item of frequencyPolarityListItems(pages, pageIndex, lineIndex)) {
|
|
39569
|
+
if (!containsPhraseOutsideParentheses(item.text, answerPhrases)) continue;
|
|
39570
|
+
const itemTokens = tokenize(item.text);
|
|
39571
|
+
const answerCoverage = strictSoftCoverage(answerTokens, itemTokens);
|
|
39572
|
+
const score = 15.8 + answerCoverage * 4.4 + Math.min(2, headingFocusHits) * 1.2;
|
|
39573
|
+
best = betterEvidence(best, {
|
|
39574
|
+
answerId: answer.id,
|
|
39575
|
+
page: item.page,
|
|
39576
|
+
text: `${heading} ${item.text}`,
|
|
39577
|
+
score,
|
|
39578
|
+
kind: "frequency_polarity_list_item"
|
|
39579
|
+
});
|
|
39580
|
+
}
|
|
39581
|
+
return best;
|
|
39582
|
+
}
|
|
39583
|
+
function bestFrequencyPolaritySupport({ mode, pages, topQuestionPages, question, answer, answerTokens, focusTokens }) {
|
|
39584
|
+
if (mode !== "single") return null;
|
|
39585
|
+
const target = frequencyPolarity(normalizeForSearch(question));
|
|
39586
|
+
if (!target) return null;
|
|
39587
|
+
const answerPhrases = answerSearchPhrases(answer.text).slice(0, 16);
|
|
39588
|
+
const specificTokens = frequencyPolarityFocusTokens(focusTokens, answerTokens);
|
|
39589
|
+
let best = null;
|
|
39590
|
+
for (let pageIndex = 0; pageIndex < pages.length; pageIndex += 1) {
|
|
39591
|
+
const page = pages[pageIndex];
|
|
39592
|
+
if (topQuestionPages?.size && !topQuestionPages.has(page.page) && !topQuestionPages.has(page.page - 1) && !topQuestionPages.has(page.page + 1)) {
|
|
39593
|
+
continue;
|
|
39594
|
+
}
|
|
39595
|
+
for (let lineIndex = 0; lineIndex < (page.lines?.length ?? 0); lineIndex += 1) {
|
|
39596
|
+
best = betterFrequencyListSupport(best, { pages, pageIndex, lineIndex, answer, answerPhrases, answerTokens, specificTokens, target });
|
|
39597
|
+
}
|
|
39598
|
+
for (const segment of cachedLineWindowSegments(page)) {
|
|
39599
|
+
for (const fragment of frequencyPolarityFragments(segment.text)) {
|
|
39600
|
+
const normalized = normalizeForSearch(fragment);
|
|
39601
|
+
if (frequencyPolarity(normalized) !== target) continue;
|
|
39602
|
+
const phraseHit = containsPhraseOutsideParentheses(fragment, answerPhrases);
|
|
39603
|
+
if (!phraseHit) continue;
|
|
39604
|
+
const fragmentTokens = tokenizeNormalized(normalized);
|
|
39605
|
+
const answerCoverage = strictSoftCoverage(answerTokens, fragmentTokens);
|
|
39606
|
+
const focusHits = tokenHitCount(specificTokens, fragmentTokens);
|
|
39607
|
+
if (specificTokens.length >= 2 && focusHits <= 0) continue;
|
|
39608
|
+
const score = 12.2 + (phraseHit ? 2.8 : 0) + answerCoverage * 4.2 + Math.min(2, focusHits) * 1.1;
|
|
39609
|
+
best = betterEvidence(best, {
|
|
39610
|
+
answerId: answer.id,
|
|
39611
|
+
page: page.page,
|
|
39612
|
+
text: fragment,
|
|
39613
|
+
score,
|
|
39614
|
+
kind: "frequency_polarity_segment"
|
|
39615
|
+
});
|
|
39616
|
+
}
|
|
39617
|
+
}
|
|
39618
|
+
}
|
|
39619
|
+
return best;
|
|
39620
|
+
}
|
|
38966
39621
|
function negatedAnswerPrefixAdjustment({ mode, pages, question, answer, answerTokens }) {
|
|
38967
39622
|
if (mode !== "single" || answerTokens.length < 2) return { adjustment: 0, evidence: null };
|
|
38968
39623
|
const questionNorm = normalizeForSearch(question);
|
|
@@ -40002,6 +40657,7 @@ ${nextPage.text}`;
|
|
|
40002
40657
|
const chunk = bestChunkSupport(context);
|
|
40003
40658
|
const polarity = polarityAdjustment(context);
|
|
40004
40659
|
const temporal = temporalCueAdjustment(context);
|
|
40660
|
+
const clinicalCourseCue2 = clinicalCourseCueAdjustment(context);
|
|
40005
40661
|
const conditionPair = conditionPairAdjustment(context);
|
|
40006
40662
|
const riskCondition = riskConditionAdjustment(context);
|
|
40007
40663
|
const genericPopulation = genericPopulationConditionAdjustmentForMode(context);
|
|
@@ -40019,10 +40675,13 @@ ${nextPage.text}`;
|
|
|
40019
40675
|
const ageEligibility = ageEligibilityAdjustment(context);
|
|
40020
40676
|
const drugDose = bestDrugDoseSupport(context);
|
|
40021
40677
|
const termDefinition = bestTermDefinitionSupport(context);
|
|
40678
|
+
const definitionExactAnswer = bestDefinitionExactAnswerSupport(context);
|
|
40679
|
+
const frequencyPolarity2 = bestFrequencyPolaritySupport(context);
|
|
40022
40680
|
const negatedAnswerPrefix = negatedAnswerPrefixAdjustment(context);
|
|
40023
40681
|
const impossibilityOnly = impossibilityOnlyAdjustment(context);
|
|
40024
40682
|
const activeTherapyIndication = activeTherapyIndicationAdjustment(context);
|
|
40025
40683
|
const recommendationItem = bestRecommendationItemSupport(context);
|
|
40684
|
+
const recommendationBlock = bestRecommendationBlockSupport(context);
|
|
40026
40685
|
const explicitRecommendationTarget = explicitRecommendationTargetAdjustment(context);
|
|
40027
40686
|
const conditionedNumber = bestConditionedNumberSupport(context);
|
|
40028
40687
|
const numericCondition = bestNumericConditionSupport(context);
|
|
@@ -40056,7 +40715,7 @@ ${nextPage.text}`;
|
|
|
40056
40715
|
const focusedWeight = context.mode === "multi" ? 0.15 : 0.9;
|
|
40057
40716
|
const lineTokenWeight = context.mode === "single" ? 0.85 : 0;
|
|
40058
40717
|
const latinFuzzyWeight = context.mode === "multi" && polarity.evidence?.kind !== "polarity_mismatch" ? 1.15 : 0;
|
|
40059
|
-
let raw = (anchor?.score ?? 0) * 1.35 + (section?.score ?? 0) * 1.2 + (rowLabel?.score ?? 0) * 0.95 + (focused?.score ?? 0) * focusedWeight + (lineToken?.score ?? 0) * lineTokenWeight + (prefix?.score ?? 0) * 1.15 + (phrase?.score ?? 0) * phraseWeight + (precedingLabel?.score ?? 0) * 1.3 + (exactAnswer?.score ?? 0) * 1.08 + (chunk?.score ?? 0) * 1 + polarity.adjustment + (temporal.support?.score ?? 0) * 1 + temporal.adjustment + conditionPair.adjustment + riskCondition.adjustment + genericPopulation.adjustment + (classSubject?.score ?? 0) * 1.15 + (frequency?.score ?? 0) * 1.1 + negativeLocal.adjustment + (boundedList.support?.score ?? 0) * 1.15 + boundedList.adjustment + (ordinalList?.score ?? 0) * 1.15 + (typeOrdinal?.score ?? 0) * 1.15 + (indicationLabel?.score ?? 0) * 1.15 + (labelDefinition?.score ?? 0) * 1.15 + (recommendationPolarity.support?.score ?? 0) * 1.05 + recommendationPolarity.adjustment + (exactNumericOption?.score ?? 0) * 1.04 + (exactHourAlias?.score ?? 0) * 1.08 + ageEligibility.adjustment + (drugDose?.score ?? 0) * 1.15 + (termDefinition?.score ?? 0) * 1.15 + negatedAnswerPrefix.adjustment + impossibilityOnly.adjustment + activeTherapyIndication.adjustment + (recommendationItem?.score ?? 0) * 1.1 + (explicitRecommendationTarget.support?.score ?? 0) * 1.05 + explicitRecommendationTarget.adjustment + (conditionedNumber?.score ?? 0) * 1.1 + (numericCondition?.score ?? 0) * 1.05 + (countRelation?.score ?? 0) * 1.1 + (ageForm?.score ?? 0) * 1.15 + (fibrosisStage?.score ?? 0) * 1.15 + (conditionNumber?.score ?? 0) * 1.15 + (romanStage?.score ?? 0) * 1.15 + (answerOrdinalRow?.score ?? 0) * 1.15 + (clozeGap?.score ?? 0) * 1.12 + (visualTableColumn?.score ?? 0) * 1.18 + (coordinateTableRow?.score ?? 0) * 1.12 + (coordinateTableGroup?.score ?? 0) * 1.16 + (coordinateMultiCellRow?.score ?? 0) * 1.16 + (coordinateTableMembership?.score ?? 0) * 1.1 + (parentheticalGroup?.score ?? 0) * 1.16 + (questionContinuationList?.score ?? 0) * 1.1 + (shortMedicalAlias?.score ?? 0) * 0.35 + (latinFuzzy?.score ?? 0) * latinFuzzyWeight + (geneSentence?.score ?? 0) * 1.18 + (clinicalFeature.support?.score ?? 0) * 1.12 + clinicalFeature.adjustment + (mkbClassExclusion.support?.score ?? 0) * 1.12 + mkbClassExclusion.adjustment + (labelNumber?.score ?? 0) * 1.15 + (classificationCode?.score ?? 0) * 1.15 + (exactShortLabelRow?.score ?? 0) * 1.2 + (shortLabelRow?.score ?? 0) * 1.15 + (answerPhraseFound ? 0.35 : 0) + (numbers.length ? numberSpecificity(context.answer.text) * 0.35 : 0) + Math.min(0.35, answerTokens.length * 0.015);
|
|
40718
|
+
let raw = (anchor?.score ?? 0) * 1.35 + (section?.score ?? 0) * 1.2 + (rowLabel?.score ?? 0) * 0.95 + (focused?.score ?? 0) * focusedWeight + (lineToken?.score ?? 0) * lineTokenWeight + (prefix?.score ?? 0) * 1.15 + (phrase?.score ?? 0) * phraseWeight + (precedingLabel?.score ?? 0) * 1.3 + (exactAnswer?.score ?? 0) * 1.08 + (chunk?.score ?? 0) * 1 + polarity.adjustment + (temporal.support?.score ?? 0) * 1 + temporal.adjustment + (clinicalCourseCue2.support?.score ?? 0) * 1.05 + clinicalCourseCue2.adjustment + conditionPair.adjustment + riskCondition.adjustment + genericPopulation.adjustment + (classSubject?.score ?? 0) * 1.15 + (frequency?.score ?? 0) * 1.1 + negativeLocal.adjustment + (boundedList.support?.score ?? 0) * 1.15 + boundedList.adjustment + (ordinalList?.score ?? 0) * 1.15 + (typeOrdinal?.score ?? 0) * 1.15 + (indicationLabel?.score ?? 0) * 1.15 + (labelDefinition?.score ?? 0) * 1.15 + (recommendationPolarity.support?.score ?? 0) * 1.05 + recommendationPolarity.adjustment + (exactNumericOption?.score ?? 0) * 1.04 + (exactHourAlias?.score ?? 0) * 1.08 + ageEligibility.adjustment + (drugDose?.score ?? 0) * 1.15 + (termDefinition?.score ?? 0) * 1.15 + (definitionExactAnswer?.score ?? 0) * 1.12 + (frequencyPolarity2?.score ?? 0) * 1.08 + negatedAnswerPrefix.adjustment + impossibilityOnly.adjustment + activeTherapyIndication.adjustment + (recommendationItem?.score ?? 0) * 1.1 + (recommendationBlock?.score ?? 0) * 0.92 + (explicitRecommendationTarget.support?.score ?? 0) * 1.05 + explicitRecommendationTarget.adjustment + (conditionedNumber?.score ?? 0) * 1.1 + (numericCondition?.score ?? 0) * 1.05 + (countRelation?.score ?? 0) * 1.1 + (ageForm?.score ?? 0) * 1.15 + (fibrosisStage?.score ?? 0) * 1.15 + (conditionNumber?.score ?? 0) * 1.15 + (romanStage?.score ?? 0) * 1.15 + (answerOrdinalRow?.score ?? 0) * 1.15 + (clozeGap?.score ?? 0) * 1.12 + (visualTableColumn?.score ?? 0) * 1.18 + (coordinateTableRow?.score ?? 0) * 1.12 + (coordinateTableGroup?.score ?? 0) * 1.16 + (coordinateMultiCellRow?.score ?? 0) * 1.16 + (coordinateTableMembership?.score ?? 0) * 1.1 + (parentheticalGroup?.score ?? 0) * 1.16 + (questionContinuationList?.score ?? 0) * 1.1 + (shortMedicalAlias?.score ?? 0) * 0.35 + (latinFuzzy?.score ?? 0) * latinFuzzyWeight + (geneSentence?.score ?? 0) * 1.18 + (clinicalFeature.support?.score ?? 0) * 1.12 + clinicalFeature.adjustment + (mkbClassExclusion.support?.score ?? 0) * 1.12 + mkbClassExclusion.adjustment + (labelNumber?.score ?? 0) * 1.15 + (classificationCode?.score ?? 0) * 1.15 + (exactShortLabelRow?.score ?? 0) * 1.2 + (shortLabelRow?.score ?? 0) * 1.15 + (answerPhraseFound ? 0.35 : 0) + (numbers.length ? numberSpecificity(context.answer.text) * 0.35 : 0) + Math.min(0.35, answerTokens.length * 0.015);
|
|
40060
40719
|
if (context.intent.listLike && context.anchorSegments?.length && !anchor) {
|
|
40061
40720
|
raw *= 0.62;
|
|
40062
40721
|
}
|
|
@@ -40077,6 +40736,8 @@ ${nextPage.text}`;
|
|
|
40077
40736
|
polarity.evidence,
|
|
40078
40737
|
temporal.support,
|
|
40079
40738
|
temporal.evidence,
|
|
40739
|
+
clinicalCourseCue2.support,
|
|
40740
|
+
clinicalCourseCue2.evidence,
|
|
40080
40741
|
conditionPair.evidence,
|
|
40081
40742
|
riskCondition.evidence,
|
|
40082
40743
|
genericPopulation.evidence,
|
|
@@ -40096,10 +40757,13 @@ ${nextPage.text}`;
|
|
|
40096
40757
|
ageEligibility.evidence,
|
|
40097
40758
|
drugDose,
|
|
40098
40759
|
termDefinition,
|
|
40760
|
+
definitionExactAnswer,
|
|
40761
|
+
frequencyPolarity2,
|
|
40099
40762
|
negatedAnswerPrefix.evidence,
|
|
40100
40763
|
impossibilityOnly.evidence,
|
|
40101
40764
|
activeTherapyIndication.evidence,
|
|
40102
40765
|
recommendationItem,
|
|
40766
|
+
recommendationBlock,
|
|
40103
40767
|
explicitRecommendationTarget.support,
|
|
40104
40768
|
explicitRecommendationTarget.evidence,
|
|
40105
40769
|
conditionedNumber,
|
|
@@ -40130,9 +40794,22 @@ ${nextPage.text}`;
|
|
|
40130
40794
|
exactShortLabelRow,
|
|
40131
40795
|
shortLabelRow
|
|
40132
40796
|
].filter(Boolean);
|
|
40797
|
+
const definitionCompletion = definitionCompletionAdjustment(context, evidence);
|
|
40798
|
+
raw += definitionCompletion.adjustment;
|
|
40799
|
+
if (definitionCompletion.evidence) evidence.push(definitionCompletion.evidence);
|
|
40133
40800
|
const contrastCue = contrastCueMismatchAdjustment(context, evidence.sort((a, b) => b.score - a.score));
|
|
40134
40801
|
raw += contrastCue.adjustment;
|
|
40135
40802
|
if (contrastCue.evidence) evidence.push(contrastCue.evidence);
|
|
40803
|
+
if (context.config?.optionFamilyComparatorGuard) {
|
|
40804
|
+
const optionFamilyComparator = optionFamilyComparatorAdjustment({ answer: context.answer, answers: context.answers, evidence });
|
|
40805
|
+
raw += optionFamilyComparator.adjustment;
|
|
40806
|
+
if (optionFamilyComparator.evidence) evidence.push(optionFamilyComparator.evidence);
|
|
40807
|
+
}
|
|
40808
|
+
if (context.config?.optionFamilyCompactComboGuard) {
|
|
40809
|
+
const optionFamilyCompactCombo = optionFamilyCompactComboAdjustment({ question: context.question, answer: context.answer, evidence });
|
|
40810
|
+
raw += optionFamilyCompactCombo.adjustment;
|
|
40811
|
+
if (optionFamilyCompactCombo.evidence) evidence.push(optionFamilyCompactCombo.evidence);
|
|
40812
|
+
}
|
|
40136
40813
|
const excludedCondition = excludedConditionMismatchAdjustment(context, evidence.sort((a, b) => b.score - a.score));
|
|
40137
40814
|
raw += excludedCondition.adjustment;
|
|
40138
40815
|
if (excludedCondition.evidence) evidence.push(excludedCondition.evidence);
|
|
@@ -40237,41 +40914,6 @@ ${nextPage.text}`;
|
|
|
40237
40914
|
}
|
|
40238
40915
|
};
|
|
40239
40916
|
}
|
|
40240
|
-
var CONFIDENCE_STRUCTURAL_KINDS = /* @__PURE__ */ new Set([
|
|
40241
|
-
"coordinate_table_row",
|
|
40242
|
-
"coordinate_table_group",
|
|
40243
|
-
"coordinate_table_group_inverse",
|
|
40244
|
-
"coordinate_table_multicell_row",
|
|
40245
|
-
"coordinate_table_membership",
|
|
40246
|
-
"parenthetical_group_segment",
|
|
40247
|
-
"preceding_question_label",
|
|
40248
|
-
"question_continuation_list",
|
|
40249
|
-
"exact_numeric_option_segment",
|
|
40250
|
-
"exact_hour_alias_segment",
|
|
40251
|
-
"visual_table_column",
|
|
40252
|
-
"exact_short_label_visual_row",
|
|
40253
|
-
"short_label_visual_row",
|
|
40254
|
-
"answer_ordinal_row",
|
|
40255
|
-
"fibrosis_stage_row",
|
|
40256
|
-
"gene_sentence_segment",
|
|
40257
|
-
"clinical_feature_segment",
|
|
40258
|
-
"mkb_class_exclusion_absent",
|
|
40259
|
-
"classification_code_segment",
|
|
40260
|
-
"label_number_proximity",
|
|
40261
|
-
"label_definition_segment",
|
|
40262
|
-
"row_label_segment",
|
|
40263
|
-
"bounded_list_segment",
|
|
40264
|
-
"ordinal_list_segment",
|
|
40265
|
-
"drug_dose_segment",
|
|
40266
|
-
"recommendation_item_segment",
|
|
40267
|
-
"explicit_recommendation_target_segment",
|
|
40268
|
-
"numeric_condition_less_than",
|
|
40269
|
-
"numeric_condition_more_than",
|
|
40270
|
-
"numeric_condition_equal",
|
|
40271
|
-
"conditioned_number_segment",
|
|
40272
|
-
"cloze_gap_local"
|
|
40273
|
-
]);
|
|
40274
|
-
var CONFIDENCE_BROAD_KINDS = /* @__PURE__ */ new Set(["bm25_question_answer", "question_chunk_answer", "answer_chunk_question", "answer_window", "focused_answer_window", "shared_multi_segment"]);
|
|
40275
40917
|
function confidenceEvidenceSummary(item) {
|
|
40276
40918
|
let bestScore = 0;
|
|
40277
40919
|
let bestKind = "";
|
|
@@ -40283,8 +40925,8 @@ ${nextPage.text}`;
|
|
|
40283
40925
|
bestScore = score;
|
|
40284
40926
|
bestKind = String(evidence.kind ?? "");
|
|
40285
40927
|
}
|
|
40286
|
-
if (
|
|
40287
|
-
if (
|
|
40928
|
+
if (CONFIDENCE_STRUCTURAL_EVIDENCE_KINDS.has(evidence.kind)) structuralScore = Math.max(structuralScore, score);
|
|
40929
|
+
if (BROAD_EVIDENCE_KINDS.has(evidence.kind)) broadCount += 1;
|
|
40288
40930
|
}
|
|
40289
40931
|
return {
|
|
40290
40932
|
bestScore,
|