跳到主内容
快讯直播
AI智模界
教程

用 AI 把目的地变成可执行行程的实战教程

很多人用 AI 写旅游攻略,得到的结果是"上午参观博物馆,下午漫步老城区"这种看着对、用起来空的文字。问题不在模型,而在于把"写攻略"当成了写作文,而不是生成一份可执行的结构化数据。

这篇教程做一件事:输入一个目的地和几天时间,输出一份能直接照着走的行程表——每天几点到几点、去哪、怎么去、大概多久、哪些信息需要出发前再确认。沿途会给出可直接照抄的提示词模板、数据结构和校验脚本。

这篇能做出什么

完成后你会得到三样东西:

1. 一份标准的行程 JSON,字段固定,便于后续加工;

2. 一份 Markdown 版行程表,能直接发到群里或存进备忘录;

3. 一个自动校验脚本,能提前发现时间冲突、一天塞太满、跨城来回跑这类低级错误。

整条流程是:把模糊需求变成结构化输入 → 让模型只做它擅长的事(聚类、排序、给备选)→ 用脚本做机械校验 → 用地图和官方页面补真实信息。模型负责"编排",真实数据必须来自权威渠道。

前置条件清单

  • 一个能调用大模型 API 的账号和密钥,模型名、接口地址以所用服务商的官方文档当前版本为准。
  • Python 3.9 以上环境,能联网安装依赖。
  • 基础的命令行操作能力,会设置环境变量即可。
  • 出行日期、天数、同行人构成、预算量级、必去和必不去的地点。
  • 一个地图应用和一个搜索引擎,用来核对景点是否开放、车程是否合理。

安装依赖:

```bash

pip install openai

```

设置密钥(不要把密钥写进代码文件):

```bash

export OPENAI_API_KEY="你的密钥"

export OPENAI_BASE_URL="你的接口地址(如服务商要求)"

```

OPENAI_BASE_URL 是否需要设置,取决于所用服务商,以官方文档当前版本为准。

步骤一:把模糊需求写成结构化输入

先别急着写提示词。把需求整理成一段固定格式的文本,后面所有环节都复用这个结构:

```yaml

目的地: 京都

出行日期: 2025-04-05 至 2025-04-08

天数: 4

同行人: 两位成人,一位 65 岁长辈,步行耐力一般

节奏: 每天 2 到 3 个主要景点,下午留 1 小时机动

住宿区域: 京都站附近

必去: 伏见稻荷、岚山竹林

不去: 需要长时间爬山的路线、夜间酒吧街

预算量级: 中等,不追求高档餐厅

饮食限制: 不吃生食

其他: 不接受一天换两次住宿

```

这段内容越具体,后面返工越少。"步行耐力一般"这种描述比"轻松一点"有用得多,模型能据此把坡道和长距离步行排除掉。

步骤二:定义行程的数据结构

先定字段,再让模型往里填。这样输出的东西天然可校验、可渲染。

```json

{

"destination": "京都",

"days": [

{

"date": "2025-04-05",

"theme": "抵达与市区适应",

"items": [

{

"start": "14:00",

"end": "16:00",

"title": "景点或活动名称",

"area": "所在区域",

"transport": "从上一站过来的方式与大致耗时",

"duration_min": 120,

"tip": "需要注意的一句话",

"need_confirm": true

}

],

"notes": "当天整体提醒"

}

]

}

```

几个字段是刻意加的:

  • area 用来做地理聚类,避免一天在东边一天在西边来回横跳;
  • duration_min 让脚本能算总时长;
  • need_confirm 标记哪些信息必须出发前自己核实,比如开放时间、是否需预约;
  • transport 只写方式和量级,具体车次以地图应用为准。

步骤三:写系统提示词

把规则写死在AI 词典:系统提示词">系统提示词里,用户消息只放具体目的地信息。提示词模板建议存成单独文件,方便复用和迭代。

