# api/cost_router.py """成本估算接口(批次 3 自 advanced_router 拆分,D1)。""" from fastapi import APIRouter, Depends, HTTPException from pydantic import BaseModel from sqlalchemy.ext.asyncio import AsyncSession from shared.services.auth_service import get_current_active_user from shared.database.database import get_db_session from shared.models.identity import User from moldinsight.services.task_query_service import TaskQueryService router = APIRouter() class CostEstimateRequest(BaseModel): task_id: str @router.post("/cost-estimate") async def estimate_cost( body: CostEstimateRequest, current_user: User = Depends(get_current_active_user), db_session: AsyncSession = Depends(get_db_session), ): """模具成本估算:优先使用 LLM,未启用时降级为规则式估算""" # 归属校验统一走 TaskQueryService(与 /api/status 共用,含 404/403 语义) await TaskQueryService.ensure_task_access(db_session, body.task_id, current_user.id) # 统一走任务视图:进行中读 Redis,完成态由 PG+RustFS 组装(Redis 大对象已瘦身) task_data = await TaskQueryService.get_task_view(db_session, body.task_id) if not task_data: raise HTTPException(404, "任务不存在") analysis_result = task_data.get("analysis_result") if not analysis_result: raise HTTPException(400, "该任务尚未完成分析") detailed_context = { "candidate_schemes": task_data.get("candidate_schemes", []), "geometry_data": task_data.get("geometry_data", {}), "metadata": {"selected_material": task_data.get("material")}, } # 优先使用 LLM from moldinsight.services.llm_service import llm_service result = await llm_service.estimate_cost(analysis_result, detailed_context) if result is not None: result["source"] = "ai" return {"status": "success", "data": result} # LLM 未启用或失败,降级为规则估算 from moldinsight.services.cost_estimate_service import estimate_cost_by_rules rules_result = estimate_cost_by_rules(analysis_result, detailed_context) return {"status": "success", "data": rules_result}