不做聊天框:表单 + 分块生成,我如何搭旅行攻略 LLM Copilot

20 阅读11分钟

关键词:LLM Copilot · 表单驱动 · 分块生成 · BYOK · Token 预算


写在前面

这篇文章不是给某一家云厂商打广告。

我做的是一个普通人能拿来就用的旅行攻略生成器:输入行程条件,产出一份完整、可读的 Markdown 攻略。质量标尺很具体——爱旅游的兄弟用 ChatGPT 生成的那份国内攻略,我拿来当参照物,不追求「比 ChatGPT 更强」,追求「同类任务下,结构和可用性接近」。

下文主要讲:产品设计为什么走表单、如何控制 Token、模型怎么拆、分段生成有什么代价。价格几乎不提,只谈 Token 体量——因为换供应商、换额度之后,价格会变,但「一篇攻略大概吃多少 Token」相对稳定。


起因:想要一份「能直接用」的攻略

我自己不做穷游博主,但会出门。身边有一位爱旅游的朋友,他习惯让 ChatGPT 写一整份国内攻略:行前准备、交通、玩什么、按日安排、免责……读起来连贯,能直接当 checklist 用。

我想做的是:

  • 不依赖每次手动跟 ChatGPT 磨 prompt;
  • 不假设用户会聊天、会追问补全;
  • 在浏览器里填完信息,一键生成结构固定的攻略;
  • 部署尽量轻:静态站 + 自备 API Key(BYOK),谁用谁承担调用量。

项目名:Wander Copilot(漫行副驾)。文章里用界面与流程截图说明设计;不附 GitHub 或在线 Demo 链接——若你觉得有用,按下文架构自己搭一版即可。


为什么不做「纯对话 Agent」

早期很自然会想到:做一个旅游对话助手,像 ChatGPT 那样边聊边补全。

实际用起来有两个问题:

  1. 信息凑不齐
    攻略需要结构化字段:几天几夜、往返时间上限、交通方式、是否自驾(车型/动力)、集合地、途经点、勾选景点……纯对话里用户容易漏项,模型只能猜,后面生成会飘。

  2. Token 不好控
    多轮对话要带历史,上下文越长,单次生成本越高,还容易话题粘连。

最近写代码常用 Cursor。它有一种 Ask 式的交互:不是完全自由聊天,而是在关键节点给几个选项,你点选继续。这启发了我——

如果目标是压 Token、拿齐字段,不如把「问答」前移到 表单:每一步收集固定结构,最后序列化成 JSON,灌进各个生成块。模型不做自由发挥,只按块写 assigned 段落。

所以产品定位不是「陪聊型 Agent」,而是 表单驱动的 LLM Copilot:可选 联网检索增强(类工具调用),但主路径是 填表 → 检索(可选)→ 分块生成 → 拼接 Markdown


整体流程(一图读懂)

用户填表(行程 / 交通 / 目的地 / 景点 / 可选参考文)
        ↓
结构化 trip JSON
        ↓
┌───────────────────────────────────────┐
│ ① 联网检索(可选,吃 Token 的大头)      │  ← 当前常用:火山方舟 Responses + web_search
│    景点列表 / 票务摘要 / 配图 URL 等     │
├───────────────────────────────────────┤
│ ② derive(纯代码,0 次模型调用)         │
│    标题 / 摘要 / 票务表格式化 / 免责声明   │
├───────────────────────────────────────┤
│ ③ 分块 LLM 生成(多次短 prompt)         │  ← 推理可走 DeepSeek 等;与搜索可拆供应商
│    行前费用 / 交通 / 玩什么 / 路线 / 按日  │
├───────────────────────────────────────┤
│ ④ stitch:固定 ## 标题 + 正文按序合并    │
└───────────────────────────────────────┘
        ↓
完整 Markdown 攻略(自驾九章 / 火车飞机七章)

交通方式分流

  • 自驾:章节最全(含路线骨架、路网与补给);其中 路线块 + 路网块合并为一次 LLM 请求,输出用分隔符拆开,省一次调用。目前最完善的是这条线——有位爱旅游的兄弟一直在用,我根据他的反馈反复改 prompt 和章节结构,所以下文 Token 样本也以自驾为主。
  • 火车 / 飞机:共用大部分生成逻辑,章节更少,Token 略低;体验与细节仍不如自驾成熟,后续会按同一套「表单 + 分块」继续补。

