Files
agent/tests/rag/test_intent_router_e2e_flows.py

127 lines
4.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import os
import pytest
from app.modules.rag.intent_router_v2 import GigaChatIntentRouterFactory
from app.modules.shared.env_loader import load_workspace_env
from tests.rag.asserts_intent_router import (
assert_domains,
assert_file_only_scope,
assert_intent,
assert_test_policy,
)
from tests.rag.intent_router_testkit import run_sequence
pytestmark = pytest.mark.intent_router
def _live_gigachat_enabled() -> bool:
load_workspace_env()
return os.getenv("RUN_INTENT_ROUTER_V2_LIVE", "").strip() == "1" and bool(os.getenv("GIGACHAT_TOKEN", "").strip())
def test_e2e_path_carryover_flow() -> None:
first, second, third = run_sequence(
[
"Посмотри файл app/core/config.py",
"Теперь объясни функцию load_config",
"Почему так?",
]
)
assert_file_only_scope(first, "app/core/config.py")
assert "app/core/config.py" in second.retrieval_spec.filters.path_scope
assert "app/core/config.py" in third.retrieval_spec.filters.path_scope
second_file_anchors = [anchor.value for anchor in second.query_plan.anchors if anchor.type == "FILE_PATH" and anchor.source == "conversation_state"]
assert second_file_anchors == ["app/core/config.py"]
assert "app/core/config.py" in second.query_plan.keyword_hints
assert "app/core" not in second.query_plan.keyword_hints
assert any(anchor.type == "FILE_PATH" and anchor.source == "conversation_state" and anchor.span is None for anchor in third.query_plan.anchors)
carried_symbols = [anchor.value for anchor in third.query_plan.anchors if anchor.type == "SYMBOL" and anchor.source == "conversation_state"]
assert carried_symbols in ([], ["load_config"])
assert third.query_plan.sub_intent == "EXPLAIN_LOCAL"
layer_ids = [item.layer_id for item in third.retrieval_spec.layer_queries]
assert "C3_ENTRYPOINTS" not in layer_ids
def test_e2e_docs_switch_from_code_topic() -> None:
first, second = run_sequence(
[
"Объясни как работает ConfigManager",
"А что про это сказано в документации?",
]
)
assert_intent(first, "CODE_QA")
assert_intent(second, "DOCS_QA")
assert second.conversation_mode == "SWITCH"
assert_domains(second, ["DOCS"])
carried = [
anchor
for anchor in second.query_plan.anchors
if anchor.type == "SYMBOL" and anchor.value == "ConfigManager" and anchor.source == "conversation_state"
]
assert carried
assert carried[0].span is None
assert "ConfigManager" in second.query_plan.expansions
assert "ConfigManager" in second.query_plan.keyword_hints
def test_e2e_tests_toggle_flow() -> None:
first, second = run_sequence(
[
"Покажи тесты для ConfigManager",
"А теперь не про тесты, а про прод код",
]
)
assert_intent(first, "CODE_QA")
assert_intent(second, "CODE_QA")
assert_test_policy(first, "INCLUDE")
assert_test_policy(second, "EXCLUDE")
assert first.query_plan.sub_intent == "FIND_TESTS"
assert second.query_plan.sub_intent == "EXPLAIN"
assert "tests" in second.query_plan.negations
assert not second.query_plan.expansions
assert second.evidence_policy.require_flow is False
def test_e2e_open_file_then_generic_next_steps_is_lightweight() -> None:
first, second = run_sequence(
[
"Открой файл app/core/config.py",
"Что дальше?",
]
)
assert_file_only_scope(first, "app/core/config.py")
assert_file_only_scope(second, "app/core/config.py")
assert second.query_plan.sub_intent in {"EXPLAIN_LOCAL", "NEXT_STEPS"}
layer_ids = [item.layer_id for item in second.retrieval_spec.layer_queries]
assert "C3_ENTRYPOINTS" not in layer_ids
assert second.evidence_policy.require_flow is False
assert "app/core/config.py" in second.query_plan.keyword_hints
@pytest.mark.skipif(
not _live_gigachat_enabled(),
reason="requires RUN_INTENT_ROUTER_V2_LIVE=1 and GIGACHAT_TOKEN in environment or .env",
)
def test_intent_router_live_smoke_path_carryover() -> None:
router = GigaChatIntentRouterFactory().build()
first, second = run_sequence(
[
"Открой файл app/core/config.py",
"Что дальше?",
],
router=router,
trace_label="intent-router-live",
)
assert_file_only_scope(first, "app/core/config.py")
assert "app/core/config.py" in second.retrieval_spec.filters.path_scope
assert second.query_plan.sub_intent in {"EXPLAIN_LOCAL", "NEXT_STEPS"}
layer_ids = [item.layer_id for item in second.retrieval_spec.layer_queries]
assert "C3_ENTRYPOINTS" not in layer_ids
assert second.evidence_policy.require_flow is False