# Geo Agent API 对接文档 ## 1. 文档目的 本文档面向前端对接,说明当前可用接口、请求结构、响应结构、错误语义和对接建议。 ## 2. 服务概览 当前服务提供两个 HTTP 接口: - `GET /healthz` - `POST /route/plan` 默认本地开发地址示例: ```text http://127.0.0.1:8000 ``` ### 2.1 CORS 当前服务已启用 CORS。 - 默认允许本地开发来源:`localhost` 和 `127.0.0.1` 的任意端口 - 当前默认允许的方法:`GET`、`POST`、`OPTIONS` - 当前默认允许所有请求头 - 如果前端部署到其他域名,需要后端调整 `.env` 中的 CORS 配置 ## 3. 健康检查 ### 3.1 请求 ```http GET /healthz ``` ### 3.2 成功响应 ```json { "status": "ok" } ``` ## 4. 路线规划接口 ### 4.1 请求 ```http POST /route/plan Content-Type: application/json ``` ### 4.2 请求体 ```json { "task_name": "multi-destination-route-planning", "origin_mode": "fixed", "origin_name": "北京站", "origin_address": "北京站", "origin_city": "北京市", "destination_name": "天安门", "destination_address": "天安门", "destination_city": "北京市", "stops": [ { "name": "王府井", "address": "王府井", "city": "北京市", "contact": null } ], "route_strategy": "shortest_distance", "transport_mode": "driving", "need_deep_link": true, "deep_link_mode": "auto", "need_html": false, "max_permutations": 10 } ``` ### 4.3 请求字段说明 - `task_name` - 可选 - 默认值为 `multi-destination-route-planning` - `origin_mode` - 必填 - 可选值:`fixed`、`current_location` - `origin_name` - 可选 - 起点展示名称 - `origin_address` - `origin_mode=fixed` 时必填 - `origin_city` - 可选 - `destination_name` - 可选 - `destination_address` - 必填 - `destination_city` - 可选 - `stops` - 必填 - 至少 1 个元素 - `route_strategy` - 可选 - 可选值:`shortest_distance`、`fastest_time`、`balanced` - `transport_mode` - 当前固定为 `driving` - `need_deep_link` - 可选 - 当前必须为 `true` - 该服务的成功结果必须包含 deep link - `deep_link_mode` - 可选 - 可选值:`personal_map`、`route_plan`、`auto` - `need_html` - 可选 - 当前建议始终传 `false` - `max_permutations` - 可选 - 本次请求希望允许的候选上限 - 不能超过服务端上限 ## 5. 成功响应结构 ### 5.1 响应示例 ```json { "success": true, "origin_mode": "fixed", "resolved_origin": { "role": "origin", "input_name": null, "input_address": "北京站", "resolved_name": "北京站", "city": "北京市", "district": "东城区", "location": "116.427354,39.902830", "lon": 116.427354, "lat": 39.90283, "poi_id": null, "source": "geo", "confidence_note": "地址解析高置信" }, "resolved_destination": { "role": "destination", "input_name": null, "input_address": "天安门", "resolved_name": "天安门", "city": "北京市", "district": "东城区", "location": "116.397463,39.909187", "lon": 116.397463, "lat": 39.909187, "poi_id": null, "source": "geo", "confidence_note": "地址解析高置信" }, "resolved_stops": [ { "role": "stop", "input_name": null, "input_address": "王府井", "resolved_name": "王府井", "city": "北京市", "district": "东城区", "location": "116.412422,39.908966", "lon": 116.412422, "lat": 39.908966, "poi_id": "B000A8WS91", "source": "search_detail", "confidence_note": "北京市内热点地名,POI查询高置信" } ], "candidates": [ { "stop_order_labels": ["王府井"], "full_order_labels": ["北京站", "王府井", "天安门"], "legs": [ { "from_label": "北京站", "to_label": "王府井", "origin_location": "116.427354,39.902830", "destination_location": "116.412422,39.908966", "distance_m": 3014, "duration_s": 845 }, { "from_label": "王府井", "to_label": "天安门", "origin_location": "116.412422,39.908966", "destination_location": "116.397463,39.909187", "distance_m": 2858, "duration_s": 1158 } ], "total_distance_m": 5872, "total_duration_s": 2003, "ranking_reason": "仅有的可行路线,总距离最短" } ], "best_route": { "stop_order_labels": ["王府井"], "full_order_labels": ["北京站", "王府井", "天安门"], "legs": [ { "from_label": "北京站", "to_label": "王府井", "origin_location": "116.427354,39.902830", "destination_location": "116.412422,39.908966", "distance_m": 3014, "duration_s": 845 }, { "from_label": "王府井", "to_label": "天安门", "origin_location": "116.412422,39.908966", "destination_location": "116.397463,39.909187", "distance_m": 2858, "duration_s": 1158 } ], "total_distance_m": 5872, "total_duration_s": 2003, "ranking_reason": "仅有的可行路线,总距离最短" }, "deep_links": { "personal_map": null, "android_route_plan": "androidamap://route?...", "ios_route_plan": "iosamap://route?..." }, "summary": "本次规划从北京站出发,途经王府井,最终到达天安门,总距离约5.87公里,总耗时约33分钟,符合最短距离策略要求。", "warnings": [ "路线时长受实时交通状况影响,实际行驶可能存在偏差", "若起点为当前位置,最优路线可能随定位变化调整" ] } ``` ### 5.2 顶层字段说明 - `success` - 是否成功生成路线规划结果 - `origin_mode` - 与请求保持一致 - `resolved_origin` - `origin_mode=fixed` 时通常不为 `null` - `origin_mode=current_location` 时通常为 `null` - `resolved_destination` - 终点解析结果 - `resolved_stops` - 所有途经点解析结果 - `candidates` - 所有候选路线 - `best_route` - 被选中的最佳路线 - `deep_links` - 给前端做按钮跳转使用 - 这是唯一应被前端当作链接处理的字段 - 当前成功结果至少会包含 `personal_map` - `summary` - 可直接展示给用户的简要说明 - 这是纯展示文案,不是结构化链接字段,也不应被前端解析为跳转地址 - `warnings` - 风险提示和降级说明,前端建议展示 ## 6. 关键嵌套结构说明 ### 6.1 ResolvedPoint - `role` - `origin`、`stop`、`destination` - `input_name` - 原始输入名 - `input_address` - 原始输入地址 - `resolved_name` - 实际命中的名称 - `city` - 城市名 - `district` - 区县名 - `location` - `lon,lat` 字符串 - `lon` - 经度 - `lat` - 纬度 - `poi_id` - 高德 POI ID,可能为空 - `source` - `geo`、`text_search`、`search_detail`、`manual_fallback` - `confidence_note` - 命中说明 ### 6.2 CandidateRoute - `stop_order_labels` - 仅包含中间途经点顺序 - `full_order_labels` - 包含起点和终点的完整顺序 - `legs` - 每段路线信息 - `total_distance_m` - 总距离,单位米 - `total_duration_s` - 总时长,单位秒 - `ranking_reason` - 为什么这条路线被这样排序 ### 6.3 DeepLinks - `personal_map` - 点位导入型链接 - 适合把一组点位导入到高德地图 - 更偏“查看/导入点位方案”,不是严格的即时导航协议 - `android_route_plan` - Android 导航链接 - `ios_route_plan` - iOS 导航链接 补充说明: - `deep_links` 中可能同时存在多个字段,也可能只有其中一个字段有值 - 当前实现中,成功结果会强制生成 `personal_map` - 前端应只根据 `deep_links` 的字段值控制按钮展示,不要依赖 `summary` 推断应展示哪个按钮 - `summary` 里可能会提到“个人地图链接”或“导航链接”,但这里只是说明文字,不保证包含真实 URL - 如果 `personal_map` 存在,表示当前更适合导入点位方案 - 如果 `android_route_plan` 或 `ios_route_plan` 存在,表示当前可以直接拉起导航 前端建议: - 如果值为 `null`,对应按钮不要展示 - 如果 `warnings` 非空,建议在页面显式展示提示 - `summary` 只用于文案展示,不要从 `summary` 中抽取链接或做业务判断 ## 7. 错误响应 ### 7.1 422 输入或护栏错误 出现以下情况时,接口会返回 422: - 请求结构不合法 - `stops` 为空 - `need_deep_link=false` - 固定起点缺少 `origin_address` - 终点同时出现在 `stops` - 任意点未能解析到足够精确的 POI - 任意点缺少 `poi_id` - 请求候选上限超过服务上限 - 实际排列数超过上限 错误可能有两种形态。 形态一:FastAPI/Pydantic 字段校验错误 ```json { "detail": [ { "type": "value_error", "loc": ["body"], "msg": "Value error, stops must contain at least one stop", "input": { "origin_mode": "fixed", "origin_address": "北京站", "destination_address": "天安门", "stops": [] } } ] } ``` 形态二:服务护栏错误 ```json { "detail": "Candidate permutations exceed the configured limit: stops=4, permutations=24, limit=20" } ``` ### 7.2 503 配置错误 出现以下情况时,接口会返回 503: - 模型配置缺失 - MCP 配置缺失 - MCP transport 非法 错误示例: ```json { "detail": "Missing required environment variable: AMAP_MCP_URL" } ``` ### 7.3 500 内部错误 模型运行失败、第三方异常或未预期错误会返回 500。 ### 7.4 504 上游超时 当模型服务或地图 MCP 服务超时,接口会返回 504。 错误示例: ```json { "detail": "Upstream request timed out: ..." } ``` 前端建议: - 422 显示明确的用户提示 - 503 显示“服务暂不可用” - 504 显示“请求处理超时,请稍后重试” - 500 显示通用错误提示,并建议重试 ## 8. 前端对接建议 - 直接按 `summary`、`best_route`、`warnings` 渲染即可完成第一版页面 - 如果需要路线详情页,可渲染 `candidates` 对比卡片 - 统一使用 `deep_links` 控制跳转按钮显隐 - 对 `warnings` 保持可见,不要吞掉 - 对 `current_location` 场景,要准备接受 `resolved_origin=null` ## 9. 当前接口现状 - 当前接口已经可用 - 当前已验证真实请求可成功返回结果 - 当前返回结构已稳定,可作为第一版前端对接基础 - 当前 `need_html` 还未真正实现 HTML 返回,不建议前端依赖该字段做页面内容请求 ## 10. 对接 TODO - 前端确认是否需要候选路线对比视图 - 前端确认 deep link 的按钮交互形式 - 前后端统一 422 错误展示文案 - 后续若输出结构调整,需要同步更新本文档