- Added new modules for advisor compliance, KYC sessions, and script templates, enhancing the advisor agent's capabilities. - Implemented a comprehensive API structure under the `/api/advisor-agent` prefix, ensuring clear organization and access to new features. - Established database models and repositories for compliance rules and KYC sessions, facilitating robust data management. - Integrated exception handling and response models to improve error management and user feedback. - Updated settings to include new configurations for compliance and KYC features, ensuring flexibility and adaptability. This update significantly expands the advisor agent's functionality, providing essential tools for compliance and customer interaction while maintaining a structured API design.
95 lines
4.1 KiB
Python
95 lines
4.1 KiB
Python
from app.model.advisor_schemas import ComplianceCheckRequest
|
|
from app.service.compliance_check_service import ComplianceCheckService
|
|
from scripts.seed.import_compliance_rules import import_rules_from_markdown
|
|
|
|
class FakeLLMClient:
|
|
def __init__(self, output: str | Exception) -> None:
|
|
self.output = output
|
|
self.prompts: list[str] = []
|
|
|
|
def complete(self, prompt: str, *, timeout_seconds: float) -> str:
|
|
self.prompts.append(prompt)
|
|
if isinstance(self.output, Exception):
|
|
raise self.output
|
|
return self.output
|
|
|
|
def service_with_fake_llm(output: str | Exception) -> ComplianceCheckService:
|
|
from app.service.compliance_semantic_service import ComplianceSemanticService
|
|
|
|
semantic_service = ComplianceSemanticService(llm_client=FakeLLMClient(output))
|
|
return ComplianceCheckService(semantic_service=semantic_service)
|
|
|
|
def test_semantic_detection_warns_when_llm_finds_implicit_risk():
|
|
service = service_with_fake_llm(
|
|
'{"risk_level":"WARN","reason":"话术暗示确定性收益","suggestion":"改为提示收益波动风险"}'
|
|
)
|
|
|
|
result = service.check_text(ComplianceCheckRequest(text="这款产品收益表现很踏实,基本不用担心波动。"))
|
|
|
|
assert result.risk_level == "WARN"
|
|
assert result.can_copy is True
|
|
assert result.required_action == "warn_confirm"
|
|
assert result.hits == []
|
|
assert result.ai_analysis is not None
|
|
assert result.ai_analysis.risk_level == "WARN"
|
|
assert result.ai_analysis.reason == "话术暗示确定性收益"
|
|
assert result.ai_analysis.suggestion == "改为提示收益波动风险"
|
|
assert result.ai_analysis.degraded is False
|
|
assert result.ai_analysis.prompt_version == "compliance-semantic-v1"
|
|
|
|
def test_semantic_detection_is_skipped_when_hard_rule_matches():
|
|
import_rules_from_markdown()
|
|
fake_llm = FakeLLMClient('{"risk_level":"INFO","reason":"无风险","suggestion":""}')
|
|
|
|
from app.service.compliance_semantic_service import ComplianceSemanticService
|
|
|
|
service = ComplianceCheckService(semantic_service=ComplianceSemanticService(llm_client=fake_llm))
|
|
|
|
result = service.check_text(ComplianceCheckRequest(text="这款产品保本保收益。"))
|
|
|
|
assert result.risk_level == "BLOCK"
|
|
assert result.ai_analysis is None
|
|
assert fake_llm.prompts == []
|
|
|
|
def test_semantic_detection_degrades_to_warn_on_timeout():
|
|
service = service_with_fake_llm(TimeoutError("semantic timeout"))
|
|
|
|
result = service.check_text(ComplianceCheckRequest(text="这款产品表现比较稳,您可以考虑。"))
|
|
|
|
assert result.risk_level == "WARN"
|
|
assert result.can_copy is True
|
|
assert result.required_action == "warn_confirm"
|
|
assert result.ai_analysis is not None
|
|
assert result.ai_analysis.degraded is True
|
|
assert result.ai_analysis.reason == "AI semantic detection degraded: timeout"
|
|
|
|
def test_semantic_detection_degrades_to_warn_on_empty_output():
|
|
service = service_with_fake_llm("")
|
|
|
|
result = service.check_text(ComplianceCheckRequest(text="请帮我检查这句话。"))
|
|
|
|
assert result.risk_level == "WARN"
|
|
assert result.ai_analysis is not None
|
|
assert result.ai_analysis.degraded is True
|
|
assert result.ai_analysis.reason == "AI semantic detection degraded: empty_output"
|
|
|
|
def test_semantic_detection_degrades_to_warn_on_malformed_output():
|
|
service = service_with_fake_llm("not json")
|
|
|
|
result = service.check_text(ComplianceCheckRequest(text="请帮我检查这句话。"))
|
|
|
|
assert result.risk_level == "WARN"
|
|
assert result.ai_analysis is not None
|
|
assert result.ai_analysis.degraded is True
|
|
assert result.ai_analysis.reason == "AI semantic detection degraded: malformed_output"
|
|
|
|
def test_semantic_detection_degrades_to_warn_on_refusal():
|
|
service = service_with_fake_llm('{"refusal":"cannot answer"}')
|
|
|
|
result = service.check_text(ComplianceCheckRequest(text="请帮我检查这句话。"))
|
|
|
|
assert result.risk_level == "WARN"
|
|
assert result.ai_analysis is not None
|
|
assert result.ai_analysis.degraded is True
|
|
assert result.ai_analysis.reason == "AI semantic detection degraded: refusal"
|