欢迎光临
我们一直在努力

智能旅行规划助手 — 实习面试问答手册

智能旅行规划助手 — 实习面试问答手册

本文档基于项目 helloagents-trip-planner 的实际代码整理,供软件开发实习生面试使用。
建议配合项目 README 和本地 Demo 演示一起准备。


一、30 秒电梯演讲(开场必背)

面试官:先简单介绍一下这个项目。

回答示例:

这是一个 AI 驱动的智能旅行规划 Web 应用。用户在首页填写目的地、日期、预算、偏好等信息后,后端会先调用 高德地图 API 获取真实景点、酒店和天气数据,再把这些结构化信息交给 大语言模型(LLM) 生成多日行程;前端用 Vue 3 展示每日路线、地图标记、预算汇总,并支持行程伴游问答、历史记录和 PDF 导出。

我主要负责(或参与)前后端联调、Agent 行程生成链路、POI 坐标准确性治理、异步任务接口 等工作。项目采用 前后端分离:FastAPI 提供 REST API,Vue 3 + Ant Design Vue 负责交互与可视化。


二、项目背景与目标

Q1:为什么要做这个项目?解决了什么问题?

回答:

传统旅行规划要么靠人工查攻略、拼表格,耗时长;要么纯靠 AI 生成,容易出现 虚构景点、坐标不准、地图无法展示 的问题。

