蔚来大模型算法岗(智能座舱/自动驾驶)实习一面面经
- 轮次
- 实习一面
- 时间
- 2026-09
- 来源
- 牛客网
《面试题目》
- 你做过智能座舱或自动驾驶相关的项目吗?具体做了什么?
- 座舱场景的 Agent 环境,模型部署在端侧还是云端?为什么?
- 如果让你设计一个「车内语音助手 Agent」,你会怎么做?
- 语音场景下,怎么处理噪音、打断、多轮对话?
- 如果用户说「打开空调并把温度调到 24 度」,Agent 怎么理解复合指令?
- 如果涉及车窗、车门等安全操作,怎么增加二次确认?
- 座舱场景对延迟要求极高,怎么优化 Agent 的响应速度?
- 如果端侧算力有限,怎么设计模型选型?
- 你怎么评估座舱 Agent 的用户体验?有哪些指标?
- 如果让你设计一个「行程规划 Agent」,结合车辆续航、充电桩,你会怎么做?
- 如果电量不足以到达目的地,Agent 怎么提醒和规划?
- 自动驾驶场景下,大模型能做什么?VLA、VLM 的进展?
- 从一段式、两段式到 VLA/VLM,你对这些技术有什么思考?
- 如果让你设计一个「驾驶行为分析 Agent」,你会怎么做?
- 多模态在自动驾驶中怎么用?视觉、雷达、语音怎么融合?
- 如果让你做「自动驾驶数据挖掘」,怎么用大模型?
- 你怎么看大模型在自动驾驶端到端方案中的角色?
- 如果让你设计一个「智能泊车 Agent」,你会怎么做?
- 泊车场景下,怎么处理复杂环境?
- 如果让你设计一个「车辆健康监测 Agent」,实时检测故障,你会怎么做?
- 故障诊断的误报率怎么控制?
- 如果让你设计一个「车主助手 Agent」,回答车辆使用问题,RAG 怎么设计?
- 车辆手册有很多表格和图片,怎么处理?
- 如果用户问「这个灯亮了什么意思」,Agent 怎么诊断?
- 你怎么评估车辆 Agent 的准确性?
- 如果让你做 Agent 的 A/B 实验,怎么设计?
- 座舱场景下,怎么保证 Agent 的隐私安全?
- 如果用户数据要上传云端,怎么脱敏?
- 你怎么看大模型在智能座舱的未来?
- 如果让你从零搭建座舱 Agent 平台,核心模块有哪些?
- 你怎么做 Agent 的版本管理和 OTA 升级?
- 如果模型升级导致行为变化,怎么保证稳定性?
- 你最近关注智能座舱/自动驾驶的哪些新技术?
- 如果让你设计一个「多屏互动 Agent」,协调仪表盘、中控、HUD,你会怎么做?
- 多屏场景下,怎么保证信息一致性?
- 如果让你设计一个「情感交互 Agent」,识别用户情绪并回应,你会怎么做?
- 情绪识别准确率怎么保证?
- 你怎么评估 Agent 的「拟人化」程度?
- 你最近读过什么自动驾驶相关的论文?有什么启发?
- 手撕:实现一个函数,给定一个数组,返回数组中所有元素的排列组合。
《参考解析》
端侧还是云端:按「安全等级 + 延迟预算 + 数据敏感度」切三层,而不是二选一
先算延迟账:座舱语音链路的体验门槛大致是「唤醒到首字出声 ≤ 700ms1s,用户说完到动作执行完 ≤ 1.5s」。云端方案里,车联网一次 RTT 在 4G 弱网下能到 800ms1s,再叠加 LLM 首 token 300800ms,稳态很难达标;端侧 7B int4 在高通 8295 或 Orin-X 这类座舱 SoC 上,首 token 可以压到 150400ms,且完全离线可用。所以合理的答案是分层:
- L0 本地规则/命令词直达:ASR 结果命中固定语法(「下一首」「调高音量」)直接执行,不经过模型,<200ms。
- L1 端侧小模型:1.5B~7B,AWQ/GPTQ int4 量化,配 KV cache 复用与投机解码(Medusa、EAGLE 这类 draft 头),处理高频短指令与车控意图槽位。
- L2 云端大模型:开放域闲聊、长上下文、复杂规划、手册 RAG、多轮推理。
层间路由用一个轻量分类器 + 阈值:意图置信度 > 0.8 且槽位完整就留在端侧,否则升级云端,并把本地 ASR 文本与对话状态一起带上,避免用户重新说一遍。两条硬约束:一是车窗、车门、后备箱、双闪这类执行类指令必须端侧兜底,不能因为进隧道没信号就失效;二是舱内摄像头与麦克风的原始音视频不出车,只上传文本或结构化摘要。数据敏感度上还可以再分档:声纹、人脸这类生物特征模板永久本地;行车轨迹这类上传前做泛化(把精确坐标降精度、切掉起终点附近路段)。
复合指令与安全二次确认:schema 约束解码 + 风险分级门控
「打开空调并把温度调到 24 度」只是最简单的复合句,真实场景更像「打开空调、温度 24 度、再把主驾座椅通风开到二档、顺便导航回家」。做法是把自然语言解析成一串结构化的动作对象,用 function calling 输出,temperature 设 0,并用 constrained decoding(vLLM 的 guided decoding、outlines、XGrammar)把输出钉死在 schema 上,避免 JSON 截断或字段胡编:
[{"action":"AC_ON"},{"action":"AC_SET_TEMP","value":24},{"action":"SEAT_VENT","seat":"driver","level":2}]
执行时按序串行,每个动作带 dependsOn 与超时;前一个失败就中断并把已执行的动作回滚(空调开过了就说明「空调已开,座椅通风没做成」),不要静默吞掉。
安全二次确认的核心是给动作打风险等级再分别定策略,而不是所有操作都弹确认:
- L0 只读查询(电量、续航、胎压):直接答,不确认。
- L1 舒适件(空调、氛围灯、音乐):直接执行,可撤销。
- L2 车身件(车窗、天窗、后备箱、儿童锁):必须二次确认——TTS 复述「确认打开右后车窗吗?」,3~5 秒超时,只接受明确肯定词(「确认/是/好」),否定或超时一律不执行;同时做条件门控,车速 > 5km/h 禁止开后备箱、行驶中禁止开全部车窗。
- L3 行驶相关(车道保持、自动变道):语音只做提示和确认入口,真正执行交给 ADAS 域控,并校验驾驶员在环(手握方向盘、视线前视)。
确认话术要短、要可打断(用户说「算了」立刻取消),且确认状态要带上下文有效期(比如 10 秒内有效,过期重新问),否则容易出现「上一轮的确认」被下一个指令误用。
多模态在自动驾驶里怎么融合:先分清「感知层融合」和「语言层推理」
面试里最容易答糊的地方是把 VLM 当成感知的替代。实际分工是:感知层用 BEV + Transformer 做特征级融合(BEVFormer 把多相机投到统一 BEV 空间,BEVFusion 再把激光雷达点云与图像在 BEV 上拼起来),输出检测/占据栅格/轨迹;语言模型层负责长尾语义理解、决策解释、数据挖掘与仿真场景生成。
「一段式 / 两段式 / VLA」的差别在于接口:两段式是感知模块输出中间表征给规划模块,模块边界清晰、易调试,但误差会累积;一段式(UniAD 那种)把感知、预测、规划塞进一个网络联合优化,减少信息损失,但可解释性和可调试性差、训练更吃数据;VLA 是引入视觉-语言-动作,让语言充当中间推理链,输出「前方施工,先减速后向左借道」这样可读的决策。
VLA 在车端的现实问题是延迟:7B 级 VLM 想在车端跑到 10Hz 不现实,所以工程上普遍走双系统——VLM 以 12Hz 出语义级意图/风险判断并写进 memory,规控小模型以 1020Hz 执行,VLM 在影子模式下先跑一段、对齐后再上车。融合的工程坑有三个:时间戳同步(相机 30Hz、毫米波 10~20Hz、IMU 100Hz,要做硬件触发对齐而不是软件凑)、外参标定漂移(跑一段时间就得在线标定)、模态退化(雨雾天激光雷达衰减、强逆光相机失效),训练时用随机丢模态(sensor dropout)能显著提升鲁棒性。评测别只看开环 L2 距离和碰撞率,那个会系统性高估,必须看闭环/实车的接管率(MPI)与危险场景通过率。
座舱 RAG:表格别整块塞,图片先转成结构化文本
车辆手册是典型的「表格 + 示意图 + 多车型年款」语料,直接按 512 token 切块做向量检索必翻车。
表格的处理原则是先把表拆成记录,再进检索:解析时展开合并单元格,把每一行转成一条带上下文的文本,例如 (表名=轮胎气压标准, 车型=ES6 2024 款, 轮胎规格=255/50 R20, 前轮冷态胎压=2.4 bar)。chunk 里必须冗余带上表名、单位和适用车型,否则召回出来的「2.4」没有任何意义。数值类问题(胎压多少、油液型号、保险丝安培数)更稳的做法是走 text2sql 或结构化查询工具,把命中的表按车型过滤后算,而不是靠向量相似度碰运气。
图片的处理是三步:① 用 VLM 给每张图生成结构化描述(图里有什么、箭头指向哪、编号列表内容、图注文字),转成文本 chunk 入库;② 检索时图文都返回,答案里回显原图链接或页码;③ 故障灯这类强视觉问题(用户问「这个灯亮了什么意思」或直接拍照)单独走一个 VLM 分类分支,按颜色和形状先判风险等级——红色=立即安全停车并联系售后,黄色=尽快检修,绿色/蓝色=状态指示——再拿识别到的灯名去召回对应手册条目,最后给出「能否继续行驶」的明确结论,而不是只念一段说明。
检索层用 BM25 + 向量混合召回、RRF 融合,车型/年款/配置作为元数据硬过滤(这一条不能软,胎压和油液型号在不同年款上确实不同),rerank 后取 top-3~5 进上下文。拒答阈值要有:最高相关性低于阈值就回「请查阅《用户手册》第 X 章」并给出页码,宁可让用户翻手册,也不要编一个数字。
手撕:数组全排列的写法与复杂度
标准回溯,原地交换版本最短。以 n=3 为例,从位置 i 开始,把 i 和后面每个位置交换、递归、再换回来:
def permute(nums):
res, n = [], len(nums)
def dfs(i):
if i == n:
res.append(nums[:]) # 必须拷贝,nums 后面还会被改
return
for j in range(i, n):
nums[i], nums[j] = nums[j], nums[i]
dfs(i + 1)
nums[i], nums[j] = nums[j], nums[i]
dfs(0)
return res
复杂度:输出共 n! 个排列,每个排列拷贝 O(n),所以时间 O(n · n!);递归栈深度 n,额外空间 O(n)(不含输出)。要强调两个坑:一是 res.append(nums) 而不是 nums[:],会得到一堆指向同一列表的引用,最后全是同一个排列;二是元素有重复时 swap 法会吐重复结果,[1,1,2] 会输出 6 条而不是 3 条。去重两种写法:用 used 数组,先排序,再 if used[j] or (j > 0 and nums[j] == nums[j-1] and not used[j-1]): continue;或者用 set 兜底但代价是额外的哈希开销,面试里最好主动提「排序 + used + 剪枝」这个标准解。
规模边界也要主动说:n=10 就是 3628800 个排列,全部物化会打爆内存,此时应改成生成器逐条 yield;如果只需要第 k 个排列,不要枚举,用 next_permutation 迭代或康托展开(Cantor expansion)在 O(n²) 内直接算出来。再补一句边界:空数组返回 [[]](或按题意返回空),单元素返回它自身。