
1. 从人挤人的黄金周说起为什么需要一个AI行程规划师每年国庆黄金周朋友圈里总有两拨人一拨在景区看后脑勺另一拨在家里看第一拨人堵在高速上。这个场景我观察了很多年也亲身经历过几次——凌晨四点起床赶高铁、到了目的地发现热门景点预约已满、临时改路线结果绕了三个小时冤枉路。问题不在于出去玩这件事本身而在于行程规划这件事的信息密度和动态变化速度已经远远超出了人工处理的极限。传统的行程规划方式无非几种翻攻略、问朋友、跟团、或者干脆走到哪算哪。翻攻略的问题是信息滞后且同质化严重你看到的必去打卡点可能已经是三年前的热门现在去就是排队两小时拍照五分钟。问朋友的问题是样本量太小别人的偏好和你的实际情况未必匹配。跟团就更不用说了时间被切得稀碎自由度几乎为零。那大模型能做什么大模型的核心能力在于信息整合、偏好理解和实时推理。它可以在几秒内把天气、交通、人流、预算、个人偏好这些维度全部纳入考量生成一份动态可调的行程方案。这不是简单的推荐几个景点而是一个完整的决策链路从我想去哪到我该怎么去到去了之后怎么安排到临时有变怎么调整。我这次做的事情就是用蓝耘元生代MaaS平台提供的大模型推理能力结合鸿蒙系统的分布式特性搭一个能跑在手机、平板、车机上的AI行程规划师。目标很明确让用户在国庆这种极端出行场景下也能快速拿到一份靠谱的、可执行的、能随时调整的行程方案。关键词就三个大模型推理、鸿蒙分布式、实时行程规划。这篇文章会从架构设计、模型选型、鸿蒙端集成、实际踩坑几个维度展开适合有一定开发基础、想了解大模型落地应用的朋友参考。即使你暂时不打算动手写代码里面关于怎么让大模型输出真正可用的结构化数据的思路应该也能给你一些启发。2. 为什么选MaaS而不是自己部署算力账、时间账和效果账2.1 自建推理服务的三个隐性成本一开始我也想过自己部署一个开源模型毕竟现在7B、13B的模型满地都是看起来门槛不高。但真正算完账之后我放弃了这条路。第一笔是算力成本。你要跑一个能稳定输出结构化行程的模型至少需要13B以上的参数规模量化之后显存占用也在10GB以上。国庆期间如果真有用户量并发请求一上来单卡根本扛不住。租GPU实例的费用按小时算黄金周七天下来这笔钱足够你买好几年的MaaS调用额度了。第二笔是时间成本。自己部署不是把模型拉下来跑起来就完事了。你得处理推理框架的版本兼容、显存优化、请求队列、超时重试、模型热更新这一整套工程问题。我粗略估算了一下从零搭一套能用的推理服务至少需要两周的全职投入。而国庆黄金周是固定的倒推回来时间根本不够。第三笔是效果成本。开源模型在通用对话上表现不错但行程规划这种任务需要模型具备较强的结构化输出能力和领域知识。自己部署的模型如果不做微调输出的行程经常是建议上午去A下午去B这种模糊表述缺少时间、交通方式、预算这些关键字段。而MaaS平台上的模型通常已经做过指令微调和格式对齐输出质量明显更稳定。2.2 蓝耘元生代MaaS的接入逻辑蓝耘元生代MaaS平台的核心价值在于把模型推理这件事变成了一个API调用。你不需要关心底层是几张卡、用的什么推理框架、模型怎么加载只需要关注输入和输出。接入流程大致是这样的在平台上创建一个推理服务实例选择适合的模型我选的是一个13B级别的指令微调模型对中文场景支持较好获取API Endpoint和认证密钥在客户端构造请求把用户的需求转成Prompt解析模型返回的结构化数据渲染成行程卡片这里有一个关键设计决策我把行程规划拆成了两阶段推理。第一阶段让模型理解用户意图输出一个JSON格式的行程骨架包含天数、每天的核心活动类型、预算范围。第二阶段再针对每一天让模型填充具体的时间安排、交通方式、备选方案。这样做的好处是每次请求的上下文更短推理速度更快而且如果某一天的结果不满意只需要重新生成那一天不用全部重来。# 第一阶段生成行程骨架 skeleton_prompt 你是一个专业的行程规划助手。根据用户需求输出一个JSON格式的行程骨架。 用户需求{user_input} 输出格式 { days: 3, budget_level: 中等, pace: 轻松, daily_themes: [历史文化, 自然风光, 美食探索] } 只输出JSON不要其他内容。 这个Prompt的设计要点是明确输出格式、限制输出范围、强调只输出JSON。实测下来如果不加只输出JSON这句话模型有大概30%的概率会在JSON前后加一段解释性文字导致解析失败。2.3 模型选型的几个硬指标在MaaS平台上选模型的时候我主要看三个指标指标要求原因中文理解能力强用户输入是口语化的中文夹杂方言和网络用语结构化输出稳定性高需要稳定输出JSON不能时好时坏推理延迟低于3秒用户等超过5秒就会觉得卡顿最后选的模型在这三项上表现比较均衡。特别值得一提的是结构化输出稳定性这个指标在模型对比页面上通常不会直接标出来需要自己写测试用例去跑。我的测试方法是构造20条不同风格的输入看模型输出JSON的格式正确率。低于90%的模型直接排除因为在实际使用中一次解析失败就意味着用户要重新输入一遍需求体验非常差。3. 鸿蒙端集成分布式能力怎么用在行程规划上3.1 鸿蒙的分布式软总线解决了什么实际问题行程规划这个场景有一个天然的特点用户会在不同设备之间切换。在手机上输入需求在平板上看详细行程在车机上导航到第一个景点。传统做法是每个设备各自调API、各自渲染数据同步靠云端轮询延迟高且体验割裂。鸿蒙的分布式软总线让这些设备可以像一台设备一样协同。具体到我的项目里我用了两个核心能力分布式数据管理行程数据在手机、平板、车机之间自动同步任何一端修改其他端实时更新跨设备调用手机端负责接收用户输入和调用MaaS API平板端负责渲染详细的行程视图车机端负责导航和语音播报这意味着用户可以在手机上快速输入国庆去成都三天带老人不想太累然后上车后车机自动弹出已经规划好的行程直接开始导航。整个过程不需要用户手动同步或重新输入。3.2 端侧预处理把一部分推理放在本地虽然MaaS提供了强大的云端推理能力但并不是所有事情都要送到云端。我在鸿蒙端做了一层本地预处理主要处理三类任务第一类是输入清洗。用户输入往往很随意比如国庆想去个不太挤的地方预算三千左右三天最好有山有水。这中间包含了时间、预算、天数、偏好四个维度的信息。我在端侧用规则引擎先做一轮提取把能结构化的字段先结构化减少云端模型的负担。第二类是缓存命中判断。如果用户输入的需求和之前某个请求高度相似比如只是改了预算数字直接返回缓存结果并做增量调整不用重新调用模型。国庆期间请求量大这个优化能省下不少推理成本。第三类是敏感信息过滤。用户的输入里可能包含手机号、身份证号这类信息在端侧先过滤掉只把脱敏后的需求送到云端。这既是合规要求也是保护用户隐私的必要措施。// 端侧输入清洗的简化逻辑 function preprocessInput(rawText) { const result { days: extractDays(rawText), // 提取天数 budget: extractBudget(rawText), // 提取预算 preferences: extractKeywords(rawText), // 提取偏好关键词 cleanedText: removePII(rawText) // 去除个人敏感信息 }; return result; }3.3 跨设备状态同步的坑分布式数据管理听起来很美好但实际用起来有几个坑需要提前知道。第一个坑是数据冲突。如果用户在手机和平板上同时修改了行程同步的时候以哪个为准我的做法是给每个修改操作打上时间戳和设备ID冲突时以时间戳较新的为准同时在UI上给用户一个提示检测到其他设备有更新已合并。第二个坑是网络抖动。分布式软总线在设备间网络不稳定的情况下同步可能会延迟甚至失败。我的处理方式是本地先写入标记为待同步后台起一个重试队列网络恢复后自动同步。用户感知不到这个过程但数据最终是一致的。第三个坑是权限管理。不是所有设备都应该有完整的读写权限。比如车机端只应该有读取权限不应该能修改行程。鸿蒙的分布式权限管理可以做到这一点但需要在开发阶段就规划好每个设备的角色。4. 让大模型输出能直接用的行程Prompt工程与后处理4.1 为什么直接问模型帮我规划行程不好用我最初的做法很直接把用户需求拼成一句话扔给模型让它输出行程。结果发现三个问题第一输出格式不稳定。有时候是Markdown表格有时候是纯文本列表有时候是JSON。前端解析起来非常痛苦。第二信息粒度太粗。模型会说上午参观博物馆下午游览公园但不告诉你博物馆叫什么、几点开门、怎么从酒店过去、门票多少钱。这种行程看起来很美实际上没法执行。第三缺少备选方案。国庆期间景点限流、交通管制是常态如果只有一个方案一旦某个环节出问题整个行程就崩了。4.2 分阶段Prompt设计从骨架到血肉我的解决方案是分阶段生成每个阶段有明确的输出格式和质量要求。第一阶段需求理解与骨架生成这个阶段的Prompt核心是让模型把模糊需求转成结构化参数。关键技巧是给模型一个输出模板而不是让它自由发挥。skeleton_prompt 分析以下用户需求提取关键参数。如果某个参数用户没有明确说明根据常识推断一个合理值。 用户需求{user_input} 请按以下JSON格式输出 { destination: 目的地城市, days: 天数整数, budget_level: 经济/中等/高端, pace: 紧凑/适中/轻松, travel_companions: 独自/情侣/家庭/朋友, interests: [兴趣标签1, 兴趣标签2], constraints: [限制条件1, 限制条件2] } 只输出JSON。 第二阶段每日详细行程生成拿到骨架后针对每一天单独生成详细安排。这个阶段的Prompt需要包含时间、地点、交通、预算、备选五个要素。daily_prompt 根据以下行程骨架生成第{days}天的详细安排。 行程骨架{skeleton} 第{days}天主题{theme} 要求 1. 每个活动包含时间段、地点名称、活动描述、交通方式、预计花费 2. 每个时间段提供一个备选方案 3. 考虑国庆期间的人流因素热门景点建议安排在早上 4. 午餐和晚餐各推荐两个选择 输出JSON格式 { day: {days}, theme: {theme}, schedule: [ { time: 08:00-10:00, place: 地点名称, activity: 活动描述, transport: 交通方式, cost: 预计花费, backup: 备选方案 } ], meals: { lunch: [餐厅1, 餐厅2], dinner: [餐厅1, 餐厅2] } } 4.3 后处理把模型输出变成可渲染的数据模型输出的JSON虽然格式正确但内容质量参差不齐。我加了一层后处理逻辑主要做四件事第一字段校验。检查必填字段是否存在时间格式是否合法预算数字是否在合理范围内。如果某个字段缺失或异常触发重试或使用默认值。第二地点去重。模型有时候会在不同天推荐同一个地点这在行程规划里是不合理的。后处理阶段会检测重复并替换。第三时间冲突检测。检查相邻活动之间是否有足够的交通时间。如果两个活动之间只隔了15分钟但距离很远自动调整时间或替换活动。第四备选方案有效性验证。备选方案不能和主方案是同一个地方也不能是明显不合理的选项比如凌晨三点去逛公园。def postprocess_itinerary(raw_json): itinerary json.loads(raw_json) # 字段校验 required_fields [day, theme, schedule] for field in required_fields: if field not in itinerary: raise ValueError(fMissing field: {field}) # 地点去重 seen_places set() for item in itinerary[schedule]: if item[place] in seen_places: item[place] find_alternative(item[place]) seen_places.add(item[place]) # 时间冲突检测 for i in range(len(itinerary[schedule]) - 1): current itinerary[schedule][i] next_item itinerary[schedule][i 1] if has_conflict(current, next_item): adjust_schedule(itinerary[schedule], i) return itinerary4.4 实测中的意外情况与应对在实际测试中我遇到了几个预料之外的问题。问题一模型对国庆的理解偏差。我原本以为模型知道国庆意味着人多、涨价、限流但实际上如果不明确提示模型会按照平时的逻辑来规划。解决方案是在Prompt里显式加入当前是国庆黄金周景点人流大交通拥堵部分场馆需要提前预约这样的上下文。问题二预算计算不准确。模型给出的花费估算经常偏低尤其是门票和交通。我的做法是维护一个本地价格库把常见景点的门票价格、出租车起步价、地铁票价这些数据存在端侧模型只负责推荐地点具体花费由本地价格库计算。问题三输出语言风格不统一。有时候模型用书面语有时候用口语有时候夹杂英文。我在Prompt里加了使用简洁的中文口语化表达这个约束同时在後处理阶段做一轮文本规范化。5. 国庆场景下的特殊处理人流、限流与动态调整5.1 人流预测数据的接入国庆期间最大的变量就是人流。同样的行程平时可能很轻松国庆期间可能寸步难行。我在系统里接入了人流预测数据数据来源是公开的景区预约平台和历史客流统计。具体做法是在生成行程时给每个景点打一个拥挤度标签分为舒适较挤拥挤爆满四档。如果某个景点的拥挤度是爆满系统会自动把它替换成备选方案或者建议用户调整到早上最早的时间段。def adjust_for_crowd(itinerary, crowd_data): for item in itinerary[schedule]: place item[place] if place in crowd_data: crowd_level crowd_data[place][level] if crowd_level 爆满: item[place] item[backup] item[note] 原地点国庆期间人流过大已自动替换 elif crowd_level 拥挤: item[time] shift_to_early(item[time]) item[note] 建议提前前往避开高峰 return itinerary5.2 实时调整用户在路上也能改行程行程规划不是一次性的用户在旅途中随时可能想调整。我在鸿蒙端做了一个语音快捷调整功能用户长按首页的麦克风按钮说明天下午不想去博物馆了换个轻松点的系统会调用MaaS的增量推理接口只重新生成第二天下午的安排其他部分保持不变。这个功能的关键在于上下文管理。每次调整请求都需要带上当前的行程状态让模型知道哪些部分已经确定、哪些部分可以改。我的做法是在端侧维护一个行程状态对象每次调整时把状态序列化后作为上下文传给模型。5.3 离线降级方案国庆期间网络拥堵是常态如果MaaS API调用失败系统需要有降级方案。我的设计是一级降级使用端侧缓存的最近一次成功生成的行程提示用户网络不稳定当前显示的是缓存方案二级降级如果缓存也没有切换到本地规则引擎基于预设的模板和用户偏好生成一个基础行程三级降级如果规则引擎也无法工作展示一个静态的国庆出行小贴士页面至少不让用户看到空白页这个降级链路在实测中触发过几次用户反馈是虽然不如在线生成的详细但至少能用。6. 从开发到上线我踩过的五个坑6.1 坑一低估了Prompt的长度对延迟的影响我一开始把所有的约束条件、格式要求、示例都塞进一个Prompt里结果单次请求的输入Token数超过了2000推理延迟直接飙到8秒以上。后来我把Prompt拆成系统指令和用户输入两部分系统指令固定不变可以复用KV Cache延迟降到了3秒以内。提示MaaS平台通常支持系统指令和用户输入分离的接口设计用好了能显著降低延迟。6.2 坑二JSON解析的容错没做好模型输出的JSON偶尔会有小问题比如多了一个逗号、少了一个引号、或者用了中文引号。我一开始用标准的JSON解析器遇到这些问题直接抛异常。后来换成了宽松解析模式先尝试标准解析失败后做一轮文本清洗再解析成功率从85%提升到了99%。6.3 坑三鸿蒙分布式权限配置遗漏在鸿蒙上做跨设备数据同步需要在配置文件中声明分布式权限。我一开始只声明了基本的网络权限结果平板端一直读不到手机端写入的数据。排查了半天才发现是权限问题。这个坑的教训是鸿蒙的分布式能力需要显式声明权限而且不同设备类型的权限配置可能不同。6.4 坑四没有做请求频率限制国庆期间如果用户量突然增大不加限制的API调用可能会触发MaaS平台的限流。我在端侧加了一个简单的令牌桶算法每个用户每分钟最多发起5次推理请求超出后提示操作太频繁请稍后再试。这个限制在实测中没有影响正常使用但有效防止了异常流量。6.5 坑五忽略了模型输出的多样性同一个需求模型每次生成的行程可能都不一样。这在测试阶段是好事说明模型有创造力。但在生产环境用户会困惑为什么我刷新一下行程就变了我的解决方案是固定随机种子同一个用户ID加同一个需求生成的行程保持一致。如果用户主动点击换一个方案才使用新的随机种子。7. 这套方案还能怎么扩展7.1 从行程规划到行程执行目前这套系统主要解决的是规划阶段的问题。下一步可以往执行阶段延伸接入实时交通数据在用户即将出发时推送建议提前15分钟出发当前路段拥堵接入景区排队数据在用户接近景点时提示当前排队约40分钟建议先游览附近的其他景点。7.2 多模态输入的接入现在用户输入主要靠文字和语音。鸿蒙设备有丰富的传感器未来可以支持拍照输入用户拍一张景区地图系统自动识别地图上的景点和路线结合用户偏好生成游览顺序。这需要MaaS平台支持多模态模型目前我用的模型还是纯文本的但接口层面已经预留了扩展空间。7.3 社交化行程分享国庆出行往往是家庭或朋友一起行程规划需要多人协同。可以基于鸿蒙的分布式能力做一个行程房间功能多个人加入同一个房间每个人都可以提出偏好和修改建议系统综合所有人的意见生成一个折中方案。这个功能的技术难点在于多用户偏好的冲突消解需要设计一套投票或权重机制。7.4 成本优化的空间目前每次行程生成大约消耗1500个Token按MaaS平台的定价单次成本在几分钱左右。如果用户量达到十万级国庆七天的推理成本大约在几千元。这个成本是可以接受的但如果想进一步优化有几个方向一是把常用的行程模板缓存起来相似需求直接返回缓存结果二是用更小的模型处理简单请求大模型只处理复杂需求三是在端侧做更多的预处理减少云端推理的输入长度。这套系统从构思到跑通前后花了大约三周时间其中大部分时间花在Prompt调优和后处理逻辑上真正写鸿蒙端代码的时间反而不多。我的体会是大模型应用的核心难点不在模型本身而在怎么把模型的输出变成用户真正能用的东西。模型可以给你一个看起来不错的行程但要让这个行程在国庆的人山人海里真正可执行需要大量的工程细节来兜底。如果你也想做类似的东西我的建议是先从一个小场景切入比如只做一日游规划把整个链路跑通再逐步扩展。不要一上来就追求大而全那样很容易在细节里迷失。