TCL鸿鹄实验室一面:AI语音项目被问麻了

话不多说,上面经(一面已过)。

一、面试背景

岗位:TCL鸿鹄实验室 - AI语音。相关时长:约35分钟。形式:技术一面

我这边背景:百度高级研发,6年经验,主做AI语音项目(商机智能平台),之前华为待过,算是从大厂跳大厂的节奏。

面试官很专业,问的问题基本都是围绕我的项目深度展开,没问八股,全是场景题和设计题。我只能说——干得漂亮

(那也就是说,刷的算法,背的八股,基本上是没用了,而且不只这一个面,很多面试都不考算法和基础八股了,这难道只是我的幸存者偏差吗)

二、核心问题复盘

1️⃣ 自我介绍(2分钟)

标准流程,我简单说了下三段经历:

  • 百度:商机智能平台,面向广告主的智能营销系统,融合文心大模型
  • 华为:政务审批与执法平台,流程引擎那一套
  • 之前:互联网营销系统

面试官听完直接切入项目细节,没有废话。

2️⃣ 多租户智能对话引擎设计

问题你们的多租户对话引擎怎么设计的?WebSocket连接层怎么做的?

我的回答

这块我负责三个核心模块:

  1. 核心业务服务设计
  2. 实时数据链路
  3. 结构化入仓

连接层架构

用户 → 外部WebSocket接入层(Gateway) → Netty服务 → Kafka → 对话服务(UFO)

关键设计

第一层:接入层

  • 不让业务服务直接暴露WebSocket,单独做了一层Gateway
  • WebSocket连接建立时带Token,解析出租户ID、用户ID等,存到Redis
  • 后续消息根据UID路由到正确节点

第二层:WebSocket实现

  • 没用Spring自带的WebSocket(太重)
  • 用Netty自己实现了一套,更轻更稳定
  • Netty的线程模型天然适合这种I/O密集场景

第三层:消息路由

  • 前端发消息 → Netty → Kafka → 对话服务
  • 对话服务无状态,不知道客户端在哪个节点
  • 通过Redis查SessionID → 本地Map找节点 → 写回WebSocket

面试官追问:为什么Netty比Spring WebSocket好?

我说:本质上是Reactor多线程模型,一个线程监听多个连接,避免"一连接一线程"的高开销。Netty在此基础上做了一层抽象,EventLoop绑定多个Channel,同一Channel的所有I/O事件永远在同一个线程处理,避免线程切换开销。

3️⃣ Kafka消息顺序性与不丢消息

问题:Kafka怎么保证消息顺序?怎么保证不丢消息?(这倒是老一套了,感觉例行公事,消息丢失,顺序消费这玩意)

我的回答

这块分两套策略,顺序消费和不丢消息是两个问题。

顺序性保证

Kafka本身只能保证单Partition有序,所以我们做了两层约束:

生产端

  • 按业务Key(用户ID)做分区
  • 通过Hash指定Partition
  • 同一用户的消息一定在同一分区

消费端

  • 一个Partition对应一个消费线程
  • 业务处理必须串行
  • 要提升并发就加Partition数量

不丢消息保证

分三层:生产端、Broker、消费端

生产端

  • acks=all(所有副本确认)
  • 重试机制
  • 幂等生产配置

Broker

  • 多副本机制
  • Leader + Follower复制
  • 极端情况:多节点同时挂了才丢数据(概率极低)

消费端

  • 关闭自动提交
  • 先处理业务,再手动commit
  • 处理失败不提交,重新消费

4️⃣ ThreadPoolExecutor参数配置

问题:IO密集型的线程池怎么配?(线程池,线程池,还是线程池)

我的回答

核心公式:

线程数 ≈ CPU核心数 × (1 + 等待时间/计算时间)

IO密集型特点:大部分线程在等待,等待时间 > 计算时间,所以线程数可以远大于CPU核心数。

我的经验值(8核机器):

  • 核心线程数:16-32(CPU核数 × 2-4)
  • 最大线程数:64-96(核心线程 × 2-3)
  • 队列: 短任务(如RPC调用):有界队列,容量1000左右长任务(如WebSocket消息):小队列或不排队
  • 拒绝策略:CallerRunsPolicy,让调用线程自己执行,天然限流

