13 KiB
13 KiB
Geo Agent API 对接文档
1. 文档目的
本文档面向前端对接,说明当前可用接口、请求结构、响应结构、错误语义和对接建议。
2. 服务概览
当前服务提供两个 HTTP 接口:
GET /healthzPOST /route/planPOST /load/plan
默认本地开发地址示例:
http://127.0.0.1:8000
2.1 Authorization
除 GET /healthz 外,当前业务接口都需要通过 Authorization 请求头进行鉴权。
请求头格式:
Authorization: <AGENT_HTTP_AUTH_KEY>
说明:
- 不使用
Bearer前缀 - 服务端从
.env中读取AGENT_HTTP_AUTH_KEY - 如果服务端未配置该值,请求会返回
503 - 如果请求头缺失或值不匹配,请求会返回
401
2.2 CORS
当前服务已启用 CORS。
- 默认允许本地开发来源:
localhost和127.0.0.1的任意端口 - 当前默认允许的方法:
GET、POST、OPTIONS - 当前默认允许所有请求头
- 如果前端部署到其他域名,需要后端调整
.env中的 CORS 配置
3. 健康检查
3.1 请求
GET /healthz
3.2 成功响应
{
"status": "ok"
}
4. 路线规划接口
4.1 请求
POST /route/plan
Authorization: <AGENT_HTTP_AUTH_KEY>
Content-Type: application/json
4.2 请求体
{
"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_addressorigin_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 响应示例
{
"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_originorigin_mode=fixed时通常不为nullorigin_mode=current_location时通常为null
resolved_destination- 终点解析结果
resolved_stops- 所有途经点解析结果
candidates- 所有候选路线
best_route- 被选中的最佳路线
deep_links- 给前端做按钮跳转使用
- 这是唯一应被前端当作链接处理的字段
- 当前成功结果至少会包含
personal_map
summary- 可直接展示给用户的简要说明
- 这是纯展示文案,不是结构化链接字段,也不应被前端解析为跳转地址
warnings- 风险提示和降级说明,前端建议展示
6. 关键嵌套结构说明
6.1 ResolvedPoint
roleorigin、stop、destination
input_name- 原始输入名
input_address- 原始输入地址
resolved_name- 实际命中的名称
city- 城市名
district- 区县名
locationlon,lat字符串
lon- 经度
lat- 纬度
poi_id- 高德 POI ID,可能为空
sourcegeo、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 字段校验错误
{
"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": []
}
}
]
}
形态二:服务护栏错误
{
"detail": "Candidate permutations exceed the configured limit: stops=4, permutations=24, limit=20"
}
7.2 503 配置错误
出现以下情况时,接口会返回 503:
- 模型配置缺失
- MCP 配置缺失
- MCP transport 非法
错误示例:
{
"detail": "Missing required environment variable: AMAP_MCP_URL"
}
7.3 500 内部错误
模型运行失败、第三方异常或未预期错误会返回 500。
7.4 504 上游超时
当模型服务或地图 MCP 服务超时,接口会返回 504。
错误示例:
{
"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 错误展示文案
- 后续若输出结构调整,需要同步更新本文档
11. 装载规划接口
11.1 请求
POST /load/plan
Authorization: <AGENT_HTTP_AUTH_KEY>
Content-Type: application/json
11.2 请求体
{
"merchant_id": 1,
"area": "中大",
"license_plate": "粤A4Y0Y5"
}
11.3 请求字段说明
merchant_id- 必填
- 商户 ID
area- 必填
- 按区域筛选待出货出货单,精确匹配
license_plate- 必填
- 目标运输车辆车牌号
11.4 成功响应示例
{
"success": true,
"license_plate": "粤A4Y0Y5",
"selected_shipment_ids": [13],
"summary": "待出货出货单共1个,出货单ID13的销售品幅宽均为170cm,判定为针织面料,包含2条销售品,未超过车辆针织最大装载容量120条,因此选择该出货单进行装载。",
"warnings": [
"当前装载条数为2条,未达到针织面料最大运输容量120条,属于欠载方案。"
]
}
11.5 响应字段说明
success- 是否成功完成装载规划
license_plate- 本次规划对应的车牌号
selected_shipment_ids- 被选中的出货单 ID 列表
summary- 可直接展示给用户的装载说明
warnings- 欠载、字段缺失、无法判定面料等提示信息
11.6 错误语义
401Authorization请求头缺失或值不正确
422- 装载规则护栏错误或输入不满足规划要求
503- 装载模型配置、业务 API 配置或服务端鉴权配置缺失
502- 上游业务 API 返回错误,例如车辆不存在或接口请求失败
504- 装载模型或业务 API 超时
500- 未预期的内部错误
11.7 当前行为说明
- Agent 会先查询指定
area的未出货出货单,再查询指定车牌的车辆容量 - 面料类型仅通过
sales_items[].printing_job_width判断 - 装载量按销售品条数计算,不按
quantity长度或米数计算 - 默认不允许混装针织和梭织
- 优先选择不超载且尽量接近最大容量的方案
- 如果只能欠载,会在
warnings中明确提示