欢迎光临
我们一直在努力

32-面试实战系统设计手撕与项目讲述

32 · 面试实战:系统设计、手撕题、项目讲述与速查清单

「AI-Agent 面试深度指南」· 模块八 · 后训练、RL 与面试实战 · 第 32 篇 / 共 32 篇

引言

知识储备与面试表现之间隔着一堵墙:你懂的东西,未必能在 60 秒内有条理地说出来。本篇是整套指南的"输出层"——把前面 31 篇的知识,转换成面试现场能直接使用的答题框架、代码模板与讲述结构。

三部分:系统设计题的通用解法、三道高频手撕题的可运行骨架、以及项目经历与速查清单。

一、系统设计题:五步法

1.1 Step 1:澄清需求(2 分钟)

必问的六项:用户量级与并发、可接受延迟与成本、成功率目标、是否需要人工兜底、是否涉敏感数据与合规、知识来源与更新频率。

不要急着画架构——先问清边界。面试官考察的第一件事就是你会不会问问题。

1.2 Step 2:总体架构(画出来)

接入层(HTTP/SSE)
→ 意图路由(小模型)
→ 编排层(计划/状态机)
→ 执行层(工具集:检索、业务 API、工单、人工转接)
→ 验证层(约束检查 + 评委)
→ 输出层(引用、结构化结果)
旁路:日志/trace、评测、成本统计、权限与审计

1.3 Step 3:挑三个点深挖

不要平均用力,选三个能体现深度的点展开:

  • 上下文:稳定前缀、压缩、按需加载、缓存命中;
  • 可靠性:危险操作 HITL、幂等、失败分类重试、降级路径;
  • 评估:自建集、pass^k、失败归因、CI 回归。

1.4 Step 4:权衡与演进(体现功力)

  • 先单 Agent + 好提示词做基线,再按需加规划/反思/多 Agent;
  • 多 Agent 只在有信息增量时使用,且要用 A/B 证明值得;
  • 成本:小模型路由 + 缓存 + 减轮数;
  • 冷启动:先用规则与模板兜住高频问题,逐步让 Agent 接管。

1.5 Step 5:准备三个追问

  • “怎么保证不胡说?” → 只基于检索内容回答 + 引用 + 无证据时拒答;
  • “怎么防止越权?” → 工具权限分级 + 用户身份贯穿 + 执行层校验;
  • “怎么评估?” → 三层:组件级(recall@k)、任务级(pass^k + 成本)、业务级(人工介入率)。

加分动作:主动讲一个你踩过的具体坑(工具爆炸、上下文膨胀、评估造假)与解决办法。

二、手撕题一:ReAct 主循环

def run_react(question, tools, llm, max_steps=8):
messages = [{"role": "system", "content": SYSTEM},
{"role": "user", "content": question}]
trace, seen = [], {}
for step in range(max_steps):
reply = llm(messages, tools=tools.specs())
call = reply.tool_call
if call is None:
return reply.content, trace # 收尾
if call.name not in tools: # 工具不存在
messages.append(tool_msg(call.id,
f"错误:无此工具。可用:{list(tools)}"))
continue
key = (call.name, json.dumps(call.args, sort_keys=True))
if key in seen: # 重复调用
messages.append(tool_msg(call.id,
"已用相同参数调用过,请换方法或说明无法完成"))
continue
seen[key] = 1
try:
result = tools[call.name](**call.args)
except Exception as e: # 结构化错误回传
result = f"执行失败:{type(e).__name__}: {e};请修正参数重试"
messages.append(tool_msg(call.id, truncate(str(result))))
trace.append({"step": step, "call": call, "result": result})
return "达到最大步数,已知信息如下:", trace # 部分回答

评分点:轮数上限、重复检测、错误回传(而非抛异常)、结果截断、轨迹记录、耗尽时的部分回答。

三、手撕题二:检索与重排

def rrf_fuse(rank_lists, k=60):
scores = {}
for ranks in rank_lists:
for i, doc_id in enumerate(ranks):
scores[doc_id] = scores.get(doc_id, 0) + 1.0 / (k + i + 1)
return sorted(scores.items(), key=lambda x: x[1])

def retrieve(query, vec_index, bm25, filters, topk=50):
dense = vec_index.search(embed(query), topk, filter=filters) # 语义
sparse = bm25.search(tokenize(query), topk, filter=filters) # 关键词
return [d for d, _ in rrf_fuse([dense, sparse])][:topk]

def rerank(query, docs, cross_encoder, topn=5):
scores = cross_encoder.predict([(query, d.text) for d in docs])
ranked = [d for _, d in sorted(zip(scores, docs), key=lambda x: x[0])]
return dedup_by_parent(ranked)[:topn]

