ДОМЕНЫ - ВОПРОСЫ - СКЛАД - Починить selected-object follow-up по складу и включить разговорные/UI-варианты в обязательный domain-loop

This commit is contained in:
2026-04-14 14:18:38 +03:00
parent 9048632d3e
commit d41819eabd
67 changed files with 3800 additions and 195 deletions
+53 -9
View File
@@ -38,6 +38,10 @@ def _has_account_token(text: str) -> bool:
return bool(ACCOUNT_TOKEN_RE.search(text))
def _has_iso_date(text: str) -> bool:
return bool(re.search(r'\b\d{4}-\d{2}-\d{2}\b', text))
def _aggregate_available_for_shape(
*,
available: set[str],
@@ -77,13 +81,35 @@ def classify_query_for_route(
question_class = str(parsed_intent.get("question_class", "")).strip().lower()
exact_markers = [
"документ по номеру",
"document by number",
"source-of-record",
"источник",
"цепочка",
"почему",
"source",
"chain",
"why",
"subconto3",
"субконто3",
"supplier",
"поставщик",
"buyer",
"покупатель",
"purchase",
"закуп",
"document",
"документ",
"date",
"дата",
]
inventory_markers = [
"склад",
"остаток",
"поставщик",
"закуплен",
"куплен",
"продан",
"inventory",
"stock",
"supplier",
"purchase",
"sale",
]
causal_markers = [
"свяжи",
@@ -109,16 +135,35 @@ def classify_query_for_route(
needs_exact_object_trace = _contains_any(text, exact_markers) and (
question_class in {"drilldown_explain", "simple_factual", "cross_entity"}
)
if question_class == "simple_factual" and "документ по номеру" in text:
if _contains_any(text, inventory_markers) and question_class in {
"drilldown_explain",
"simple_factual",
"cross_entity",
}:
needs_exact_object_trace = True
if question_class in {"drilldown_explain", "simple_factual", "cross_entity"} and (
("41" in text and _contains_any(text, ["остаток", "balance", "stock"]))
or (
_contains_any(text, ["supplier", "поставщик", "buyer", "покупатель"])
and _contains_any(text, ["purchase", "закуп", "document", "документ"])
)
):
needs_exact_object_trace = True
if question_class == "simple_factual" and "document by number" in text:
needs_exact_object_trace = True
if question_class == "unknown" and "41" in text and _has_iso_date(text):
needs_exact_object_trace = True
needs_causal_chain = _contains_any(text, causal_markers) and question_class in {
"drilldown_explain",
"cross_entity",
}
if _contains_any(text, inventory_markers) and "???????" in text:
needs_causal_chain = True
needs_cross_entity_join = (
question_class == "cross_entity"
or (_contains_any(text, cross_markers) and " и " in text and "->" not in text)
or (_contains_any(text, cross_markers) and " ? " in text and "->" not in text)
)
needs_ranking = _contains_any(text, ranking_markers) and question_class in {
@@ -132,7 +177,7 @@ def classify_query_for_route(
needs_full_period_aggregation = is_heavy and not is_baseline_heavy
needs_runtime_truth = needs_exact_object_trace or _contains_any(
text, ["runtime", "source-of-record", "источник регистра"]
text, ["runtime", "source-of-record", "???????????????? ????????????????"]
)
freshness_sensitive = question_class in {
"period_trend",
@@ -141,7 +186,6 @@ def classify_query_for_route(
}
ambiguous_object_scope = question_class == "ambiguous_fuzzy"
if ambiguous_object_scope and _has_account_token(text):
# Ambiguous account prompts should avoid hard downcast into canonical-only answers.
needs_runtime_truth = True
available_aggregates = {