43 lines
1.7 KiB
Python
43 lines
1.7 KiB
Python
"""最终用户画像路由:仅员工/管理员可查询三源整合画像。
|
||||
|
|
|
|||
|
|
权限约定:
|
|||
|
|
- 客户(CUSTOMER):**无权访问本接口**,整合画像属于内部经营数据;
|
|||
|
|
- 员工/管理员(EMPLOYEE/ADMIN):必须显式指定 customer_id,可查任意客户。
|
|||
|
|
|
|||
|
|
整合逻辑在 ComposedProfileService(LLM 整合 + Redis 缓存 + 降级),
|
|||
|
|
本路由只做鉴权与编排;画像仅供参考,不用于适当性校验。
|
|||
|
|
"""
|
|||
|
|
from fastapi import APIRouter, Depends, Query
|
|||
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|||
|
|
|
|||
|
|
from api.deps import get_current_user
|
|||
|
|
from config.deps import get_db
|
|||
|
|
from model.sys_user import SysUser
|
|||
|
|
from service.memory.composed_profile import ComposedProfileService
|
|||
|
|
from utils.exceptions import ForbiddenError
|
|||
|
|
from utils.response import success
|
|||
|
|
|
|||
|
|
router = APIRouter()
|
|||
|
|
|
|||
|
|
|
|||
|
|
async def require_profile_viewer(user: SysUser = Depends(get_current_user)) -> SysUser:
|
|||
|
|
"""仅员工或管理员可查询最终用户画像,客户一律拒绝。"""
|
|||
|
|
if user.user_type == "ADMIN":
|
|||
|
|
return user
|
|||
|
|
if user.user_type != "EMPLOYEE":
|
|||
|
|
raise ForbiddenError("仅员工可查询用户画像")
|
|||
|
|
return user
|
|||
|
|
|
|||
|
|
|
|||
|
|
@router.get("/profile/composed", summary="查询最终用户画像(画像+记忆+持仓三源整合,仅员工)")
|
|||
|
|
async def get_composed_profile(
|
|||
|
|
customer_id: int = Query(..., description="目标客户 ID"),
|
|||
|
|
user: SysUser = Depends(require_profile_viewer),
|
|||
|
|
db: AsyncSession = Depends(get_db),
|
|||
|
|
):
|
|||
|
|
"""返回整合后的最终用户画像 JSON 及降级 warnings。"""
|
|||
|
|
service = ComposedProfileService()
|
|||
|
|
# 完整响应体先查 Redis(20 分钟过期),重复请求直接命中缓存
|
|||
|
|
data, _warnings = await service.compose_response(db, customer_id=customer_id)
|
|||
|
|
return success(data)
|