面试题库
共 328 题,当前筛选 4 题。
课程全部30 天从前端工程师到 Agent 工程师5 天提示词工程零基础Claude 高效使用:从对话到 Claude CodeCodex 与 OpenAI Agents SDK 高效使用7 天 MCP:把工具接进任何 Agent7 天 Agent Skills:把经验做成可复用能力5 天上下文工程14 天 RAG:从检索到可信回答14 天用 Agent 搭一条 AI 短剧生产线
标签
全部#framework-design4#evaluation30#cost29#reliability24#architecture22#agent-skills21#security18#observability15#streaming12#error-handling11#idempotency10#system-design10
还有 362 个标签收起标签
#api-design9#coding-agent9#distributed-systems8#multi-agent8#rag8#chunking7#debugging7#pipeline-design7#structured-output7#agent-loop6#mcp6#operations6#prompt-injection6#sse6#tool-calling6#tool-design6#context5#context-engineering5#deployment5#embeddings5#hybrid-search5#message-bus5#scheduling5#system-prompt5#agentic-rag4#behavioral4#client4#concurrency4#consistency4#ingestion4#prompt-engineering4#rate-limiting4#retrieval4#routing4#trade-offs4#abstention3#agents-sdk3#caching3#communication3#context-window3#cost-control3#data-quality3#failure-modes3#image-generation3#interview-prep3#langgraph3#latency3#llm-as-judge3#llm-basics3#long-context3#model-migration3#model-routing3#orchestration3#ordering3#progressive-disclosure3#prompt-basics3#prompt-caching3#protocol3#provider-abstraction3#ranking3#recall3#redis-streams3#responses-api3#resume3#retry3#runtime3#scalability3#skills3#state-management3#statelessness3#subagents3#timeline3#versioning3#workflow-engine3#access-control2#agent-design2#async-task2#auth2#checkpointing2#citation-verification2#citations2#claude-md2#code-review2#compaction2#context-rot2#contextual-retrieval2#cost-tradeoff2#data-modeling2#database2#distribution2#fallback2#ffmpeg2#golden-set2#grounding2#interview-process2#long-term-memory2#media-pipeline2#memory2#multi-hop2#multi-tenancy2#oauth2#prioritization2#project-storytelling2#prompt-techniques2#query-rewriting2#react2#refusal2#reproducibility2#rerank2#retrieval-quality2#retrospective2#scripts2#sharding2#state-machine2#tool-permissions2#tooling2#tools2#tracing2#transport2#tts2#ux2#vector-database2#verification2#workflow2#agent-basics1#agent-quality1#agent-sdk1#agents-md1#altitude1#analytics1#approvals1#architecture-review1#async1#atomicity1#attention-budget1#av-sync1#backoff1#bi-encoder1#bm251#budget-control1#build-vs-buy1#cancellation1#candidate-selection1#capacity-planning1#career1#chain-of-thought1#ci1#circuit-breaker1#claude-code1#cli-design1#client-integration1#cloud1#compliance1#compression1#configuration1#confused-deputy1#consistent-hashing1#content-hash1#content-safety1#context-assembly1#context-compression1#context-management1#copyright1#coreference1#correctness1#cost-accounting1#cost-analysis1#cost-optimization1#cross-encoder1#cross-model1#customer-support1#dag1#decision-making1#decomposition1#degradation1#deliberate-practice1#design1#diagnostics1#dimensions1#docker1#documentation1#embedding-migration1#encoding1#engineering-judgement1#engineering-tradeoffs1#error-propagation1#escalation1#eval1#event-driven1#evidence1#failure-analysis1#fairness1#faithfulness1#fan-out1#feedback-loop1#fencing-token1#few-shot1#filter-pushdown1#filtering1#fine-tuning1#forking1#four-elements1#framework-selection1#frontend1#global-market1#graph-rag1#guardrails1#hallucination1#handoff1#handoffs1#headless1#hnsw1#hooks1#human-in-the-loop1#hybrid1#hyde1#incremental-recompute1#incremental-sync1#index-maintenance1#index-routing1#indexing1#information-retrieval1#instruction-hierarchy1#integration1#intent-routing1#interrupt-merge1#invalidation1#isolation1#iterative-scan1#ivfflat1#json-parsing1#json-schema1#just-in-time1#jwt1#knowledge-organization1#labeling1#latency-budget1#lease1#least-privilege1#llm-output-quality1#long-session1#loop-guard1#maintenance1#mcp-basics1#mental-model1#messages-api1#metadata1#methodology1#metrics1#migration1#mobile1#model-selection1#moderation1#modularity1#multi-turn1#multimodal1#nodejs1#normalisation1#notifications1#ocr1#offline-testing1#openai1#overlap1#pagination1#parent-child1#pdf-parsing1#performance1#permissions1#persistence1#pgvector1#pipeline-reliability1#portfolio1#primitives1#priority-queue1#proactive-messaging1#product-engineering1#production-readiness1#prompt1#prompt-assembly1#prompt-bloat1#prompt-design1#prompt-limits1#prompt-surface1#prompt-template1#prompt-versioning1#prompting1#protocol-versions1#quality1#quality-check1#quantization1#query-transformation1#quiet-hours1#rag-basics1#rank-fusion1#reasoning1#reconnect1#redis1#reflection1#replay1#reporting1#retrieval-failure1#retrieval-metrics1#retry-semantics1#retry-strategy1#review1#risk-assessment1#rollback1#rollout1#rrf1#safety1#sampling1#sandbox1#sandboxing1#scaling1#schema-design1#schema-validation1#scoping1#secrets-management1#self-assessment1#self-introduction1#self-presentation1#self-reflection1#server-design1#service-architecture1#session-management1#sessions1#similarity1#skill-authoring1#skill-description1#skill-design1#spec1#split-brain1#stakeholder-communication1#star1#state-persistence1#stateless1#stdio-transport1#stopping-criteria1#storytelling1#subagent1#subscriptions1#subtitles1#task-graph1#team-governance1#test-set1#test-strategy1#testing1#thresholds1#timezone1#token-accounting1#token-budget1#tool-budget1#tool-execution1#tool-naming1#tool-schema1#trust-boundary1#tuning1#validation1#vector-index1#workflow-design1#xml-tags1#zero-downtime1
30 天从前端工程师到 Agent 工程师
D3 Pi SDK 上手:三层架构、Agent Loop 对照(dg P01/P02/M02/M03)
Agent 框架内部的 Agent Loop 一般要解决哪些问题?What problems does an agent framework's built-in agent loop have to solve?
国内高频海外高频基础#agent-loop#framework-design分析过程 · 先想清楚再作答
- 这题看着像背清单,区分度其实在「你有没有自己写过一遍」。只答「循环调用模型直到结束」会被认为读过文档但没写过代码。
- 最稳的拆法是把手写版的代码从上往下念一遍,每一行都是内核必须解决的一件事:发模型请求、维护消息历史、判断停止原因决定继不继续、按工具名分派、按 schema 校验参数、把工具结果回填成一条消息、控制最大轮数。这条链路念完,答案自然是完整的。
- 点名停止原因这一环最能加分:循环的出口条件不是「模型说完了」,而是这一轮的停止原因是不是「要调工具」。很多人把它含糊过去,而它恰恰是整个循环的开关。
- 然后补上手写版通常没做、但框架必须做的三件:并发执行同一批工具调用、把每一步以事件形式播报出去(否则外部完全是黑箱)、以及上下文超限时的压缩与会话持久化。
- 最后落到工具报错这一条,它是最能体现工程经验的:工具异常不应该被吞掉,要转成一条带错误标记的工具结果回给模型,让模型自己改参数重试;吞掉异常返回一句「操作失败」,模型会以为工具成功了。
- 可以预期的追问:怎么防死循环?答最大轮数只是兜底,更实际的是给单次运行设 token 与耗时预算,并在工具调用前留一个可以拦截的钩子,触发条件时把拦截原因回传给模型让它改道。
How to reason about it · think before answering
- This looks like a checklist question, but the real signal is whether you have written such a loop yourself. 'Call the model repeatedly until it stops' reads as documentation-only knowledge.
- The safest structure is to walk down your own hand-written loop line by line, because every line is one problem the kernel must own: issue the model request, maintain message history, decide from the stop reason whether to continue, dispatch by tool name, validate arguments against the schema, fold the tool result back in as a message, and cap the number of turns.
- Naming the stop reason explicitly scores well: the loop exits not when 'the model finished talking' but when the turn's stop reason is not a tool-use one. Most candidates blur past this, and it is the switch that drives the whole loop.
- Then add the three things a hand-rolled version usually skips but a framework cannot: running a batch of tool calls concurrently, emitting the whole run as an event stream so callers are not staring at a black box, and compaction plus session persistence once the context outgrows the window.
- Close on tool errors, which is where production experience shows: a failing tool should raise, and the kernel should turn that into a tool result flagged as an error so the model can fix its arguments and retry. Swallowing the exception and returning 'operation failed' as a normal result makes the model believe the tool succeeded.
- Expect the follow-up: how do you stop runaway loops? A max-turn cap is only a backstop; per-run token and wall-clock budgets plus a pre-execution hook that can block a call and hand the reason back to the model are what actually work.
答题要点
- 循环骨架:调模型、维护消息历史、按停止原因判断继不继续、分派工具、校验参数、回填工具结果
- 停止原因是循环的出口条件,工具分支意味着还要再来一轮,其他取值意味着结束
- 工具执行的工程细节:同一批调用可以并发、执行前后要留钩子、异常要转成带错误标记的工具结果回给模型
- 对外要有事件流,否则调用方看不到 Agent 在做什么,也没法做可观测性
- 安全阀:最大轮数、token 与耗时预算、上下文超限时的压缩,以及会话的持久化与恢复
Key points
- The skeleton: call the model, maintain history, branch on the stop reason, dispatch tools, validate arguments, fold results back in
- The stop reason is the loop's exit condition — a tool-use reason means one more turn, anything else means done
- Tool execution details: batch calls can run concurrently, hooks belong before and after, and exceptions become error-flagged tool results the model can react to
- An event stream is mandatory, otherwise callers see a black box and observability is impossible
- Safety valves: max turns, token and latency budgets, context compaction, and session persistence for resume
选择使用 Agent 框架还是手写 Agent,你会怎么权衡?How do you decide between adopting an agent framework and hand-rolling the loop?
国内高频海外高频进阶#framework-design#engineering-tradeoffs分析过程 · 先想清楚再作答
- 题眼在「权衡」。答「框架更快」或者「手写更可控」都只说了一半,面试官想听的是你有没有一条能当场执行的判据,而不是立场。
- 给判据:问自己「我需不需要看见并改动这段循环里的每一步」。需要就手写——学习调试阶段、合规审计要求每次模型调用和工具调用都可拦截可留痕、或者场景本身只有一两个工具两三轮循环,那点代码量的收益抵不过一整棵依赖树。
- 不需要就用框架,判断标准是这几件事你是不是迟早都要做:工具数量上去、要把每一步实时推给前端、会话要能重启后继续、上下文满了要压缩、要随时换模型。这些凑齐了就是一个小型框架,自己写等于重新发明一个没人帮你测的版本。
- 然后主动说出框架的三笔代价,这是区分度所在:一是排障栈变深,工具没被调用可能是描述、schema、钩子拦截三种完全不同的原因;二是你继承了一堆没写过的默认值,模型、系统提示词、内置工具都是别人替你选的;三是升级会改变你没测过的行为,代码一行没动线上表现却变了,这类问题最难定位。
- 结论要给出可落地的折中:先手写一遍把循环吃透,再上框架;上了框架也要显式覆盖掉默认值,并把框架版本锁死。这样既拿到了开发速度,也没把行为的控制权整个交出去。
- 可以预期的追问:那你怎么评估一个框架好不好?答看它的分层能不能让你「只要一半」——只要模型调用层、循环自己写行不行;必须整包吞下的框架,迟早要为用不上的那一半付代价。
How to reason about it · think before answering
- The hinge word is 'decide'. 'Frameworks are faster' and 'hand-rolling is more controllable' are each half an answer; what earns points is a criterion you can apply on the spot rather than a preference.
- Offer the criterion: ask whether you need to see and change every step inside the loop. If yes, hand-roll — during learning and debugging, under compliance rules that require every model call and tool call to be interceptable and auditable, or when the scenario really is two tools and three turns and the saved lines do not justify a large dependency tree.
- If no, take the framework, and justify it by what you will inevitably need anyway: more tools, streaming every step to a UI, sessions that survive a restart, compaction when context fills up, swapping models on demand. Assemble all of those yourself and you have written a small framework — an untested one.
- Then volunteer the three costs, which is where the signal is: debugging spans more layers, so a tool that never runs could be a bad description, a schema rejection, or a hook that blocked it; you inherit defaults you never wrote, including the model, the system prompt, and the built-in tools; and upgrades change behavior you never tested, which is brutal to diagnose because your own code did not change.
- Land on a practical middle: hand-roll once to internalize the loop, then adopt a framework, override its defaults explicitly, and pin its version. You keep the delivery speed without handing over control of behavior.
- Expect the follow-up: how do you judge a framework? By whether its layering lets you take only half of it — model layer only, loop your own. Anything you must swallow whole will eventually bill you for the half you do not use.
答题要点
- 判据是「需不需要看见并改动循环里的每一步」,需要就手写,不需要就用框架
- 手写更合适:学习调试、合规要求每步可拦截可留痕、场景极简、对依赖体积与冷启动敏感
- 框架更合适:工具多、要事件流、要会话持久化与压缩、要多模型——这些凑齐等于自己造一个框架
- 框架的三笔代价:排障栈变深、继承一堆没写过的默认值、升级会改变没测过的行为
- 折中做法:先手写吃透循环再上框架,显式覆盖默认值并锁死版本
Key points
- The criterion is whether you need to see and modify every step of the loop
- Hand-roll for learning and debugging, for compliance that demands interceptable and auditable steps, for genuinely tiny scenarios, and where dependency size or cold start matters
- Use a framework once you need many tools, an event stream, persistent sessions, compaction, and model swapping — building all of that is writing a framework yourself
- Three costs: deeper debugging surface, inherited defaults you never wrote, and upgrades that shift untested behavior
- The middle path: hand-roll once, then adopt, override defaults explicitly, and pin the version
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
用了 Agent 框架之后,你怎么知道它内部到底发生了什么?出问题从哪里查?Once you adopt an agent framework, how do you know what it is doing internally, and where do you start debugging?
国内高频海外高频深入#observability#framework-design#debugging分析过程 · 先想清楚再作答
- 这题是「框架 vs 手写」那道题的实操版,考的是你有没有在框架上真的排过障。答「打日志」是最弱的答案,因为循环已经不在你的代码里了,你没有地方插日志。
- 先给正确的观察位置:框架的事件流。一次执行会依次发出运行开始、每一轮的开始与结束、消息的开始与增量与结束、工具执行的开始与结束、运行结束。这些事件就是循环的每一步在外部的投影——轮次的开始与结束对应手写版 for 循环的一次迭代,运行结束对应你 return 的那一刻。
- 给一条可复用的排查链:以「工具没被调用」为例,先看事件流里有没有发出工具执行开始的事件。发出了就是执行阶段的问题(参数、实现、超时);没发出就说明模型压根没决定调它,问题在工具描述或参数 schema,跟工具实现一点关系都没有。这条二分法能省掉大量瞎试。
- 补上另外两条线索:一是分层定位,报错栈落在模型层就查鉴权、模型 id 与请求格式,落在内核层就查循环与工具执行;二是把框架版本锁死,因为默认值随版本变化,「代码一行没改但行为变了」这类问题的第一嫌疑人就是升级。
- 生产视角要主动说:事件流不只是调试用的,它是可观测性的接入点——每一步耗时、工具成功率、token 与成本归集都从这里接出去。但要提醒一句,文本增量事件是逐 token 触发的,回调里做重活会拖慢整条流式链路,正确做法是攒一批再处理。
- 可以预期的追问:如果框架没有暴露你需要的那个钩子怎么办?答先看它的分层能不能降一层用(比如绕过应用层直接用内核层),再考虑用它的扩展机制在工具调用前后插手;实在不行才是 fork,而 fork 的代价是你从此要自己跟上游合并。
How to reason about it · think before answering
- This is the hands-on version of the framework-versus-hand-rolling question, and it tests whether you have actually debugged on top of a framework. 'Add logging' is the weakest answer, because the loop is no longer in your code and there is nowhere to add it.
- Name the right observation point: the event stream. One run emits run start, each turn's start and end, message start and deltas and end, tool execution start and end, and run end. Those events are the loop's steps projected outward — turn start and end correspond to one iteration of your hand-written for loop, and run end to your return statement.
- Give a reusable triage chain, taking 'the tool never ran' as the example: check whether a tool-execution-start event was emitted. If it was, the problem lives in execution — arguments, implementation, timeout. If it was not, the model never decided to call it, so the problem is the tool description or the parameter schema and has nothing to do with the implementation. That single split removes most guesswork.
- Add two more threads: locate the failure by layer, since a model-layer stack points at auth, model id or request shape while a kernel-layer stack points at the loop or tool execution; and pin the framework version, because defaults shift between releases and 'behavior changed with no code change' almost always means an upgrade.
- Volunteer the production angle: the event stream is not just for debugging, it is the observability seam where per-step latency, tool success rate and token or cost accounting are collected. Warn that text-delta events fire per token, so heavy work in that callback stalls the stream — batch first, then process.
- Expect the follow-up: what if the framework does not expose the hook you need? Try dropping a layer first (bypass the application layer and drive the kernel directly), then its extension mechanism for intercepting around tool calls; forking is the last resort, and its real price is owning upstream merges forever.
答题要点
- 观察位置是框架的事件流,不是日志:运行开始、轮次开始与结束、消息增量、工具执行开始与结束、运行结束
- 轮次的开始与结束对应手写版循环的一次迭代,运行结束对应 return,能做这个映射就能读懂任何事件表
- 排查二分法:工具没被调用时,先看有没有发出工具执行开始的事件——发了查实现,没发查描述与 schema
- 按分层定位:模型层的栈查鉴权与模型 id,内核层的栈查循环与工具执行;同时锁死框架版本,升级是行为变化的第一嫌疑人
- 事件流也是可观测性接入点,但文本增量事件极其频繁,回调里不要做重活,攒一批再处理
Key points
- Observe through the event stream, not ad-hoc logs: run start, turn start and end, message deltas, tool execution start and end, run end
- Turn start and end map to one iteration of the hand-written loop, and run end maps to the return — that mapping makes any event table readable
- Triage split: if a tool never ran, check for a tool-execution-start event; present means debug the implementation, absent means debug the description and schema
- Locate by layer — model-layer stacks mean auth or model id, kernel-layer stacks mean the loop or tool execution — and pin the framework version, since upgrades silently move defaults
- The event stream is also the observability seam, but text deltas fire per token, so batch before doing real work in that callback