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