面试题库
共 328 题,当前筛选 22 题。
还有 359 个标签收起标签
30 天从前端工程师到 Agent 工程师
D1 LLM API 基础:messages/roles、token、流式、temperature;Agent 到底是什么
用户切到后台或者直接关掉网页,回来后怎么恢复那条还在生成的回复?The user backgrounds the app or closes the tab. How do you restore a reply that was still being generated?
国内高频海外高频深入#streaming#reliability#architecture分析过程 · 先想清楚再作答
- 先识别这题和「网络断了」不是同一个问题:客户端已经不存在了,任何写在前端的重试逻辑都不会执行。
- 由此推出唯一出路:生成过程必须能脱离这个客户端独立存活,也就是把流本身放到服务端持久化。
- 落到具体架构:发起请求时给这轮生成分配一个流 id,服务端一边把 token 推给当前连接,一边把同样的内容写进 Redis 之类的存储;会话记录里保存这个 activeStreamId。
- 恢复路径是另开一个 GET 端点:客户端带着会话 id 请求,服务端按 activeStreamId 找到那条流并接着推;找不到活跃流就返回 204,让前端知道没有需要恢复的东西。
- 说清代价,别只说方案:多了一份存储、一套过期清理、以及「同一条流可能被多个连接消费」的并发问题。
- 延伸:这套结构和普通聊天产品的「消息已持久化,重进会话直接读库」不同——区别在于回复还在生成中,需要的是可续的流而不是一条静态记录。
How to reason about it · think before answering
- First separate this from a dropped connection: the client is gone, so no client-side retry will ever run.
- That leaves one option — the generation must outlive the client, which means persisting the stream server-side.
- Concretely: assign a stream id per generation; the server pushes tokens to the live connection while also writing them to storage such as Redis, and the chat record stores that activeStreamId.
- Recovery is a separate GET endpoint: the client asks with the chat id, the server locates the stream by activeStreamId and resumes; with no active stream it returns 204.
- Name the costs, not just the design: extra storage, expiry/cleanup, and concurrency when several connections consume the same stream.
- Extension: this differs from ordinary message persistence because the reply is still being produced — you need a resumable stream, not a static row.
答题要点
- 客户端已经不在了,前端重试无从谈起,必须让生成过程在服务端独立存活
- 发起生成时分配流 id,服务端边推送边把内容写进 Redis,会话里记录 activeStreamId
- 恢复走单独的 GET 端点:按会话 id 找到活跃流接着推,没有活跃流就返回 204
- 代价:额外存储、过期清理,以及同一条流被多个连接消费的并发处理
- 与「消息持久化后重新读库」的区别在于回复仍在生成中,需要的是可续的流
Key points
- The client is gone, so recovery must live server-side: the generation has to outlive the connection
- Assign a stream id at start; the server writes tokens to Redis while streaming, and the chat stores activeStreamId
- Resume through a dedicated GET endpoint that replays the active stream, returning 204 when there is none
- Costs: extra storage, expiry and cleanup, and concurrent consumers of one stream
- It differs from plain message persistence because the reply is still in flight, so you need a resumable stream
D3 Pi SDK 上手:三层架构、Agent Loop 对照(dg P01/P02/M02/M03)
Pi SDK 的三层架构分别对应什么职责?这样分层解决了什么问题?What are the responsibilities of Pi SDK's three layers, and what does that layering buy you?
国内高频海外高频基础#framework-design#architecture分析过程 · 先想清楚再作答
- 前半句是记忆题,后半句才有区分度。只背出三个包名而说不出「为什么这么切」,面试官会判断你只是照着文档看了一遍。
- 先把三层说准:最底层是统一的模型调用层,负责把各家 provider 的请求格式、鉴权、流式分包收敛成一套接口,还统计 token 与成本;中间是 Agent 内核层,构建在模型层之上,负责 Agent 循环、工具执行、状态管理和事件流;最上层是应用层,负责会话存取、扩展与资源装载、内置工具,以及交互式、打印、进程间调用、嵌入式 SDK 这几种运行模式。依赖方向严格单向向下。
- 然后回答「解决了什么」:分层的价值是让你能「只要一半」——只想要统一的模型调用层就停在最底层,想要完整循环但不要终端交互就停在中间层。这条判据可以用来评估任何框架,比复述包名有用得多。
- 补一个很实际的收益:排障时先判断问题落在哪一层。报错栈里出现模型层,多半是鉴权、模型 id 或请求格式;出现内核层,那是循环或工具执行;两者的排查方向完全不同。
- 可以预期的追问:这套分层跟你手写的版本怎么对应?答手写版把三层揉在了一个文件里——fetch 那几行是模型层,while 循环和工具分派是内核层,命令行交互是应用层。能当场做这个映射,比任何背诵都有说服力。
How to reason about it · think before answering
- The first half is recall; the second half carries the signal. Reciting three package names without explaining the cut suggests you only skimmed the docs.
- State the layers precisely: the bottom is a unified model layer that normalizes each provider's request format, auth and streaming into one interface while tracking tokens and cost; the middle is the agent kernel built on top of it, owning the agent loop, tool execution, state and the event stream; the top is the application layer, owning session storage, extension and resource loading, built-in tools, and the interactive, print, RPC and embedded-SDK run modes. Dependencies point strictly downward.
- Then answer what it buys: layering lets you take only half. Want just a unified model layer and your own loop? Stop at the bottom. Want the full loop but none of the terminal UX? Stop in the middle. That test generalizes to any framework and is worth far more than the package names.
- Add the practical payoff: when something breaks, first place it in a layer. A stack trace through the model layer points at auth, a wrong model id or a malformed request; one through the kernel points at the loop or tool execution. The two investigations look nothing alike.
- Expect the follow-up: how does this map onto the loop you wrote by hand? All three layers were collapsed into one file — the fetch calls were the model layer, the while loop and tool dispatch were the kernel, and the CLI was the application layer. Making that mapping live is more convincing than any recitation.
答题要点
- 模型层:统一各家 provider 的请求格式、鉴权与流式,附带 token 与成本统计,只收录支持工具调用的模型
- 内核层:Agent 循环、工具执行与结果回填、状态管理、事件流,构建在模型层之上
- 应用层:会话存取、扩展与资源装载、内置工具,以及交互式、打印、进程间调用、嵌入式 SDK 几种运行模式
- 依赖单向向下,好处是每层可单独替换、单独测试,也能「只要一半」
- 排障时先定位问题落在哪一层,模型层和内核层的排查方向完全不同
Key points
- Model layer: normalizes provider request formats, auth and streaming, tracks tokens and cost, and only ships tool-calling models
- Kernel layer: the agent loop, tool execution and result folding, state management and the event stream, built on the model layer
- Application layer: session storage, extension and resource loading, built-in tools, and the interactive, print, RPC and embedded-SDK run modes
- Dependencies point one way, so each layer is replaceable and testable on its own and you can adopt only part of the stack
- For debugging, place the failure in a layer first — model-layer and kernel-layer investigations diverge immediately
D8 为什么 Gateway/Worker 分离;Postgres 表设计(sessions/runs/messages)+ Drizzle
为什么生产级 Agent 服务通常要把 Gateway 和 Worker 拆开?什么情况下不该拆?Why do production agent services usually split a gateway from workers, and when should you not split?
国内高频海外高频基础#architecture#scalability分析过程 · 先想清楚再作答
- 题眼在后半句。只答「解耦、可扩展」是从架构书上抄来的,面试官想知道你有没有被某个具体现象逼着拆过——所以答案里必须出现「什么现象」和「不拆的代价」。
- 先给一条可复用的推导链:Agent 的一次执行是长耗时且时长不可预测的(模型响应加上多轮工具调用,几秒到几十秒),而接入层要承载全部流量、必须是毫秒级的短请求;把两种时长量级差三个数量级的工作放进同一个进程,慢的那一类必然会挤占快的那一类的资源。
- 把现象说具体:单进程时一台机器同时跑十几次长执行,连接与内存被占满,新来的健康检查开始超时,编排系统判定实例已死并重启它——正在跑的执行全部陪葬。这个「健康检查被自己的业务拖挂」的故事比任何抽象论证都有说服力。
- 然后给判据:能在 Worker 做的不放 Gateway,接入层只留鉴权、限流、落库、投递这四件耗时确定的事。拆开之后 Gateway 无状态可以任意扩缩,Worker 的并发度可以按模型配额单独调,两者的扩容曲线本来就不一样。
- 主动说代价,这是区分度所在:接口语义从 200 变成 202,客户端要多一次订阅往返;系统里多了一条总线和一张 runs 表,可观测性和排障链路都变长;本地开发要起更多进程。所以单次执行只有几百毫秒、没有工具调用、日活很小的场景不该拆——那时候拆分带来的复杂度远大于收益。
- 可以预期的追问:不拆但用线程池或者子进程行不行?答案是能缓解「挤占」但解决不了「重启即丢失」和「多实例状态不共享」,因为那两件事的根因是状态在进程里,不是并发模型不对。
How to reason about it · think before answering
- The hinge is the second half. Answering only 'decoupling and scalability' sounds copied from a textbook; the interviewer wants to know which concrete symptom forced you to split, and what splitting costs.
- Offer a reusable chain: one agent run is long and unpredictable (model latency plus several tool calls, seconds to tens of seconds), while the ingress path carries all traffic and must stay in the millisecond range. Put workloads three orders of magnitude apart in the same process and the slow one starves the fast one.
- Make the symptom concrete: a single process running a dozen long executions saturates connections and memory, health checks start timing out, the orchestrator declares the instance dead and restarts it, and every in-flight run dies with it. That story lands harder than any abstract argument.
- Then state the rule: anything a worker can do should not live in the gateway, which keeps only auth, rate limiting, persistence and dispatch — four steps with bounded latency. After the split the stateless gateway scales with traffic while worker concurrency is tuned against model quota; the two curves were never the same.
- Volunteer the cost, which is where candidates separate: the contract becomes 202 instead of 200 so clients need a second subscribe round trip, you now operate a bus and a runs table, tracing spans more hops, and local development needs more processes. So do not split when a run takes a few hundred milliseconds, uses no tools, and serves modest traffic.
- Expect the follow-up: could a thread pool or child processes do instead? They ease starvation but fix neither 'restart loses in-flight work' nor 'two instances cannot see each other's state', because the root cause is state living inside the process, not the concurrency model.
答题要点
- 一次 Agent 执行是几秒到几十秒的长任务,接入层是毫秒级短请求,两者同进程时长任务必然挤占短请求的资源
- 单进程的三个具体死法:重启丢掉在途执行、多实例状态各存各的、长执行把健康检查拖超时导致实例被误杀
- 判据是「能在 Worker 做的不放 Gateway」,接入层只留鉴权、限流、落库、投递
- 拆开后 Gateway 无状态按流量扩容、Worker 按模型配额扩容,两条曲线可以独立调
- 代价是接口从 200 变 202、多一次订阅往返、排障链路变长;单次执行仅几百毫秒且无工具调用的场景不该拆
Key points
- A run takes seconds to tens of seconds while ingress requests are millisecond-scale; in one process the long work starves the short work
- Three concrete failure modes: restarts lose in-flight runs, multiple instances hold separate state, and long runs stall health checks so the orchestrator kills a healthy instance
- The rule is that anything a worker can do stays out of the gateway, which keeps only auth, rate limiting, persistence and dispatch
- After splitting, gateways scale on traffic and workers scale on model quota — two independent curves
- Costs: a 202 contract plus a subscribe round trip, an extra bus and table to operate, longer traces; skip the split for sub-second runs with no tool calls
D9 Redis Streams 消息总线:XADD/XREADGROUP/XACK/XAUTOCLAIM、consumer group、毒消息
Redis Streams 和 Kafka 该怎么选?什么情况下 Streams 明显不够用?How do you choose between Redis Streams and Kafka, and when is Streams clearly not enough?
国内高频海外高频进阶#message-bus#redis-streams#architecture分析过程 · 先想清楚再作答
- 这题的坏答案是「看数据量」。吞吐从来不是第一判据——单机 Redis 每秒几万条 XADD 毫无压力,绝大多数业务的量级根本碰不到天花板。答成「量小用 Streams、量大用 Kafka」会被认为没做过选型。
- 换成两个真正的判据来推:一、这些消息需要保留多久;二、会不会有第二类消费方。生命周期是「执行一次就没用了」、且只有执行层这一个消费方,Streams 完全够用,还省掉一整套运维;需要「三个月内任意时间点重放」、或者同一份数据要同时喂给实时执行、离线数仓、风控三条链路,那就该上 Kafka。
- 再补三条结构性差异:Streams 是内存为主、保留全靠你自己 MAXLEN 或 XTRIM,Kafka 是磁盘顺序写、保留几周是常态;Streams 一个组里加多少消费者都行,Kafka 的消费者数受分区数限制,多了就有人空转;顺序保证的粒度不同,Streams 是单条流内有序而组内分配随机,Kafka 是同 key 落同分区、分区内有序。
- 然后主动说出那条最能体现深度的话:Redis 的持久化是有损的。AOF 默认每秒刷盘,最坏丢最后一秒的写入;主从异步复制,故障切换时未同步的消息会消失。所以用 Streams 时架构上必须有一个真相之源——本课是 Postgres 的 runs 表,流只是触发器,丢了消息那个 run 还停在 pending,补投任务会把它捡回来。把总线当唯一数据源是最危险的误用。
- 结论落成一句可复用的判断:Streams 适合「触发执行」,Kafka 适合「数据管道」。前者的消息是一次性的命令,后者的消息是需要被多方反复读取的事实。
- 可以预期的追问:那 RabbitMQ、SQS 呢?答:RabbitMQ 强在复杂路由和延迟队列(Streams 没有原生延迟投递,要自己带「下次可执行时间」重投);SQS 强在零运维,代价是没有回放、也没有严格顺序(FIFO 队列另算)。把判据说成「保留时长、消费方数量、路由复杂度、运维预算」四条,比背产品参数强得多。
How to reason about it · think before answering
- The bad answer is 'it depends on volume'. Throughput is never the first criterion — a single Redis node handles tens of thousands of XADDs per second, and most workloads never approach that ceiling. 'Small volume Streams, large volume Kafka' reads as never having run a real evaluation.
- Use two real criteria instead: how long the messages must be retained, and whether a second class of consumer will appear. If a message is useless once executed and the execution layer is the only consumer, Streams is plenty and saves an entire operational surface. If you need replay from any point in the last three months, or the same data must feed real-time execution, an offline warehouse and a risk engine, choose Kafka.
- Add three structural differences: Streams is memory-first with retention you enforce yourself via MAXLEN or XTRIM, while Kafka does sequential disk writes and keeps weeks by default; a Streams group takes any number of consumers, while Kafka consumers are capped by partition count and extras idle; ordering granularity differs — Streams orders a single stream but dispatches randomly within a group, Kafka pins a key to a partition and orders within it.
- Then volunteer the line that shows real depth: Redis persistence is lossy. AOF fsyncs once per second by default, so the last second of writes can vanish, and replication is asynchronous, so a failover can drop unreplicated messages. Using Streams therefore requires a source of truth elsewhere — here the Postgres runs table, with the stream acting only as a trigger; a lost message leaves the run pending and a sweeper republishes it. Treating the bus as the only datastore is the dangerous misuse.
- Land on a reusable rule: Streams suits triggering work, Kafka suits data pipelines. One carries one-shot commands, the other carries facts that many parties re-read.
- Expect: what about RabbitMQ or SQS? RabbitMQ wins on complex routing and delayed delivery (Streams has no native delay, you republish with a next-eligible timestamp); SQS wins on zero operations at the cost of replay and strict ordering (FIFO queues aside). Framing the criteria as retention, number of consumers, routing complexity and operational budget beats reciting product specs.
答题要点
- 第一判据不是吞吐,是「消息要保留多久」和「会不会有第二类消费方」
- 只有执行层一个消费方、消息执行完即失效:Streams 够用,且大概率你已经有 Redis,零新增运维
- 需要长期保留与任意时间点回放、或多条下游链路共用同一份数据:选 Kafka
- 结构差异:Streams 内存为主、保留靠自己裁剪、组内分配随机;Kafka 磁盘顺序写、按 key 分区且分区内有序、消费者数受分区限制
- Redis 持久化有损(AOF 每秒刷盘、异步复制),所以真相之源必须是数据库,流只当触发器,靠补投任务兜底
- 一句话判断:Streams 适合触发执行,Kafka 适合数据管道
Key points
- The first criterion is not throughput but retention length and whether a second class of consumer will exist
- One consumer class and messages that expire on execution: Streams is enough, and you probably already run Redis
- Long retention with arbitrary replay, or one dataset feeding several downstream pipelines: pick Kafka
- Structural differences: Streams is memory-first with self-managed trimming and random in-group dispatch; Kafka is sequential-disk, key-partitioned with in-partition ordering, and caps consumers at partition count
- Redis persistence is lossy (per-second AOF fsync, async replication), so the database must be the source of truth with the stream as a trigger plus a republish sweeper
- One-line rule: Streams triggers work, Kafka moves data
D12 长期记忆:pgvector、embedding、chunking、memory_search 工具
pgvector 和专用向量数据库相比,优劣分别是什么?你会怎么选?How does pgvector compare with a dedicated vector database, and how would you choose?
国内高频海外高频进阶#vector-database#pgvector#architecture分析过程 · 先想清楚再作答
- 这题考的是选型判断力,不是产品参数背诵。开口就报「Milvus 支持分布式、Qdrant 过滤更强」是最没有区分度的答法——面试官想知道你按什么判据选,以及你有没有算过运维成本。
- 先给三个提问维度,把选型变成可推导的:数据量到什么量级、要不要和业务表在同一个事务里提交、过滤条件复不复杂。这三问能覆盖绝大多数真实场景。
- pgvector 的赢面几乎全在后两问上:记忆表和业务表在同一个库,写记忆和更新执行记录可以放进同一个事务;按用户过滤就是普通 where 条件;备份、监控、连接池、迁移工具全部复用。**多一个有状态服务的运维成本,通常比向量检索的性能更早成为瓶颈**——这句话最能体现你上过线。
- 再诚实地说它的天花板:单表到千万级向量时 HNSW 索引构建吃内存、写入放大明显,ANN 与元数据过滤的融合不如专用库,水平扩展只能靠 Postgres 自己那一套。不肯说缺点的人会被认为在推销。
- 结论要能写死:百万级以内、需要和业务表一起过滤或同事务提交、团队人手紧,用 pgvector;上千万条、检索本身就是主要负载、有专人维护,上专用库。别在第一天就选专用库。
- 可以预期的追问:以后想换库,迁移成本大不大?答案会让很多人意外——换库不用重算 embedding,向量是模型产出的,跟存它的库无关,导出导入即可,成本主要在双写和灰度。真正要全量重算的是换 embedding 模型,那才是硬锁定。
How to reason about it · think before answering
- This is a judgment question, not a feature-recital. Opening with 'Milvus does sharding, Qdrant filters better' carries no signal — they want your decision criteria and whether you have priced the operational overhead.
- Offer three questions that make the choice derivable: what scale, does it need to commit in the same transaction as business tables, and how complex is the metadata filtering.
- pgvector wins on the last two: memories live in the same database as the business tables, so writing a memory and updating a run share one transaction; filtering by user is an ordinary WHERE clause; backups, monitoring, pooling and migrations are all reused. The line that shows operational experience is that one more stateful service usually becomes the bottleneck before vector search performance does.
- Be honest about the ceiling: past roughly ten million vectors in one table, HNSW index builds eat memory and write amplification shows; ANN plus metadata filtering is weaker than a purpose-built engine; horizontal scaling is whatever Postgres gives you. Refusing to name downsides reads as salesmanship.
- Commit to a rule: under a million vectors, needing joins or shared transactions, small team — pgvector. Tens of millions, retrieval as the primary workload, someone owning the service — dedicated store. Do not start with the dedicated store on day one.
- Expect the follow-up on migration cost. Switching stores does not require re-embedding — vectors belong to the model, not the store, so export and import; the cost is dual-write and rollout. Switching the embedding model is what forces a full recompute, and that is the real lock-in.
答题要点
- 三个判据:数据量级、要不要和业务表同事务提交、元数据过滤复不复杂
- pgvector 的优势是同库同事务、普通 SQL 过滤、运维零新增——少一个有状态服务往往比性能更值钱
- pgvector 的天花板:千万级向量时索引构建吃内存、写入放大、ANN 与过滤融合弱、扩展受限于 Postgres
- 专用向量库给的是分布式分片、更强的过滤与 ANN 融合、混合检索,代价是多一个要备份要监控的有状态服务
- 换向量库不用重算 embedding;换 embedding 模型才要全量重算,真正的锁定点是模型不是库
Key points
- Three criteria: scale, need for same-transaction commits with business tables, and filtering complexity
- pgvector gives one database, one transaction, ordinary SQL filters and zero new operations — often worth more than raw performance
- Its ceiling: memory-hungry index builds and write amplification at tens of millions, weaker ANN-plus-filter fusion, scaling limited to Postgres
- Dedicated stores buy sharding, better filtered ANN and hybrid search, at the price of another stateful service to back up and monitor
- Changing stores needs no re-embedding; changing the embedding model does — the lock-in is the model, not the database
D15 多 Agent 模式全景(Router/Supervisor、Planner-Executor、Critic、Swarm、Blackboard)与何时不该用;LangGraph 入门
常见的多 Agent 协作模式有哪些?分别适合什么形状的任务?What are the common multi-agent collaboration patterns, and what shape of task suits each?
国内高频海外高频基础#multi-agent#orchestration#architecture分析过程 · 先想清楚再作答
- 这题看似送分,其实在筛「背过名词」和「拆过系统」。只报五个名字最多拿及格分,面试官真正想听的是你用什么维度把它们区分开——有维度说明你能给没见过的架构归类,没维度说明你只是读过一篇综述。
- 给一个可复用的维度:模式的差别不在名字,在图的形状。盯四件事就够——有没有分叉(运行时三选一)、有没有扇出(同时交给多个人)、有没有汇合(多份产出合到一起)、有没有回边(可以打回重做)。
- 然后逐个落位:Router/Supervisor 只有分叉,一次只找一个专家,难点在判断该找谁;Planner-Executor 是扇出加汇合,适合一件事拆成几件、几件之间没有先后;Critic 是分叉加回边,适合对错有明确判据、且重做比发出去便宜的产出;Swarm 也是分叉加回边,但下一棒交给谁由当前这位自己决定;Blackboard 是扇出加汇合加回边,参与者互相不知道对方存在,只认公共状态。
- 主动指出 Critic 和 Swarm 的四个特征一模一样,区别落在「回边由谁决定」——Critic 是固定的评审节点在判,Swarm 是当前这位自己判。**主动承认自己的判据在哪里失效,比多背一个模式名更能加分**,因为它证明你真的用过这套维度而不是刚编出来。
- 每种模式还要配一句代价,这是区分度所在:Router 多一次路由调用的延迟;Planner-Executor 的并行会带来状态写冲突,字段必须配合并规则;Critic 的回路必须有次数上限,否则永远出不了稿;Swarm 事先不知道会走多少步,成本和延迟都难封顶;Blackboard 的终止条件最难写,容易谁都不接活或者反复触发。
- 可以预期的追问:生产上你最常用哪个?答 Router/Supervisor,理由是它的失败模式最好理解——路由判错了看一眼路由理由就知道,而且它是唯一一个能顺便省钱的模式,简单意图可以路由到便宜的小模型。
How to reason about it · think before answering
- This looks like a giveaway but it separates people who memorised names from people who have split a system. Listing five names is a bare pass; the interviewer wants the axis you use to tell them apart, because an axis means you can classify an architecture you have never seen.
- Offer a reusable axis: the difference is not the name, it is the shape of the graph. Four questions suffice — is there a branch (pick one at runtime), a fan-out (hand it to several at once), a join (merge several outputs), a back edge (send it back for rework).
- Then place each one: Router/Supervisor is branch only, one specialist per turn, the hard part is deciding who; Planner-Executor is fan-out plus join, for work that splits into independent pieces; Critic is branch plus back edge, for output with a clear pass/fail test where redoing is cheaper than shipping; Swarm is also branch plus back edge, but the next hop is chosen by whoever holds the baton; Blackboard is fan-out plus join plus back edge, participants unaware of each other, reacting only to shared state.
- Point out yourself that Critic and Swarm score identically on all four, and that the real difference is who decides the back edge — a fixed reviewer node versus the current agent. Volunteering where your own criterion breaks down scores better than reciting one more pattern name, because it proves you have used the axis rather than invented it on the spot.
- Attach a cost to each: Router adds one routing call of latency; Planner-Executor's parallelism creates write conflicts so fields need merge rules; Critic loops need a hard retry cap or nothing ever ships; Swarm has no upfront bound on steps so cost and latency are hard to cap; Blackboard has the hardest termination condition and tends to either stall or re-trigger.
- Expect: which do you use most in production? Say Router/Supervisor, because its failure mode is the easiest to read — check the recorded routing reason — and because it is the one pattern that can save money, by routing simple intents to a cheaper model.
答题要点
- 先给维度再给名字:分叉、扇出、汇合、回边四个特征就能把五种模式分开
- Router/Supervisor 只有分叉,一次只找一个专家,难点是判断该找谁
- Planner-Executor 是扇出加汇合,适合拆成几件互不依赖的小任务再合成一份交付
- Critic 是分叉加回边,适合对错有明确判据、重做比发出去便宜的产出,必须配打回次数上限
- Swarm 与 Critic 的四个特征相同,区别在回边由谁决定;Blackboard 靠公共状态解耦,终止条件最难写
- 每种模式配一句代价:多一次调用的延迟、并行的写冲突、回路的死循环、步数不封顶、终止条件难定
Key points
- Give the axis before the names: branch, fan-out, join and back edge separate all five patterns
- Router/Supervisor is branch only — one specialist per turn, the hard part is choosing who
- Planner-Executor is fan-out plus join — split into independent subtasks, then merge into one deliverable
- Critic is branch plus back edge — for output with a clear pass/fail test, and it needs a hard retry cap
- Swarm scores the same as Critic; the difference is who decides the back edge. Blackboard decouples via shared state and has the hardest termination condition
- Pair each with a cost: extra call latency, parallel write conflicts, infinite review loops, unbounded step count, fuzzy termination
从单 Agent 升级到多 Agent,通常是被什么信号触发的?升级之后系统会多付出什么?What signals typically trigger the move from a single agent to a multi-agent system, and what does the upgrade cost you?
国内高频海外高频进阶#multi-agent#cost#architecture分析过程 · 先想清楚再作答
- 这题考的是「你是被业务逼着拆的,还是照着博客拆的」。答「业务变复杂了」等于没答,面试官要的是**可观测的信号**:什么现象出现时你才动手。
- 给五个按出现顺序排的信号:一是提示词开始互相打架(加一条规则,另一个指标就掉);二是工具列表长到自己都要查文档;三是某一步的失败需要单独处理,不该整轮重来;四是想给某一步单独换模型;五是评估颗粒度不够,只能整体打分好或不好。
- 第四个信号要展开讲,它是唯一一个反常识的:多 Agent 通常更贵,但按步换模型是它唯一能省钱的场景——分诊这种短判断走便宜的小模型,拟方案走大模型。单 Agent 做不到按步换模型。这一条在面试里是明显的亮点。
- 然后主动给代价,不给代价的回答会被当成布道:延迟按步数乘倍数(原来两秒变六秒,而用户耐心大约三秒);成本按调用次数线性涨,因为每一步都要把当前状态重新塞进上下文,典型是三倍;调试难度按状态维度涨,出错要同时回答路由对不对、每个子 Agent 拿到的状态对不对、合并有没有互相覆盖。
- 再补一句反向判断,证明你不是无脑拆:工具太多的第一反应应该是合并工具、收敛描述,拆 Agent 是第二反应;质量差的第一反应应该是把单 Agent 版本调到最好,那个版本还会成为多 Agent 的对照基线。
- 可以预期的追问:拆完怎么证明比原来好?答:留住单 Agent 版本当基线,用同一批标准样本集跑 A/B,比准确率也比每次对话的成本与延迟。说不出对照基线的人,通常也说不清自己为什么拆。
How to reason about it · think before answering
- This question tests whether business pain forced the split or a blog post did. Answering the business got complex is a non-answer; the interviewer wants observable signals — what symptom made you act.
- Give five, in the order they usually appear: prompts start fighting each other (add one rule, another metric drops); the tool list grows until you need the docs yourself; one step's failure needs isolated handling instead of redoing the whole turn; you want a different model for one specific step; and evaluation granularity is too coarse to say more than good or bad.
- Expand on the fourth, the counter-intuitive one: multi-agent is usually more expensive, but per-step model selection is the one case where it saves money — a short triage decision on a cheap small model, a drafting step on a larger one. A single agent cannot swap models per step. This lands well in interviews.
- Then volunteer the costs, or the answer reads as evangelism: latency multiplies by step count (two seconds becomes six, while user patience is about three); cost grows linearly with calls because every step re-sends the current state as context, typically three times; and debugging cost grows with state dimensions, since a failure now requires checking routing, each sub-agent's input state, and whether merges overwrote each other.
- Add the reverse check to show you are not splitting reflexively: too many tools should first prompt consolidation and tighter descriptions, with splitting as the second response; poor quality should first prompt tuning the single-agent version to its best, which then becomes the baseline the multi-agent version is measured against.
- Expect: how do you prove the split helped? Keep the single-agent version as a baseline and A/B both against the same golden set, comparing accuracy alongside per-conversation cost and latency. People who cannot name a baseline usually cannot explain why they split either.
答题要点
- 五个可观测信号:提示词互相打架、工具多到要查文档、某一步需要独立重试、想按步换模型、评估颗粒度不够
- 按步换模型是多 Agent 唯一能省钱的场景:短判断走小模型、拟方案走大模型,单 Agent 做不到
- 代价一:延迟按步数乘倍数,两秒变六秒,而用户对客服机器人的耐心大约三秒
- 代价二:成本线性涨,每一步都要把状态重新塞进上下文,典型是原来的三倍
- 代价三:调试难度按状态维度涨,所以多 Agent 和链路追踪必须一起上
- 反向判断:工具多先合并再拆分,质量差先把单 Agent 调到最好——那个版本还是多 Agent 的对照基线
Key points
- Five observable signals: prompts fighting each other, a tool list you must look up, one step needing isolated retries, wanting a different model per step, and evaluation too coarse to act on
- Per-step model selection is the only case where multi-agent saves money: small model for triage, larger model for drafting — impossible in a single agent
- Cost one: latency multiplies with step count, two seconds becomes six, while patience for a support bot is about three
- Cost two: spend grows linearly with calls since every step re-sends state as context, typically three times the original
- Cost three: debugging cost grows with state dimensions, so multi-agent and tracing have to ship together
- Reverse check: consolidate tools before splitting, and tune the single agent to its best first — that version becomes your baseline
什么情况下不应该引入多 Agent 系统?请给出可操作的判据,而不是「视情况而定」。When should you not introduce a multi-agent system? Give operational criteria, not it depends.
国内高频海外高频深入#multi-agent#architecture#trade-offs分析过程 · 先想清楚再作答
- 这是本组最有区分度的题,因为它反着问。绝大多数候选人会顺着「多 Agent 很强大」讲下去,而面试官问这题正是想找那个会说不的人——**在真实团队里,拦住一次不必要的架构升级,价值高于实现三个模式**。
- 先给结论式的默认值:默认答案是不拆。然后给三条判据,命中任意一条才拆——一是单个 Agent 的系统提示词里出现了互斥的行为要求(既要严格核对退款规则又要热情挽留,这两条不是难写,是不可能同时最优);二是工具数量超过模型能稳定选对的规模(经验线大约八个,超线的第一反应是合并工具而不是拆 Agent);三是某一步需要独立的失败与重试语义。三条都不命中,单 Agent 加几个工具就够。
- 接着点名最常见的错拆:把提示词问题当成架构问题。「回答质量不好,所以拆成三个 Agent」——质量差有九成来自提示词含糊、工具描述互相干扰、上下文塞了无关历史,这三样拆完一样存在,只是分散到三个地方更难查。**拆 Agent 解决的是职责冲突,不是能力不足。**
- 再补两类明确不该拆的场景:一是低延迟要求的场景,多一跳就多一次模型往返,对语音或实时补全这类交互直接不可用;二是只读的简单查询链路,三五个工具的客服助手拆了只是把一次调用变成三次,准确率不会涨、账单会涨。
- 然后给一条可执行的验证路径,这是加分项:任何拆分都先留住单 Agent 版本当对照基线,用同一批标准样本集跑 A/B,同时比准确率、每次对话成本和延迟。**拿不出对照基线的架构升级,等于没有证据的重构。**
- 可以预期的追问:那如果老板就是要求上多 Agent 呢?答:那就把它当成一个可回退的实验来做——先按判据拆最有把握的那一刀(通常是互斥规则那一条),保留基线,两周后拿数据说话。这个回答同时展示了技术判断和沟通方式,比硬顶或硬上都好。
How to reason about it · think before answering
- This is the highest-signal question in the set because it is asked in reverse. Most candidates keep selling how powerful multi-agent is, while the interviewer is looking for someone who will say no — on a real team, blocking one unnecessary architecture upgrade is worth more than implementing three patterns.
- Lead with the default: do not split. Then give three criteria, any one of which justifies splitting — the system prompt contains mutually exclusive behavioural requirements (strictly enforce refund rules while also warmly retaining the customer; these are not hard to write, they are impossible to optimise together); the tool count exceeds what the model picks reliably (roughly eight as a rule of thumb, and the first response to crossing it is consolidating tools, not splitting agents); or one step needs its own failure and retry semantics. None of the three, and a single agent with a few tools is enough.
- Then name the most common bad split: treating a prompt problem as an architecture problem. Quality is poor, so we split into three agents — but nine times out of ten poor quality comes from vague prompts, tool descriptions that interfere with each other, or irrelevant history in the context. All three survive the split and are now harder to find. Splitting fixes conflicting responsibilities, not weak capability.
- Add two scenarios that clearly should not split: latency-sensitive interactions, where each extra hop is another model round trip and voice or realtime completion becomes unusable; and read-only lookup flows, where a support assistant with three or four tools gains no accuracy from splitting and simply triples the bill.
- Then offer an executable verification path, which earns points: keep the single-agent version as a baseline for any split and A/B both against the same golden set, comparing accuracy, per-conversation cost and latency together. An architecture upgrade with no baseline is a refactor with no evidence.
- Expect: what if your manager insists on multi-agent? Frame it as a reversible experiment — make the one cut you are most confident in (usually the conflicting-rules criterion), keep the baseline, and bring data in two weeks. That answer shows technical judgement and a way to disagree without stonewalling.
答题要点
- 默认答案是不拆;三条判据命中任意一条才拆:提示词有互斥要求、工具超过约八个的告警线、某一步需要独立的失败与重试语义
- 工具太多的第一反应是合并工具与收敛描述,拆 Agent 是第二反应
- 最常见的错拆是把提示词问题当架构问题——质量差多半来自提示词含糊、工具描述干扰、上下文塞了无关历史,拆完这三样照旧存在
- 明确不该拆:低延迟交互(每多一跳就多一次模型往返)、只读的简单查询链路(准确率不涨、账单涨)
- 任何拆分都要留单 Agent 版本当对照基线,用同一批标准样本集比准确率、成本和延迟
- 代价要说出口:延迟按步数乘倍数、成本约三倍、调试要同时排查路由与状态合并
Key points
- Default to not splitting; split only if one of three criteria holds: mutually exclusive prompt requirements, tool count past the roughly-eight warning line, or a step needing its own failure and retry semantics
- Too many tools should first trigger tool consolidation and tighter descriptions; splitting agents is the second response
- The most common bad split is treating a prompt problem as an architecture problem — vague prompts, interfering tool descriptions and irrelevant history all survive the split
- Clear do-not-split cases: latency-sensitive interactions where every hop adds a model round trip, and read-only lookup flows where accuracy does not move but the bill does
- Always keep the single-agent version as a baseline and compare accuracy, cost and latency on the same golden set
- Say the costs out loud: latency multiplies with steps, spend roughly triples, and debugging now spans routing plus state merging
D17 Planner–Executor–Critic + 共享工作区:workspace state、toolBudget、并行 fan-out、review 回路
Planner-Executor-Critic 这种结构解决了什么问题?它和 Supervisor 路由的区别在哪?What problem does the Planner-Executor-Critic structure solve, and how is it different from Supervisor routing?
国内高频海外高频基础#multi-agent#orchestration#architecture分析过程 · 先想清楚再作答
- 题眼在后半句。只答「拆解、执行、评审」是在背名词,面试官想确认的是你能不能用图的形状把两种模式分开,而不是靠记忆背模式表。
- 先用形状拆:Supervisor 是一个岔路口,运行时在几条路里选一条走,一次只交给一个人,图上只有分叉;Planner-Executor-Critic 是先扇出、再汇合、中间还有一条回边。分叉解决「交给谁」,扇出解决「一件事要拆成几件」,回边解决「谁来验收」。
- 再给适用判据:一次只需要一个专家、难点在判断该找谁,用 Supervisor;一件事必须拆成几件且几件之间没有先后依赖,才值得扇出;产出的对错有明确判据、且错了重做比错了发出去便宜,才值得加 Critic。三条判据都不命中就别上这套结构。
- 结论要落到代价,这是区分「读过文档」和「上线过」的地方:拆出三件事意味着模型调用次数从一次变成七次起步(拆解一次、三次执行、三次评审),有一轮打回就是九次;延迟被最慢的那件事决定而不是平均值,而且并行只省延迟不省钱。
- 可以预期的追问:Critic 一定要单独一个节点吗?答案是不一定——如果验收判据是可以用代码判的(比如 JSON schema 校验、必填字段检查),就别花一次模型调用,代码判更快更准也更便宜。只有判据本身需要理解语义时,Critic 才值得是一次模型调用。
How to reason about it · think before answering
- The hinge is the second half. Reciting plan, execute, review is naming shapes from memory; the interviewer wants to see you separate the two patterns by graph shape.
- Separate by shape: a Supervisor is a fork — at runtime it picks one of several paths and hands the work to exactly one agent, so the graph only branches. Planner-Executor-Critic fans out, joins, and adds a back edge. Branching answers who takes this, fan-out answers this must be split into several pieces, the back edge answers who signs it off.
- Then give the criteria: use a Supervisor when only one specialist is needed per request and the hard part is picking them; only fan out when a request genuinely splits into independent pieces with no ordering between them; only add a Critic when correctness has an explicit rubric and redoing is cheaper than shipping something wrong. If none of these hold, do not build this.
- Land on cost, which is where shipped-it separates from read-the-docs: three subtasks turn one model call into seven (one plan, three executions, three reviews) and nine after a single rejection round; latency is set by the slowest branch rather than the average, and parallelism buys latency, never money.
- Expect: does the Critic have to be its own node? Not necessarily — if the rubric is checkable in code (schema validation, required fields), check it in code: faster, cheaper, and more reliable. A Critic earns a model call only when the rubric requires understanding meaning.
答题要点
- Supervisor 是分叉(一次派一个人),Planner-Executor-Critic 是扇出加汇合加回边(拆成几件并行做,做完有人验收)
- 三条适用判据:一次只需一个专家用路由;能拆成互不依赖的几件才扇出;对错有明确判据且重做便宜才加评审
- 拆解的代价是模型调用从一次涨到七到九次、延迟由最慢的分支决定,而并行只省延迟不省成本
- 评审判据能用代码判就别用模型判,Critic 只在需要理解语义时才值一次模型调用
Key points
- A Supervisor branches (one agent per request); Planner-Executor-Critic fans out, joins, and loops back (split, run in parallel, then sign off)
- Three criteria: route when one specialist suffices; fan out only for genuinely independent pieces; add review only when the rubric is explicit and redoing beats shipping wrong
- The cost is seven to nine model calls instead of one, with latency set by the slowest branch — parallelism buys latency, not money
- If the rubric is checkable in code, check it in code; a Critic deserves a model call only when semantics must be understood
D19 跨服务 Agent 集成:用户级 JWT 铸造、JWKS 验签、inject/memory/usage 三类接口、幂等 externalId
设计一组给外部服务调用的 Agent 平台接口,你会怎么划分职责边界?You are designing the API surface an Agent platform exposes to other services. How do you draw the responsibility boundaries?
国内高频海外高频深入#api-design#security#architecture分析过程 · 先想清楚再作答
- 这是开放题,考的是你有没有一条能反复用的划分依据。上来就罗列接口清单的人会被追问到没词;先给依据再给清单的人,追问反而是加分机会。
- 给一条判据:**按「谁拥有这份数据」划,不按「谁调用它」划。** 会话、执行记录、记忆、成本台账都属于平台,所以平台开的三个口子恰好是「写一条进来(inject)」「读写记忆(memory)」「查账(usage)」;编排逻辑属于对方,平台就不该提供「帮我跑一遍这个图」的接口——那是把对方的职责搬到自己身上,将来两边都改不动。
- 第二条判据是**贯穿全课的安全不变量:身份只能来自令牌,不能来自请求体**。所有接口都不接受 userId 参数,服务端一律从令牌的 sub 取。这条一旦破例,权限模型就整个塌了:查成本的接口如果接受 userId 查询参数,任何一张有效令牌都能遍历所有人的消费金额。同一条原则在 D12 的记忆检索工具上也出现过——不给模型身份参数,服务端自己填。
- 第三条是**返回粒度要按最小必要给**。usage 只返回汇总不返回明细,因为明细里带着执行 id 和模型选型,等于把平台的内部策略一并交出去;memory 要支持按 query 检索并限制条数,不提供「把这个人的所有记忆倒出来」的接口——一旦提供,它迟早会被某个图省事的调用方用成默认写法。
- 第四条是**每个写接口都要能被安全重放**:带 externalId、唯一约束兜底、重复返回 200。跨服务调用一定会重复,这不是要不要做的问题。
- 可以预期的追问:那限流按什么维度做?答「每用户,不是每调用方」——按调用方限流的话,一个用户的异常重试会把所有人的额度吃光;另外写接口要防回环,注入的消息要打来源标记,否则两个服务能把彼此拉进无限循环,账单是唯一会提醒你的东西。
How to reason about it · think before answering
- This is an open design question testing whether you have a reusable criterion. Candidates who start listing endpoints run out of material under follow-ups; candidates who give the criterion first turn follow-ups into extra points.
- Offer the criterion: draw boundaries by who owns the data, not by who calls it. Sessions, run records, memories and the cost ledger belong to the platform, so the platform exposes exactly three things — write one event in (inject), read and write memory, and read usage. Orchestration belongs to the caller, so the platform should not offer run this graph for me; that pulls someone else's responsibility inside your walls and freezes both sides.
- Second criterion, the security invariant that runs through the whole course: identity comes from the token, never from the request body. No endpoint accepts a userId; the server always reads sub. Break this once and the authorization model collapses — a usage endpoint that accepts a userId query parameter lets any valid token enumerate everyone's spend. The same principle appeared on the memory search tool: the model gets no identity parameter, the server fills it in.
- Third, return the minimum necessary. Usage returns aggregates, not line items, because line items carry run ids and model choices — that hands over your internal strategy. Memory supports a query with a result limit rather than dump everything this user ever said; once that exists, some caller in a hurry will make it the default.
- Fourth, every write endpoint must be safely replayable: an externalId, a uniqueness constraint underneath, and 200 on a repeat. Cross-service calls will be duplicated; this is not optional.
- Expect: what dimension do you rate-limit on? Per user, not per caller — limiting per caller lets one user's runaway retries consume everyone's budget. Also guard against loops: tag injected messages with their source, or two services can pull each other into an infinite cycle and the bill is the only thing that tells you.
答题要点
- 按「谁拥有这份数据」划边界,不按「谁调用」划:会话、记忆、台账属于平台,编排属于对方
- 三个口子对应三种所有权:inject 写入、memory 读写、usage 查账;不提供「帮我跑图」这种越界接口
- 所有接口都不接受 userId 参数,身份一律从令牌 sub 取——这条破例一次权限模型就塌了
- 返回粒度按最小必要:usage 只给汇总不给明细,memory 按 query 限条数而不是全量倒出
- 每个写接口都带 externalId 并由唯一约束兜底,重复返回 200
- 限流按每用户而不是每调用方;注入的消息要打来源标记防止两个服务互相回环
Key points
- Draw boundaries by data ownership, not by caller: sessions, memory and the ledger belong to the platform, orchestration belongs to the caller
- Three endpoints for three kinds of ownership — inject, memory, usage — and no run this graph for me endpoint that crosses the line
- No endpoint accepts a userId; identity always comes from the token's sub, and one exception collapses the model
- Return the minimum necessary: usage gives aggregates only, memory takes a query with a limit instead of dumping everything
- Every write endpoint carries an externalId backed by a uniqueness constraint and answers 200 on repeats
- Rate-limit per user rather than per caller, and tag injected messages with their source so two services cannot loop forever
D21 评估与可观测:golden set、LLM-as-judge、tracing、失败率/成本面板;Pi vs LangGraph 总结;W3 复盘
什么时候该用 LangGraph 这类编排框架,什么时候不该用?When should you reach for an orchestration framework like LangGraph, and when should you not?
国内高频海外高频进阶#architecture#framework-selection#langgraph分析过程 · 先想清楚再作答
- 这题最怕答成特性对比表。面试官想听的是判据,而且是能反过来说「不该用」的判据——只会说该用的人,通常是没被框架坑过的人。
- 先给三条该拆的判据(一条都不命中就别拆,也别引框架):**提示词里出现了互斥的行为要求**(既要严谨又要俏皮,调好一个另一个就坏);**工具多到选错率明显上升**;**某一步需要独立的失败与重试语义**(比如查库存失败该重试,拟退款方案失败该转人工,两者不能共用一套策略)。
- 然后给框架本身的判据,核心是一句:**要让多个角色并行写同一份状态,就必须显式;不需要并行,显式就是纯负担。** LangGraph 的价值是把合并规则声明在字段上——三个执行者并行写同一个工作区,谁的写入怎么合并,这件事必须有地方声明。反过来,一两个工具、循环最多两轮的场景,一个 while 加一个 switch 就够了,引入框架是净亏。
- 对比 Pi 这类高层 SDK 时,用维度而不是特性:上手成本(Pi 默认值多所以快,代价是模型和人设都是它替你挑的)、状态管理的显式程度(Pi 的历史在会话内部你感知不到,所以想改「同一个工作区怎么合并」时根本没有位置可改)、调试形态(Pi 给事件流是一条时间线,LangGraph 给逐节点增量和检查点是一棵可回放可分叉的树——**线性问题看时间线更快,多角色问题必须看树**)。
- 跨语言这条值得单独提,因为它常被忽略:**Java 和 Swift 都没有 LangGraph**,跨语言团队要么统一到 TS/Python,要么自己手写同一套结构。选框架的时候把这条算进去,比上线后再发现便宜。
- 可以预期的追问:那你怎么选?给一句可执行的:**你更怕看不见的默认值,还是更怕写不完的样板?** 怕前者选显式框架,怕后者选高层 SDK。这句话比任何特性表都实用。
How to reason about it · think before answering
- The trap is answering with a feature matrix. The interviewer wants criteria, specifically criteria that can also say do not use it — people who can only argue for adoption usually have not been burned by a framework.
- Start with three criteria for splitting at all (if none holds, do not split and do not add a framework): the prompt contains mutually exclusive behavioural demands (rigorous and playful at once, where tuning one breaks the other); tools have grown numerous enough that selection error is visibly rising; or some step needs its own failure and retry semantics (an inventory lookup should retry, a refund draft should escalate to a human, and they cannot share one policy).
- Then the framework criterion, which is one sentence: if multiple roles write the same state concurrently, it must be explicit; if you do not need concurrency, explicitness is pure overhead. LangGraph's value is declaring merge rules on the field — with three executors writing one workspace, how those writes combine has to be declared somewhere. Conversely, with two tools and a loop that runs at most twice, a while and a switch suffice and a framework is a net loss.
- When comparing against a higher-level SDK like Pi, use dimensions rather than features: onboarding cost (Pi's defaults make it fast, at the price of it choosing your model and persona); explicitness of state (Pi keeps history inside the session, so when you want to change how one workspace merges there is no place to change it); and debugging shape (Pi gives an event stream, one timeline; LangGraph gives per-node deltas and checkpoints, a replayable and forkable tree — linear problems read faster as a timeline, multi-role problems require the tree).
- Cross-language deserves its own mention because it is routinely forgotten: neither Java nor Swift has LangGraph, so a polyglot team either standardises on TS/Python or hand-writes the same structure. Pricing that in during selection is cheaper than discovering it after launch.
- Expect: so how do you choose? Give something actionable: do you fear invisible defaults more, or endless boilerplate more? Fear the former and pick the explicit framework; fear the latter and pick the high-level SDK. That sentence is more useful than any feature table.
答题要点
- 先答该不该拆:提示词有互斥的行为要求、工具多到选错率上升、某步需要独立的失败与重试语义——一条不命中就别拆也别引框架
- 框架判据一句话:多个角色并行写同一份状态就必须显式;不需要并行,显式就是纯负担
- LangGraph 的价值是把合并规则声明在字段上;Pi 的历史在会话内部,想改合并方式根本没有位置可改
- 调试形态不同:事件流是一条时间线,逐节点增量加检查点是一棵可回放可分叉的树;线性问题看时间线,多角色问题必须看树
- Java 和 Swift 都没有 LangGraph,跨语言团队要么统一栈要么手写同一套结构,选型时就要算进去
- 一句可执行的选型判据:更怕看不见的默认值就选显式框架,更怕写不完的样板就选高层 SDK
Key points
- First decide whether to split at all: mutually exclusive prompt demands, rising tool-selection error, or a step needing its own retry semantics — none holding means no split and no framework
- The framework criterion in one line: concurrent writes to shared state require explicitness; without concurrency, explicitness is pure overhead
- LangGraph's value is declaring merge rules on the field; Pi keeps history inside the session, leaving nowhere to change merge behaviour
- Different debugging shapes: an event stream is a timeline, per-node deltas plus checkpoints are a replayable forkable tree — timelines for linear problems, trees for multi-role ones
- Neither Java nor Swift has LangGraph, so polyglot teams standardise or hand-write the structure — price that in at selection time
- An actionable heuristic: fear invisible defaults, choose the explicit framework; fear endless boilerplate, choose the high-level SDK
D23 MCP 与 Skills:协议、server/client、与 function calling 区别;Claude Agent SDK 一览
什么场景下应该考虑用 MCP,而不是直接写 function calling?不该用的时候硬上会付出什么代价?When should you reach for MCP instead of plain function calling, and what does it cost when you shouldn't?
国内高频海外高频进阶#mcp#architecture#trade-offs分析过程 · 先想清楚再作答
- 题眼在后半句。只会说「MCP 更标准更解耦」的人,等于说「微服务更解耦」——听起来对,但没有判据,面试官会立刻追问「那你们所有工具都做成 MCP server 了吗」。
- 先给判据,而且要是可执行的三条:能力要被多个宿主复用、能力由另一个团队或第三方维护、需要不改宿主代码就能增删能力。命中任意一条才考虑,**一条都不命中就直接写本地函数**——把默认答案摆成「不上」,这条比三条判据本身更能体现工程判断。
- 每条判据配一句为什么:多宿主复用把 N 乘 M 变成 N 加 M;别人维护时进程边界就是责任边界,他们改他们的、你不用发版;热插拔让加一个内部工具从一次发布降级成一次配置变更。
- 然后老实说代价,这是区分「用过」和「读过」的地方:多一个进程要保活、多一次握手要处理超时与重连、排障链路从一段变三段——工具没被调用,现在可能是模型没选、可能是 schema 翻译时丢了字段、也可能是 server 压根没起来。stdio 的子进程还要你自己回收,否则留孤儿进程。
- 还有一条容易被忽略但很加分:MCP 不改变你的成本结构。工具描述照样每轮都进上下文,工具多了照样会让模型选错——D5 那条「工具超过一定数量就该合并描述」在接了 MCP 之后一字不变,甚至更需要,因为现在别人可以往你的工具列表里塞东西。
- 可以预期的追问:那内部工具一律不上 MCP 吗?不是。有一类值得例外——你希望它能被 IDE 里的助手和运维机器人一起用,那第一条判据就命中了,即使它是你自己维护的。
How to reason about it · think before answering
- The hinge is the second half. Answering only 'MCP is more standard and decoupled' is like saying 'microservices are more decoupled' — true-sounding but with no criterion, and the interviewer will immediately ask whether you turned every tool into an MCP server.
- Give three actionable criteria: the capability must be reused by more than one host, owned by another team or a third party, or added and removed without changing host code. Any one of them justifies MCP; none of them means write a local function. Making 'no' the default answer shows more engineering judgment than the criteria themselves.
- Attach a reason to each: multi-host reuse turns N times M into N plus M; external ownership makes the process boundary the responsibility boundary, so their change is not your release; hot-swapping demotes adding an internal tool from a deployment to a config change.
- Then state the costs honestly, which is where shipped experience shows: another process to keep alive, another handshake with its own timeouts and reconnects, and a debugging path that went from one hop to three — a tool that never got called might mean the model did not pick it, the schema lost fields in translation, or the server never started. On stdio you also own reaping the child process.
- One more point that is easy to miss and scores well: MCP does not change your cost structure. Tool descriptions still enter the context every turn, and more tools still degrade tool selection. The rule that you should consolidate tools past a certain count survives MCP unchanged — arguably it matters more, because now other people can add entries to your tool list.
- Expect the follow-up: so internal tools never go through MCP? Not quite. If you want the same capability available to an IDE assistant and an ops bot as well, the first criterion is met even though you own the code.
答题要点
- 三条判据,命中任意一条才考虑 MCP:多宿主复用、由他人维护、需要不改代码增删能力
- 默认答案是不上:三条都不命中就直接写本地函数,这是更好的工程决策
- 代价是多一个进程要保活、多一次握手要处理超时、排障从一段链路变成三段
- MCP 不改变成本结构:工具描述照样每轮进上下文,工具过多照样会让模型选错,该合并还是要合并
- 第三方能力接进来之后,工具列表不再完全由你掌控,这本身就是需要设计的一件事
Key points
- Three criteria, any one justifies MCP: reuse across hosts, ownership by another team, or add/remove without touching host code
- The default is no — if none of the three apply, a local function is the better engineering decision
- Costs: another process to supervise, another handshake with timeouts, and a debug path that grows from one hop to three
- MCP does not change your cost structure: descriptions still enter context every turn and too many tools still hurt selection
- Once third-party capabilities are attached, your tool list is no longer fully under your control, which is itself a design problem
Codex 与 OpenAI Agents SDK 高效使用
D4 OpenAI Agents SDK:agents、handoffs、guardrails、sessions、tracing
什么时候该把一个 Agent 拆成多个、用 handoff 交接?什么时候「一个大 Agent 加很多工具」反而更好?When should you split one agent into several connected by handoffs, and when is a single agent with many tools the better design?
国内高频海外高频进阶#agents-sdk#handoffs#architecture分析过程 · 先想清楚再作答
- 这题考的是拆分判据,不是会不会用 API。答「工具多了就拆」是最常见的错误,工具数量不是判据。
- 先说清 handoff 与工具的区别:调工具是替你去问一句再回来,handoff 是把对话整个交给另一个 Agent,之后由它负责;实现上 handoff 也是一个名为 transfer_to_xxx 的工具,但语义是转移控制权。
- 判据是「指令会不会互相打架」:两组任务需要的背景知识、约束、语气彼此独立且冲突时,塞进一份 instructions 会让模型反复切换上下文、提示越长越贵、出错率上升,这时拆;工具虽多但共享同一套背景的,不拆。
- 补拆分的代价:多一次模型调用(分诊那一跳)、路由可能错、输入护栏只在第一个 Agent 上跑、跨 Agent 的历史要靠 inputFilter 裁剪。
- 可预期的追问:分诊错了怎么办?用 RECOMMENDED_PROMPT_PREFIX 提高交接准确率,用 lastAgent 做回归断言,用 tracing 看交接发生在哪一轮,必要时让专家 Agent 也能交接回分诊台。
How to reason about it · think before answering
- This tests your splitting criterion, not API fluency; 'split when there are many tools' is the common wrong answer.
- First separate handoffs from tools: a tool call fetches an answer and returns; a handoff transfers the whole conversation so the receiving agent owns it, even though it is implemented as a transfer_to_xxx tool.
- The criterion is whether instructions conflict: when two task groups need independent, clashing background, constraints and tone, one instruction block forces constant context switching, longer prompts and more errors, so split; many tools sharing one background do not justify a split.
- Name the costs: an extra model call for triage, possible misrouting, input guardrails only on the first agent, and history trimming across agents via inputFilter.
- Expect the follow-up: what if triage misroutes? Use RECOMMENDED_PROMPT_PREFIX, assert on lastAgent in regression tests, inspect the handoff turn in tracing, and allow experts to hand back.
答题要点
- handoff 转移的是对话控制权,工具调用只是取一次结果
- 拆分判据是指令是否互相打架,不是工具数量
- 拆的代价:多一跳、可能路由错、输入护栏只在第一个 Agent 生效
- 用前缀提示、lastAgent 断言与 tracing 控制路由质量
Key points
- A handoff transfers conversational control; a tool call only fetches a result
- Split on conflicting instructions, not on tool count
- Costs: an extra hop, possible misrouting, input guardrails only on the first agent
- Control routing quality with the recommended prefix, lastAgent assertions and tracing
7 天 MCP:把工具接进任何 Agent
D1 为什么需要一个协议:host / client / server 三角、JSON-RPC 消息与三种原语
MCP 和模型自带的函数调用到底差在哪?什么情况下你不该用 MCP?How is MCP actually different from a model's built-in function calling, and when should you not use MCP?
国内高频海外高频基础#mcp-basics#architecture分析过程 · 先想清楚再作答
- 这题在筛「有没有真正接过工具」。把 MCP 说成「函数调用的升级版」就露馅了,因为两者根本不在同一层,答对的人第一句就会先把层次拆开。
- 拆法:问自己「这一步是模型 API 的事,还是工具从哪来的事」。函数调用是模型 API 的能力——你把工具定义放进请求,模型回一个要调谁;MCP 管的是那份定义和执行体住在哪个进程里、用什么语言交换。
- 接着点出两者是叠加而非替代:MCP 客户端拿到 tools/list 之后,还要把它翻译成模型 API 的工具参数,最终仍然走函数调用那条路。
- 结论:MCP 解决的是 M 个应用乘 N 个工具的重复接线,把乘法变成加法;它换来的代价是多一层进程、一层序列化、一层要排查的地方。
- 不该用的三种情况:工具只有自己这一个程序用;调用极频繁且对延迟敏感(远程一次往返几十到几百毫秒,一轮连调五次用户就有感);这件事根本不需要模型决定,产品逻辑本来就是确定的。
- 可预期的追问:那本机 stdio 的开销很小,是不是就可以随便用?答案是开销不只在传输,还在多一个要部署、要监控、要授权的进程上。
How to reason about it · think before answering
- The screen is whether you have actually wired tools yourself. Calling MCP an upgraded function call fails, because the two sit at different layers.
- Separate the layers first: function calling is a model API feature — you pass tool definitions in the request and the model replies with which one to invoke. MCP governs where that definition and its executor live and how they are exchanged.
- They compose rather than compete: an MCP client still translates tools/list output into the model API's tool parameters, so the final hop is ordinary function calling.
- Conclusion: MCP turns an M-applications-by-N-tools wiring problem into M plus N, at the cost of an extra process, an extra serialization boundary, and an extra place to debug.
- Skip MCP when the tool has exactly one consumer, when calls are hot and latency-sensitive (a remote round trip is tens to hundreds of milliseconds, five per turn is noticeable), or when the decision does not need a model at all.
- Likely follow-up: local stdio is cheap, so why not use it everywhere? Because the cost is not only transport — it is one more process to deploy, monitor, and authorize.
答题要点
- 函数调用是模型 API 的能力,MCP 是工具定义与执行体的分发协议,两者叠加而不是替代
- MCP 的价值是把 M 乘 N 的适配器数量变成 M 加 N,代价是多一层进程与序列化
- 单一消费者、延迟敏感的热路径、以及本来就确定的产品流程,这三种情况不该用 MCP
- 判据是「这个能力要不要给第二个程序用」,只要答案是要,协议的成本就摊得开
Key points
- Function calling is a model API capability; MCP is a distribution protocol for tool definitions and executors — they stack, not compete
- MCP converts M-by-N adapters into M plus N, paying with an extra process and serialization hop
- Skip it for single-consumer tools, latency-sensitive hot paths, and flows that are deterministic by design
- The test is whether a second program will ever need this capability; if yes, the protocol cost amortizes
MCP 规范为什么规定一个客户端只连一个服务端?多路复用不是更省资源吗?Why does the MCP spec require one client per server instead of multiplexing many servers over one connection?
国内高频海外高频进阶#architecture#security分析过程 · 先想清楚再作答
- 这题看着在问性能,其实在问安全边界。只从连接数和资源占用切入的回答会被判为没读过设计原则那一节。
- 拆法:先问「共享一条通道之后,谁能看见谁」。规范写死了两条原则——服务端不应该读到整段对话,也不应该看得见别的服务端;一对一是实现这两条最直接的手段。
- 举一个具体后果:接一个第三方天气服务端时,一对一隔离让它只能看到你传的城市名;共享通道则可能让它读到你和内部数据库服务端之间的往来,那就是一次数据泄露。
- 结论:完整对话历史留在宿主,服务端只拿到这次真正需要的参数;宿主是唯一的安全边界执行者,也是唯一做跨服务端编排的地方。
- 代价要主动说:接 N 个服务端就有 N 条连接、N 套生命周期要管,客户端实现的复杂度大头正是在这里,而不是在发报文上。
- 可预期的追问:那多个服务端的工具重名怎么办?答案是聚合与消歧是宿主侧的职责,规范建议加服务端标识前缀,并且明确说不要依赖服务端自报的名字,因为它不保证唯一也未经验证。
How to reason about it · think before answering
- It reads like a performance question but is really about security boundaries. Answering only in terms of connection count signals you never read the design principles.
- Ask who can see whom once a channel is shared. The spec fixes two principles: servers should not read the whole conversation, and should not see into other servers. One-to-one is the most direct way to enforce both.
- Concrete consequence: with isolation, a third-party weather server sees only the city you passed. On a shared channel it could observe traffic between you and an internal database server — a data leak.
- Conclusion: full history stays with the host, each server receives only the arguments this call needs, and the host is the single place where boundaries are enforced and cross-server orchestration happens.
- State the cost yourself: N servers means N connections and N lifecycles, and that is where most client complexity lives, not in sending messages.
- Likely follow-up: how do you handle tool name collisions across servers? Aggregation and disambiguation belong to the host; the spec suggests prefixing with a server identifier and explicitly warns against relying on the server's self-reported name, which is neither unique nor verified.
答题要点
- 一对一是安全设计而非性能设计:服务端读不到整段对话,也看不见别的服务端
- 完整历史留在宿主,服务端只收到本次调用真正需要的参数
- 跨服务端的聚合、消歧、授权都由宿主统一做,边界只有一处需要加固
- 代价是连接与生命周期管理,这是客户端实现复杂度的主要来源
Key points
- One-to-one is a security decision, not a performance one: servers cannot read the conversation or see peers
- Full history stays in the host; a server receives only the arguments for the current call
- Aggregation, disambiguation, and authorization all happen in the host, so there is a single boundary to harden
- The cost is connection and lifecycle management, which dominates client implementation complexity
7 天 Agent Skills:把经验做成可复用能力
D6 组织与分发:插件与市场、版本与团队共享,以及函数调用、MCP、Skills 三者的分工
函数调用、MCP 和 Skills 三者的关系是什么?什么时候用哪个?How do function calling, MCP and Agent Skills relate, and when do you use which?
国内高频海外高频进阶#agent-skills#mcp#tool-calling#architecture分析过程 · 先想清楚再作答
- 这是本课最高频的一题。答错的典型是把三者摆成竞争关系,说「Skills 比 MCP 更轻量所以更好」——它们解决的根本不是同一个问题。
- 先给一句能背下来的分工:**MCP 管接线,Skills 管经验**,而函数调用是接线之前那根最短的线。
- 再落到缺口上。函数调用与 MCP 补的是**能力**:模型本来读不到你的数据库、发不出工单,给它工具它就能了。Skills 补的是**经验**:模型本来就会写提交信息,只是不知道你们这儿的格式。能力的缺口用工具补,经验的缺口用技能补。
- 然后给两条对比里最有信息量的差异。第一,上下文成本:工具定义每一轮都要重发,而 skill 每轮只有名字与描述,正文按需加载。第二,装不上时的降级:工具与协议是二值的,接不上就没有;**一个 skill 装不上仍然是一份人能读的 Markdown**,这正是它能在几十家客户端铺开的原因——它不要求宿主实现协议,只要求宿主会读文件。
- 选型给一条能当场走的流程:先分缺能力还是缺做法。缺能力时按复用面选,只有这一个应用要用就写函数调用,多个 Agent 都要用才值得做成 MCP 服务端。缺做法时按确定性选,靠指令说清楚就写进 skill 正文,结果必须逐字一致就配脚本。
- 最后一定要说配合。三者常态是叠着用:MCP 服务端把工单系统接进来成为工具,skill 的正文里写「先用工单查询工具拉出本周工单,再按这份模板归类」。**工具给它手,skill 给它章法。**
- 可预期的追问是「那什么时候不该用 MCP」。答案是只有一个应用要用、动作又只有两三个的时候——为它起一个服务端是过度设计,直接写函数调用更短。
How to reason about it · think before answering
- The most common question in this course. The classic mistake is framing the three as competitors and saying skills are lighter than MCP, when they do not solve the same problem.
- Lead with the one-line division: MCP handles wiring, Skills handle experience, and function calling is the shortest wire of all.
- Then name the gaps. Function calling and MCP supply capability: the model cannot reach your database or file a ticket until you give it a tool. Skills supply experience: the model can already write a commit message, it just does not know your format.
- Give the two most informative contrasts. Context cost: tool definitions are resent every turn, while a skill costs only its name and description per turn with the body loaded on demand. Degradation: tools and protocols are binary, but a skill that fails to install is still readable Markdown, which is exactly why the format spread across dozens of clients. It requires the host to read files, not to implement a protocol.
- For selection give a runnable decision path. First separate missing capability from missing method. For capability, choose by reuse surface: one application means function calling, several agents justify an MCP server. For method, choose by determinism: instructions go in the skill body, byte-identical results go in a bundled script.
- Close on composition. The normal case stacks them: an MCP server exposes the ticket system as a tool, and a skill body says to pull this week's tickets with that tool and then group them by a template. Tools give hands, skills give procedure.
- Expected follow-up: when should you not use MCP? When only one application needs it and there are just two or three actions. Standing up a server is over-engineering.
答题要点
- 分工是 MCP 管接线、Skills 管经验,函数调用是接线之前最短的线。
- 能力的缺口用工具或协议补,经验的缺口用技能补,三者不是竞争关系。
- 工具定义每轮重发,skill 每轮只有名字与描述,正文按需加载。
- skill 装不上仍是一份人能读的 Markdown,这是它跨客户端铺开的根本原因。
- 选型先分缺能力还是缺做法:能力按复用面选,做法按确定性选;常态是三者叠着用。
Key points
- MCP is wiring, Skills are experience, function calling is the shortest wire.
- Capability gaps need tools or a protocol; experience gaps need skills. They do not compete.
- Tool definitions cost every turn; a skill costs only name and description until activated.
- A skill that fails to install is still readable Markdown, which is why it spread across clients.
- Choose by capability versus method: capability by reuse surface, method by determinism, and expect to combine all three.
14 天 RAG:从检索到可信回答
D5 向量索引与库选型:HNSW 与倒排文件、量化省内存、带过滤的查询与多租户隔离
什么时候应该把向量搬出 PostgreSQL?给出可量化的触发条件,也说说不该搬的理由。When should you move your vectors out of PostgreSQL into a dedicated vector database? Give measurable triggers, and also make the case for staying.
国内高频海外高频进阶#vector-database#architecture#trade-offs分析过程 · 先想清楚再作答
- 这题考的是工程判断,不是技术偏好。开口就说「专用向量库更专业」的人会被追问到答不上来;面试官想看的是你有没有把迁移成本算进去。
- 先给默认立场并给出理由:第一版留在 PostgreSQL,因为事务、备份、时间点恢复、权限、跟业务表 JOIN 和现成的运维工具全是白送的。多一个数据库就多一份同步、一份一致性问题、一份值班负担,这些成本很少被写进选型文档。
- 然后给四条可量化的触发线:数据量(判据不是行数而是索引还塞不塞得进内存)、写入频率(分钟级流式更新会让聚类失真、让图持续膨胀)、过滤复杂度(十几个属性的任意组合让部分索引和分区都排列组合不过来)、团队运维能力(没人愿意长期照看第二个数据库,前三条再成立也别搬)。
- 第三条要展开一点,因为它最常是真正的原因:专用向量库把过滤做进了索引结构本身,而不是扫完索引再筛,所以在复杂过滤下天然占优。把这一点说出来,说明你理解的是机制而不是口碑。
- 还要主动给一条常被忽略的替代路径:很多「向量检索不够用」的问题,真正的解法是混合检索加重排,而不是换数据库。先把关键词一路加回来、把重排接上,再决定要不要搬——顺序搞反了会白搬一次。
- 可预期的追问:真要搬怎么迁?答分三步——先双写并在影子流量上比对两边的召回与延迟,再把读流量按比例切过去,最后才停掉旧路径。中间任何一步指标不达标就停下,这比一次性切换安全得多。
How to reason about it · think before answering
- This tests engineering judgement, not tooling preference. Opening with 'dedicated vector databases are better' invites follow-ups you cannot answer.
- State the default position and justify it: keep the first version in PostgreSQL, because transactions, backups, point-in-time recovery, permissions, joins with business tables and the tooling your team already knows all come free. A second datastore adds synchronisation, a consistency surface and an on-call burden that selection documents rarely price in.
- Then give four measurable triggers: data volume (the test is whether the index still fits in memory, not the raw row count), write frequency (minute-level streaming updates distort clusters and inflate graphs), filter complexity (arbitrary combinations of a dozen attributes defeat both partial indexes and partitioning), and operational capacity.
- Expand on filter complexity, because it is most often the real reason: dedicated vector databases push filtering into the index structure instead of applying it after the scan, which is a mechanical advantage rather than a reputational one.
- Volunteer the alternative people skip: many 'vector search is not good enough' problems are actually solved by hybrid retrieval plus re-ranking, not by a new database. Add the keyword path and a re-ranker first, then decide.
- Expected follow-up: how would you migrate? Dual-write, compare recall and latency on shadow traffic, shift read traffic gradually, and only then retire the old path. Stop at any step where the metrics regress.
答题要点
- 默认留在 PostgreSQL:事务、备份、恢复、权限、JOIN 和现成运维都是白送的,多一个库就多一份同步与值班成本。
- 触发线一是数据量,判据是索引还塞不塞得进内存,而不是行数本身。
- 触发线二是写入频率,分钟级流式更新会让聚类失真、让图持续膨胀。
- 触发线三是过滤复杂度,专用库把过滤做进索引结构,复杂过滤下有机制上的优势。
- 触发线四反过来看:没有长期运维第二个数据库的人手,前三条成立也不该搬;很多问题的真正解法是混合检索加重排。
Key points
- Default to staying in PostgreSQL: transactions, backups, recovery, permissions, joins and familiar tooling are free, and a second store adds sync and on-call cost.
- Trigger one is data volume, measured by whether the index still fits in memory rather than by row count.
- Trigger two is write frequency: minute-level streaming updates distort clusters and inflate graphs.
- Trigger three is filter complexity: dedicated stores push filtering into the index structure, a mechanical advantage under complex predicates.
- Trigger four cuts the other way: without people to run a second database, do not move even if the first three hold. Often hybrid retrieval plus re-ranking is the real fix.
D7 第一周综合:把六天的零件装成一个可一键启动的检索问答服务并复盘
你会怎么划分一个检索增强生成系统的模块边界?其中哪一层最应该做成可替换的,为什么?How would you draw the module boundaries of a RAG system, and which layer most needs to be swappable? Why?
国内高频海外高频基础#architecture#modularity#embeddings分析过程 · 先想清楚再作答
- 这题考的是你有没有真的维护过这类系统。只按「解析、切块、检索、生成」复述一遍流程图,面试官会判定你只搭过 demo——流程图人人都会画,切口画在哪才是经验。
- 给一条可复用的判据再往下推:切口应该落在「将来最可能被整个换掉」的地方,而不是按代码量或者功能名称均分。
- 用它过一遍:embedding 一年会换好几次,换一次库里所有向量作废、必须全量重算,所以它必须是接口;存储可能从 PostgreSQL 换成专用向量库,而且摄取和查询都要通过它,所以它是两条链路的唯一交界;切块策略在调优期天天改,所以它必须是配置项而不是硬编码。
- 结论:最该做成可替换的是 embedding 那一层,理由不是「设计模式」,而是「换模型这件事真的会发生,且发生时代价极高」。
- 顺手点出抽象的代价:每多一层间接就多一次跳转和一份心智负担,所以判据是「那件事会不会真的发生」,不会发生的别抽象。
- 可预期的追问:那生成模型要不要也抽象?答案是要,但优先级低——换生成模型不需要重算任何存量数据,回滚也便宜,所以它是配置项而不是一层接口。
How to reason about it · think before answering
- This question separates people who have maintained such a system from people who have only built a demo. Reciting the pipeline diagram is not an answer; where you cut it is.
- Offer a reusable criterion first: cut where a layer is most likely to be replaced wholesale, not by lines of code or by tidy functional names.
- Apply it. Embedding models change several times a year, and each change invalidates every stored vector, so that layer must be an interface. Storage may move from PostgreSQL to a dedicated vector database, and both ingestion and query talk through it, so it is the single shared boundary. Chunking changes daily during tuning, so it belongs in config, not in code.
- Conclusion: the embedding layer is the one that must be swappable, because the swap is both likely and expensive, not because interfaces are good style.
- Name the cost of abstraction too: every indirection is one more hop while debugging, so the test is whether the change will actually happen.
- Expected follow-up: should the generation model be abstracted as well? Yes, but at lower priority, because swapping it does not force recomputation of stored data and rollback is cheap. It is a config value, not a layer.
答题要点
- 先给判据:切口落在最可能被整体替换的那一层,不按代码量或功能名称均分。
- embedding 是最该抽象的一层:换模型意味着存量向量全部作废、必须全量重算,代价高且真的会发生。
- 存储层是摄取与查询唯一的交界,接口要先定下来再谈两边实现。
- 切块与检索路数做成配置项,因为它们在调优期改动最频繁,改一次不该动代码。
- 抽象有成本,判据是那件事会不会真的发生;不会发生的抽象就是过度设计。
Key points
- Lead with the criterion: cut where a layer is most likely to be replaced wholesale.
- The embedding layer is the one to abstract: swapping models invalidates every stored vector and forces a full recompute.
- Storage is the single boundary shared by ingestion and query, so define its interface before either implementation.
- Chunking and retrieval routes belong in configuration because they change most often during tuning.
- Abstraction costs indirection, so only abstract changes that will actually happen.
摄取链路和查询链路应该共享哪些代码?强行复用会带来什么具体问题?What should the ingestion path and the query path share, and what concretely goes wrong when you over-share?
国内高频海外高频进阶#architecture#ingestion#retrieval分析过程 · 先想清楚再作答
- 题眼在「强行」两个字。面试官想看的是你能不能说出复用的边界,而不是背诵「不要重复自己」。
- 先说清两条链路的性质差异:摄取是批处理,几十秒跑完,失败重跑一遍就行;查询是在线请求,几百毫秒要出结果,失败用户当场看到。错误处理、超时、并发策略天然不同。
- 所以结论是:**共享接口,不共享流程**。两边唯一该共享的是存储层的那个接口,以及 embedding 的函数签名——注意后者共享的是签名和模型选择,不是调用流程。
- 给出强行复用的具体症状:抽出来的公共模块里开始出现 isIngest 这类分支,一个改动要同时验证两条链路,最后没人敢动它。
- 补一条真正必须一致的东西:给块算向量和给问题算向量必须用同一个模型。这不是复用代码,是复用配置——而且要把模型名写进向量表,否则模型换了没人发现,检索会静默地返回垃圾。
- 可预期的追问:那切块逻辑呢?查询侧压根不切块,所以它只属于摄取链路;真要在查询侧用到(比如 D11 的父子回填),走的也是存储层读回大块,不是把切块器搬过来。
How to reason about it · think before answering
- The word to notice is 'over-share'. The interviewer wants the boundary, not a recital of DRY.
- Start from how the two paths differ. Ingestion is batch: tens of seconds, and a failure just means rerunning it. Query is online: hundreds of milliseconds, and a failure is visible to the user immediately. Error handling, timeouts and concurrency are simply not the same problem.
- Hence the rule: share the interface, not the flow. The only genuinely shared thing is the storage interface, plus the embedding function signature.
- Name the symptom of over-sharing: the extracted module fills up with isIngest branches, every change has to be verified on both paths, and eventually nobody dares touch it.
- Add the one thing that truly must match: chunks and queries must be embedded by the same model. That is shared configuration, not shared code, and the model name belongs in the vector table so a silent mismatch is detectable.
- Expected follow-up: what about chunking? The query path never chunks. Even when it needs a parent block, it reads it back through storage rather than importing the chunker.
答题要点
- 共享接口不共享流程:唯一的交界是存储层,加上 embedding 的函数签名。
- 两条链路的错误处理与延迟约束根本不同,批处理可以重跑,在线请求必须快速失败。
- 强行复用的症状是公共模块里长出 isIngest 分支,改一次要验两条链路。
- 必须一致的是模型选择而不是代码:块与查询要用同一个 embedding 模型,并把模型名记进向量表。
- 切块只属于摄取;查询侧需要大块时通过存储层读回,而不是把切块器搬过去。
Key points
- Share the interface, not the flow: storage is the only boundary, plus the embedding signature.
- The two paths have different error handling and latency budgets; batch can rerun, online must fail fast.
- Over-sharing shows up as isIngest branches and changes that must be verified twice.
- What must match is the model choice, not the code: record the model name alongside every stored vector.
- Chunking belongs to ingestion only; the query path reads larger units back through storage.
D11 高级索引:父子文档、摘要索引、上下文检索,以及树状聚合与图检索的取舍
同一份语料建了三套索引,检索时你怎么决定走哪一套?You have built three different indexes over the same corpus. How do you decide which one a query goes to?
国内高频海外高频进阶#index-routing#evaluation#architecture分析过程 · 先想清楚再作答
- 这题是送分还是丢分,取决于你有没有先反问一句『真的需要三套吗』。上来就答路由策略的人,默认了一个没被验证的前提。
- 第一步是承认多数情况下答案是『都不走,走默认那套』。我们在 30 篇语料上把五种索引结构各测一遍,**召回率全部停在 93.8%,没有一种跑赢基线**;唯一动了的是 nDCG@10(块头把它从 0.6438 抬到 0.7218),而两段式的摘要索引还掉到了 87.5%。每种结构补的都是一个特定短板,你没有那个短板时它只带来成本。
- 第二步才是路由,而判据不是『哪套准』——那是离线评估该回答的问题,不是运行时能知道的。运行时能拿到的只有**问题的形状**:细节型(答案落在某一段)、概括型(要全库的一个概括)、多跳型(要跨实体串联)。按形状分流,正好对应块级索引、树状聚合索引、图索引。
- 实现上就是一个轻量意图分类器,跟前一天的意图路由是同一套东西,不必再造一个。分类结果作为元数据带进请求,方便事后拿评估集回看分错了多少。
- 兜底策略要说清楚:分类错了**回落到默认那一套**,不要并行全查一遍再融合。并行看着稳,实际上把延迟和成本按索引套数翻倍,而多出来的那两路大概率一条都进不了上下文预算。
- 可预期的追问是『怎么知道分类器分对了』。答案是把路由决策记进日志,定期拿标准答案集回放:对每个问题分别走三套索引,看分类器选的那套是不是指标最好的那套。这是一个能持续跑的离线作业,不需要人工标注。
How to reason about it · think before answering
- Whether this is an easy point or a lost one depends on whether you first ask 'do we actually need three?'. Jumping straight to routing accepts an unverified premise.
- Step one is admitting the answer is usually 'none of them — use the default'. Across 30 documents we measured five index structures and every one landed at 93.8% recall, none beating the baseline. The only metric that moved was nDCG@10, which headers lifted from 0.6438 to 0.7218, while the two-stage summary index fell to 87.5%. Each structure patches one specific weakness; without that weakness it is pure overhead.
- Step two is routing, and the criterion is not 'which index is more accurate' — that is an offline evaluation question, not something you know at request time. What you do have at request time is the shape of the question: detail-seeking, summarizing, or entity-chaining. Those map onto the chunk index, the tree-summary index and the graph index.
- Implementation is a lightweight intent classifier — the same one from the previous day's intent routing, no need to invent another. Carry the decision as request metadata so you can replay it later.
- Spell out the fallback: on a misclassification, fall back to the default index rather than fanning out across all three and fusing. Fan-out looks safe but multiplies latency and cost by the number of indexes, and the extra routes usually never make it into the context budget anyway.
- Expect 'how do you know the classifier is right'. Log every routing decision and replay the golden set periodically: run each question through all three indexes and check whether the classifier picked the best-scoring one. It is a standing offline job that needs no human labelling.
答题要点
- 先反问是否真需要三套:实测五种索引结构召回率全部持平在 93.8%,没有对应短板就是纯成本。
- 运行时的判据是问题的形状——细节型、概括型、多跳型,分别对应块级、树状摘要、图索引。
- 复用前一天的意图路由做分类,把路由决策记进请求元数据。
- 分类错了回落到默认索引,不要并行全查再融合——延迟和成本按套数翻倍。
- 用标准答案集定期回放,检验分类器选的那套是不是指标最好的那套。
Key points
- First challenge the premise: all five index structures landed at the same 93.8% recall in our measurement, so an index without a matching weakness is pure cost.
- At request time the usable signal is question shape — detail, summary, or entity-chaining — mapping to chunk, tree-summary and graph indexes.
- Reuse the previous day's intent router for classification and record the routing decision as request metadata.
- Fall back to the default index on misclassification instead of fanning out and fusing, which multiplies latency and cost.
- Replay the golden set periodically to check whether the classifier picks the best-scoring index.
14 天用 Agent 搭一条 AI 短剧生产线
D1 一条 AI 短剧生产线长什么样:工序拆解、任务图架构与四类生成模型选型
为什么要在厂商 SDK 之上再套一层自己的 provider 接口?什么时候这层反而是负担?Why wrap a vendor SDK in your own provider interface, and when does that layer become a liability?
国内高频海外高频基础#provider-abstraction#architecture分析过程 · 先想清楚再作答
- 这题在筛「有没有真的换过一次厂商」。只答「解耦、方便替换」的人,说的是一句所有人都会说的话,区分度在于你能不能给出「这层带来了什么、又赔上了什么」的具体清单。
- 怎么拆:先问自己「如果不套这层,哪些能力会散掉」。答案有三样,而且都能落到具体文件上——离线可跑(网络出口收敛到一处才可能打桩)、多厂商并存(业务代码写的是动作而不是某家的四步流程)、计量收口(每次调用的花费必须有唯一一处记账)。
- 接着说抽象的位置:接口要按业务动作定义,不按厂商的 HTTP 请求定义。异步视频任务的提交、轮询、取件、下载四步,对业务代码来说是一个 generate;把这四步漏到业务层,抽象就白做了。
- 结论与代价:这层会磨掉各家的独有能力(某家支持首尾帧、某家支持结构化运镜参数)。正确处理不是把接口撑大,而是留一个可选透传字段,让需要它的那一处显式承认自己绑定了某一家。
- 什么时候是负担:你只会用一家、也永远不会离线跑的时候;以及出现两个信号时——为加一个厂商改了接口签名让另外三个实现跟着改,或者接口里出现了只有一家有的参数名。这两个信号说明抽象抽在了厂商能力的最小公倍数上,位置错了。
- 可预期的追问:那要不要直接用某个统一网关或聚合 SDK?可以,但你仍然需要自己的接口,因为聚合层解决的是协议差异,解决不了你自己的落盘契约与记账口径。
How to reason about it · think before answering
- The screen is whether you have ever actually swapped a vendor. Answering only decoupling and easy replacement is what everyone says; the signal is naming what the layer buys and what it costs.
- How to break it down: ask what you lose without the layer. Three concrete things — offline runnability (you can only stub when network egress is funneled into one place), multi-vendor coexistence (business code expresses an action, not one vendor's four-step flow), and metering (every call's cost must be recorded in exactly one place).
- Then place the abstraction: define it by business action, not by the vendor's HTTP request. Submit, poll, retrieve, download for an async video job is one generate to the caller; leaking those four steps upward defeats the purpose.
- Conclusion and cost: the layer sands off vendor-specific capabilities, such as first-and-last-frame conditioning or structured camera parameters. The fix is not a wider interface but one optional passthrough field, so the single call site explicitly admits it is vendor-bound.
- When it is a liability: single vendor forever and no offline path. Two warning signs — adding a vendor forced a signature change across the other implementations, or a vendor-only parameter name appeared in the interface. Both mean you abstracted the least common multiple of vendor features.
- Likely follow-up: why not just use an aggregation gateway or SDK? You still need your own interface, because aggregators normalize protocols but not your on-disk artifact contract or your cost ledger.
答题要点
- 三个理由要说具体:离线可跑、多厂商并存、计量收口,每一个都对应一处真实代码
- 接口按业务动作定义,异步任务的提交轮询取件下载四步必须关在实现里
- 把落盘路径写进接口契约,因为厂商返回的图片与视频链接都是会失效的临时链接
- 代价是磨掉独有能力,用可选透传字段处理,而不是撑大公共接口
- 两个「抽错了」的信号:加厂商要改签名、接口里出现厂商专有参数名
Key points
- Name three concrete reasons: offline runnability, multi-vendor coexistence, and a single metering point
- Define the interface by business action; submit-poll-retrieve-download stays inside the implementation
- Put the output file path in the contract, because vendor image and video URLs are short-lived temporary links
- The cost is losing vendor-specific features; handle it with one optional passthrough field, not a fatter interface
- Two signs you abstracted wrong: adding a vendor changes the signature, or a vendor-only parameter leaks into the interface
D8 工作流引擎:把流水线做成可断点续跑的任务图
什么时候该自己写调度,什么时候该直接上现成的工作流引擎?When should you write your own scheduler, and when should you adopt an off-the-shelf workflow engine?
国内高频海外高频基础#architecture#build-vs-buy#workflow-engine分析过程 · 先想清楚再作答
- 这题考的是技术选型的成熟度。两个极端都会被扣分:什么都自己写显得不懂杠杆,什么都上框架显得没判断力。面试官想听的是你的切换信号是什么。
- 先给一条通用判据:自己写的收益是理解和贴合,框架的收益是省掉你还没遇到的那些问题。所以决策取决于「你现在需要的功能有多少落在框架的核心能力上」。
- 自己写划算的情形:单机、节点数是个位数、路径是你定死的、需要的只是拓扑排序加幂等加状态落盘这几件事。这时候自己写不到三百行,而且换来的理解是通用的——你会彻底搞懂幂等键为什么要包含依赖指纹、状态为什么必须每步落盘。
- 该换的三个信号:一是开始需要跨机器调度,自己实现分布式调度的复杂度是指数级上升的;二是开始需要人工介入节点,流程要挂起几小时甚至几天,状态必须外置到数据库而不是一个 JSON 文件;三是开始需要给非工程师看和操作,那你需要的其实是一个带界面的产品。
- 反过来说,过早引入重型框架的代价很具体:每一个业务改动都要先绕过它的抽象,而它的收益要等规模上来才兑现。这是典型的成本前置、收益后置。
- 可预期的追问是「自己写的那一套能不能平滑迁走」。答:能,前提是你从一开始就把节点定义成纯声明(依赖、输入、产物、执行体),调度和状态不侵入业务。这样迁移时改的是引擎,不是六个节点。
How to reason about it · think before answering
- This tests selection maturity. Both extremes lose points: building everything yourself shows no sense of leverage, adopting a framework for everything shows no judgment. The interviewer wants your switching signals.
- Give a general criterion: writing it yourself buys understanding and fit; a framework buys you past problems you have not hit yet. So the decision hinges on how much of what you need overlaps with the framework's core.
- Writing your own pays off when: single machine, a handful of nodes, a path you fixed yourself, and you only need topological ordering plus idempotency plus state persistence. That is under three hundred lines, and the understanding transfers to any engine you adopt later.
- Three signals to switch: you need cross-machine scheduling, where rolling your own scales in complexity exponentially; you need human-in-the-loop nodes, so runs suspend for hours or days and state must live in a database rather than a JSON file; or non-engineers need to see and operate it, in which case you need a product with a UI, not an engine.
- Conversely, adopting a heavy framework too early has a concrete cost: every business change must route around its abstractions, while its benefits only land at scale. Cost up front, payoff deferred.
- Expect the follow-up 'can you migrate off your own version cleanly'. Yes, if nodes were declarative from the start — dependencies, inputs, outputs, body — with scheduling and state kept out of the business code. Then migration replaces the engine, not the nodes.
答题要点
- 判据是你需要的功能与框架核心能力的重叠度,不是「自研还是选型」的立场。
- 自己写划算:单机、节点数少、路径固定,只需要拓扑排序加幂等加状态落盘。
- 该换的三个信号:跨机器调度、人工介入导致流程长时间挂起、非工程师要操作。
- 过早上重型框架的代价是每次业务改动都要绕过它的抽象,收益却要等规模。
- 把节点写成纯声明,调度与状态不侵入业务,将来迁移改的是引擎而不是节点。
Key points
- Decide by how much your needs overlap the framework's core, not by a build-versus-buy stance.
- Rolling your own wins on a single machine with few nodes and a fixed path, needing only topo order, idempotency and state persistence.
- Three switching signals: cross-machine scheduling, human-in-the-loop suspension, and non-engineers needing to operate it.
- Adopting a heavy framework early costs a detour around its abstractions on every change, with benefits deferred to scale.
- Keep nodes declarative and scheduling non-invasive so a later migration replaces the engine, not the nodes.