(四)路书Agnet-综合天气距离交通节奏等多因素来编排旅行路线

这是 RouteBook Agent 开发记录的第四篇。上一篇介绍了工作流循环如何让需求补问、地点确认和行程修改逐步收敛。

这一篇进入路书最核心的部分:用户选好地点以后,系统怎样综合天气、距离、交通方式和旅行节奏,把它们编排成一份真正可执行的分日路线。

项目地址:github.com/lukeSuperCo...

一、路线规划不是把景点平均分到几天

经过需求理解和地点确认以后,系统已经拿到一组真实 POI。以北京三日游为例,用户可能选择了故宫、天安门、国家博物馆、景山公园、颐和园、圆明园和八达岭长城。

每个地点都有高德 POI ID、经纬度、行政区和类别,但这些数据还不是行程。

如果简单按照选择顺序平均分配,可能把故宫和八达岭放在同一天,也可能在雨天安排大量户外活动。看起来每天都有内容,实际却需要频繁跨区,交通时间甚至比游览时间还长。

所以当前项目把路线编排看成一个多因素约束问题:

text 复制代码
天气情况
+ 地点距离
+ 交通方式
+ 旅行节奏
+ 必去和排除规则
+ 每日活动与交通上限
= 分日行程和日内路线

完整过程不是让模型一次生成最终答案,而是分成几步:

text 复制代码
检查真实地点
→ 获取旅行日期的天气
→ 按区域、天气和每日容量分配地点
→ 优化每天的游览顺序
→ 查询高德正式路线
→ 校验距离、耗时和跨区约束
→ 不可行时有限修复
→ 保存分日行程并展示地图

二、旅行节奏先决定每天的容量

同样三个景点,对不同用户可能意味着完全不同的强度。

当前项目把旅行节奏分为轻松、适中和紧凑三档。每一档不仅限制地点数量,还限制活动时间、全天交通时间和单段交通时间:

节奏 每日地点 活动时长 交通总时长 单段交通
轻松 最多 2 个 420 分钟 120 分钟 75 分钟
适中 最多 3 个 540 分钟 180 分钟 100 分钟
紧凑 最多 4 个 660 分钟 240 分钟 120 分钟

代码中,这些限制被定义为确定性的容量模板:

python 复制代码
CAPACITY_TEMPLATES = {
    "relaxed": DailyCapacity(
        maximum_places=2,
        maximum_activity_minutes=420,
        maximum_transport_minutes=120,
        maximum_segment_minutes=75,
    ),
    "moderate": DailyCapacity(
        maximum_places=3,
        maximum_activity_minutes=540,
        maximum_transport_minutes=180,
        maximum_segment_minutes=100,
    ),
    "compact": DailyCapacity(
        maximum_places=4,
        maximum_activity_minutes=660,
        maximum_transport_minutes=240,
        maximum_segment_minutes=120,
    ),
}

这样,"轻松一点"不再只是一句写进攻略的文案,而会真正减少每天的地点数和可接受交通时间。

容量模板也是后续校验的边界。即使某几个地点从地图上看距离不远,如果游览时间加起来已经超过当天强度,系统仍然会判定方案不合理。

三、让天气真正参与分日安排

很多行程生成器是在路线排完以后才附上一句"下雨记得带伞"。在 RouteBook Agent 中,天气会更早进入规划过程,直接影响地点被安排到哪一天。

规划开始时,系统先根据旅行日期调用和风天气逐日预报,再把天气归纳为三种倾向:

text 复制代码
雨、雪、雷暴、雾等不利天气 → 优先室内
晴、少云                       → 优先户外
其他天气                       → 室内外均衡

地点类别也被分成室内和户外偏好:

python 复制代码
INDOOR_CATEGORIES = {"museum", "dining", "shopping", "religious"}
OUTDOOR_CATEGORIES = {"park", "attraction", "landmark"}

假设北京三日游的天气是:

text 复制代码
第一天:中雨
第二天:晴
第三天:多云

那么国家博物馆等室内地点在第一天的优先级会更高,景山公园、颐和园或长城等户外地点更倾向安排在第二天,第三天则根据区域和剩余容量均衡分配。

实现时,每个地点都会对所有未满的日期计算一个排序值:

python 复制代码
return weather_penalty, len(result[index]), index

三个值依次表示地点类别是否符合当天天气、当天已有地点数量和日期顺序。系统优先选择天气惩罚更低、当前负载更小的日期。

因此,"第一天有雨就安排室内活动"不是模型临时生成的一句建议,而是天气数据实际参与了分日计算。