```text

你是一名行程编排助手。你的任务是把目的地需求整理成结构化行程,不是写散文。

硬性规则:

1. 只输出 JSON,不要输出任何解释、前言、Markdown 代码块标记。

2. 严格遵循给定的 JSON 结构,字段名不要改,不要新增字段。

3. 每天安排 2 到 3 个主要项目,项目之间按地理位置聚类,同一区域的项目放在同一天。

4. 时间使用 24 小时制 HH:MM,同一天的项目时间不得重叠,且按时间升序排列。

5. 不要编造具体地址、电话、票价、营业时间。凡是这类信息,把 need_confirm 设为 true,

并在 tip 里写"出发前请核实开放时间"。

6. 不确定的景点或店铺,宁可不写,也不要凭空生成名称。

7. 考虑同行人的体力,连续两天不要安排强度相近的远距离路线。

8. 全部用中文输出,专有名词可保留原文。

输出格式:{"destination": "...", "days": [...]}

```

第 5、6 条很关键。模型对具体营业时间的记忆经常滞后,让它主动标"待确认",比让它编一个像真的时间更安全。

步骤四:调用模型生成行程

下面是一个可直接运行的脚本,读取提示词文件与需求文件,输出 JSON。

```python

import json

import os

from pathlib import Path

from openai import OpenAI

client = OpenAI(

api_key=os.environ["OPENAI_API_KEY"],

base_url=os.environ.get("OPENAI_BASE_URL"),

)

MODEL = "以所用服务商官方文档当前推荐的模型为准"

system_prompt = Path("system_prompt.txt").read_text(encoding="utf-8")

trip_input = Path("trip.yaml").read_text(encoding="utf-8")

resp = client.chat.completions.create(

model=MODEL,

messages=[

{"role": "system", "content": system_prompt},

{"role": "user", "content": f"请根据以下需求生成行程:\n{trip_input}"},

],

temperature=0.4,

response_format={"type": "json_object"},

)

raw = resp.choices[0].message.content

Path("itinerary_raw.json").write_text(raw, encoding="utf-8")

print("已保存,长度:", len(raw))

```

说明几点:

  • response_format 是否支持、字段名如何写,以所用服务商官方文档当前版本为准。不支持时,去掉该参数,改用下面的清洗函数。
  • temperature 设低一些,行程编排属于结构化任务,不需要发挥。
  • 把原始输出单独存一份文件,出问题时可回溯,不用重新花钱调接口。

如果模型把 JSON 包在代码块或解释文字里,用这个函数兜一下:

```python

import json

import re

def extract_json(text: str) -> dict:

text = text.strip()

if text.startswith("```"):

text = re.sub(r"^```[a-zA-Z]*\n?", "", text)

text = re.sub(r"\n?```$", "", text)

start = text.find("{")

end = text.rfind("}")

if start == -1 or end == -1:

raise ValueError("未找到 JSON 内容")

return json.loads(text[start:end + 1])

```

步骤五:写校验脚本,别信自己的眼睛

模型输出的行程一定有细节问题,靠肉眼看不出来。用脚本做机械校验,几秒钟跑完。

```python

import json

from datetime import datetime

def to_min(hhmm: str) -> int:

t = datetime.strptime(hhmm, "%H:%M")

return t.hour * 60 + t.minute

def check(path: str) -> None:

data = json.load(open(path, encoding="utf-8"))

problems = []

for day in data["days"]:

date = day["date"]

items = day["items"]

1. 时间是否重叠

for a, b in zip(items, items[1:]):

if to_min(a["end"]) > to_min(b["start"]):

problems.append(f"{date} 时间重叠:{a['title']} 与 {b['title']}")

2. 单日总时长是否超载

busy = sum(to_min(i["end"]) - to_min(i["start"]) for i in items)

if busy > 9 * 60:

problems.append(f"{date} 安排过满,共 {busy // 60} 小时")

3. 是否跨区域太频繁

areas = [i["area"] for i in items]

if len(set(areas)) > 2:

problems.append(f"{date} 涉及 {len(set(areas))} 个区域,建议合并")

4. 待确认项统计

todo = [i["title"] for i in items if i.get("need_confirm")]

if todo:

print(f"[{date}] 需出发前核实:{'、'.join(todo)}")

if problems:

print("发现问题:")

for p in problems:

print(" -", p)

else:

print("基础校验通过,仍需人工核对开放信息。")

check("itinerary_raw.json")

```

这个脚本只做四件事:时间不重叠、单日不超载、区域不散、把待确认项列出来。发现"某天涉及 4 个区域"这类问题,直接回到提示词里补一条"每天区域不超过 2 个",重新生成。

步骤六:渲染成能用的行程表

JSON 自己看很累,转成 Markdown 表格。下面这段代码不依赖额外库。

```python

