逐日AI

面试题库

共 328 题,当前筛选 2 题。

30 天从前端工程师到 Agent 工程师

D3 Pi SDK 上手:三层架构、Agent Loop 对照(dg P01/P02/M02/M03)

  • 用了 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

    分析过程 · 先想清楚再作答

    1. 这题是「框架 vs 手写」那道题的实操版,考的是你有没有在框架上真的排过障。答「打日志」是最弱的答案,因为循环已经不在你的代码里了,你没有地方插日志。
    2. 先给正确的观察位置:框架的事件流。一次执行会依次发出运行开始、每一轮的开始与结束、消息的开始与增量与结束、工具执行的开始与结束、运行结束。这些事件就是循环的每一步在外部的投影——轮次的开始与结束对应手写版 for 循环的一次迭代,运行结束对应你 return 的那一刻。
    3. 给一条可复用的排查链:以「工具没被调用」为例,先看事件流里有没有发出工具执行开始的事件。发出了就是执行阶段的问题(参数、实现、超时);没发出就说明模型压根没决定调它,问题在工具描述或参数 schema,跟工具实现一点关系都没有。这条二分法能省掉大量瞎试。
    4. 补上另外两条线索:一是分层定位,报错栈落在模型层就查鉴权、模型 id 与请求格式,落在内核层就查循环与工具执行;二是把框架版本锁死,因为默认值随版本变化,「代码一行没改但行为变了」这类问题的第一嫌疑人就是升级。
    5. 生产视角要主动说:事件流不只是调试用的,它是可观测性的接入点——每一步耗时、工具成功率、token 与成本归集都从这里接出去。但要提醒一句,文本增量事件是逐 token 触发的,回调里做重活会拖慢整条流式链路,正确做法是攒一批再处理。
    6. 可以预期的追问:如果框架没有暴露你需要的那个钩子怎么办?答先看它的分层能不能降一层用(比如绕过应用层直接用内核层),再考虑用它的扩展机制在工具调用前后插手;实在不行才是 fork,而 fork 的代价是你从此要自己跟上游合并。

    How to reason about it · think before answering

    1. 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.
    2. 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.
    3. 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.
    4. 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.
    5. 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.
    6. 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

D5 工具系统与事件驱动:参数校验、错误回传让模型自纠错、事件订阅(dg P05/P06/M05/M07)

  • Agent 的事件系统一般会暴露哪些生命周期事件?为什么不能只等最终返回值?Which lifecycle events does an agent runtime typically expose, and why is waiting for the final return value not enough?
    国内高频海外高频进阶#event-driven#observability

    分析过程 · 先想清楚再作答

    1. 这题看起来是背清单,实际考的是你有没有做过带界面的 Agent。只报事件名不解释用途,会被判成看过文档但没接过前端。
    2. 先说动机:一次带工具的循环短则几秒长则几分钟,中间要调模型、调工具、可能还失败重试,而返回值只有最后一句话。对调用方来说中间全是黑盒——不知道它在干什么,也不知道该不该再等。
    3. 再报清单并各配一句用途:run:start / run:end / run:error 是一轮的开始与两种结束;model:delta 是模型吐出的文本片段,前端拿它做打字机效果;tool:proposed 是模型决定要调工具但还没执行,权限确认就挂在这个事件上;tool:start / tool:end / tool:error 是工具执行的三个出口,tool:end 带耗时;approval:required 让界面弹确认框。
    4. 然后说出这套设计真正的价值:同一条事件流同时喂三个消费者——界面渲染进度、日志系统做链路追踪、计量系统拿 run:end 的 token 数算成本。不为三件事写三套埋点,这是架构判断而不是 API 罗列。
    5. 补两条实现纪律,能显著拉开差距:事件必须带 runId 和自增序号,因为跨进程传输后顺序不保证;监听器里不写业务逻辑,且监听器抛错不能炸掉主循环——事件是旁路不是主干。
    6. 可以预期的追问:model:delta 一个 token 一条事件会不会太多?会,所以要按时间窗合批,攒 50 毫秒推一次,用户感知不到差别而消息量掉一个数量级。

    How to reason about it · think before answering

    1. It looks like a listing question but it really tests whether you have shipped an agent with a UI. Reciting event names without saying what each one is for reads as documentation-deep only.
    2. Start with the motivation: a tool-using loop runs from seconds to minutes, calling models and tools and sometimes retrying, while the return value is just the final sentence. Everything in between is a black box to the caller, who cannot tell whether to keep waiting.
    3. List them with a purpose each: run:start, run:end and run:error mark the turn and its two endings; model:delta carries text fragments for the typewriter effect; tool:proposed fires when the model has chosen a tool but has not executed it, which is where the approval gate hangs; tool:start, tool:end and tool:error are the three exits of execution, with duration on tool:end; approval:required tells the UI to show a confirmation card.
    4. Then name the real payoff: one event stream feeds three consumers — the UI renders progress, logging gets distributed tracing, and metering reads token counts off run:end. One stream instead of three instrumentation layers is an architecture answer, not an API listing.
    5. Add two implementation rules that separate candidates: every event carries a runId and a monotonic sequence number because ordering is not guaranteed once events cross processes, and listeners must contain no business logic and never let an exception escape into the main loop. Events are a side channel, not the trunk.
    6. Expect the follow-up: isn't one event per token too many? Yes, so batch on a time window — flush every 50ms, which is imperceptible to users and cuts message volume by an order of magnitude.

    答题要点

    • 动机:一轮循环几秒到几分钟,返回值只有最后一句话,中间全是黑盒,调用方无法判断该不该继续等
    • 常见事件:run:start / run:end / run:error、model:delta、tool:proposed、tool:start / tool:end / tool:error、approval:required
    • 同一条事件流同时喂界面、日志链路追踪和成本计量三个消费者,不用写三套埋点
    • 事件要带 runId 和自增序号,跨进程后顺序不保证,消费端要能自己排序
    • 监听器不写业务逻辑,且抛错不能影响主循环;model:delta 要按 50 毫秒时间窗合批

    Key points

    • Motivation: a turn takes seconds to minutes and only returns the final sentence, so the caller cannot tell whether to keep waiting
    • Typical events: run:start/end/error, model:delta, tool:proposed, tool:start/end/error, approval:required
    • One stream serves the UI, distributed tracing and cost metering — no need for three instrumentation layers
    • Every event carries a runId and a sequence number since ordering is not guaranteed across processes
    • Listeners hold no business logic and must not throw into the main loop; batch model:delta on a 50ms window