天气偏好也不是绝对禁令。有雨不代表必须删除所有户外必去地点,晴天也不代表不能参观博物馆。天气只是多个约束之一,还要和必去优先级、区域距离及每日容量共同判断。

如果天气接口暂时不可用,规划器会跳过天气权重,继续按距离和容量生成路线,并把天气标记为 unavailable,而不是编造预报。

四、让距离近的地点尽量安排在同一天

天气解决"哪一天更适合室内或户外",距离解决"哪些地点适合放在一起"。

当前实现先使用城市和行政区做粗粒度聚合:

python 复制代码
grouped[f"{place.city}:{place.district}"].append(place)

同一区域的地点优先作为一组进入分日安排,必去地点优先于普通推荐地点,避免普通候选先占满容量。

例如故宫、天安门和景山空间上接近,更容易进入同一天;颐和园和圆明园可以组成另一天;八达岭距离市区较远,后续正式路线校验会避免它与多个市中心地点混排。

初始分日的决策顺序可以概括为:

text 复制代码
必去地点优先
→ 同城市、同行政区优先聚合
→ 符合当天的天气类型优先
→ 不超过旅行节奏规定的每日容量
→ 各天地点数量尽量均衡

行政区不是最终距离。两个地点即使在同一个区,也可能相距较远;相邻地点也可能跨越行政区。因此它只用于低成本地缩小搜索空间,后面还要继续进行日内排序和正式路线验证。

五、用"最近邻 + 2-opt"优化日内顺序

地点分配到某一天后,还要决定先去哪里、再去哪里。

当前项目先用最近邻算法生成初始顺序:从第一个地点出发,每一步选择距离当前地点最近的未访问地点。

python 复制代码
while remaining:
    next_place = min(
        remaining,
        key=lambda item: distance_meters(current, item),
    )
    ordered.append(next_place)

初始排序使用经纬度估算直线距离,并根据平均纬度修正经度方向的尺度。最近邻速度快,但可能产生局部绕路,所以系统再执行有限 2-opt:尝试反转路线中的一段,只要总长度变短就保留新顺序。

text 复制代码
A → B → C → D

尝试反转 B 到 C

A → C → B → D

当前最多执行四轮改进,足以消除小规模路线中的明显交叉和绕行,又不会引入过高计算成本。

这一步使用的仍然是直线距离,只负责快速得到候选顺序。展示给用户的正式公里数和耗时,必须由高德道路路径验证。

六、交通方式和正式路线怎样参与校验

日内顺序确定后,后端对相邻地点逐段查询高德路径:

text 复制代码
地点 A → 地点 B
地点 B → 地点 C
地点 C → 地点 D

当前适配器接入了高德驾车和步行路径规划接口:

python 复制代码
/v5/direction/driving
/v5/direction/walking

当交通方式为 walking 时调用步行接口,其他模式在当前版本暂时走驾车接口。公共交通、骑行和混合出行已经在领域模型中预留,但还需要接入对应的供应商路径能力。

高德返回的距离和耗时会被保存为结构化路线段:

python 复制代码
PlannedSegment(
    origin_place_id=left.id,
    destination_place_id=right.id,
    mode=mode,
    distance_meters=route.distance_meters,
    duration_seconds=route.duration_seconds,
    provider=route.provider,
    status=route.status,
)

正式路线结果会反过来参与可行性检查:

  • 全天交通总时长是否超过当前旅行节奏;
  • 任意一段交通是否过长;
  • 是否同一天跨越三个以上行政区且路线超过 60 公里;
  • 用户不接受远郊时,是否出现超过 30 公里的市区与远郊混排;
  • 地点数量和活动时间是否超过当天容量。

因此,距离和交通方式不是地图展示阶段才使用的数据,它们会直接决定当前分日方案能否被提交。

如果发现可修复冲突,规划器会调整普通候选地点并再次验证,最多进行三轮。如果必去地点、旅行天数和交通上限无法同时满足,系统返回结构化冲突,不能通过删除必去地点或伪造更短耗时让方案通过。

高德接口暂时失败时,对应路线段会标记为 unverified。行程可以降级生成,但不会把估算数据伪装成已经验证的道路事实。

七、多因素编排是怎样组合起来的

天气、距离、交通方式和旅行节奏并不是简单加成一个总分,而是在不同阶段解决不同问题:

