2026-08-30 秋招XX AI全栈开发一面复盘

发布于 2026-08-30 04:00 2616 字 14 min read 手写 每个字都是我自己敲的。

Zhiheng Wang avatar

Zhiheng Wang

技术文章、个人随笔、项目与作品体验记录

2026-08-30 秋招XX AI全栈开发一面复盘 XX AI 全栈工程师(上海)的一面,形式是牛客 AI 面试。8月30日面完后记下了这些,结果没有留下记录。 整体流程是自我介绍、八股、Agent、项目追问,少了一个手撕环节。我当时觉得它挺公式化,但转念一想,真人面试官的追问就不公式了吗? 题目与我的作答 1. 前端与 Redis 八股 八股选了 TypeScript 方向,记得四道:...

2026-08-30 秋招XX AI全栈开发一面复盘

XX AI 全栈工程师(上海)的一面,形式是牛客 AI 面试。8月30日面完后记下了这些,结果没有留下记录。

整体流程是自我介绍、八股、Agent、项目追问,少了一个手撕环节。我当时觉得它挺公式化,但转念一想,真人面试官的追问就不公式了吗?

题目与我的作答

1. 前端与 Redis 八股

八股选了 TypeScript 方向,记得四道:

  1. JavaScript 在浏览器里的事件是怎么执行的?
  2. TypeScript 泛型有什么作用?
  3. 缓存穿透、缓存击穿、缓存雪崩有什么区别?
  4. Redis 的两种持久化机制有什么区别?当时记成一个 A 开头、一个 R 开头。

这部分留下了题目,没有留下我逐题回答的原话。下面把它们按复习时能讲清楚的程度补上。

2. Function Calling → 私有 API → Agent 设计模式

后面这组是递进追问,不是几个互不相关的八股。

先问 Function Calling。我当时说,本地内置了 Python 解释器,把 Tools 写好、规约好,模型自己调用工具去跑。但我又提到,本地环境不能覆盖所有场景,还会涉及一些 API。

于是它继续问:私有 API、网络服务这种工具,具体怎么实现?我回答了 MCP。

再往后问 Agent 有哪些设计模式。我当时只知道 ReAct,不清楚还有哪些更通用的模式。这两块是我自己觉得答得不好的地方。

3. 最自豪的 AI 项目,以及和 AI 迭代中发现的问题

Agent 部分结束后,开始问项目:

  • 讲一个自己最自豪、最想讲的 AI / Vibe Coding 项目,解决了什么问题,怎么做的。
  • 有没有一开始没发现,后来和 AI 反复迭代才发现的问题?最后怎么定位、怎么解决?
  • 再围绕这个问题继续追问一些细节。

我记住了这条追问线,但没有留下具体讲的是哪个项目、举了哪个问题,后面几次追问也记不清了。这一段先保留到这里。

复盘与重做

以下是事后整理的知识解释和重答思路,不是把它们补写成我当时已经答出来的内容。

1. 浏览器事件执行:同步代码、微任务、任务

可以先从一段最短的代码说起:

console.log(1);

setTimeout(() => console.log(2), 0);

Promise.resolve().then(() => console.log(3));

console.log(4);

输出是 1、4、3、2。

1 和 4 是同步代码,先执行。Promise.then 的回调进入微任务队列,setTimeout 的回调是后续任务。当前这段代码执行完、调用栈清空后,先清空微任务,再有机会处理下一个任务,所以 3 在 2 前面。计时器写0也不表示回调会立刻打断当前代码。

讲事件循环时,把这条顺序说清楚,再按追问补浏览器提供的计时器、网络等异步能力,以及渲染时机,就比较容易展开。这里讲的是同一个页面 JavaScript 执行环境里的顺序,不是说整个浏览器只有一个线程。

2. TypeScript 泛型:保留输入和输出的类型关系

泛型可以把类型当成参数。同一份函数能处理不同类型,同时保留类型检查。

function identity<T>(x: T): T {
  return x;
}

const a = identity(123);      // number
const b = identity("hello");  // string

如果写成 any,函数确实也能接收这些值,但返回值和输入之间的类型关系就丢了。这里的 T 表示:传进来是什么类型,返回的仍然是那个类型。

需要限制参数能力时,就加约束:

function printLength<T extends { length: number }>(x: T) {
  console.log(x.length);
}

这时 T 可以变化,但必须有 length。接口也一样,例如 ApiResponse<T> 可以复用响应结构,让 data 分别是 User、Product,不用每次重写一遍。Python 的 TypeVar、list[int] 也是类型参数化的例子,只是 Python 的类型提示本身不会把运行时变成静态类型语言。

3. 缓存三件套:先分清故障发生在哪里

情况发生了什么常见处理
穿透查的数据根本不存在,缓存和数据库都没有,请求反复打到数据库参数校验、缓存空值、布隆过滤器
击穿某个热点 Key 失效,大量请求同时回源合并回源请求、互斥更新、提前刷新或逻辑过期
雪崩大量 Key 同时失效,或者缓存服务整体不可用TTL 加随机值,配合限流、降级、多级缓存和高可用

