"""奶龙基金智能助手:只处理一期公开客服范围。""" from app.core.config import get_settings from app.core.contracts import AgentDefinition, AgentRequest, CoreResult, RequestContext from app.core.errors import RecoverableAgentError from app.core.knowledge_contracts import KnowledgeSearchResult from app.service.agent.base import BaseAgent from app.service.agent.customer_service_routing import CustomerServiceIntentRouter def _human_service_phone() -> str: return get_settings().customer_service_phone class CustomerServiceAgent(BaseAgent): definition = AgentDefinition( agent_type="customer_service", version="1.0.0", allowed_tools=("query_knowledge",), allowed_roles=("visitor", "customer"), allowed_portals=("api",), requires_model_intent_classification=False, supported_intents=( "security_notice", "account_entry", "human_transfer", "compliance_refusal", "chitchat", "public_knowledge", "faq", "product_inquiry", "policy_explain", ), ) def __init__(self) -> None: super().__init__(self.definition) async def handle(self, request: AgentRequest, context: RequestContext) -> CoreResult: message = request.message.strip() route = CustomerServiceIntentRouter.classify(message) if route.intent == "security_notice": return CoreResult( text=( "请立即停止操作,不要继续提供验证码、密码或身份证件信息,并尽快联系" f"人工客服 {_human_service_phone()}。" ), transfer_required=True, transfer_reason="security_notice", ) if route.intent == "compliance_refusal": return CoreResult( text=( "我不能推荐具体产品、承诺收益或代您交易;如需进一步了解,请联系" f"人工客服 {_human_service_phone()}。" ), transfer_required=True, transfer_reason="compliance_refusal", ) if route.intent == "account_entry": if "visitor" in context.roles: return CoreResult(text="我无法查询账户数据,请先登录后前往“我的账户”查看相关状态。") return CoreResult(text="我无法查询账户数据,请前往“我的账户”查看相关状态。") if route.intent == "human_transfer": return CoreResult( text=( f"您可以联系人工客服 {_human_service_phone()}(工作日 09:00-18:00)" "进一步核实。" ), transfer_required=True, transfer_reason="human_transfer", ) if route.is_chitchat: if request.metadata.chitchat_streak == 4: return CoreResult(text="和您聊天很开心呀。您是想了解相关的基金业务或公开信息吗?") return CoreResult(text="您好呀,我是奶龙基金智能助手,很高兴和您聊天。") try: output = await self.call_tool( "query_knowledge", {"query": message, "intents": route.knowledge_intents, "top_k": 5}, intent="public_knowledge", context=context, ) result = ( output if isinstance(output, KnowledgeSearchResult) else KnowledgeSearchResult.model_validate(output) ) except RecoverableAgentError: return self._knowledge_transfer("knowledge_unavailable") answers = [ hit.answer.strip() for hit in result.hits if isinstance(hit.answer, str) and hit.answer.strip() ] if not answers: return self._knowledge_transfer("knowledge_not_found") return CoreResult(text=answers[0]) @staticmethod def _knowledge_transfer(reason: str) -> CoreResult: phone = _human_service_phone() if reason == "knowledge_unavailable": text = ( "您好呀,我暂时无法从公开资料中确认这个问题,请联系" f"人工客服 {phone} 进一步核实。" ) else: text = ( "您好呀,我暂时没有查到匹配的公开资料,请联系" f"人工客服 {phone} 进一步核实。" ) return CoreResult(text=text, transfer_required=True, transfer_reason=reason)