image.png


模型选型:可替换,而非绑死一家

当前组合只是现阶段可行方案,不是终局。下文 Token 以用量为主;具体人民币请到各平台官网看当期价目(活动、额度会变)。

能力我用过的思路说明
联网搜索火山方舟 Responses API + web_search拉景点、票务摘要、配图等;占 Token 多
分块正文生成曾用 / 可接 DeepSeek 等 OpenAI 兼容端点与搜索拆开,降低对单一平台的依赖
自用部署BYOK:用户自填 Key,密钥仅存浏览器不为读者代付账单

也试过 「DeepSeek 负责推理、火山只负责搜索」:两侧分开算账,某一侧额度紧张时更容易替换。


火山方舟:额度策略与部署约束(自用必读)

若你走火山方舟,建议先弄清计费节奏,避免以为「免费会一直自动停」:

  1. 新人安心体验
    新账号有一段体验期/体验额度,具体规则以火山控制台为准。这边提一嘴,可以在模型推理 - 在线推理 里面创建多个接入点。生成和搜索模型分开用,这样可以用便宜模型进行搜索和内容总结,看个人选择了。

  2. 协作奖励等免费 Token
    体验结束后,仍可能通过「协作奖励」等渠道拿到免费 Token。这类额度用完后会进入按量计费,一般不会像「体验包用尽」那样自动帮你掐断——若 Key 暴露在浏览器或反代配置里,存在继续扣费的风险。自用务必:额度告警、密钥轮换、别把 Key 提交到公开仓库

  3. 请求必须过一层服务
    火山方舟的 API 不能像部分 OpenAI 兼容服务那样,默认就适合「纯静态页 + 浏览器直连」:常见情况是 CORS / 安全策略 要求你至少有一层 后端或边缘反代(Worker、Nginx、自建 BFF 等),由前端把 Key 放在请求头里交给反代转发。
    → 架构上:静态前端 + 反代(或轻量后端)+ 火山,不是「只有 HTML 就能调火山」。

本文不写火山价目表;只强调:免费额度用完 ≠ 自动停服,要自己控量。


替代方案:DeepSeek + 博查(可前端直连)

若希望 尽量少运维、静态页直接打 API,可以换一条组合(我做过对比,未作为唯一终局):

组件作用部署特点
DeepSeek分块正文生成、目的地推理等多数情况下 浏览器可直接请求(以官方文档/CORS 为准)
博查 等搜索 API替代火山侧的联网检索同样常可 前端直连,需自查博查当期计费与 QPS
  • 优点:不必为火山单独养反代;推理与搜索供应商解耦。
  • 缺点:搜索能力与火山 web_search 的整合度、引用格式不同,要重做检索结果到 prompt 的适配;总价需自己在官网相加,本文不代算。

免费 Token 用尽后,也计划把文档更新为「DeepSeek + 博查 / 其他平价搜索」等组合;骨架仍是 OpenAI 兼容 + BYOK,换 endpoint 即可。


Token 预算:一篇攻略吃多少(参考样本)

口径说明:下表来自 自驾 + 完整联网 的内部测试;火车/飞机未在同一成熟度下压测,数字仅供量级参考。

样本条件2 人、自驾 3 天、3 个景点、开启完整联网(与兄弟实测场景接近,你可按自己开关改数字)。

阶段约 Token
POI 票务联网检索~14k
POI 配图联网检索~10k
分块 LLM 生成(约 5 次)~20k
目的地推荐 + 景点拉取~8k
自驾单篇合计~50k~65k

火车 / 飞机 少一块自驾路线生成,大约 ~35k~50k(逻辑通,但产品与 prompt 仍在补齐,不要默认与自驾同质量)。

关闭部分联网后,数字会明显下降——产品里检索是可选开关,不是默认全开。

image.png


设计迭代:为「结果质量」服务,不是为炫技

主要调整都对着最后那份 Markdown 像不像一份真攻略

1. 分块请求,而不是一次塞满

如果把整份攻略交给模型一次写完:

  • 单次 prompt 长、输出长,Token 峰值高
  • 结构容易乱,后期难改某一章。

