多版本行程归一合并 (Trip Itinerary Merger)
Overview
把来源混杂的多版本旅行信息合并为单一可信日程。核心价值:出发前自动发现时间冲突(航班 vs 活动、景点预约重叠、交通衔接不足),避免"落地才发现活动订重了 / 赶不上飞机"。同时覆盖费用均摊(含汇率)、待办追踪(预约/签证/订票)与当地风俗风险提示。
触发场景
当用户出现以下任一请求时使用本 skill:
- "帮我把这些行程合并一下" + 多份素材(聊天记录、截图、PDF、攻略文本)
- "整理一份行程表" / "行程归一" / "帮我校对行程有没有冲突"
- "算一下这次旅行人均多少钱" / "费用均摊 / AA"
- "生成日历行程" / "导出 ICS"
- 出行前检查:签证、预约、订票待办清单,当地风俗风险
输入类型 → 解析方式
| 输入类型 | 解析方式 |
|---|---|
| 聊天行程草稿 | 直接读取文本,提取日期/时间/地点/活动/人名/金额 |
| 截图行程 | 用 Read 工具读取图片(多模态识别),逐项提取文字与时间 |
| 机票/酒店订单 PDF | 用 Read 工具直接读取 PDF,提取航班号、起降时间、航站楼、酒店名、入住/退房日期、订单号 |
| 网页/攻略片段 | 直接读取文本或 WebFetch,提取推荐景点/餐厅/活动,标注为"建议"而非"已确认" |
工作流
Step 1: 收集与解析
- 列出用户提供的所有素材,给每份素材分配来源版本号(如"聊天 v1"、"订票截图 v2"、"攻略 v3")
- 逐份解析,抽取原始行程项,暂不做取舍,每项保留
source字段记录来源版本 - 对缺失信息(时间、日期、地点)标记
pending,不猜测;需要用户补充时明确列出待确认项
Step 2: 归一化为统一 JSON
- 按
references/itinerary_schema.md的结构把全部解析结果合并为一个 JSON 文件 - 统一时区:所有事件时间用目的地当地时间表示,用 IANA 时区名标注(如
Asia/Tokyo、Europe/Paris、America/New_York) - 统一地点:合并别名("成田 / 东京成田机场 / NRT" → 标准名),原始写法保留到
notes - 版本差异处理(核心规则):
- 同一时间段多个版本不一致 → 全部保留并标conflict,输出差异表让用户裁决,不自动替用户选
- 明显是草稿更正(同一活动时间被后一版修改)→ 以最新素材为准,并在 notes 注明旧值
- 固定信息(航班、酒店、已付门票)优先于攻略建议:固定项标confirmed,攻略项标suggested - 输出归一化 JSON 供 Step 3-4 的脚本使用,同时保留一份供用户核对的 Markdown 差异说明
Step 3: 冲突检测与交通预留
- 运行
scripts/conflict_check.py <itinerary.json>做自动冲突检测 - 检测规则(完整规则见
references/conflict_rules.md):
- 时间重叠:同一天两个事件重叠
- 交通衔接不足:固定事件(航班/火车/预约)与相邻活动之间缓冲时间不够
- 跨时区疲劳:长途飞行当天活动过密(飞行后安排 ≤1 个轻松活动) - 自动填充交通预留时间(默认值,可在 JSON 的
buffer_before/buffer_after字段覆盖):
- 国际航班:起飞前 180 分钟到达机场
- 国内航班:起飞前 120 分钟
- 火车/大巴:发车前 30-45 分钟
- 景点/餐厅预约:提前 15-30 分钟到场
- 跨城市移动(transfer):90-120 分钟(含交通+行李+找路) - 对每个冲突输出:冲突双方、涉及版本、建议调整方案(如"把 X 提前到 10:00 或取消 Y")
Step 4: 费用计算
- 从素材提取所有费用项到
costs数组(机票、酒店、门票、餐费、交通、购物),字段见 schema - 运行
scripts/cost_split.py <itinerary.json> [--currency CNY] [--rate-file rates.json]:
- 汇率转换:优先用用户提供或--rate-file指定的汇率;否则脚本自动请求公开汇率 API(open.er-api.com),失败则用内置参考汇率并在报告中醒目标记"汇率待确认"
- 按人数均摊:支持按项目指定分摊人(如机票只 2 人分、餐费全员分)
- 输出:按类别汇总、人均分摊、个人结算差额(谁应收 / 谁应补)
Step 5: 输出交付
向用户交付以下内容(按需生成,非全部必须):
- 统一日程表(Markdown 表格,按日期分天):
日期 | 时间(目的地时区) | 行程项 | 地点 | 状态 | 备注 - 日历文件:运行
scripts/build_ics.py <itinerary.json> --output trip.ics,confirmed 项生成 VEVENT,待办生成 VTODO,交付 .ics 文件(可导入 Apple 日历 / Google Calendar / Outlook) - 冲突与差异报告:Step 3 检测结果 + Step 2 版本差异表,需用户裁决的项单独列出
- 待办清单:签证、订票、预约(博物馆/餐厅/交通卡)等,按
references/risk_checklist.md逐项检查 - 费用报表:Step 4 结果
- 风俗与风险提示:按目的地给出当地风俗(着装/小费/拍照禁忌/饮食禁忌/斋月等)、季节风险(天气/旺季/治安)、必要准备(电源插头/电话卡/保险/现金)
交付时用 deliver_attachments 把 .ics、行程 JSON、Markdown 报告一并发出。
脚本说明
scripts/conflict_check.py
python3 conflict_check.py itinerary.json [--buffer-min 30] [--json]
- 默认按内置规则检测重叠 + 缓冲不足;
--buffer-min N全局覆盖最小缓冲分钟数 --json输出结构化 JSON 便于后续处理- 返回码 0 表示无冲突
scripts/build_ics.py
python3 build_ics.py itinerary.json --output trip.ics
- confirmed 与 pending 事件都生成 VEVENT(pending 标 TENTATIVE)
todos数组生成 VTODO(NEEDS-ACTION)- 时间按事件自带时区转 UTC 写入,兼容 Apple/Google/Outlook
scripts/cost_split.py
python3 cost_split.py itinerary.json [--currency CNY] [--rate-file rates.json]
--currency目标币种(默认 CNY)--rate-file手动汇率{"USD": 7.1, "EUR": 7.7, ...},优先于自动获取- 输出:分类汇总、人均、个人结算差额
输出规范
- 行程表用中文,时间用 24 小时制 + 目的地时区(如
2026-10-01 09:00 (Asia/Tokyo)) - 所有生成文件 UTF-8 编码;交付用
deliver_attachments - 汇率未确认时在费用报表顶部醒目标记;冲突未裁决前行程表对应项标
⚠️ 冲突待裁决
示例与演示资产(assets/)
assets/map-demo/ 是完整的端到端示例,可用来演示或测试本 skill:
| 文件 | 说明 |
|---|---|
merged_trip.json |
示例统一行程 JSON(东京 5 日游,5 数据源合并,含故意设置的冲突) |
trip.ics.txt |
由 build_ics.py 生成的日历文件(skillhub 平台不允许 .ics 扩展名,故命名为 .txt,导入日历前请重命名为 trip.ics) |
trip_map.html |
交互式航线行程地图(Leaflet,本地化依赖,双击即可打开):上海⇄东京航线飞行动画、点击目的地查看完整行程、按天筛选、冲突红色脉冲标记、费用汇总与待办清单 |
试用方法:用 merged_trip.json 分别运行三个脚本复现输出,再打开 trip_map.html 查看可视化效果。