This commit is contained in:
2026-04-13 16:29:27 +08:00
commit 962209617f
13 changed files with 4342 additions and 0 deletions

431
docs/frontend_api.md Normal file
View File

@@ -0,0 +1,431 @@
# Geo Agent API 对接文档
## 1. 文档目的
本文档面向前端对接,说明当前可用接口、请求结构、响应结构、错误语义和对接建议。
## 2. 服务概览
当前服务提供两个 HTTP 接口:
- `GET /healthz`
- `POST /route/plan`
默认本地开发地址示例:
```text
http://127.0.0.1:8000
```
## 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`
- 可选
- 是否需要生成 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`
- 给前端做按钮跳转使用
- 这是唯一应被前端当作链接处理的字段
- `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` 中可能同时存在多个字段,也可能只有其中一个字段有值
- 前端应只根据 `deep_links` 的字段值控制按钮展示,不要依赖 `summary` 推断应展示哪个按钮
- `summary` 里可能会提到“个人地图链接”或“导航链接”,但这里只是说明文字,不保证包含真实 URL
- 如果 `personal_map` 存在,表示当前更适合导入点位方案
- 如果 `android_route_plan``ios_route_plan` 存在,表示当前可以直接拉起导航
前端建议:
- 如果值为 `null`,对应按钮不要展示
- 如果 `warnings` 非空,建议在页面显式展示提示
- `summary` 只用于文案展示,不要从 `summary` 中抽取链接或做业务判断
## 7. 错误响应
### 7.1 422 输入或护栏错误
出现以下情况时,接口会返回 422
- 请求结构不合法
- `stops` 为空
- 固定起点缺少 `origin_address`
- 终点同时出现在 `stops`
- 请求候选上限超过服务上限
- 实际排列数超过上限
错误可能有两种形态。
形态一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 错误展示文案
- 后续若输出结构调整,需要同步更新本文档