必须补的细节:过滤要在召回阶段做(pre-filter);去重相邻块;控制 token 预算;召回为空时降级。

四、手撕题三:并发、限流与重试

class TokenBucket: # 限流
def __init__(self, rate, capacity):
self.rate, self.capacity = rate, capacity
self.tokens, self.ts = capacity, time.time()
def acquire(self, n=1):
now = time.time()
self.tokens = min(self.capacity,
self.tokens + (now self.ts) * self.rate)
self.ts = now
if self.tokens < n:
time.sleep((n self.tokens) / self.rate); self.tokens = 0
else:
self.tokens -= n

def retry(fn, retries=3, base=0.5): # 退避重试
for i in range(retries):
try:
return fn()
except RetryableError: # 超时/限流/5xx
if i == retries 1: raise
time.sleep(base * 2**i + random.uniform(0, .1)) # 抖动防惊群
except FatalError: # 参数错/权限不足
raise

必答要点:区分可重试与不可重试;加抖动;设超时;写操作用幂等键;并发结果按原顺序回传;连续失败要熔断。

五、项目经历:四段式讲述

5.1 结构:背景 → 难点 → 方案 → 数据 → 复盘

背景(30 秒):业务是什么、谁用、原来怎么做、为什么需要 Agent。

难点(决定含金量):不要说"模型不够聪明",要说具体工程问题。例如:工具从 20 涨到 200 个后调用准确率从 93% 掉到 71%;长任务刷新页面就丢状态;检索召回差导致业务方不敢用。

方案(分层讲):架构图 + 四要素(上下文怎么组织、工具怎么治理、怎么保证可靠、怎么评估)。

数据(最有说服力):成功率(说明口径与样本量)、成本/延迟变化、业务指标(人工介入率、处理时长)。

复盘(展示深度):做错了什么、重做会怎么改、还差什么。

5.2 简历写法对照

反例:“负责智能客服 Agent 开发,使用 RAG、ReAct、多智能体技术。”

正例:“主导智能客服 Agent 从 0 到 1 上线。针对 300+ 工具导致调用准确率仅 72% 的问题,设计分组按需加载 + 语义检索的工具治理方案,准确率提升至 93%,单轮工具选择 token 下降 40%;构建 420 条生产回流评测集与失败归因流程,平均排查时长从 2 小时降至 20 分钟。”

检验标准:每一条都能被追问三句而你答得上来。

六、速查清单(考前自查)

能答出 80% 即可上场:

  • 能否画出 Agent = 模型 + 上下文 + 工具的架构图,并说出每部分的三条优化手段?
  • 能否说清上下文工程四件事:稳定前缀、按需加载、压缩、隔离?
  • 能否讲清 KV Cache 的前缀匹配性质及其对布局的约束?
  • 能否给出工具治理的四层阶梯与 MCP/A2A 的定位?
  • 能否说清 RAG 完整流水线与三个最常见失败点?
  • 能否比较 BM25 与向量检索的能力边界,并写出 RRF?
  • 能否区分四类记忆与各自存储策略?
  • 能否比较 ReAct / Plan-and-Solve / Reflection 的取舍并给出决策树?
  • 能否说出"什么时候不该用多 Agent"及容错手段?
  • 能否区分 pass@k 与 pass^k,并指出多步任务的幂律衰减?
  • 能否设计一套评估方案(指标 + 数据集 + 验证器 + 归因 + A/B)?
  • 能否说清后训练四阶段各自解决什么问题、RL 的前提条件?
  • 能否独立完成带边界处理的 ReAct 循环与混合检索模块?
  • 能否在 60 秒内讲清一个项目(背景—难点—方案—数据—复盘)?
  • 七、行为面试与反问

    STAR 结构:情境(一句话)→ 任务(目标与约束)→ 行动(你做的决策与取舍)→ 结果(量化 + 复盘)。每个故事都要有一个具体决定和它的代价。

    反问环节(加分项,不是走过场):团队现在 Agent 系统最大的瓶颈是什么?评测体系怎么建的、失败案例如何回流?新同学前三个月负责什么?业务上 Agent 是降本还是增收、人工兜底比例多少?技术栈自研还是开源、为什么?

    问"评测体系"的人和问"加班多不多"的人,给面试官的印象完全不同。

    小结

    技术决定下限,表达决定上限。把这套指南的知识练成"60 秒讲清一个知识点"的能力,就是秋招最稳的护城河。最后一件事:遇到不会的问题,用三步应对——承认边界 → 给出分析框架 → 说明你会怎么查证。这比硬编体面得多,也更像一个真正的工程师。

    赞(0)
    未经允许不得转载:171主机测评 » 32-面试实战系统设计手撕与项目讲述
    分享到: 更多 (0)

    评论 抢沙发

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