我的项目核心思路是:「真实数据 + AI 编排」——

  • 用高德地图拿到 真实 POI(景点/酒店)和天气;
  • 用 LLM 负责 行程安排、餐饮建议、预算估算、文字描述;
  • 后端再做 坐标回填与校验,保证前端地图能正确打点。
  • 这样既保留了 AI 的灵活性,又提高了结果的可信度和可执行性。

    Q2:项目的用户是谁?核心使用场景是什么?

    回答:

    面向 有出行计划但不想花大量时间做攻略的用户,典型场景包括:

    • 周末/小长假城市游,快速生成 2~5 日行程;
    • 按偏好(历史文化、美食、自然风光等)筛选景点;
    • 生成后在结果页查看地图路线、调整关注点后导出 PDF;
    • 对已生成行程进行 伴游问答(如「第 2 天下午适合去哪?」)。

    三、技术栈说明

    Q3:项目用了哪些技术?为什么选它们?

    回答:

    层级技术选型理由
    后端框架 FastAPI 异步友好、自动生成 OpenAPI 文档、Pydantic 数据校验成熟
    LLM OpenAI 兼容接口(OpenAI / DeepSeek 等) 通过统一 HelloAgentsLLM 封装,便于切换模型和 Base URL
    地图 高德 Web 服务 API + JS API 国内 POI、天气、路线数据准确;前后端分别调用 HTTP API 和 JS SDK
    HTTP 客户端 httpx(后端)、axios(前端) 异步/拦截器支持好,对接第三方 API 方便
    数据模型 Pydantic v2 请求/响应强类型校验,减少接口脏数据
    前端 Vue 3 + TypeScript + Vite 组合式 API + 类型安全,开发效率高
    UI Ant Design Vue 表单、卡片、步骤条等组件齐全,适合 B 端/工具类产品
    路由 Vue Router 首页 / 结果 / 历史 / 探索页分离
    PDF 导出 html2canvas + jsPDF 将 DOM 渲染为图片再写入 PDF,实现成本低
    图片 Unsplash API(可选) 为景点补充展示图
    Agent 框架 本地 hello_agents 兼容层 参考 Datawhale Hello-Agents 教程,轻量封装 LLM 与 MCP 工具

    Q4:前后端是如何通信的?

    回答:

    • 前端通过 VITE_API_BASE_URL(默认 http://localhost:8000)访问后端;
    • 后端开启 CORS,允许 localhost:5173 等开发源;
    • 主要接口:
      • POST /api/trip/plan_async — 提交异步规划任务
      • GET /api/trip/plan_result/{job_id} — 轮询任务结果
      • POST /api/assistant/chat — 行程伴游
      • GET /api/map/poi — POI 搜索
      • POST /api/map/route — 路线规划
    • 数据格式统一为 JSON,后端用 Pydantic 模型约束字段。

    四、系统架构与运行流程

    Q5:请描述一下项目的整体架构。

    回答:

    项目是典型的 三层前后端分离架构:

    ┌─────────────────────────────────────────────────────────┐
    │ 前端 (Vue 3) │
    │ Home → 提交表单 │ Result → 地图/导出 │ History/Explore │
    └───────────────────────────┬─────────────────────────────┘
    │ HTTP / JSON
    ┌───────────────────────────▼─────────────────────────────┐
    │ 后端 (FastAPI) │
    │ API 路由层 → Agent/Service 层 → 外部 API (LLM/高德/Unsplash) │
    └─────────────────────────────────────────────────────────┘

    • API 路由层:trip.py、assistant.py、map.py、poi.py
    • 业务层:MultiAgentTripPlanner(行程规划)、AmapService(地图)、HelloAgentsLLM(大模型)
    • 数据层:本项目无独立数据库,历史记录存 浏览器 localStorage

    Q6:用户点击「生成旅行计划」后,完整流程是什么?

    回答(按时间顺序):

    前端:

  • 用户在 Home.vue 填写城市、日期、偏好、预算等,点击提交;
  • 调用 generateTripPlan():
    • 先 POST /api/trip/plan_async,立即拿到 job_id;
    • 每 2 秒轮询 GET /api/trip/plan_result/{job_id},更新进度条;
  • 成功后把计划写入 sessionStorage 和 localStorage 历史,跳转 Result.vue。
  • 后端(MultiAgentTripPlanner.plan_trip):

  • 步骤 1 — 搜索景点:调用高德 POI 文本搜索,获取真实名称与坐标;
  • 步骤 2 — 查询天气:地理编码拿 adcode,再查天气预报;
  • 步骤 3 — 搜索酒店:按住宿偏好搜索酒店 POI;
  • 步骤 4 — LLM 生成行程:把用户需求 + 景点列表 + 天气 + 酒店列表拼成 Prompt,要求 LLM 输出固定 JSON 结构;
  • 解析与治理:
    • 从 LLM 回复中提取 JSON(支持 markdown 代码块);
    • 坐标回填:用高德搜索结果覆盖/修正景点坐标;
    • 酒店强制对齐:名称无法匹配时按天轮换回填真实酒店;
    • POI 一致性校验:检查坐标是否在中国范围、是否使用模板默认坐标等;
  • 若任一步失败,走 _create_fallback_plan() 返回兜底行程,避免接口完全不可用。
  • 结果页:

    • 加载高德 JS API,按景点坐标打 Marker、画 Polyline;
    • 可调用伴游 API 问答、导出 PDF。

    Q7:你说的「多智能体」具体是怎么协作的?

    回答(诚实且准确):

    从代码实现上看,当前版本是 「多步骤流水线 + 单一 LLM 规划」,而不是多个独立 Agent 互相对话:

    • 「景点搜索」「天气查询」「酒店搜索」由 AmapService 直接调用;
    • 「行程编排」由 一个 LLM 调用 完成,Prompt 里注入了前三步的结构化结果;
    • 项目保留了 hello_agents 里的 SimpleAgent、MCPTool 兼容层,便于后续扩展成真正的 Tool Calling Agent。

    面试时可以这样说:「当前是 Pipeline 式多阶段协作,架构上预留了 Agent + Tool 扩展能力。」


    五、核心模块深入

    Q8:TripRequest 里有哪些字段?后端如何校验?

    回答:

    主要字段包括:city、destinations(多城市)、start_date、end_date、travel_days(1~30)、transportation、accommodation、preferences、budget_per_person、travel_pace、companions、dietary_restrictions、free_text_input。

    使用 Pydantic 做类型和范围校验,例如 travel_days 必须 ≥1 且 ≤30。FastAPI 会在入参不符合模型时直接返回 422,减少业务层重复校验。

    Q9:LLM 返回的不是纯 JSON 怎么办?

    回答:

    在 _parse_response() 里做了 多层提取策略:

  • 优先找 ` ```json … ````代码块;
  • 否则找普通 ` ```… ````;
  • 再否则从第一个 { 到最后一个 } 截取;
  • 用 json.loads() 解析;
  • 解析失败则记录日志,返回 fallback 计划,保证用户体验不中断。
  • 这是对接 LLM 时的常见工程化处理,因为模型偶尔会加解释性文字或格式不规范。

    Q10:为什么要把景点/酒店坐标从 LLM 结果里「强制回填」?

    回答:

    这是项目里最关键的 工程问题之一。

    LLM 容易:

    • 改写 POI 名称(如「如家快捷酒店」vs「如家酒店(XX路店)」);
    • 编造或复制模板坐标(代码里专门检测默认北京坐标 116.397128, 39.916527);
    • 名称和坐标 张冠李戴(名字是 A 景点,坐标却是 B 景点)。

    解决方案:

  • Prompt 里明确要求 必须从给定列表逐字复制 name/address/location;
  • 解析后 _enforce_hotels_from_search_results():精确匹配 + 子串模糊匹配 + 按天轮换回填;
  • 景点侧建立 attraction_map,按名称匹配后替换 location;
  • _validate_plan_against_poi_search() 打日志告警,便于排查。
  • 我还写了 diagnose_coordinates.py 脚本,专门验证某城市 POI 坐标范围和名称匹配率。

    Q11:前端为什么用异步任务 + 轮询,而不是一次同步请求?

    回答:

    行程生成链路包含 多次外部 API + 一次长文本 LLM 调用,整体可能耗时 1~3 分钟甚至更久。

    如果只用同步 POST /api/trip/plan:

    • 浏览器/网关可能 超时断开;
    • 用户看不到真实进度,体验差。

    因此前端改为:

  • plan_async 立即返回 job_id;
  • 后端用 asyncio.create_task + asyncio.to_thread 在后台线程跑同步规划逻辑;
  • 前端每 2 秒轮询,最多约 10 分钟;
  • axios 全局 timeout 设为 5 分钟,轮询单次 30 秒。
  • 这是典型的 长任务异步化 方案。生产环境可进一步升级为 WebSocket 或 Redis 任务队列,但实习项目用内存 _job_store 足够演示。

    Q12:历史记录存在哪里?有什么限制?

    回答:

    存在浏览器 localStorage(tripPlanHistory),最多保留 50 条;当前激活 ID 在 sessionStorage。

    优点:无需后端数据库,部署简单;
    缺点:换设备/清缓存会丢失,不支持多用户 —— 面试时可主动说 「这是 MVP 阶段的权衡,后续可接 SQLite/PostgreSQL + 用户体系」。


    六、开发过程中遇到的问题与解决方案

    这一部分是实习面试的高频考点,建议结合具体例子讲,体现 发现问题 → 定位 → 解决 → 验证 的能力。

    问题 1:地图上的景点位置不准确 / 全部打在一个点

    现象: 结果页高德地图 Marker 偏移,或多个景点坐标相同。

    原因:

    • LLM 自行「编造」经纬度;
    • 景点名与高德搜索结果不一致,导致坐标和名称错配;
    • 高德返回的 location 是 "lng,lat" 字符串,解析错误会导致异常。

    解决:

  • 后端先用高德搜索拿 权威 POI 列表;
  • LLM 只负责选哪些景点、怎么排 day,不负责造坐标;
  • _parse_response 阶段强制用搜索结果回填 location;
  • 校验中国大陆经纬度范围(经度 73~136,纬度 18~54);
  • 编写 test_poi_fix.py、diagnose_coordinates.py 做回归测试。
  • 收获: 明白了 「LLM 适合生成语义内容,不适合作为地理数据源」,结构化数据要以 API 为准。


    问题 2:LLM 改写酒店名称,导致 POI 对不上

    现象: 行程里酒店名不在高德返回列表中,前端无法关联真实位置。

    解决:

  • Prompt 增加 正反示例,强调 hotel.name 必须逐字复制;
  • 实现 _match_hotel_poi():先精确匹配,再单向子串匹配;
  • 仍匹配不上则 _enforce_hotels_from_search_results() 按天轮换填入搜索结果;
  • _validate_plan_against_poi_search() 输出不一致告警。

  • 问题 3:请求超时,前端显示「生成失败」

    现象: 同步接口在 LLM 慢时经常失败。

    解决:

    • 后端新增 plan_async + plan_result;
    • 前端 api.ts 改为提交任务后轮询;
    • 进度条结合后端 stage/progress 与前端模拟进度,提升感知体验。

    问题 4:高德 API 返回字段类型不一致

    现象: POI 的 tel 有时是字符串,有时是列表,直接赋值导致 Pydantic 校验失败或前端展示异常。

    解决: 在 AmapService.search_poi() 里统一处理:列表取第一个,非字符串置 None。


    问题 5:LLM JSON 解析失败导致 500

    解决:

    • 多策略提取 JSON;
    • 解析失败走 _create_fallback_plan() 兜底;
    • 降低 temperature(如 0.4)提高输出稳定性。

    问题 6:CORS / 环境变量配置问题

    现象: 本地前端调后端跨域失败,或 Key 未加载。

    解决:

    • FastAPI 配置 CORSMiddleware,允许 Vite 开发端口;
    • 使用 python-dotenv + pydantic-settings 统一管理 .env;
    • 启动时 validate_config() 检查必要 Key 是否存在。

    七、面试官可能追问的技术问题

    Q13:FastAPI 的异步在这里是怎么用的?

    回答:

    路由函数是 async def,但 LLM 和 httpx 同步调用较重,所以异步任务通过 asyncio.to_thread() 把 同步规划逻辑放到线程池,避免阻塞事件循环。这是 Python 异步 Web 开发里常见的折中做法。

    Q14:如果 LLM API 挂了怎么办?

    回答:

    当前有 _create_fallback_plan() 返回基础模板行程;生产环境还可以:重试 + 指数退避、切换备用模型、缓存热门城市模板、向用户明确提示「AI 服务暂不可用」。

    Q15:如何保证 Prompt 输出稳定?

    回答:

    • 提供 完整 JSON Schema 示例 在 system prompt;
    • 约束必须使用的 POI 列表(含正确/错误示例);
    • 较低 temperature;
    • 后端 Pydantic 二次校验;
    • 关键字段(坐标、酒店名)不信任 LLM,以 API 数据为准。

    Q16:项目有哪些不足?如果继续迭代你会做什么?

    回答(展示思考深度):

    现状改进方向
    任务队列在内存 接 Redis/Celery,支持重启不丢任务
    无用户系统 JWT 登录 + 数据库存行程
    Agent 是 Pipeline 引入 Function Calling,让 LLM 自主决定何时查 POI/路线
    路线规划 API 已有 可在生成阶段就把相邻景点路线算进日程
    缺少自动化测试 为 POI 回填、JSON 解析写单元测试
    伴游无上下文记忆 加 session 或多轮对话 history

    Q17:你在这个项目里具体负责什么?

    回答模板(请按真实情况修改):

    我主要负责后端行程规划模块和前后端联调。包括:设计 MultiAgentTripPlanner 的四步流水线;实现 LLM 响应 JSON 解析与 POI 坐标回填;排查并修复地图打点不准的问题;对接异步任务接口,解决长请求超时;前端完成结果页地图展示和历史记录功能。

    原则: 只讲自己真正做过的部分,细节要能答上来。

    Q18:遇到过最难的 bug 是什么?

    回答示例:

    最难的是 「景点名称和坐标不匹配」——表面上行程 JSON 合法,Pydantic 也能过,但地图把「鼓浪屿」打到了另一个 POI 的位置。

    我通过日志对比 LLM 输出与高德搜索结果,发现模型会轻微改写名称;随后加了名称映射、坐标强制回填和诊断脚本,并补充 POI 校验日志。这个问题让我理解了 AI 应用里「看起来正确」和「事实正确」是两回事。


    八、行为面试 / 软技能问题

    Q19:这个项目是你独立完成的还是团队完成的?

    回答模板:

    如果是课程/教程延伸:说明基于 Hello-Agents 教程,我在其基础上 扩展了 POI 治理、异步接口、前端完整流程;
    如果是团队:说明分工,强调自己模块的 owner 意识 和联调沟通。

    Q20:开发周期多长?怎么管理进度?

    回答模板:

    例如 2~3 周:第 1 周打通 MVP(表单 → LLM → 展示);第 2 周接高德地图和坐标修复;第 3 周做历史、PDF、伴游和 UI polish。用 README 和 TODO 列表跟踪,优先保证 主链路可 Demo。

    Q21:从项目中学到了什么?

    回答:

  • LLM 应用工程化:Prompt 设计、输出解析、兜底策略同样重要;
  • 第三方 API 集成:要处理超时、字段不一致、Key 配置;
  • 全栈协作:Pydantic 模型最好与前端 TypeScript 类型对齐;
  • 用户体验:长任务需要进度反馈和异步化;
  • 问题定位方法:写诊断脚本、打结构化日志,比盲目改 Prompt 更高效。

  • 九、Demo 演示建议(面试现场加分)

  • 提前启动 前后端,确认 .env 中 LLM 和高德 Key 有效;
  • 演示路径:填表单 → 看进度 → 结果页地图 → 问伴游一个问题 → 打开历史记录;
  • 准备 1 个失败案例(如断网)说明 fallback 机制;
  • 打开 http://localhost:8000/docs 展示 API 文档,体现 FastAPI 优势;
  • 若被问代码,能快速打开:
    • backend/app/agents/trip_planner_agent.py — 主流程
    • frontend/src/services/api.ts — 异步轮询
    • backend/app/services/amap_service.py — 地图封装

  • 十、快速记忆卡片

    关键词一句话
    项目定位 AI + 高德真实数据的旅行规划助手
    后端 FastAPI + Pydantic + LLM + 高德 HTTP API
    前端 Vue3 + TS + Ant Design Vue + 高德 JS API
    核心流程 搜 POI → 查天气 → 搜酒店 → LLM 编排 → 坐标回填 → 返回
    最大难点 LLM 幻觉导致 POI/坐标不准
    核心解法 API 数据为准,LLM 只编排;解析后强制回填与校验
    长任务 plan_async + 轮询 job_id
    存储 localStorage 历史,无数据库
    亮点 伴游问答、知识图谱、PDF 导出、探索页主题 POI

    十一、常见「坑」提醒(避免面试翻车)

  • 不要说「完全是多个 AI Agent 自主对话」—— 与当前实现不符,除非你真的改了架构;
  • 不要说「坐标都是 AI 生成的」—— 恰恰相反,核心是 不信任 AI 的坐标;
  • 准备好 API Key 成本:LLM 和高德都有调用费用,面试官可能问;
  • 诚实说明数据持久化局限:无后端 DB 是已知 trade-off,不是疏忽;
  • 能解释 hello_agents 是本地兼容层,参考 Datawhale 教程,避免被问「框架源码在哪」答不上来。

  • 祝你面试顺利。 建议把本文档中标注「请按真实情况修改」的部分,换成你自己的贡献描述,并对着镜子练习 项目介绍 1 分钟版 和 技术难点 2 分钟版 各一遍。

    赞(0)
    未经允许不得转载:171主机测评 » 智能旅行规划助手 — 实习面试问答手册
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址