1. 从一句标题说起这个项目到底在做什么国庆黄金周八亿人次的出行洪流抢票、订酒店、排行程、查攻略每年都有人被堵在高速上刷手机骂导航也有人到了目的地才发现博物馆约满了。这个项目的出发点特别朴素能不能让大模型把做攻略这件事彻底接过去用户只需要说一句我十月一号从某地出发带老人和小孩玩四天预算中等不想太累剩下的行程、交通、住宿建议、备选方案全部自动生成而且是在手机本地就能跑得动的轻量交互。技术栈上这个项目用了两块东西蓝耘元生代 MaaS 平台负责模型能力的托管与调用**鸿蒙HarmonyOS**负责端侧的应用承载和系统级能力整合。MaaS 是 Model as a Service 的缩写说白了就是把大模型当成水电一样按需取用你不用自己买卡、搭环境、调推理框架平台把模型部署好你通过 API 或者 SDK 直接调。鸿蒙这边则是利用它的分布式能力和元服务卡片机制把AI 行程规划师做成一个可以随时唤起、跨设备流转的轻应用。适合谁来参考这篇内容三类人。第一类是想做 AI 应用但不想碰底层推理的独立开发者MaaS 这条路能让你一周内出原型。第二类是鸿蒙生态里的应用开发者想知道怎么把大模型能力接进 HarmonyOS 的工程结构里。第三类是产品经理或者做旅游、本地生活方向的从业者想理解AI 行程规划这个场景在工程上到底卡在哪、哪些是真需求哪些是伪需求。我先把结论放前面这个项目最难的地方不是调模型而是行程规划的约束求解和端侧交互的响应体验。模型能写出一篇漂亮的攻略但攻略不等于可执行的行程中间差着一整套结构化校验和兜底逻辑。下面我把整个思路、实现细节、踩过的坑一层层拆开讲。2. 整体架构设计与技术选型思路2.1 为什么选 MaaS 而不是自己部署模型自己部署一个大模型做行程规划听起来很酷实际算一笔账就清醒了。假设你要跑一个 7B 到 14B 参数量的模型推理需要 GPU一张消费级显卡勉强能跑量化版本但并发一上来就崩。国庆这种场景用户请求是脉冲式的可能十分钟内涌进来几千次调用你自己那台机器根本扛不住。而且模型版本迭代快今天调好的 prompt明天换个模型可能效果就变了维护成本极高。MaaS 平台解决的就是这个弹性问题。蓝耘元生代这类平台把模型推理封装成标准接口你按调用量付费流量高峰自动扩容低谷不浪费资源。对独立开发者来说这意味着前期零硬件投入把精力全部放在业务逻辑和交互体验上。我实测下来从注册到跑通第一个对话接口大概二十分钟比配本地环境快太多。选型时我重点看了三个维度模型能力是否覆盖中文行程场景、接口是否稳定、是否支持流式输出。流式输出对行程规划特别重要因为用户不想盯着转圈等十秒边生成边显示体验好很多。这三点蓝耘元生代都满足所以定了它。2.2 鸿蒙端为什么是合适的载体鸿蒙在这个项目里的价值不只是又一个手机系统。它有几个特性刚好戳中行程规划场景元服务卡片用户不用打开完整 App在桌面卡片上就能看到今天的行程摘要点一下展开详情。出行场景里用户是高频短时查看卡片比 App 更合适。分布式流转手机上规划好的行程可以流转到平板或者车机上继续看。一家人出行副驾的人拿平板看路线司机看车机导航数据是打通的。端云协同轻量计算放端侧重模型调用放云端鸿蒙的这套机制天然适配 MaaS 的调用模式。我试过纯 Web 方案也试过纯原生安卓最后选鸿蒙是因为它的卡片和流转能力是系统级的不用自己造轮子。当然代价是要学 ArkTS 和鸿蒙的工程结构这个后面会讲。2.3 整体数据流是怎么走的把整个链路画成文字版用户在鸿蒙端输入需求 → 端侧做初步的意图解析和参数抽取 → 组装成结构化请求 → 调用 MaaS 平台的模型接口 → 模型返回结构化行程 JSON → 端侧做校验和补全 → 渲染成卡片和详情页 → 用户微调后本地缓存。这里有个关键设计模型返回的必须是结构化数据不是自然语言。早期我让模型直接写攻略结果前端没法解析用户想改一个景点都改不了。后来改成让模型输出 JSON字段包括每天的时间段、地点、交通方式、预计耗时、备选方案前端拿到就能渲染成可交互的列表。这个改动是整个项目体验的分水岭。3. 核心细节解析行程规划到底难在哪3.1 约束求解模型不是万能的很多人以为把需求丢给大模型就完事了实际做下来会发现模型在生成内容上很强在满足硬约束上很弱。什么叫硬约束比如博物馆周一闭馆、某景点需要提前三天预约、老人不能走超过两公里的步行路线、预算不能超过三千。这些是客观事实和硬性条件模型可能会忽略也可能会编造。我的做法是把约束分成两类软约束交给模型硬约束交给规则引擎。软约束是不想太累、喜欢自然风光这种主观偏好模型处理得很好。硬约束是闭馆时间、预约规则、预算上限这种我用一个本地的规则表来校验模型输出不满足就回退重生成或者自动修正。举个例子模型给第一天排了三个景点我本地规则一算三个景点之间的通勤时间加起来超过四小时明显不合理就触发重排。这个校验逻辑不复杂但能挡掉大部分看起来很美但没法执行的行程。3.2 Prompt 工程怎么让模型稳定输出 JSON让模型稳定输出结构化 JSON是这类应用的必修课。我踩过的坑包括模型偶尔加个好的以下是为您规划的行程这种前缀导致 JSON 解析失败字段名有时用中文有时用英文数组长度不稳定。解决办法是三层保险。第一层在 system prompt 里明确要求只输出 JSON不要任何解释文字并给出完整的 schema 示例。第二层在请求参数里设置较低的 temperature我用的 0.3 左右减少随机性。第三层端侧做容错解析遇到非法 JSON 就用正则提取第一个{到最后一个}之间的内容再试一次。下面是我实际用的 prompt 骨架脱敏后分享出来你是一个专业的行程规划助手。用户会给你出行需求你需要输出严格的 JSON。 输出格式 { days: [ { date: 第1天, items: [ { time: 09:00-11:30, place: 地点名称, type: 景点/餐饮/交通/休息, duration_min: 150, transport: 步行/地铁/打车, transport_min: 20, note: 备注如需要预约, backup: 备选方案 } ] } ], tips: [整体提示1, 整体提示2] } 要求 1. 只输出 JSON不要任何其他文字。 2. 每天安排不超过 4 个主要活动。 3. 考虑老人和小孩的体力连续步行不超过 30 分钟。 4. 每个地点给出备选方案。这个 prompt 我迭代了十几版核心经验是schema 越具体输出越稳定。字段类型、取值范围、单位都写清楚模型就不容易跑偏。3.3 端侧参数抽取别让用户填表单行程规划类应用最大的流失点就是表单。让用户填出发地、目的地、日期、人数、预算、偏好填完一半人就跑了。我的做法是让用户用自然语言说一句话端侧做轻量抽取。鸿蒙端我用了一个小型的意图识别逻辑把用户输入里的关键实体抽出来日期十月一号→ 具体日期、人数带老人和小孩→ 3 人以上、偏好不想太累→ 节奏舒缓、预算中等→ 映射到区间。抽取不出来的字段用默认值兜底然后在生成结果页让用户一键微调而不是在开始前逼用户填完。这个先给结果再让改的思路比先填表再给结果的转化率高很多。用户看到一份具体的行程改起来有参照比面对空白表单容易得多。4. 实操过程从零到能跑通的完整步骤4.1 第一步在 MaaS 平台跑通模型调用先在蓝耘元生代平台上创建应用拿到 API Key 和接口地址。然后写一个最小的调用脚本验证链路。我用 Python 做的验证因为调试方便import requests import json API_URL 你的接口地址 API_KEY 你的密钥 def plan_trip(user_input): headers { Authorization: fBearer {API_KEY}, Content-Type: application/json } payload { model: 你选定的模型名, messages: [ {role: system, content: SYSTEM_PROMPT}, {role: user, content: user_input} ], temperature: 0.3, stream: False } resp requests.post(API_URL, headersheaders, jsonpayload, timeout60) return resp.json() result plan_trip(十月一号从某地出发带老人小孩玩四天预算中等不想太累) print(result)这一步的重点是先确认接口通、模型能返回内容别急着写前端。我见过有人前端写了一大堆结果接口调不通排查起来两头乱。先把后端链路跑通拿到稳定的返回再动端侧。注意API Key 千万不要硬编码在客户端代码里。鸿蒙端调用要走你自己的后端中转或者用平台提供的临时凭证机制。密钥泄露是这类项目最常见的安全事故。4.2 第二步搭建鸿蒙工程结构鸿蒙的工程结构对新手有点门槛我简单说一下关键目录。用 DevEco Studio 创建工程后主要关注这几个地方entry/src/main/ets/放 ArkTS 代码页面和逻辑都在这。entry/src/main/ets/pages/页面文件每个页面一个.ets文件。entry/src/main/ets/model/数据模型定义行程的接口类型放这。entry/src/main/resources/资源文件字符串、颜色、图片。我建了三个页面输入页、结果页、详情页。输入页就一个输入框加一个按钮结果页展示每天的行程卡片详情页展示单个活动的细节和备选方案。页面跳转用鸿蒙的router机制数据传递用AppStorage或者路由参数。ArkTS 的语法和 TypeScript 很像有前端基础的话上手很快。但要注意鸿蒙有自己的状态管理装饰器比如State、Prop、Link用错了数据不刷新这个坑我踩过好几次。4.3 第三步端云联调与流式渲染端侧调模型接口最影响体验的是等待时间。一次完整的行程生成模型可能要跑五到十秒。如果等全部生成完再显示用户会以为卡死了。所以要做流式渲染。流式渲染的逻辑是模型每返回一段内容端侧就解析一段能渲染的先渲染。但行程是 JSON 结构流式返回的 JSON 是不完整的没法直接解析。我的处理方式是分段生成先让模型生成第一天的行程渲染出来再生成第二天依次类推。这样用户能很快看到第一天的内容心理等待时间大大缩短。具体实现上我把请求拆成多次每次请求一天。虽然总调用次数变多了但体验好很多。而且每次请求的 prompt 更聚焦模型输出质量也更稳定。4.4 第四步本地缓存与离线兜底出行场景网络不稳定是常态高铁上、山区里信号差用户打开应用不能白屏。我在端侧做了本地缓存用户生成过的行程存在本地数据库里没网也能看。鸿蒙的关系型数据库或者首选项存储都能用行程数据量不大首选项存储就够。离线兜底还有一层如果用户没网又想规划新行程端侧可以给一个基于模板的简易方案虽然不如模型生成的好但至少能用。这个模板我准备了几个常见的出行场景比如城市三日游、周边两日游用户选一个再微调。5. 常见问题与排查技巧实录5.1 模型输出不稳定怎么办这是最高频的问题。表现是同样的输入有时返回标准 JSON有时带一堆解释文字有时字段缺失。排查思路按顺序来先看 temperature 是不是太高超过 0.7 随机性就明显了行程规划这种任务建议 0.2 到 0.4。再看 prompt 里的 schema 是不是够具体字段有没有给示例值。最后看模型本身有些模型对 JSON 格式的遵循能力就是弱一些换个模型可能就好了。我整理了一个速查表问题表现可能原因解决方向返回带解释文字prompt 约束不够强化只输出 JSON指令字段名中英文混用schema 未固定在 prompt 里给完整字段示例数组长度忽长忽短未限制数量明确每天不超过 N 个活动内容重复啰嗦temperature 偏高降到 0.3 左右忽略硬约束模型能力限制端侧规则引擎兜底5.2 鸿蒙端数据不刷新ArkTS 的状态管理是新手最容易翻车的地方。我遇到过一次模型返回了新数据但页面还是旧的。排查半天发现是用了普通变量存数据没用State装饰。鸿蒙里只有被状态装饰器标记的变量变化时才会触发 UI 刷新。还有一个坑是对象嵌套。如果State修饰的是一个对象改对象内部的属性有时不会触发刷新。解决办法是重新赋值整个对象或者用Observed和ObjectLink处理嵌套。这个细节官方文档里有但容易忽略。5.3 接口超时和限流国庆期间流量大接口超时和限流是必然要面对的。我的处理是三层端侧设置合理的超时时间我用的 30 秒超时后给用户明确的提示和重试按钮请求做防抖用户连点按钮不会重复发请求后端做队列高峰期请求排队处理而不是直接拒绝。实操心得限流不可怕可怕的是用户不知道发生了什么。给一个当前咨询人数较多正在为您排队的提示比直接报错体验好十倍。5.4 行程合理性校验的边界规则引擎不是越严越好。我一开始设了很多校验规则结果模型生成的行程经常被判定不合格反复重生成耗时很长。后来我调整了策略只校验硬约束闭馆、预算、体力上限软约束景点搭配是否最优交给模型不追求完美。这个取舍很重要。行程规划没有标准答案用户要的是能用且合理不是数学最优解。过度校验反而让体验变差。6. 一些关于场景和边界的思考做这个项目的过程中我越来越觉得AI 行程规划这个场景的价值不在于替代人做决策而在于降低决策的启动成本。很多人不是不会规划是懒得开始。给一个 70 分的初稿用户改起来就有方向了这比让用户从零开始强太多。技术边界上MaaS 加鸿蒙这套组合适合的是中等复杂度、对端侧体验有要求、但不想投入大量运维的应用。如果你的场景需要极致的低延迟或者数据完全不能出本地那可能要考虑端侧小模型。如果只是做个 Demo 验证想法MaaS 是最快的路径。最后分享一个我在实际使用中的小体会行程规划类应用备选方案比主方案更重要。用户真正会用的往往是如果这个景点约满了我去哪的那个备选。模型生成主方案很容易生成合理的备选才见功力。我在 prompt 里专门要求每个活动都给 backup 字段这个细节让整个应用的实用度上了一个台阶。