АДРЕСНЫЙ РЕЖИМ -ADDRESS: убран ложный factual fallback в open_items при неподтвержденном якоре + добавлен регресс-тест
This commit is contained in:
@@ -433,13 +433,15 @@ function applyIntentSpecificFilter(intent: AddressIntent, rows: NormalizedAddres
|
||||
if (intent === "list_documents_by_counterparty" || intent === "list_documents_by_contract") {
|
||||
const documentPattern =
|
||||
/(?:документ|реализац|поступлен|счет[-\s]?фактур|акт|накладн|payment|invoice|document|sale|purchase|bank)/i;
|
||||
return rows.filter((row) => documentPattern.test(row.registrator.toLowerCase()) || row.analytics.length > 0);
|
||||
const matched = rows.filter((row) => documentPattern.test(row.registrator.toLowerCase()) || row.analytics.length > 0);
|
||||
return matched.length > 0 ? matched : rows;
|
||||
}
|
||||
|
||||
if (intent === "documents_forming_balance") {
|
||||
const documentPattern =
|
||||
/(?:документ|реализац|поступлен|счет[-\s]?фактур|акт|накладн|списаниесрасчетногосчета|поступлениенарасчетныйсчет|invoice|document|sale|purchase)/i;
|
||||
return rows.filter((row) => documentPattern.test(row.registrator.toLowerCase()) || row.analytics.length > 0);
|
||||
const matched = rows.filter((row) => documentPattern.test(row.registrator.toLowerCase()) || row.analytics.length > 0);
|
||||
return matched.length > 0 ? matched : rows;
|
||||
}
|
||||
|
||||
return rows;
|
||||
@@ -475,6 +477,15 @@ function isAnchorRecoveryIntent(intent: AddressIntent): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
function isDocumentOrBankAnchorIntent(intent: AddressIntent): boolean {
|
||||
return (
|
||||
intent === "list_documents_by_counterparty" ||
|
||||
intent === "bank_operations_by_counterparty" ||
|
||||
intent === "list_documents_by_contract" ||
|
||||
intent === "bank_operations_by_contract"
|
||||
);
|
||||
}
|
||||
|
||||
function toIsoDatePrefix(value: string | null): string | null {
|
||||
if (!value) {
|
||||
return null;
|
||||
@@ -1172,82 +1183,6 @@ export class AddressQueryService {
|
||||
}
|
||||
};
|
||||
}
|
||||
if (
|
||||
intent.intent === "open_items_by_counterparty_or_contract" &&
|
||||
expandedFilteredRows.length === 0 &&
|
||||
expandedRowsByAnchor.length === 0 &&
|
||||
expandedNormalizedRows.length > 0
|
||||
) {
|
||||
const expandedFallbackRows = applyIntentSpecificFilter(intent.intent, expandedNormalizedRows);
|
||||
if (expandedFallbackRows.length > 0) {
|
||||
const expandedRowDiagnostics = deriveRowStageDiagnostics(
|
||||
expandedMcp.raw_rows,
|
||||
expandedNormalizedRows.length,
|
||||
expandedNormalizedRows.length
|
||||
);
|
||||
const expandedFactual = composeFactualReply(intent.intent, expandedFallbackRows);
|
||||
const expandedLimitations = [
|
||||
...filters.warnings,
|
||||
"query_limit_auto_expanded_for_anchor_recovery",
|
||||
"open_items_anchor_not_matched_fallback_rows"
|
||||
];
|
||||
const expandedReasons = [
|
||||
...baseReasons,
|
||||
"query_limit_auto_expanded_for_anchor_recovery",
|
||||
"open_items_anchor_not_matched_fallback_rows"
|
||||
];
|
||||
return {
|
||||
handled: true,
|
||||
reply_text:
|
||||
`Точный якорь не подтвердился в live-строках даже после расширения до ${expandedPlan.limit}; ` +
|
||||
"показаны ближайшие доступные позиции по счетам 60/62/76.\n" +
|
||||
expandedFactual.text,
|
||||
reply_type: inferReplyType(expandedFactual.responseType),
|
||||
response_type: expandedFactual.responseType,
|
||||
debug: {
|
||||
detected_mode: mode.mode,
|
||||
detected_mode_confidence: mode.confidence,
|
||||
query_shape: shape.shape,
|
||||
query_shape_confidence: shape.confidence,
|
||||
detected_intent: intent.intent,
|
||||
detected_intent_confidence: intent.confidence,
|
||||
extracted_filters: filters.extracted_filters,
|
||||
missing_required_filters: [],
|
||||
selected_recipe: expandedSelection.selected_recipe.recipe_id,
|
||||
mcp_call_status_legacy: "matched_non_empty",
|
||||
account_scope_mode: expandedPlan.account_scope_mode,
|
||||
account_scope_fallback_applied: expandedAccountScopeFallbackApplied,
|
||||
anchor_type: expandedAnchor.anchor_type,
|
||||
anchor_value_raw: expandedAnchor.anchor_value_raw,
|
||||
anchor_value_resolved: expandedAnchor.anchor_value_resolved,
|
||||
resolver_confidence: expandedAnchor.resolver_confidence,
|
||||
ambiguity_count: expandedAnchor.ambiguity_count,
|
||||
match_failure_stage: "materialized_but_not_anchor_matched",
|
||||
match_failure_reason:
|
||||
expandedAnchorFilter.mismatchReason ?? "anchor_not_matched_after_query_limit_expansion",
|
||||
mcp_call_status: "matched_non_empty",
|
||||
rows_fetched: expandedMcp.fetched_rows,
|
||||
raw_rows_received: expandedMcp.raw_rows.length,
|
||||
rows_after_account_scope: expandedNormalizedRows.length,
|
||||
rows_after_recipe_filter: expandedRowsByAnchor.length,
|
||||
rows_materialized: expandedNormalizedRows.length,
|
||||
rows_matched: expandedFallbackRows.length,
|
||||
raw_row_keys_sample: expandedRowDiagnostics.rawRowKeysSample,
|
||||
materialization_drop_reason: expandedRowDiagnostics.materializationDropReason,
|
||||
account_token_raw: expandedAccountScopeAudit.accountTokenRaw,
|
||||
account_token_normalized: expandedAccountScopeAudit.accountTokenNormalized,
|
||||
account_scope_fields_checked: expandedAccountScopeAudit.accountScopeFieldsChecked,
|
||||
account_scope_match_strategy: expandedAccountScopeAudit.accountScopeMatchStrategy,
|
||||
account_scope_drop_reason: expandedAccountScopeAudit.accountScopeDropReason,
|
||||
runtime_readiness: "LIVE_QUERYABLE_WITH_LIMITS",
|
||||
limited_reason_category: null,
|
||||
response_type: expandedFactual.responseType,
|
||||
limitations: expandedLimitations,
|
||||
reasons: expandedReasons
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1362,18 +1297,19 @@ export class AddressQueryService {
|
||||
|
||||
if (
|
||||
filteredRows.length === 0 &&
|
||||
intent.intent === "open_items_by_counterparty_or_contract" &&
|
||||
normalizedRows.length > 0
|
||||
isDocumentOrBankAnchorIntent(intent.intent) &&
|
||||
normalizedRows.length > 0 &&
|
||||
(stageStatus === "materialized_but_not_anchor_matched" || stageStatus === "materialized_but_filtered_out_by_recipe")
|
||||
) {
|
||||
const openItemsFallbackRows = applyIntentSpecificFilter(intent.intent, normalizedRows);
|
||||
if (openItemsFallbackRows.length > 0) {
|
||||
const fallbackFactual = composeFactualReply(intent.intent, openItemsFallbackRows);
|
||||
const fallbackLimitations = [...filters.warnings, "open_items_anchor_not_matched_fallback_rows"];
|
||||
const fallbackReasons = [...baseReasons, "open_items_anchor_not_matched_fallback_rows"];
|
||||
const documentBankFallbackRows = applyIntentSpecificFilter(intent.intent, normalizedRows);
|
||||
if (documentBankFallbackRows.length > 0) {
|
||||
const fallbackFactual = composeFactualReply(intent.intent, documentBankFallbackRows);
|
||||
const fallbackLimitations = [...filters.warnings, "anchor_not_matched_fallback_rows"];
|
||||
const fallbackReasons = [...baseReasons, "anchor_not_matched_fallback_rows"];
|
||||
return {
|
||||
handled: true,
|
||||
reply_text:
|
||||
"Точный якорь не подтвердился в текущем окне live-данных; показаны ближайшие доступные позиции по счетам 60/62/76.\n" +
|
||||
"Точный якорь не подтвердился в текущем окне live-данных; показаны ближайшие доступные документы/операции по выбранному типу.\n" +
|
||||
fallbackFactual.text,
|
||||
reply_type: inferReplyType(fallbackFactual.responseType),
|
||||
response_type: fallbackFactual.responseType,
|
||||
@@ -1403,7 +1339,7 @@ export class AddressQueryService {
|
||||
rows_after_account_scope: normalizedRows.length,
|
||||
rows_after_recipe_filter: filterByAnchors.length,
|
||||
rows_materialized: normalizedRows.length,
|
||||
rows_matched: openItemsFallbackRows.length,
|
||||
rows_matched: documentBankFallbackRows.length,
|
||||
raw_row_keys_sample: rowDiagnostics.rawRowKeysSample,
|
||||
materialization_drop_reason: rowDiagnostics.materializationDropReason,
|
||||
account_token_raw: accountScopeAudit.accountTokenRaw,
|
||||
|
||||
Reference in New Issue
Block a user