先用“不存在、一个热点、大面积失效”把三种情况分开,再针对场景展开。TTL 加随机值能缓解同时过期,解决不了 Redis 整体宕机,不能把所有方案混在一起背。

4. RDB 和 AOF:快照与写操作日志

RDB 保存某个时间点的数据快照,文件通常比较紧凑,适合备份和恢复。代价是宕机时可能丢掉最近一次快照之后的修改。

AOF 记录写操作,通过重放恢复数据。具体能丢多少数据取决于刷盘策略:always 尽量及时刷盘;everysec 每秒刷盘,通常可能丢最近约一秒的写入;no 交给操作系统决定。它也会做重写,不能理解成日志永远只增不减。

两种可以结合使用,重点是根据可接受的数据丢失窗口、性能和恢复需求选择,不能简单说一种在所有场景都更好。

5. Function Calling:把模型和执行程序分开

我当时说“模型自己调用 Python 解释器去跑”,容易把两层混在一起。

模型看到工具说明和参数格式后,生成的是“调用哪个工具、传什么参数”的结构化请求。真正执行函数、操作解释器、访问网络或数据库的是外面的程序。执行完,再把结果交回模型,让它继续判断。

用户问题
  → 模型返回工具名、参数
  → 程序检查参数与权限,执行工具
  → 工具结果放回上下文
  → 模型继续回答,或再调用工具

所以“内置 Python 解释器”可以是工具的一种实现,但不是 Function Calling 本身的定义。先讲清楚这两层,后面的远程工具问题也就容易接了。

6. 私有 API:先解释调用怎么发生,再说 MCP

模型不需要自己持有私有服务的密钥,也不直接替我完成网络请求。可以在后端封装一个工具函数,由它带着服务需要的身份和权限,通过 HTTP、SDK 或 RPC 调用接口,把结果整理好再返回。

我当时直接回答 MCP,跳到了工具接入方式这一层。MCP 可以用来标准化工具发现和调用,但不用 MCP,也能把一个私有 API 包装成工具。

把这条路径说完整会更清楚:

模型提出工具调用
  → 后端工具函数
  → 带认证访问私有服务
  → 得到业务结果
  → 返回模型

如果工具通过 MCP 接入,宿主里的 Client 先向 Server 查询可用工具及参数说明,再把这些能力提供给模型;执行时由 Client 把调用交给 Server。常见的方法名是 tools/list 和 tools/call。

MCP Server 可以在本机,也可以在远端。本机常见 STDIO,远端可以使用 HTTP;它不等于“远程 API”,也不是所有工具调用的必经步骤。除 Tools 外,它还可以提供 Resources 和 Prompts。

7. Agent 设计模式:从 ReAct 往外展开

我当时只知道 ReAct。复习时可以按任务怎么组织来记几种思路:

  • ReAct:推理、行动、观察结果,再继续推理,边做边决定下一步。
  • Plan-and-Execute:先列计划,再逐步执行,必要时调整计划。
  • Reflection:先得到一版结果,再检查、修正。
  • Router / Supervisor:按任务类型分发,或由一个协调者安排其他 Agent。

这不是一个互斥、穷尽的分类表。实际系统往往会混合使用,再配合重试、超时、最大步数、检查点、人工确认等控制。

8. 项目追问:需要补一个具体故事

这一部分还缺当时的具体回答,不能拿现在的项目经历直接回填。后续回忆时,只需要把一件事说清楚:

做的是哪个项目 → 最初漏掉了什么问题 → 怎么发现 → 和 AI 怎么迭代 → 最后怎么确认解决了。

如果某次追问已经记不起来,就留在这里,不把通用答题建议写成当时的对话。

顺带整理几个容易混的概念

这些来自后续复习,不另外算成面试官问过的题:

  • Multi-Agent 是多个 Agent 分工协作;职责、工具和上下文可以不同,但会增加通信、成本和调试难度。
  • Trace 记录一次任务里的模型调用、工具调用、耗时和错误,是排查执行过程的线索,不是一种 Agent 架构。
  • Swarm 在不同系统里的具体含义不同,常用来描述多个 Agent 之间动态协作或交接,不能把某个框架的做法当成唯一标准。
  • Memory 可以存放在外部;只有被取出并放进当前请求的部分,才是模型这一次真正看到的上下文。
  • RAG 主要解决取什么资料来辅助生成;Agent 主要讨论怎样决定和执行后续行动,两者可以结合。
  • Redis 的过期删除处理到期的 Key,内存淘汰处理内存不足时留谁;LRU 看最近使用,LFU 看频率。主从复制复制数据,Sentinel负责监控与故障切换,Cluster通过16384个槽分片并提供相应故障转移能力。

当时想写的帖子叫“秋招第一面和第一挂”,但“第一挂”说的是另一家公司的结果,不能因此把这场也记成挂了。

执笔 手写

随机文章

© 2026 Zhiheng Wang @traceonsnow
Powered by theme astro-koharu · Inspired by Shoka
加载中...