逐日AI

面试题库

共 328 题,当前筛选 3 题。

14 天用 Agent 搭一条 AI 短剧生产线

D8 工作流引擎:把流水线做成可断点续跑的任务图

  • 怎么让一个会调用付费接口的生成节点是幂等的?缓存键里该放什么、不该放什么?How do you make a node that calls a paid generation API idempotent? What belongs in the cache key and what does not?
    国内高频海外高频进阶#idempotency#caching#workflow-engine

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

    1. 这题的区分度全在「不该放什么」那一半。只答「把输入哈希一下」的人,通常没在真实项目里被缓存坑过——缓存的两种病方向相反,一种是永远不命中,一种是命中了不该命中的。
    2. 先给判据:键里应该出现的,是所有会改变产物的东西;不该出现的,是所有每次都会变但不影响产物的东西。这一条能直接推出下面两张清单。
    3. 该放的四样:节点标识、实现版本号、本节点的输入(模型 id、提示词、时长、分辨率)、以及全部依赖的指纹。版本号和依赖指纹是最容易漏的两样——漏了版本号,改完代码读到旧产物;漏了依赖指纹,上游换了剧本你还在用旧的镜头。
    4. 不该放的:运行标识、时间戳、随机数、绝对路径、以及任何带机器名或临时目录的东西。放进去等于每次都是新键,你会以为缓存写坏了,其实是键设计错了。
    5. 还有两条落地细节值得主动说:判断「做没做完」要看磁盘上产物齐不齐,不能只信状态文件,因为文件可能被手删;以及幂等的粒度要想清楚,一个节点里跑四个镜头,第三镜失败就是四镜全重做,粒度更细更省钱但任务图会大很多。
    6. 可预期的追问是「依赖指纹会不会失效得太狠」。答:会。上游只是文案改了、产物其实一样,下游也会跟着重做。更省的做法是对依赖的产物内容做哈希而不是对它的键做哈希,代价是每次都要把产物读一遍——小文件划算,大视频不划算,这是要自己量的一笔账。

    How to reason about it · think before answering

    1. The discriminator is the second half: what must not go in. People who only say 'hash the inputs' have usually never been burned by a cache. The two failure modes point in opposite directions: never hitting, and hitting when it should not.
    2. State the criterion first: include everything that changes the artifact, exclude everything that changes every run without affecting the artifact. Both lists fall out of that.
    3. Include four things: node id, implementation version, this node's own inputs (model id, prompt, duration, resolution), and the fingerprints of all dependencies. The version and the dependency fingerprints are the two people forget — miss the version and new code reads old artifacts; miss the dependencies and an upstream script change never propagates.
    4. Exclude: run id, timestamps, random values, absolute paths, and anything carrying a hostname or temp directory. Any of those makes every key new, and you will blame the cache instead of the key.
    5. Two implementation details worth volunteering: decide 'is it done' by checking the artifacts on disk, not the state file, because files get deleted by hand; and think about granularity — four shots in one node means one failed shot redoes all four, while finer granularity saves money at the cost of a much larger graph.
    6. Expect the follow-up 'does hashing dependency keys over-invalidate'. Yes. An upstream wording change that produces an identical artifact still invalidates downstream. Hashing the dependency's artifact content instead is tighter but requires reading the artifact every time — worth it for small files, not for large videos.

    答题要点

    • 判据一句话:会改变产物的进键,每次都变但不影响产物的不进键。
    • 必放四样:节点标识、实现版本号、本节点输入、全部依赖的指纹。
    • 禁放:运行标识、时间戳、随机数、绝对路径与机器相关信息。
    • 命中判定看磁盘上产物是否齐全,不能只信状态文件。
    • 幂等粒度要显式选择:节点粒度实现简单,镜头粒度更省钱但图更大。

    Key points

    • One criterion: include what changes the artifact, exclude what changes every run without affecting it.
    • Must include: node id, implementation version, the node's own inputs, and all dependency fingerprints.
    • Must exclude: run id, timestamps, random values, absolute paths and host-specific data.
    • Decide cache hits by checking artifacts on disk, not by trusting the state file.
    • Choose the idempotency granularity explicitly: per node is simpler, per shot saves more but grows the graph.
  • 要支持断点续跑,你需要持久化哪些状态?只存每个节点的完成状态够不够?What state must you persist to support resuming a workflow? Is per-node completion status enough?
    国内高频海外高频深入#workflow-engine#state-persistence#resume

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

    1. 题眼在「够不够」三个字,它在暗示你答案是不够。只存完成状态的系统,重跑时只知道「这个节点做过」,却答不出「做的是哪一版」——于是改完代码重跑,它照样跳过。
    2. 拆的角度是:续跑要回答三个问题。哪些节点做完了?它们做的是不是我现在要的那一版?它们的产物还在不在?三个问题分别对应三样要持久化的东西。
    3. 所以除了状态,还要存指纹和产物位置。指纹回答「是不是同一版」,产物位置回答「东西还在不在」。本课的做法是把产物按指纹落进内容寻址的目录,这样第三个问题退化成一次文件存在性检查,连记都不用记。
    4. 还要区分两层:产物缓存是全局的,跨运行共享,它提供的是幂等;节点状态是每次运行一份,它提供的是断点续跑。混成一层的话,换个运行标识就得重花一次钱。
    5. 落盘时机也是这题的一部分:状态必须在每个节点跑完之后立刻写,而不是整个流程结束再写一次。进程被强杀、机器掉电、容器被驱逐,在跑十几分钟的视频任务时并不罕见。
    6. 可预期的追问是「失败节点的残产物要不要删」。答:不删。留着它,下一次跑到这里判断产物齐不齐就直接得到结论;但判定必须是「outputs 里每个文件都在」才算命中,缺一个就重做,否则残产物会被当成成功的。

    How to reason about it · think before answering

    1. The words 'is it enough' hint that it is not. A system storing only completion status knows a node ran, but not which version ran, so it happily skips after you change the code.
    2. Frame it as three questions a resume must answer: which nodes are done, are they the version I want now, and are their artifacts still there? Each maps to something you must persist.
    3. So beyond status you need the fingerprint and the artifact location. The fingerprint answers 'same version?', the location answers 'still there?'. Storing artifacts in a content-addressed directory named by the fingerprint collapses the third question into a file-existence check.
    4. Also separate two layers: the artifact cache is global and shared across runs, providing idempotency; node state is per run, providing resume. Collapse them and a new run id costs you full price again.
    5. Write timing is part of the answer: persist state right after each node completes, not once at the end. Hard kills, power loss and container eviction are not rare during ten-minute video jobs.
    6. Expect the follow-up 'do you delete a failed node's partial artifacts'. No. Keep them, and make the hit condition 'every declared output exists'. Missing one means redo, so partials are never mistaken for success.

    答题要点

    • 只存完成状态不够,还要存指纹和产物位置,分别回答「哪一版」和「还在不在」。
    • 产物按指纹落进内容寻址目录后,「还在不在」退化成一次文件存在性检查。
    • 两层分开:缓存全局共享提供幂等,节点状态每次运行一份提供断点续跑。
    • 状态要在每个节点跑完后立刻落盘,不能等整个流程结束再写。
    • 失败节点的残产物保留,但命中判定必须是全部产物齐全才算数。

    Key points

    • Completion status alone is not enough: persist the fingerprint and artifact location to answer 'which version' and 'still present'.
    • Content-addressed artifact directories reduce 'still present' to a file-existence check.
    • Keep two layers: a global cache for idempotency, per-run node state for resume.
    • Persist state immediately after each node, not once at the end of the run.
    • Keep failed nodes' partial artifacts, but only count a hit when every declared output exists.
  • 什么时候该自己写调度,什么时候该直接上现成的工作流引擎?When should you write your own scheduler, and when should you adopt an off-the-shelf workflow engine?
    国内高频海外高频基础#architecture#build-vs-buy#workflow-engine

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

    1. 这题考的是技术选型的成熟度。两个极端都会被扣分:什么都自己写显得不懂杠杆,什么都上框架显得没判断力。面试官想听的是你的切换信号是什么。
    2. 先给一条通用判据:自己写的收益是理解和贴合,框架的收益是省掉你还没遇到的那些问题。所以决策取决于「你现在需要的功能有多少落在框架的核心能力上」。
    3. 自己写划算的情形:单机、节点数是个位数、路径是你定死的、需要的只是拓扑排序加幂等加状态落盘这几件事。这时候自己写不到三百行,而且换来的理解是通用的——你会彻底搞懂幂等键为什么要包含依赖指纹、状态为什么必须每步落盘。
    4. 该换的三个信号:一是开始需要跨机器调度,自己实现分布式调度的复杂度是指数级上升的;二是开始需要人工介入节点,流程要挂起几小时甚至几天,状态必须外置到数据库而不是一个 JSON 文件;三是开始需要给非工程师看和操作,那你需要的其实是一个带界面的产品。
    5. 反过来说,过早引入重型框架的代价很具体:每一个业务改动都要先绕过它的抽象,而它的收益要等规模上来才兑现。这是典型的成本前置、收益后置。
    6. 可预期的追问是「自己写的那一套能不能平滑迁走」。答:能,前提是你从一开始就把节点定义成纯声明(依赖、输入、产物、执行体),调度和状态不侵入业务。这样迁移时改的是引擎,不是六个节点。

    How to reason about it · think before answering

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