Files
group_fqcd_jr/app/service/agent/customer_service_agent.py
T

114 lines
4.6 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.
"""奶龙基金智能助手:只处理一期公开客服范围。"""
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)