fix(ai): recognize conversational document filters

This commit is contained in:
caoxiaozhu
2026-07-20 10:31:15 +08:00
parent 7a3755ac55
commit 2a9b3e3273
12 changed files with 250 additions and 54 deletions

View File

@@ -266,6 +266,46 @@ def test_semantic_ontology_service_extracts_entities_time_and_constraints() -> N
assert result.time_range.end_date == "2026-04-30"
def test_semantic_ontology_service_recognizes_colloquial_travel_city_filter(
monkeypatch,
) -> None:
session_factory = build_session_factory()
with session_factory() as db:
service = SemanticOntologyService(db)
monkeypatch.setattr(
service,
"_parse_with_model",
lambda **_kwargs: (None, [], "model_unavailable_for_rule_regression"),
)
result = service.parse(
OntologyParseRequest(
query="出差上海的单据请筛选一下",
user_id="pytest",
)
)
entity_map = {item.type: item.normalized_value for item in result.entities}
assert result.scenario == "expense"
assert result.intent == "query"
assert result.permission.level == "read"
assert entity_map["expense_type"] == "travel"
assert entity_map["location"] == "上海"
generic_result = service.parse(
OntologyParseRequest(
query="上海的单据请筛选一下",
user_id="pytest",
)
)
generic_entities = {
item.type: item.normalized_value for item in generic_result.entities
}
assert generic_result.scenario == "expense"
assert generic_result.intent == "query"
assert generic_entities["location"] == "上海"
def test_semantic_ontology_service_extracts_budget_query_fields() -> None:
session_factory = build_session_factory()
with session_factory() as db:

View File

@@ -562,6 +562,77 @@ def test_orchestrator_history_query_filters_location_time_and_returns_real_amoun
assert "321.45" in response.result["answer"]
def test_orchestrator_colloquial_travel_city_filter_returns_only_matching_documents(
monkeypatch,
) -> None:
monkeypatch.setattr(
"app.services.runtime_chat.RuntimeChatService.complete",
lambda *_args, **_kwargs: None,
)
session_factory = build_session_factory()
with session_factory() as db:
employee = Employee(
id="emp-colloquial-filter",
employee_no="E9021",
name="张三",
email="colloquial-filter@example.com",
)
db.add_all(
[
employee,
ExpenseClaim(
id="claim-colloquial-shanghai",
claim_no="EXP-SHANGHAI-001",
employee=employee,
employee_id=employee.id,
employee_name="张三",
department_name="交付部",
expense_type="travel",
reason="前往上海支持客户项目",
location="上海",
amount=Decimal("888.00"),
currency="CNY",
occurred_at=datetime(2026, 7, 8, 9, 0, tzinfo=UTC),
status="paid",
),
ExpenseClaim(
id="claim-colloquial-beijing",
claim_no="EXP-BEIJING-001",
employee=employee,
employee_id=employee.id,
employee_name="张三",
department_name="交付部",
expense_type="travel",
reason="前往北京支持客户项目",
location="北京",
amount=Decimal("666.00"),
currency="CNY",
occurred_at=datetime(2026, 7, 9, 9, 0, tzinfo=UTC),
status="paid",
),
]
)
db.commit()
response = run_for_fixture_tenant(
OrchestratorService(db),
OrchestratorRequest(
source="user_message",
user_id="colloquial-filter@example.com",
message="出差上海的单据请筛选一下",
),
)
query_payload = response.result["query_payload"]
assert response.status == "succeeded"
assert response.trace_summary.scenario == "expense"
assert response.trace_summary.intent == "query"
assert query_payload["record_count"] == 1
assert [item["claim_no"] for item in query_payload["records"]] == [
"EXP-SHANGHAI-001"
]
def test_orchestrator_archive_query_filters_archived_claims_and_limits_preview(
monkeypatch,
) -> None: