api.routes

FastAPI 路由定义:POI 查询、行程规划、Agent 对话、历史记录。

Attributes

router

Functions

_build_poi_cache(req)

将 PlanRequest 转换为 run_planning 所需的 poi_cache 格式。

poi_lookup(req)

批量查询 POI 坐标和地址。

suggest(req)

获取方案建议列表。

plan(req)

执行完整规划,返回每日行程与高德地图可视化数据。

chat(req)

LLM Agent 对话接口,SSE 流式输出。

list_history([page, page_size, session])

获取历史记录分页列表。

get_history_detail(record_id[, session])

获取单条历史记录的完整数据(含 plan_result 全量 JSONB)。

create_history(req[, session])

保存一条历史记录(分享方案到分享站)。

delete_history(record_id, req[, session])

删除一条历史记录(需 device_id 匹配创建者)。

Module Contents

api.routes.router
api.routes._build_poi_cache(req: backend.api.schemas.PlanRequest)

将 PlanRequest 转换为 run_planning 所需的 poi_cache 格式。

前端传来的坐标数据可直接映射,无需额外转换。 时间窗以 (start, end) 元组形式传递。

Args:

req: 前端传入的规划请求,含酒店/景点坐标及时间窗。

Returns:

dict: {"hotel": {...酒店信息...}, "spots": [...景点列表...]}。

async api.routes.poi_lookup(req: backend.api.schemas.POILookupRequest)

批量查询 POI 坐标和地址。

前端传入城市 + 名称列表,后端调用高德 POI 搜索 API, 返回每个名称的坐标和地址。未找到的名称列入 failed 列表, 若跨城市则附带建议地址。

Args:

req: POI 查询请求,含城市名和名称列表。

Returns:

POILookupResponse: 查询结果,items 为成功项,failed 为失败列表。

async api.routes.suggest(req: backend.api.schemas.PlanRequest)

获取方案建议列表。

不指定 n_days,run_planning 内部回退到 ca_suggest(), 遍历多种聚类方法 × 天数,返回建议列表。 响应中附带 cost_matrix/dist_matrix/polylines,供后续深度规划复用。

Returns:

dict: 含 suggestions(建议列表)、algo_time、cost_matrix、dist_matrix、 polylines、amap_api_key、amap_security_code。

Raises:

HTTPException 500: 建议搜索引擎内部错误。

async api.routes.plan(req: backend.api.schemas.PlanRequest)

执行完整规划,返回每日行程与高德地图可视化数据。

n_days 为必填,mode 可选 "fast"(CA) 或 "deep"(VNS)。 若 req 携带 cost_matrix/dist_matrix(来自 suggest 响应), 则将矩阵作为 override 传给 run_planning,跳过驾车 API 调用。

Returns:

dict: 含 solution、best_days、daily_schedules、cost_matrix、dist_matrix、 polylines、commentary、amap_api_key、amap_security_code。

Raises:

HTTPException 400: n_days 未指定时。 HTTPException 500: 规划引擎内部错误。

async api.routes.chat(req: backend.api.schemas.ChatRequest)

LLM Agent 对话接口,SSE 流式输出。

Mock 模式返回死 token,方便前端联调。 正式上线后设置 MOCK_MODE=False 即可切换 DeepSeek 真实调用。

Raises:

HTTPException 500: LLM 调用异常或数据格式错误。

async api.routes.list_history(page: int = Query(default=1, ge=1), page_size: int = Query(default=20, ge=1, le=100), session: sqlalchemy.ext.asyncio.AsyncSession = Depends(get_session))

获取历史记录分页列表。

仅返回摘要字段(id/city/n_days/cost/spot_count/note/created_at), 不加载 JSONB 大字段(plan_result),避免列表页传输大量数据。

Args:

page: 页码,从 1 开始。 page_size: 每页条数,最大 100。

Returns:

HistoryListResponse: { items, total, page, page_size }。

async api.routes.get_history_detail(record_id: uuid.UUID, session: sqlalchemy.ext.asyncio.AsyncSession = Depends(get_session))

获取单条历史记录的完整数据(含 plan_result 全量 JSONB)。

Args:

record_id: 记录 UUID。

Returns:

HistoryDetail: 含 plan_result/request_params 等完整字段。

Raises:

HTTPException 404: 记录不存在。

async api.routes.create_history(req: backend.api.schemas.HistoryCreate, session: sqlalchemy.ext.asyncio.AsyncSession = Depends(get_session))

保存一条历史记录(分享方案到分享站)。

设计说明:device_id 由前端 localStorage 自动生成,服务端不做强鉴权—— 这是软鉴权设计。核心考量: 1. 不引入注册/登录系统,保持访客零门槛 2. device_id 仅用于删除时校验「是否是本人」,防止误删他人方案 3. device_id 无法防恶意攻击(前端可伪造),但此场景无敏感数据,可接受

Args:

req: HistoryCreate,包含 city/n_days/plan_result 等必填字段。

Returns:

dict: { id: str } 新创建的记录 UUID。

Raises:

HTTPException 422: 请求体校验失败(Pydantic 自动处理)。

async api.routes.delete_history(record_id: uuid.UUID, req: backend.api.schemas.HistoryDeleteRequest, session: sqlalchemy.ext.asyncio.AsyncSession = Depends(get_session))

删除一条历史记录(需 device_id 匹配创建者)。

Args:

record_id: 记录 UUID。 req: HistoryDeleteRequest,包含 device_id。

Returns:

dict: { ok: true }

Raises:

HTTPException 404: 记录不存在。 HTTPException 403: device_id 不匹配,无权删除。