import json

def render(path: str) -> str:

data = json.load(open(path, encoding="utf-8"))

out = [f"# {data['destination']} 行程\n"]

for day in data["days"]:

out.append(f"## {day['date']} {day.get('theme', '')}\n")

out.append("| 时间 | 安排 | 区域 | 交通 | 备注 |")

out.append("| --- | --- | --- | --- | --- |")

for i in day["items"]:

flag = "(待核实)" if i.get("need_confirm") else ""

out.append(

f"| {i['start']}-{i['end']} | {i['title']}{flag} | {i['area']} "

f"| {i['transport']} | {i['tip']} |"

)

if day.get("notes"):

out.append(f"\n> {day['notes']}\n")

return "\n".join(out)

md = render("itinerary_raw.json")

open("行程.md", "w", encoding="utf-8").write(md)

print(md)

```

生成后建议再做一件事:把每天的行程单独复制到日历应用或备忘录,出行时离线也能看。JSON 文件留在电脑里,临时改行程时改 JSON 再重新渲染,比手改 Markdown 省事。

步骤七:把"待确认"逐条落实

这是最容易被跳过、却决定攻略能不能用的一步。带着 need_confirm 列表,按顺序核对:

1. 景点是否开放、是否需要预约、有无闭馆日。以景区或场馆官方页面为准。

2. 交通耗时用地图应用实测一次,不要用模型给的时间。

3. 门票、交通卡、当地交通规则,以官方渠道的信息为准。

4. 天气与季节因素。把出行日期的天气情况重新贴回提示词,让它调整室内外安排。

核对完,把 need_confirm 改成 false,或者把确认到的信息写进 tip。这份 JSON 就成了真正可执行的行程。

常见坑与排错

坑一:模型编出不存在的景点或店铺。

症状是名字听起来很合理,搜索查不到。对策是在提示词里明确"不确定就不写",并且对每个地名都搜一次。地名核对是人工环节,不要指望模型自查。

坑二:营业时间、票价写成具体数字。

这类信息变化快,模型给的多半是旧值。对策是提示词里禁止输出具体时间与价格,统一标"待核实"。

坑三:一天排了六个景点,看着很赚,实际走不动。

对策是用校验脚本卡单日总时长上限,并在提示词里写明同行人构成。带长辈和带孩子是两种完全不同的排法。

坑四:地理上东一个西一个。

对策是把"每天区域不超过 2 个"写进硬性规则,并用校验脚本检查。注意模型给的车程往往偏乐观,实际以地图应用为准。

坑五:输出被截断或夹带解释文字。

长行程容易超出单次输出上限。对策是按天拆分生成:先让模型给整体框架,再逐天生成细节,最后合并 JSON。

坑六:JSON 解析失败。

先看原始输出有没有被代码块包住,用前面的 extract_json 处理;仍然失败就降低温度重新生成,或要求模型"只输出 JSON"。

坑七:把一个目的地直接换成另一个,结果全是套话。

不同城市的交通结构差别很大。换目的地时,把当地交通方式、是否需要租车、景点分布特征补充进输入,不要只改地名。

下一步建议

跑通基础流程后,可以往几个方向延伸:

  • 加预算表:让模型只输出"消费项类别 + 量级",具体金额留空,出行前按官方渠道填写。
  • 多方案对比:同一目的地生成"紧凑版""轻松版"两套行程,把校验结果作为选择依据。
  • 接入地图服务:用地图接口替换模型估算的车程,这一步能把行程的可用性提升一个档次。接口用法以对应服务商官方文档当前版本为准。
  • 做成模板库:把不同场景(亲子、长辈同行、单人短途、出差顺路游)的输入模板存下来,下次只改日期和目的地。
  • 沉淀复盘:行程走完后,把实际耗时和计划耗时的差异记回 JSON,下次生成时作为约束条件喂给模型。

核心思路只有一句:让模型做它擅长的编排与聚类,把事实核查交给官方渠道和地图应用。只要守住这条边界,AI 写出来的就不只是攻略,而是一份能直接照着走的行程。

AI 生成本文由 AI 基于公开信息自动生成,仅供参考。