| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- import json
- from datetime import UTC, datetime
- import pytest
- from zbt.core.errors import AppError
- from zbt.domains.agent.tools import build_agent_tool_registry
- from zbt.domains.catalog.repository import InMemoryCatalogRepository
- from zbt.domains.catalog.service import ProductCatalogService
- from zbt.domains.enrollment.repository import InMemoryEnrollmentRepository
- from zbt.domains.enrollment.service import EnrollmentService
- from zbt.domains.identity.models import H5User
- from zbt.domains.knowledge.index import InMemoryKnowledgeIndex
- from zbt.domains.knowledge.repository import InMemoryKnowledgeRepository
- from zbt.domains.knowledge.service import KnowledgeService
- from zbt.harness.policy import HarnessPolicyEngine
- from zbt.harness.tooling import ToolExecutionContext
- NOW = datetime(2026, 7, 27, 4, 0, tzinfo=UTC)
- def test_customer_knowledge_tool_returns_published_evidence_with_source() -> None:
- catalog = ProductCatalogService(InMemoryCatalogRepository(), lambda: NOW)
- enrollment = EnrollmentService(
- InMemoryEnrollmentRepository(),
- catalog,
- lambda: NOW,
- "x" * 32,
- )
- knowledge = KnowledgeService(
- InMemoryKnowledgeRepository(),
- lambda: NOW,
- InMemoryKnowledgeIndex(),
- )
- document = knowledge.create_document(
- title="安心医疗险保险条款",
- document_type="INSURANCE_TERMS",
- source_name="安心医疗险条款.pdf",
- product_code="MED-BASIC",
- content="疾病医疗等待期为30天,意外伤害不受等待期限制。",
- created_by="admin-01",
- )
- knowledge.index_document(document["document_id"])
- knowledge.test_search(document["document_id"], "医疗险等待期是多少天?")
- knowledge.publish_document(document["document_id"])
- registry = build_agent_tool_registry(catalog, enrollment, knowledge=knowledge)
- context = ToolExecutionContext(
- persona="customer",
- h5_user=H5User(
- id="01H5USER000000000000000001",
- mobile="18800000001",
- mobile_masked="188****0001",
- display_name="体验用户",
- status="ACTIVE",
- created_at=NOW,
- ),
- )
- tool = registry.build(
- names=("search_insurance_knowledge",),
- context=context,
- policy_engine=HarnessPolicyEngine(),
- )[0]
- result = json.loads(tool.invoke({"query": "医疗险等待期是多少天?", "limit": 3}))
- assert result["data"]["total"] == 1
- assert result["data"]["items"][0]["title"] == "安心医疗险保险条款"
- assert result["data"]["items"][0]["source_name"] == "安心医疗险条款.pdf"
- assert result["data"]["items"][0]["document_version"] == 1
- assert result["data"]["answer_constraints"]["direct_evidence_only"] is True
- assert result["data"]["answer_constraints"]["no_scenario_expansion"] is True
- assert result["data"]["answer_constraints"]["no_numeric_inference"] is True
- assert "30天" in result["summary"]
- assert result["blocks"][0]["type"] == "knowledge_sources"
- assert result["blocks"][0]["items"][0]["source_name"] == "安心医疗险条款.pdf"
- assert [execution.name for execution in context.executions] == [
- "search_insurance_knowledge"
- ]
- def test_agentic_knowledge_tool_executes_rewrites_with_metadata_filters() -> None:
- catalog = ProductCatalogService(InMemoryCatalogRepository(), lambda: NOW)
- enrollment = EnrollmentService(
- InMemoryEnrollmentRepository(),
- catalog,
- lambda: NOW,
- "x" * 32,
- )
- knowledge = KnowledgeService(
- InMemoryKnowledgeRepository(),
- lambda: NOW,
- InMemoryKnowledgeIndex(),
- )
- for title, product_code, content in (
- (
- "安心医疗险保险条款",
- "MED-BASIC",
- "疾病医疗等待期为30天,意外伤害不受等待期限制。",
- ),
- (
- "家庭意外险常见问题",
- "ACC-FAMILY",
- "意外医疗不设置疾病等待期,具体责任以意外险条款为准。",
- ),
- ):
- document = knowledge.create_document(
- title=title,
- document_type="INSURANCE_TERMS",
- source_name=f"{title}.md",
- product_code=product_code,
- content=content,
- created_by="admin-01",
- )
- knowledge.index_document(document["document_id"])
- knowledge.test_search(document["document_id"], content[:20])
- knowledge.publish_document(document["document_id"])
- registry = build_agent_tool_registry(catalog, enrollment, knowledge=knowledge)
- context = ToolExecutionContext(
- persona="customer",
- h5_user=H5User(
- id="01H5USER000000000000000001",
- mobile="18800000001",
- mobile_masked="188****0001",
- display_name="体验用户",
- status="ACTIVE",
- created_at=NOW,
- ),
- )
- tool = registry.build(
- names=("search_insurance_knowledge",),
- context=context,
- policy_engine=HarnessPolicyEngine(),
- )[0]
- result = json.loads(
- tool.invoke(
- {
- "query": "安心医疗险多久后可以报销疾病医疗?",
- "alternate_queries": [
- "安心医疗险疾病等待期",
- "MED-BASIC等待期天数",
- ],
- "product_code": "MED-BASIC",
- "document_types": ["INSURANCE_TERMS"],
- "limit": 3,
- }
- )
- )
- plan = result["data"]["agentic_retrieval"]
- assert plan["executed_queries"] == [
- "安心医疗险多久后可以报销疾病医疗?",
- "安心医疗险疾病等待期",
- "MED-BASIC等待期天数",
- ]
- assert plan["filters"] == {
- "product_code": "MED-BASIC",
- "document_types": ["INSURANCE_TERMS"],
- }
- assert plan["attempt"] == 1
- assert result["data"]["items"]
- assert {
- item["product_code"] for item in result["data"]["items"]
- } == {"MED-BASIC"}
- def test_agentic_knowledge_tool_limits_iterative_retrieval_to_three_rounds() -> None:
- catalog = ProductCatalogService(InMemoryCatalogRepository(), lambda: NOW)
- enrollment = EnrollmentService(
- InMemoryEnrollmentRepository(),
- catalog,
- lambda: NOW,
- "x" * 32,
- )
- knowledge = KnowledgeService(
- InMemoryKnowledgeRepository(),
- lambda: NOW,
- InMemoryKnowledgeIndex(),
- )
- context = ToolExecutionContext(
- persona="customer",
- h5_user=H5User(
- id="01H5USER000000000000000001",
- mobile="18800000001",
- mobile_masked="188****0001",
- display_name="体验用户",
- status="ACTIVE",
- created_at=NOW,
- ),
- )
- tool = build_agent_tool_registry(
- catalog,
- enrollment,
- knowledge=knowledge,
- ).build(
- names=("search_insurance_knowledge",),
- context=context,
- policy_engine=HarnessPolicyEngine(),
- )[0]
- for index in range(3):
- result = json.loads(tool.invoke({"query": f"第{index + 1}轮检索问题"}))
- assert result["data"]["agentic_retrieval"]["attempt"] == index + 1
- with pytest.raises(AppError) as error:
- tool.invoke({"query": "第四轮检索问题"})
- assert error.value.code == "AGENTIC_RETRIEVAL_LIMIT_REACHED"
|