改成 一章(或一组章)一次请求

  • 每次 prompt 只带该块需要的 trip JSON 片段
  • 模型任务单一,更好控风格
  • 总体 Token 有时反而更省(因为不必反复塞全文历史)。

2. 合并请求的小技巧

自驾场景里,「路线骨架」和「路网与补给」 合并成 一次 LLM 调用,模型输出两段,用分隔符切开再插入——少打一轮 API。

3. 代价:块边界可能有重复

分段之后,个别段落之间会出现轻微内容重叠(例如交通与按日安排都提到某段路)。我对比过 ChatGPT 生成的长攻略,也很难完全避免。当前策略是接受小幅重复,换结构和稳定性——若你后续做后处理,可以加「去重摘要」层,演示版未做。

4. derive:能不用模型就不用

行程摘要、免责声明、部分格式化表格用代码直出,不占用生成 Token,也避免模型「编造」格式。

image.png

image.png


部署:静态站与「要不要反代」

和上一节 模型选型 直接相关:

路线典型形态
火山方舟(含联网搜索)静态前端 + 至少一层反代/后端 转发 /api/v3/* 等;浏览器不宜假设能直连火山
DeepSeek + 博查多数可 前端直连 两家 API(以当时官方 CORS 为准),静态托管即可

我走火山时,用过 边缘反代(如 Cloudflare Worker):

  • 只转发,不存 Key、不记 body
  • Key 由用户在请求头携带;
  • 本地开发可走 Vite proxy,与生产行为一致。

不绑定某一家 Worker;自建可换 Nginx、其他边缘函数。若你选 DeepSeek + 博查且确认能直连,这层可以省略,换自己的 Key 管理策略即可。


需要注意的几件事

  1. 非实时数据
    票价、开放时间来自检索摘要与模型常识,不构成实时承诺,出行请以景区/交通官方为准。

  2. BYOK 与安全
    Key 存在用户浏览器;不要把生产 Key 写进公开仓库。反代只为解决 CORS,不是让你把 Key 托管给第三方。

  3. 不是通用聊天产品
    适合「生成一份完整攻略」,不适合陪聊、改口癖、长期记忆。

  4. 联网越多,Token 越多
    完整联网 + 多景点会接近上文 50k+ 档位;自用可关部分检索。

  5. 供应商与额度
    火山「协作奖励」等免费 Token 用尽后可能继续计费、不会自动掐断;务必自控额度。架构按可替换设计(含 DeepSeek + 博查等前端可直连方案)。

  6. 质量对标的是「任务产出」
    对标的是兄弟那份 ChatGPT 攻略成品,不是对标 ChatGPT 所有能力。


下一步优化(规划中)

Redis 缓存热点目的地

景点列表、票务检索、配图 URL 与目的地强相关,更新频率低。每次生成都重打一遍,浪费检索侧 Token。

可缓存项单次约 Token说明
景点 JSON 列表~5k热门城市命中率高
票务检索~14k
配图检索~10k
合计可省~25k~30k典型篇可从 ~60k 压到 ~30k~35k

分块生成 (~20k) 依赖用户个性化输入(天数、车型、勾选景点),难以缓存,是 Token 下限。

Redis 后端尚在规划,当前个人版本未全上线;文中按「规划 / 完整版」区分,避免过度承诺。

其他

  • 火车 / 飞机路径与自驾对齐体验;
  • 供应商组合文档化(DeepSeek 推理 + 多方搜索);
  • 块边界去重(可选)。

收尾

我做 Wander Copilot,是想证明一件事:

不需要做一个「什么都能聊」的 Agent,只要把任务收窄、把信息用表单收齐、把生成拆块,普通人也能稳定拿到一份够用的攻略。

Token 比价格更值得先算清楚;供应商可以换,表单 + 分块 + BYOK 这套骨架可以留。

如果你也在做类似 Copilot,欢迎按截图里的流程对照实现;有建议可以在评论区聊。


附录:表单收集哪些字段

步骤内容
基本信息出发地、人数、日期、天数、往返时间上限
交通方式自驾 / 火车 / 飞机(自驾含车型与动力)
集合地 / 途经可选
目的地AI 推荐卡片,用户选定
景点联网列表勾选
网络参考可选:搜索攻略摘录作为素材