这是经验值,具体要看压测结果。核心指标是CPU利用率、队列长度、拒绝次数。

5️⃣ 语音实时通信的首包延迟优化(重点来了!)

问题:如果场景是语音实时双向通信,首包延迟怎么优化?网络抖动丢包怎么办?

我的回答(我说实话,这块最开始卡壳了,后来面试官正好接了个电话,我赶紧重整思路,最后还是说出来了)

这块核心是低延迟流式通信 + 弱网环境的问题。

首包延迟优化

我分三层来答:

第一层:连接建立

  • WebSocket预连接:用户进入页面就建立连接,不等点击通话
  • 用WSS不用WS,避免重定向
  • TCP Fast Open(TFO):跳过三次握手
  • 就近接入:CDN或加速节点,连接最近的网关

第二层:协议层

  • 不带冗余心跳,首次只传关键数据
  • 用Protobuf替代JSON,减少传输量
  • WebSocket消息头优化,减少边界等待

第三层:服务端

  • 预热进程池
  • 首帧优先级最高,优先转发

网络抖动丢包

应用层

  • 前向纠错(FEC)
  • 丢包重传(NACK)
  • 包合并 + 抖动缓冲
  • 动态调整发送频率

策略层

  • 客户端 + 网关做抗抖动缓冲
  • 网络好时多缓冲,差时少缓冲
  • 严重时降码率、静音检测(没声音不发包)
  • 极端情况:错误隐藏(用前一帧插值)

这块我说得比较细,面试官点头表示认可。

6️⃣ 大模型幻觉对抗(AI时代经典问题!)

问题:大模型幻觉怎么解决?输出JSON格式怎么保证?

我的回答

这块我们分三层:数据层、生成层、结果层

数据层

  • 不让模型自由发挥,通过用户问题 → 检索企业数据 → 拼进Prompt
  • 多路召回(关键词 + 向量),再做一次排序过滤
  • 上下文精简:只保留相关对话,减少干扰

生成层

  • 强规则Prompt:"只能基于提供的数据回答,数据中没有不允许编造"
  • 结构化输出:让模型输出JSON(商机名称、推荐理由、数据来源),限制表达范围
  • 降低温度(0.5左右),减少随机性
  • 多轮对话拆成两步:先理解意图,再生成结果

结果层

  • 规则校验:字段完整、类型正确
  • 数据一致性检查:查库确认数据存在
  • 自我修复:模型输出格式错误时,把错误内容喂回去,让模型修正(成功率95%+)
  • 兜底策略:重试3次失败 → 返回模板回答

三、面试感受

整场面试没有八股文,也没有算法,全是围绕项目的深度挖掘,整的我全白学了,不过也没关系,这样挺好的。

面试官问得很细,但都是在考察我的系统设计能力工程落地能力

我的感觉:

  1. 项目要熟:每个技术选型要能说清楚为什么
  2. 要有深度:不能停留在"怎么用",要讲"为什么这么设计"
  3. 要能拆解:复杂问题分层次回答,一层一层剥

最后我问了面试官三个问题:

  • 公司技术栈是什么?
  • 多久出结果?
  • 这个岗位具体做什么?

面试官说:"语音相关,AI方向,后面还有二面。暗示过了

四、总结

这场面试问的核心点:

  1. WebSocket架构设计
  2. 消息中间件(Kafka顺序性 + 可靠性)
  3. 并发编程(线程池配置)
  4. 实时音视频(首包延迟 + 抗抖动)
  5. AI工程化(幻觉对抗 + 结构化输出)

全是实打实的场景题,没有虚的,这多亏我之前自己搞了一个全双工语音项目

建议如果你也面AI语音岗,把上面这几个点吃透,尤其是实时通信和大模型应用这两块,问的概率很高。

#AI求职实录#
全部评论
点赞 回复 分享
发布于 今天 00:33 广东

相关推荐

03-16 17:06
已编辑
门头沟学院 Java
查看8道真题和解析
点赞 评论 收藏
分享
评论
4
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务