背景:传统旅行规划信息分散在各攻略平台,用户需自行跨渠道查景点、比门票、算预算、排行程,耗时且难以个性化;通用对话助手也无法对 "城市 + 预算 + 天数" 这类结构化输入做建模。目标:构建一个以 LLM 为核心的智能旅游助手 —— 输入目的地、预算、天数即可自动生成结构化行程规划(每日上午 / 下午 / 晚上安排、景点介绍、交通建议、预算分配、小贴士与注意事项),并提供流式 AI 旅游问答,以移动端优先的形态交付。
1. 行程规划模块(Home / Detail):表单选择并校验目的地、预算(≥100 元)、天数(1–30 天),支持热门城市快捷选择;后端调用大模型按固定 JSON 结构生成行程,结果页以折叠卡片展示每日日程、预算分配、小贴士与注意事项,支持失败重试与超时友好提示。
2. AI 对话模块(Chat):支持自由提问与快捷问题,采用 SSE 流式逐字渲染,带 "正在思考" 状态;行程详情页可一键携带城市上下文进入对话。
3. 个人中心模块(Profile):注册、登录、退出(用户名密码 + 头像,localStorage 持久化);历史记录区分对话 / 查询两类,支持滑动删除、一键清空与 20 条进度提示,点击可回跳对应行程或聊天;收藏与设置页当前为占位。
4. 后端服务模块(travel-II):Express 提供 /api/travel/recommend、/api/travel/chat 及心跳接口;通过 LangChain ChatOpenAI 统一封装,支持 SiliconFlow / DeepSeek 双模型供应商切换。
- 行程规划流:首页表单(城市 / 预算 / 天数)→ 前端校验 → 写入历史 → 跳转 /detail → POST /recommend → 后端校验并组装 prompt → LLM 生成整份 JSON → 正则提取与解析 → Detail 渲染每日日程 / 预算 / 贴士 → 底部按钮进入 AI 对话。
- AI 对话流:Chat 输入或点击快捷问题 → 写入历史 → POST /chat(SSE)→ llm.stream 逐块产出 → streamUtils 以 data 事件推送 → 前端 fetchStream 逐字填充气泡 → complete 事件收尾。
- 个人中心流:登录 / 注册 → Profile → 收藏 / 历史 / 设置;历史条目点击回跳对应行程或聊天。
采用前后端分离架构:
- 前端 travel:Vue 3 + Vite + Vant 4(移动端组件,按需自动引入)+ Pinia(状态管理,localStorage 持久化)+ Vue Router + Axios。细分为页面模块(Home/Detail/Chat/Profile/History/Favorites/Settings/Login/Register 九个视图)、组件模块(ChatBubble/SpotItem/BudgetTable)、请求模块(axios 封装 + fetchStream 的 SSE 解析)。
- 后端 travel-II:Node.js + Express(监听 3300)+ @langchain/openai + dotenv + cors + nodemon。细分为服务入口(index.js,含心跳与错误中间件)、路由(route/travel.js)、业务服务(services/travelService.js:LLM 初始化、行程 prompt、JSON 解析、流式对话)、工具(utils/streamUtils.js:SSE 响应封装)。
- LLM 接入层:由 .env 的 MODEL_PROVIDER 二选一切换 SiliconFlow(Qwen3.5-35B-A3B,默认)或 DeepSeek(deepseek-chat),ChatOpenAI 统一 streaming:true、temperature 0.7。
- 设计思路:以 LLM 为生成核心,后端承担 prompt 工程、结构化输出解析与 SSE 封装;前端专注表单校验、结果渲染与本地状态持久化;模型供应商做成可配置,避免厂商锁定。
系统前后端联通,行程规划可生成并完整渲染,AI 对话可流式问答,历史记录、注册登录可用。收藏与设置页面为 TODO 占位,尚未实现交互逻辑。
难点:流式接口超时;axios 的 timeout 是 "请求总时长" 而非 "空闲无数据时长";模型输出稍有偏差即解析失败。
解决方案:1.timeout/ 重试 ——ChatOpenAI 加 timeout 兜底、maxRetries 自动重试,前端 axios 放宽至 180s;2.JSON 模式 ——response_format:{type:'json_object'} 强制 JSON 输出、调低 temperature,替代正则,提升解析成功率;3. 改流式 SSE——/chat 改用 llm.stream 逐块推送,前端弃用 axios、改用 fetch+ReadableStream+AbortController 逐字渲染、不设总超时。详见 docs/backend-optimization.md(180s 放宽、/chat 流式已落地)。