阶段 主要因素 解决的问题
规划前检查 POI、必去、排除 地点能否进入规划
每日容量 旅行节奏 每天能安排多少内容
分日选择 天气、区域、优先级 地点应该放在哪一天
日内排序 经纬度距离 当天按什么顺序游览
正式验证 交通方式、道路距离、耗时 路线是否真的可执行
修复循环 容量、跨区、远郊、优先级 不可行时怎样有限调整

以"第一天有雨的北京三日游"为例,整个决策过程可能是:

text 复制代码
第一天有雨
→ 室内地点获得更高分日优先级
→ 国家博物馆等室内地点进入第一天

故宫、天安门、景山距离较近
→ 优先聚合到同一组
→ 最近邻和 2-opt 调整游览顺序

用户选择轻松节奏
→ 每天最多安排两个主要地点
→ 超出容量的普通候选被调整

用户选择步行
→ 相邻地点调用高德步行路径
→ 单段或全天步行时间过长则触发冲突

方案通过校验
→ 保存每天的地点顺序、路线段、天气和提示

这种分层设计比"让模型综合考虑所有条件"更容易验证。每一步都有明确输入、规则和输出,出现不合理结果时也能判断问题来自天气分类、区域分组、容量模板还是正式路径。

八、怎样把规划结果展示在地图上

规划完成后,路书版本中保存三类核心数据:

text 复制代码
places:地点名称、地址和经纬度
days_plan:每天的地点 ID 与顺序
route_segments:相邻地点的交通方式、距离和耗时

前端读取同一份结构化快照,而不是从聊天文本重新猜测路线。

分日面板展示每天的地点顺序、相邻路段公里数和预计耗时;地图使用高德 JavaScript API 创建编号 Marker,并通过 AMap.Driving 绘制相邻地点之间的道路路线。

后端和前端调用路径能力的目的不同:

text 复制代码
后端高德 Web 服务:计算和保存可信距离、耗时,用于业务校验
前端高德 JS API:绘制线路、缩放视野和响应地图交互

如果没有配置高德 JS Key 或 SDK 加载失败,页面会降级为内置坐标视图,仍然保留地点编号和相对路线。

当前地图主视图使用 AMap.Driving 绘制驾车道路形状。若要让折线严格跟随每段交通方式,后续还需要根据 segment.mode 接入步行、骑行和公共交通绘制插件。

九、这一阶段的体会

路线规划真正困难的地方,不是生成一句"第一天游览故宫和天安门",而是让这句话同时满足天气、距离、交通和旅行强度约束。

如果第一天有雨,天气应该改变地点分配;如果两个景点距离近,它们应该尽量进入同一天;如果用户想轻松游,每日地点数和交通时间都应该下降;如果选择步行,路线能否执行必须用步行耗时重新判断。

当前实现还不是一个通用的最优旅行求解器。天气使用的是类别级偏好,初始聚合主要依赖行政区,公共交通和多模式地图绘制也需要继续扩展。但它已经建立了一条可以解释和验证的技术链路:

text 复制代码
真实 POI
→ 天气与节奏参与分日
→ 距离参与聚合和排序
→ 交通方式与正式路线验证可行性
→ 结构化路书统一保存
→ 分日列表和地图读取同一份结果

这使 RouteBook Agent 生成的不再只是一段旅行攻略,而是一份知道每天去哪里、为什么这样安排,以及地点之间应该怎么走的结构化路书。

相关推荐
神奇的程序员1 小时前
在这个独属于ai的时代,我终究是被裁员了
前端·后端·面试
云边有个稻草人1 小时前
从单机工具到“云+端+服务”:KDMS数据库迁移工具如何支撑大型信创项目协同作战
后端
玉宇夕落1 小时前
React + JWT 登录鉴权系统
前端
李广坤1 小时前
AgentScope Tool 热更新技术方案:不重启服务,实时管控 Agent 工具
后端·架构
hunterandroid1 小时前
[鸿蒙从零到一] HarmonyOS 安全加固与数据保护实战:从密钥管理到反调试的全链路防护
前端
用户921080262861 小时前
从 Bubble 到 BubbleList:加载历史对话时才真正看懂组件通信
前端
hunterandroid1 小时前
Android WebView JSBridge 治理实战:从线上白屏崩溃到协议化通信
android·前端
ttwuai1 小时前
Go 后台接入 SSO 后菜单正常但接口 403,怎么排查权限链路?
开发语言·后端·golang
意疏1 小时前
2026年远控软件安全横评:六款主流工具逐项核查——官方文档、一手实测与安全事件,全摊开
大数据·前端·数据库