Interview Bank
328 questions total; 21 shown with current filters.
22 more tagsShow fewer tags
Build an AI Short-Drama Production Pipeline With Agents in 14 Days
D1 What an AI Short-Drama Production Pipeline Looks Like: Breaking Down the Stages, a Task-Graph Architecture, and Choosing Among Four Categories of Generation Models
Why wrap a vendor SDK in your own provider interface, and when does that layer become a liability?为什么要在厂商 SDK 之上再套一层自己的 provider 接口?什么时候这层反而是负担?
Common in ChinaCommon overseasBasic#provider-abstraction#architectureHow 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.
分析过程 · 先想清楚再作答
- 这题在筛「有没有真的换过一次厂商」。只答「解耦、方便替换」的人,说的是一句所有人都会说的话,区分度在于你能不能给出「这层带来了什么、又赔上了什么」的具体清单。
- 怎么拆:先问自己「如果不套这层,哪些能力会散掉」。答案有三样,而且都能落到具体文件上——离线可跑(网络出口收敛到一处才可能打桩)、多厂商并存(业务代码写的是动作而不是某家的四步流程)、计量收口(每次调用的花费必须有唯一一处记账)。
- 接着说抽象的位置:接口要按业务动作定义,不按厂商的 HTTP 请求定义。异步视频任务的提交、轮询、取件、下载四步,对业务代码来说是一个 generate;把这四步漏到业务层,抽象就白做了。
- 结论与代价:这层会磨掉各家的独有能力(某家支持首尾帧、某家支持结构化运镜参数)。正确处理不是把接口撑大,而是留一个可选透传字段,让需要它的那一处显式承认自己绑定了某一家。
- 什么时候是负担:你只会用一家、也永远不会离线跑的时候;以及出现两个信号时——为加一个厂商改了接口签名让另外三个实现跟着改,或者接口里出现了只有一家有的参数名。这两个信号说明抽象抽在了厂商能力的最小公倍数上,位置错了。
- 可预期的追问:那要不要直接用某个统一网关或聚合 SDK?可以,但你仍然需要自己的接口,因为聚合层解决的是协议差异,解决不了你自己的落盘契约与记账口径。
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
答题要点
- 三个理由要说具体:离线可跑、多厂商并存、计量收口,每一个都对应一处真实代码
- 接口按业务动作定义,异步任务的提交轮询取件下载四步必须关在实现里
- 把落盘路径写进接口契约,因为厂商返回的图片与视频链接都是会失效的临时链接
- 代价是磨掉独有能力,用可选透传字段处理,而不是撑大公共接口
- 两个「抽错了」的信号:加厂商要改签名、接口里出现厂商专有参数名
What does modeling a multi-step generation pipeline as a task graph buy you over a chain of sequential awaits, and what does it cost?把一条多步生成流程建成任务图,比一串顺序 await 多拿到了什么?代价是什么?
Common in ChinaCommon overseasIntermediate#task-graph#pipeline-designHow to reason about it · think before answering
- The question is what you gain, not what a DAG is. Reciting the definition scores nothing; name three capabilities the sequential version cannot have, each with a concrete scenario.
- Break it down by inverting the three pains of sequential code. First, parallelism is expressed by the graph itself — voice-over depends only on the lines, yet a sequential run queues it behind forty video jobs. Second, resumability — each node writes artifacts to a fixed path, so shot 37 failing does not destroy the first 36. Third, observability — you can say which node is stuck, not merely that some await is pending.
- Add the higher-signal point: cycle detection. Topological sort throws when dependencies form a cycle, and that is the only thing enforcing the acyclic part. Without it, a wrong dependency silently skips a step or reorders execution, which is painful to debug.
- Conclusion and cost: a task graph is not free. Every node needs a declared input and output artifact set, otherwise the graph is decorative. That artifact contract is also the precondition for idempotency and resume later on.
- Likely follow-up: should you adopt a workflow engine instead? Judge by node count and failure rate — worth it at a dozen-plus nodes with high failure and human review; for three to five nodes a hand-written graph plus topological sort is cheaper than another system to operate.
分析过程 · 先想清楚再作答
- 这题的题眼在「多拿到了什么」,不在「什么是 DAG」。背出有向无环图定义的人拿不到分,答对的人会给出三样顺序版拿不到的能力,并各配一个具体场景。
- 怎么拆:把顺序版的三个痛点倒过来说。第一,并行的可能性被图结构直接表达——配音只依赖台词、和画面无关,顺序版里它却要排在四十次视频生成后面。第二,有断点——每个节点的产物落在磁盘固定位置,第三十七个镜头失败时前三十六个还在。第三,可观测——你能回答「现在卡在哪个节点」,顺序版只能回答「卡在某个 await」。
- 补一条区分度更高的:环检测。拓扑排序在发现依赖成环时抛错,这是「无环」两个字唯一的执行者;没有它,依赖写错只会表现成漏跑一步或者顺序错乱,非常难查。
- 结论与代价:任务图不是免费的,你必须为每个节点定义清楚输入产物与输出产物,否则它只是一张漂亮的依赖声明。这份产物契约同时也是后面做幂等与断点续跑的前提。
- 可预期的追问:那是不是应该直接上工作流引擎?判据是节点数与失败率——十几个节点、失败率高、需要人工介入时才值得;三五个节点的流程用一张手写的图加拓扑排序就够,引入引擎反而多一套要运维的东西。
Key points
- Three things sequential code cannot give: parallelism expressed by structure, resumability after failure, and knowing which node is stuck
- Topological sort also detects cycles, the only mechanism enforcing the acyclic property
- The cost is declaring input and output artifacts per node; without that the graph is decorative
- That artifact contract is the precondition for idempotency and resume
- Adopt a workflow engine based on node count and failure rate; a hand-written graph wins for three to five nodes
答题要点
- 三样顺序版拿不到的:并行由图结构表达、失败后有断点、能说清卡在哪个节点
- 拓扑排序顺带做环检测,这是「有向无环」里「无环」的唯一执行者
- 代价是必须为每个节点声明输入产物与输出产物,否则图只是装饰
- 这份产物契约同时是后续做幂等与断点续跑的前提
- 上不上工作流引擎按节点数与失败率判断,三五个节点手写图更划算
For a system that depends heavily on paid third-party generation APIs, how do you make it developable and testable without keys — and how do you prove the offline mode is not fooling you?一个重度依赖付费第三方生成接口的系统,怎么做到没有密钥也能开发和测试?怎么证明这套离线模式没有骗自己?
Common in ChinaCommon overseasDeep dive#offline-testing#test-strategyHow to reason about it · think before answering
- All the signal is in the second half. Everyone says mock it; only people who have done it can say how they prove the mock is honest, because most mocks only guarantee the program does not crash.
- Break it down by first fixing where the stub goes: only at the network egress, inside each provider's one method. No environment check belongs in business code — the moment business logic branches, offline runs a different program and your testing says nothing about production.
- Then fix the quality of the stub: the offline implementation should emit artifacts of the real shape rather than a constant. For a media pipeline, actually generate placeholder files locally (solid-color frames, a test pattern with an audio track, a sine-wave clip); for retrieval, return well-formed fake documents; for streaming, emit chunks with realistic pacing. The point is to force downstream parsing, state machines, and timeline math to execute.
- The one test that proves it is honest: change an input and the output must change. Placeholder color tracks the shot description, placeholder audio length tracks the line length, total runtime tracks shot count. If every input yields identical artifacts, you only verified that nothing crashed.
- State the payoff too: a real run costs tens of minutes and real money, so an off-by-one takes half an hour to surface. Offline collapses that loop to seconds, which is what makes continued refactoring affordable. This is an engineering requirement, not a toy.
- Likely follow-up: who then covers the real path? Layer it — offline covers business logic and regression, while a small set of smoke tests exercises the real vendors on a schedule. They verify different things and do not substitute for each other.
分析过程 · 先想清楚再作答
- 这题的区分度全在后半句。前半句人人都会答「打 mock」,能答出「怎么证明它没骗自己」的才是真做过——因为绝大多数 mock 的实际效果是「保证程序不崩」,而不是「保证逻辑正确」。
- 怎么拆:先定桩的位置。桩只打在网络出口上,也就是每个 provider 的那一个方法里;业务代码里一个环境变量判断都不该有。一旦业务逻辑分叉,离线跑的就是另一个程序,你验的东西和线上没关系。
- 再定桩的质量:离线实现要产出真实形态的产物,而不是返回一个常量。做媒体流水线就用本地工具真的生成占位文件(纯色图、测试画面加音轨、正弦波音频),做检索就返回结构完整的假文档,做流式就按节奏一段段吐。目的是让下游的解析、状态机、时间轴计算真的被执行一遍。
- 证明它没骗自己的判据只有一条:**改一个输入,输出必须跟着变**。占位图的颜色随镜头描述变、占位音频时长随台词字数变、总时长随分镜数变——这说明中间的业务逻辑跑过了。如果换什么输入产物都一样,你验的只是没崩。
- 还要说收益:一次真跑几十分钟、上百块钱,一个下标写错就要等半小时才看得到;离线把这个反馈循环压到几秒,团队才会愿意持续重构这段代码。这是工程要求,不是玩具。
- 可预期的追问:那真实路径谁来保证?答案是分层——离线模式覆盖业务逻辑与回归测试,真实路径靠少量的冒烟用例定期跑,两者验的是不同的东西,不能互相替代。
Key points
- Stub only at the network egress; business code contains no offline branch
- The offline implementation must emit real-shaped artifacts so downstream parsing, state machines, and timeline math actually run
- The single acceptance test is that changing an input changes the output; otherwise you only verified it did not crash
- The payoff is collapsing a tens-of-minutes, real-money feedback loop into seconds, which is what makes refactoring affordable
- Cover the real path with a small scheduled smoke suite; it verifies something different from the offline mode
答题要点
- 桩只打在网络出口,业务代码里不出现任何离线判断分支
- 离线实现要产出真实形态的产物,让下游解析、状态机、时间轴计算真的执行
- 唯一的验收判据是「改一个输入,输出跟着变」,做不到就只验了没崩
- 收益是把几十分钟上百块的反馈循环压到几秒,团队才敢持续重构
- 真实路径靠少量定期冒烟用例覆盖,与离线模式验的是不同的东西
D2 The Script Agent: Turning a Single Sentence Into Structured Data — Character Cards, Scenes, and Shots
How do you get a model to emit valid structured data reliably, and what do you do when schema validation fails?怎么让模型稳定输出合法的结构化数据?schema 校验失败时你会怎么处理?
Common in ChinaCommon overseasBasic#structured-output#schema-validationHow to reason about it · think before answering
- The real question is the second half. Answering only use JSON mode signals you have never run this in production, because all the work happens after validation fails.
- Lay out three paths: prompt constraints plus local validation; a vendor's JSON mode or structured-output parameter; or defining the data structure as a tool's parameter schema. Vendor support and field names differ, so the latter two bind that code to one vendor.
- State the selection rule: cross-vendor or offline-capable means path one, paying with your own JSON extraction and validator; single-vendor and success-rate-driven means use their structured output. Extraction must handle code fences and surrounding chatter — parsing the whole reply directly breaks often.
- Handle failure as a ladder, not just a retry: feed the path-annotated issues back and ask it to fix only those (more effective than upgrading the model); then degrade to a minimal required-fields-only structure; then fail the round and persist the artifact for a human — never swallow the error and return an empty array.
- High-signal point: validate in two layers. Type and range checks catch malformed data but not wrong references — a nonexistent scene id or a duplicate shot number passes typing and explodes downstream. Referential integrity needs its own pass.
- Likely follow-up: how many retries? Two. The first covers a disobedient model; if it still fails with concrete issues in hand, the prompt or the schema itself is wrong and more retries just buy the same error.
分析过程 · 先想清楚再作答
- 这题的题眼在后半句。前半句答「用 JSON 模式」就结束的人,等于说自己没在生产里跑过——真正的活儿全在校验失败之后。
- 先把三条路摆开:提示词约束加本地校验;厂商提供的 JSON 模式或结构化输出参数;把数据结构定义成工具的参数 schema 让模型去调。各家对后两条的支持程度和字段名都不一样,选它就等于把这段代码绑在某一家上。
- 给出选择依据:要跨厂商、要能离线跑,就选第一条,代价是自己写抠 JSON 与校验;只服务一家且追求成功率,就用那一家的结构化输出。抠 JSON 这一步必须处理围栏与前后寒暄,直接解析整段回复在真实模型上很容易炸。
- 校验失败的处理是一条阶梯,别只答重试:把带路径的问题原样喂回去让它只修这些(比换更大的模型有效);仍不过就降级到只要必填字段的最小结构;再不过就整轮失败并留档,让人来看,而不是吞掉异常返回一个空数组。
- 还有一条区分度很高:校验要分两层。判类型与范围只能挡住格式错,挡不住写错对象——引用了不存在的场景 id、镜号重复,这类稿子能通过类型检查,然后在下游某一步才爆。引用完整性必须单独查一遍。
- 可预期的追问:重试几次合适?两次。第一次是模型没听话,第二次带着具体问题还改不对,说明是提示词或 schema 本身有问题,再重试只是花钱买同一个错误。
Key points
- Three paths: prompt plus local validation, vendor structured output, or tool parameter schema — the latter two bind you to a vendor
- JSON extraction must handle code fences and surrounding prose; never parse the whole reply directly
- Failure handling is a ladder: feed back path-annotated issues, degrade to a minimal structure, then fail the round and persist for a human
- Validate in two layers — types and ranges, then referential integrity and id uniqueness
- Cap retries at two; beyond that the prompt or schema is wrong, not luck
答题要点
- 三条路:提示词加本地校验、厂商结构化输出参数、工具参数 schema,后两条会绑定厂商
- 抠 JSON 要处理围栏与前后寒暄,不能直接解析整段回复
- 失败处理是阶梯:带路径的问题喂回去只修这些、降级到最小结构、整轮失败留档给人
- 校验分两层,类型与范围之外必须单独查引用完整性与 id 唯一性
- 重试上限两次,再不过说明是提示词或 schema 的问题,不是运气问题
In a generator-plus-reviewer loop, how do you define convergence so it does not burn budget indefinitely?生成加评审这种双角色循环,收敛条件该怎么定才不会一直烧钱?
Common in ChinaCommon overseasDeep dive#agent-loop#cost-controlHow to reason about it · think before answering
- This screens whether you have ever made such a loop actually terminate. Answering only set a max round count scores nothing — that prevents an infinite loop, it is not convergence design. The signal is naming three exits plus how the reviewer itself is built.
- Start with the reviewer: it should not be one model but two layers. Machine-checkable defects (missing fields, out-of-range numbers, length limits, invalid references) go to code; only the judgment calls go to the model. This decides score stability — a pure-model reviewer can swing by ten-plus points on the same draft, and then convergence is meaningless.
- Then the three exits: stop on threshold (the threshold means good enough, not perfect — chasing the last few points costs far more than it returns); stop at the round cap, handing back the highest-scoring draft rather than the last one, because review scores fluctuate; and escalate to a human once only judgment-call issues remain, since a model reviewing and revising itself just circles.
- Also cover the scoring weights: hard defects should dominate, say seventy percent, with the model's soft score at thirty. Otherwise one flattering model review outweighs five real field errors and the loop declares success on round one.
- Conclusion and cost: all three exits need parameters, and parameters need empirical tuning. Too high a threshold burns every round; too low ships an unusable draft. Plot the score curve before shipping and confirm it rises monotonically.
- Likely follow-up: how do you know it is improving rather than oscillating? Track the hard-defect count — it is deterministic, while the score jitters. If hard defects do not fall, the writer is not acting on feedback, and the fix is feedback granularity: tag each issue with a category so the model knows which class to repair.
分析过程 · 先想清楚再作答
- 这题在考「你有没有让这种循环真的停下来过」。只答「设一个最大轮数」拿不到分,那只是防死循环,不是收敛设计。区分度在于你能不能说出三个出口以及评审本身该怎么构造。
- 先拆评审:评审不该是一个模型,而是两层——能被程序判定的硬伤用代码查(字段缺失、数值越界、长度超限、引用不合法),程序判不了的软伤才交给模型。这一步决定了分数稳不稳定:全交给模型,同一份稿子两次评分能差十几分,循环就没有收敛可言。
- 再说三个出口:达标就停(阈值是「够用」不是「完美」,追最后几分成本远高于收益);到轮数上限就停,而且要交出历史最高分那一稿而不是最后一稿,因为评审有波动;剩下的问题全是软伤时转人工,因为让模型自己评自己改只会原地打转。
- 还要说计分方式:硬伤应该占大头(比如七成),软分占小头。否则模型一句好评就能盖过五条实打实的字段问题,循环会在第一轮就假装达标。
- 结论加代价:三个出口都需要参数,而参数必须实测调。阈值高了轮数用满,低了稿子不能看;上限大了烧钱,小了永远差一口气。上线前要把分数曲线画出来看它是不是单调上升。
- 可预期的追问:怎么知道循环真的在变好而不是在抖动?看硬伤条数,它是确定性的;分数会抖,硬伤条数不会。硬伤降不下去就说明写手根本没在按意见改,问题出在意见的粒度上——意见要带分类标签,模型才知道该改哪一类。
Key points
- Split the reviewer: code judges hard defects, the model judges only judgment calls — otherwise scores are unstable and nothing converges
- Three exits: stop on threshold, stop at the round cap returning the best draft, escalate to a human when only soft issues remain
- Weight hard defects heavily so a flattering model review cannot mask real field errors
- Tag each review issue with a category so the writer repairs one class at a time
- Measure convergence by hard-defect count, not score — the score jitters, the count does not
答题要点
- 评审分两层:硬伤用代码判,软伤才交给模型,否则分数不稳定、循环无从收敛
- 三个出口:达标就停、到轮数上限交历史最高分那一稿、只剩软伤时转人工
- 计分让硬伤占大头,避免模型一句好评盖过实打实的字段问题
- 评语必须带分类标签,写手才能只改那一类,改稿才是收敛的
- 观测收敛看硬伤条数而不是分数,分数会抖、硬伤条数是确定的
To keep character definitions consistent across many episodes, where do you store that state and how do you use it?多集内容要保持人物设定一致,你会把这份设定放在哪、怎么用?
Common in ChinaCommon overseasIntermediate#state-management#consistencyHow to reason about it · think before answering
- The crux is that models have no memory. Answering just concatenate previous episodes into the context invites a fatal follow-up: context grows linearly with episode count, so by episode five you pay repeatedly for four full episodes, and the model may still miss details.
- Break it down by separating what is invariant across episodes from what is recomputed each time. Invariant: the world, each character's appearance, personality, voice id, and a few hard rules. Recomputed: scenes and shots. Extract the invariant part into its own file and load it verbatim before generating each episode.
- Add the commonly missed point: the fields in that file are not only lore, they are downstream input parameters. Appearance text goes straight into image prompts, the voice id goes straight into the speech API. Keeping them beside the name means consistency is solved in one file rather than restated in three places.
- Choose the storage boundary by write frequency: the profile is written once and read many times, while the shot list is rewritten on every run. Mixing lifetimes in one file makes it impossible to rerun one episode without disturbing the others.
- Conclusion and cost: the profile itself can drift. Change a character's appearance mid-season and previously generated assets no longer match, so version the profile and include that version in the asset cache key — editing the profile then invalidates exactly the affected assets. That is only possible because it lives on its own.
- Likely follow-up: should you use a vector store? Usually not. Cross-episode canon is small, structured, and must be injected in full; retrieval risks dropping the one line that matters. Retrieval fits large corpora where only a few relevant items are needed.
分析过程 · 先想清楚再作答
- 这题的题眼是「模型没有记忆」。答成「把前一集的输出拼进上下文」的人会被追问到崩——上下文会随集数线性膨胀,第五集时你在为前四集的全文反复付费,而且模型仍然可能漏读。
- 怎么拆:先分辨哪些是「跨集不变」的,哪些是「每集重算」的。不变的是世界观、人物外貌、性格、音色与几条硬规则;每集重算的是场景与分镜。把不变的那部分抽成单独的档案文件,每一集生成前原样读进去。
- 接着说一个容易被忽略的点:档案里的字段不只是设定,还是**下游的输入参数**。外貌描述要原样进图像提示词,音色 id 要原样进语音接口。所以它们必须和名字放在同一份档案里,一致性问题才是在一个文件里解决的,而不是散在三处各写一遍。
- 存放位置的判据是写入频率:档案一次生成、多次读取,分镜每跑一次就重写。生命周期不同的数据放同一个文件,你就没法只重跑一集而不动其他集。按写入频率切分文件,是这类流水线最省事的一条习惯。
- 结论与代价:档案本身也会漂——中途改了人物外貌,之前生成的资产就对不上了。所以档案要有版本,且资产的缓存键要包含档案版本,改档案等于让相关资产失效。这条也是把它单独存放才做得到的。
- 可预期的追问:那要不要上向量库做检索?多数情况下不需要。跨集共享的设定是**有限的、结构化的、必须全量注入的**,检索反而可能漏掉关键一条。检索适合的是「素材库很大且只需要相关几条」的场景。
Key points
- Models are stateless; cross-episode consistency comes from an external profile, not from stuffing prior episodes into context
- Split by invariant versus recomputed: world and character profiles persist, scenes and shots are regenerated per episode
- Appearance text and voice id are downstream input parameters, so they belong beside the character's name
- Split files by write frequency — a read-mostly profile versus a rewritten shot list — or you cannot rerun one episode alone
- Version the profile and fold that version into the asset cache key so edits invalidate exactly the affected assets
答题要点
- 模型没有记忆,跨集一致性靠外部档案而不是把前几集拼进上下文
- 按「跨集不变」与「每集重算」切分:世界观与人物卡是档案,场景与分镜每集重来
- 档案里的外貌与音色 id 同时是下游的输入参数,所以必须和名字放在一起
- 按写入频率切分文件,档案读多写少,分镜每次重写,混在一起就没法只重跑一集
- 档案要有版本并进资产缓存键,改设定才能精确地让相关资产失效
D3 Character Consistency: Character Sheets, Reference Images, and Style Locking — Keeping the Same Person the Same Person in Every Shot
Where does the character consistency problem in image generation come from, and what engineering mitigations exist, with what trade-offs?生成模型的角色一致性问题是怎么来的?工程上有哪几种缓解手段,代价分别是什么?
Common in ChinaCommon overseasBasic#image-generation#consistencyHow to reason about it · think before answering
- The differentiator is your first sentence. Saying 'the prompt wasn't detailed enough' reads as a user, not an engineer; the answer they want is that each request is an independent sample with no memory across calls.
- Follow the mechanism: a prompt only constrains the degrees of freedom you actually wrote down, and everything unwritten gets re-sampled — while face recognizability lives exactly in the details text cannot exhaust.
- Present the mitigations in three layers by what each one actually locks: a prompt template locks style and framing at near-zero cost; a fixed seed locks reproducibility for one identical prompt and stops helping the moment the prompt changes; a reference image locks the face, but only one per request, so two faces in one frame cannot both be locked.
- The trade-off discussion is where candidates separate: using a reference image means you must first produce a base image, which forces a human 'pick the reference sheet' step into an otherwise unattended pipeline.
- Volunteer the counter-intuitive rule: every derived image must reference the same base image, never the previous one. Chaining references accumulates drift, and by the fifth image it is a different person.
- Expect the follow-up: what if consistency still fails? The answer is cinematography — split two-character frames into reverse-angle singles and push secondary characters to wider shots, working around the API's limits with shot design.
分析过程 · 先想清楚再作答
- 这题的区分度在第一句。答「提示词写得不够细」就掉到了使用者视角;面试官想听的是「模型每次请求都是独立采样、没有跨请求记忆」这个机制层面的原因。
- 顺着机制往下推就有了完整答案:提示词只约束了你写出来的那些自由度,没写的部分每次重新掷一遍;而人脸的辨识度恰好集中在脸型、眼距、鼻梁这些你没法用文字穷尽的细节上。
- 手段按「锁得住什么」分三层说,不要混在一起:提示词模板锁风格与构图,成本几乎为零;随机种子锁同一提示词的可复现性,换提示词即失效;参考图锁人脸,但每次请求只能带一张,双人同框锁不了两个人。
- 代价这一段才是拉开差距的地方:参考图要求你先有一张基准图,于是流程里必须插入一次「定妆并由人挑一张」的环节,这是整条自动化流水线上少数值得保留的人工卡点。
- 还要主动说一个反直觉的做法:派生图必须都参考同一张基准图,不能参考上一张。参考上一张会让偏差逐张累积,第五张已经不是同一个人了。
- 可以预期的追问:一致性做不到怎么兜底?答案是改镜头语言——把双人同框拆成正反打的单人镜头、次要角色用更远的景别,用拍法回避接口能力的边界。
Key points
- The root cause is that each request is an independent sample with no cross-request memory, so unconstrained degrees of freedom get re-rolled
- A prompt template locks style and framing at near-zero cost but cannot lock facial detail
- A fixed seed locks reproducibility for one identical prompt and stops helping once the prompt changes
- A reference image locks the face, but you must first produce a base image and only one reference is allowed per request
- Derive every variant from the same base image rather than chaining off the previous one, or drift accumulates image by image
答题要点
- 根因是模型每次请求独立采样、没有跨请求记忆,提示词没约束到的自由度会被重新掷一遍
- 提示词模板锁风格与构图,成本几乎为零,但锁不住五官
- 随机种子锁的是同一提示词的可复现性,提示词一变就失效
- 参考图锁人脸,代价是必须先有基准图,且每次请求只能带一张,双人同框锁不了两个人
- 派生图统一参考同一张基准图,不要链式参考上一张,否则偏差会逐张累积
Does fixing the random seed solve character consistency? What does a seed actually lock?固定随机种子能解决角色一致性吗?它到底锁住了什么?
Common in ChinaCommon overseasIntermediate#image-generation#reproducibilityHow to reason about it · think before answering
- This is a yes/no trap dressed as a concept question; answering 'yes' ends it. The hinge is 'what does it actually lock' — they are testing whether you separate reproducibility from consistency.
- Define it first: a seed is the random starting point of sampling. With the model, prompt and other parameters unchanged, the same seed returns the same image, so what it locks is reproducibility.
- Then explain why that is not enough here: every shot has a different prompt because action, scene and shot size all change. Change the prompt and the sampling path changes with it, so the same seed yields a different person. A seed is a reproducibility switch, not a consistency switch.
- Do not dismiss it though. It earns its place twice: single-variable debugging, where you change one word and watch the image move; and stacked with a reference image, where the reference holds the face and the seed holds the remaining degrees of freedom so a whole set looks shot on the same day.
- One production note: for a seed to actually reproduce anything, turn the prompt optimizer off. It defaults to on, rewrites your prompt server-side, and you never see the rewrite — which destroys reproducibility.
- Expect the follow-up: is seed semantics the same across vendors? No guarantee — switching vendor or even model version can make the same seed produce something else, which is one more reason to keep a provider abstraction layer.
分析过程 · 先想清楚再作答
- 这是一道判断题伪装成的概念题,答「能」直接出局。题眼是「到底锁住了什么」——面试官在测你有没有把复现和一致这两件事分开。
- 先给定义:seed 是采样的随机起点。在模型、提示词、其余参数都不变的前提下,同一个 seed 会给出同一张图,所以它锁住的是**可复现性**。
- 再说为什么在短剧场景里不够用:每一镜的提示词天然不同,动作、场景、景别都在变。提示词一变,采样路径就换了,同一个 seed 出来的是完全不同的人。所以 seed 是复现开关,不是一致性开关。
- 但不要把它说成没用。它在两个地方非常值钱:调试时做单变量对照,只改一个词看画面怎么变;以及跟参考图叠加使用,参考图管脸,seed 管其余自由度的采样起点,两者一起才让整组图像同一天在同一个棚里拍的。
- 生产视角补一句:想让 seed 真的可复现,必须把提示词优化开关关掉。那个开关默认是开的,它会在服务端改写你的提示词,改写结果你看不到,可复现性也就没了。
- 可以预期的追问:那不同厂商的 seed 语义一样吗?答案是不保证,换厂商甚至换模型版本都可能让同一个 seed 出别的图,所以 seed 不能作为跨厂商的一致性依据——这也是要有一层 provider 抽象的原因之一。
Key points
- No. A seed locks reproducibility: same model, same prompt, same other parameters plus same seed returns the same image
- Every shot in a drama has a different prompt, and a changed prompt voids the seed, so it is not a consistency mechanism
- Its real value is single-variable debugging, and stacking with a reference image — the reference holds the face, the seed holds the rest
- For a seed to reproduce anything you must disable the server-side prompt optimizer, which is on by default and rewrites your input
- Seed semantics do not carry across vendors or model versions, so a seed cannot underpin cross-provider consistency
答题要点
- 不能。seed 锁的是可复现性:模型、提示词与其余参数都不变时,同一个 seed 给出同一张图
- 短剧每一镜的提示词天然不同,提示词一变 seed 就失效,所以它不是一致性手段
- 它真正的用处是单变量调试,以及与参考图叠加——参考图管脸,seed 管其余自由度的采样起点
- 要让 seed 可复现,必须关掉服务端的提示词优化开关,它默认开启且会改写你的输入
- seed 语义不跨厂商也不跨模型版本,不能作为跨 provider 的一致性依据
How would you design the cache key for reusing generated assets so that you save money without serving the wrong asset?生成类资产要做复用,缓存键你会怎么设计,才能既省钱又不会串戏?
Common in ChinaCommon overseasDeep dive#caching#cost#image-generationHow to reason about it · think before answering
- This question is about two kinds of cache error with wildly asymmetric cost. A miss only costs money; a wrong hit puts last episode's prop into this one. The first is a number, the second is a content incident.
- The derivation is one sentence: the key must be computed from every input that changes the artifact, and nothing else. Include something irrelevant, like the output path, and one directory refactor invalidates everything and you pay again; omit something relevant, like the prompt, and a changed description silently serves the old image.
- Concretely, hash the asset kind, the owning entity id, the variant name, the full prompt, the reference image identity and the seed. Take a short digest as the id, and store those fields verbatim in the metadata so any artifact can be reproduced.
- Then name the boundaries yourself: does the model id and version belong in the key? Yes. What if the style template changes? It is part of the prompt, so it invalidates everything by construction — which is why templates should carry a version number, letting you choose the blast radius.
- One more production note: never cache failed generations, or you will faithfully reuse an empty result that safety review rejected. Cache hits also belong in the cost ledger, flagged as hits, otherwise you cannot report how much caching saved.
- Expect the follow-up: should the cache expire? Content assets usually should not expire on time; invalidate explicitly by version instead, because a time-based expiry regenerates a whole episode at the least convenient moment.
分析过程 · 先想清楚再作答
- 这题考的是缓存的两类错误,而且两类的代价完全不对称。少命中只是多花钱,错命中会把上一集的道具塞进这一集——前者可量化,后者是内容事故。
- 推导链只有一句:**键必须由所有会改变产物的输入算出来,一项不多一项不少。** 多算了不该算的(比如输出路径),改一次目录结构缓存全部失效,白花一遍钱;少算了该算的(比如提示词),换了描述还命中老图,就是串戏。
- 落到这个场景,参与哈希的是:资产类别、归属对象、变体名、完整提示词、参考图标识、随机种子。用 sha1 之类取个短摘要当 id,元数据里再把这几项原样存一份,出问题能照着复现。
- 然后主动把边界说清楚,这是加分项:模型 id 与版本要不要进键?要。风格模板改了怎么办?它是提示词的一部分,进键之后天然全部失效——所以模板要谨慎改,或者给它一个版本号,让你能决定失效的范围。
- 生产视角还有一条:失败的生成不要写进缓存,否则你会稳定复用一张被审核拦下的空结果。命中缓存的那条路径也要记台账并标成命中,不然你算不出缓存到底省了多少钱。
- 可以预期的追问:缓存要不要过期?答案是内容型资产通常不设时间过期,而是靠版本号显式失效;时间过期会在你毫无预期的时候让一整集重新生成一遍。
Key points
- Derive the key from everything that changes the artifact: asset kind, owner id, variant, full prompt, reference image identity, seed, plus model id and version
- Keep output paths and filenames out of the key, or one directory refactor invalidates the whole cache and you pay twice
- Omitting inputs like the prompt causes wrong hits, which are content incidents and far costlier than misses
- Store the hashed fields verbatim in metadata so any artifact is reproducible, and never cache failed generations
- Record cache hits in the cost ledger flagged as hits, and invalidate explicitly by version rather than by time
答题要点
- 键由所有会改变产物的输入算出:资产类别、归属对象、变体名、完整提示词、参考图标识、随机种子,再加模型 id 与版本
- 不要把输出路径或文件名放进键,改目录结构会让缓存整体失效,白付一遍钱
- 少算提示词这类输入会导致错命中,那是内容事故,代价远高于少命中
- 元数据里原样保存参与哈希的各项,出问题能复现;失败的生成不写缓存
- 命中缓存也要记台账并标成命中,否则算不出缓存省了多少;失效靠显式版本号而不是时间过期
D4 From Shot to Footage: Image-to-Video, Polling Async Tasks, and Retrying Failures
You are asked to implement a client for an asynchronous generation task. Which failure cases would you cover?让你实现一个异步生成任务的客户端,你会考虑哪些失败情况?
Common in ChinaCommon overseasIntermediate#async-task#error-handlingHow to reason about it · think before answering
- The differentiator here is coverage, not code. Answering 'wrap it in try/catch and retry' usually means you have never run this kind of API in production.
- Describe the shape first so the failures have somewhere to hang: submit and get an id, poll for status, retrieve a URL, download to disk — four steps, four families of failure.
- Then enumerate: at submit, rate limiting, auth failure, invalid parameters, content moderation; at poll, the query endpoint rate limiting you, a status that never advances, or a terminal failure; at retrieve, a valid id that yields no URL; at download, an expired link, a stream cut halfway, a disk write error.
- Then the two that span the whole flow: timeout and process restart. A timeout is not a failure, it is 'I don't know' — you must look up the idempotency key before resubmitting. A restart means in-memory task ids are gone, so the id has to be persisted before or immediately after the request, or you will have paid-for tasks you can never reclaim.
- Close with a line that shows judgment: of the four steps, only the download is safely retryable on its own; a retry at any other step can create a new billable job.
- Expect the follow-up: if the vendor offers callbacks, do you still poll? Yes. Callbacks get lost to restarts, network blips and unreachable endpoints, so the standard is callback-first with a low-frequency sweep for tasks stuck without a terminal state.
分析过程 · 先想清楚再作答
- 这题的区分度不在代码,在你能列出多少种失败。只答「加个 try catch 和重试」的人,通常没在生产上跑过这类接口。
- 先把任务的形状说清楚,失败点才有地方挂:提交拿标识、轮询查状态、取件换地址、下载落盘,四步是四类不同的失败。
- 然后逐步列:提交阶段有限流、鉴权、参数无效、内容审核;轮询阶段有查询接口自己限流、状态一直不前进、任务返回失败终态;取件阶段有标识存在但取不到地址;下载阶段有地址过期、下到一半断流、写盘失败。
- 接着说横跨全程的两类:超时与进程重启。超时的关键在于它不是失败而是「不知道成没成」,必须先按幂等键查一遍再决定要不要重提;进程重启意味着内存里的任务标识没了,所以标识必须先落盘再发请求,否则你会有一批花了钱却找不回来的任务。
- 最后给一句能体现工程判断的话:这四步里只有下载是可以无脑重试的,其余每一步的重试都可能产生一次新的计费。
- 可以预期的追问:厂商提供回调了还需要轮询吗?需要。回调会因为服务重启、网络抖动、地址不可达而丢失,生产上的标准做法是回调为主、低频轮询兜底扫描长时间没有终态的任务。
Key points
- Break failures down by the four steps: submit (rate limit, auth, invalid params, moderation), poll (query rate limit, stalled status, terminal failure), retrieve (no URL), download (expired link, cut stream, disk error)
- A timeout means unknown, not failed: look up the idempotency key for an existing artifact before resubmitting, or you pay twice
- Persist the task id promptly so in-flight tasks survive a process restart
- Only the download is safely retryable on its own; retries at the other steps can create new billable jobs
- Keep a low-frequency polling sweep even when callbacks exist, because callbacks get lost
答题要点
- 按四步拆失败:提交(限流、鉴权、参数无效、内容审核)、轮询(查询限流、状态停滞、终态失败)、取件(拿不到地址)、下载(地址过期、断流、写盘失败)
- 超时不是失败而是状态未知,重试前必须先按幂等键查一遍已有产物,否则会为同一个任务付两次钱
- 任务标识要及时落盘,进程重启后才能把在途任务认回来
- 四步里只有下载可以无脑重试,其余每一步的重试都可能产生新的计费
- 有回调也要保留低频兜底轮询,回调会丢
How do you choose a polling interval, and why is a fixed interval a bad default?轮询间隔怎么定?为什么不能一直用固定间隔死等?
Common in ChinaCommon overseasBasic#async-task#backoffHow to reason about it · think before answering
- This looks like a giveaway, but it has three layers and only the first one is obvious. They want to know whether you have actually written this loop.
- Layer one is cost: a task queued for five minutes polled every second is three hundred wasted requests. The query endpoint has its own rate limit, so you can throttle yourself and then misread 'rate limited' in the logs as a generation problem.
- Layer two is capping the backoff: multiply without a cap and you end up polling every few minutes, sleeping long after the task finished. Pick the cap from what extra wait a user tolerates — usually in the ten-to-twenty-second range.
- Layer three is where people actually get it wrong: the timeout check belongs before the sleep, and the test is whether sleeping would cross the deadline. Sleeping first means overshooting the budget by a full interval, which at a twenty-second backoff is twenty wasted seconds.
- Mention ordering too: check terminal states before the timeout. Discarding a task that just succeeded on the final poll means paying for an artifact you then throw away.
- Expect the follow-up: how do you pick the initial interval? From the typical duration of this class of task, a bit above a tenth of it; and the very first poll can be delayed slightly, since a just-submitted task is almost never done.
分析过程 · 先想清楚再作答
- 这是一道送分题,但它有三个层次,只答出第一层拿不到高分。面试官想看的是你有没有真的写过这个循环。
- 第一层是成本:一个排队五分钟的任务,用一秒的固定间隔就是三百次无效请求。查询接口自己也有速率限制,你很可能自己把自己打到限流,然后在日志里看到「生成失败:限流」,还以为是生成接口的问题。
- 第二层是退避要封顶:只乘不封顶的话,退到后面已经是几分钟查一次,任务早就好了你还在睡。上限的选法是「用户能忍受的额外等待」,一般十几到二十秒。
- 第三层最容易写错,也是这题真正的区分点:超时判断必须放在睡觉之前,判据是「睡下去会不会越过截止时间」。先睡再判会让你在预算之外多睡整整一轮,退避到二十秒时就是白等二十秒。
- 另外提一条顺序:先判终态再判超时。任务恰好在最后一次查询里成功却被当成超时扔掉,等于付了钱还丢了产物。
- 可以预期的追问:起步间隔怎么定?按这类任务的典型耗时定,比典型耗时的十分之一略大即可;再往细说就是首次查询可以稍微延后一点,因为刚提交的任务几乎不可能立刻完成。
Key points
- A fixed interval is either too tight, wasting requests and throttling yourself, or too loose, adding dead time after completion
- Use exponential backoff starting near a tenth of the task's typical duration
- Cap the backoff, choosing the cap from the extra wait a user will tolerate
- Check the timeout before sleeping, testing whether the sleep would cross the deadline, or you overshoot the budget by a full interval
- Check terminal states before the timeout so a task that just succeeded is not discarded
答题要点
- 固定间隔要么太密造成大量无效请求并把自己打到限流,要么太疏让完成后的等待过长
- 用指数退避:从接近典型耗时十分之一的间隔起步,每轮乘一个系数
- 退避必须封顶,上限按用户能忍受的额外等待来定
- 超时判断放在 sleep 之前,判据是「睡完会不会越过截止时间」,否则会在预算之外多睡一轮
- 先判终态再判超时,避免把最后一次查询里刚成功的任务误杀
When a generation API returns a failure, how do you decide whether to retry, and what happens after the retries run out?生成类接口返回失败,你怎么判断该不该重试?重试几次之后该做什么?
Common in ChinaCommon overseasDeep dive#error-handling#retry#costHow to reason about it · think before answering
- The hinge is 'decide'. Bucketing by the leading digit of the HTTP status is the classic wrong answer, because generation APIs often return HTTP 200 with a business error code in the body.
- Give a reusable test instead of reciting a code table: ask three questions — will waiting help, will changing the input help, or does a human have to step in? They map onto three dispositions: back off and retry, fix the request, alert immediately.
- Concretely: rate limits and server errors are the first bucket and the program handles them; invalid parameters and content moderation are the second, where retrying repeats the same error and burns rate-limit budget that genuinely retryable tasks needed; auth failure and insufficient balance are the third, where retrying only delays the alert.
- Handle timeout separately — this is the line that signals experience. A timeout is unknown, not failed: the job may still be running, or may have finished. So never resubmit blindly; look up the idempotency key for an existing artifact first.
- When retries are exhausted, do three things: mark the item failed with the last error code and the exact request parameters, keep processing the rest of the batch instead of aborting it, and aggregate the failures into one readable alert rather than one per item.
- Expect the follow-up: how many retries? Scale it by unit price. The more expensive the call, the fewer automatic retries, and expensive failures should go to a human for review before being redone.
分析过程 · 先想清楚再作答
- 这题的题眼是「判断」。按状态码首位数字一刀切是最常见的错误答案,因为生成类接口的业务错误码往往和 HTTP 状态码不在一个层面上——很多厂商的失败是 HTTP 200 加一个响应体里的业务码。
- 给一条可复用的判据,比背错误码表有用:问三个问题——等一等会不会好、改输入会不会好、还是必须叫人来。三个问题对应三种处置:退避重试、修请求、立刻告警。
- 落到具体:限流和服务端故障属于第一类,程序自己扛;参数无效与内容审核属于第二类,重试一万次都是同一个错,而且会挤占限流额度让真正该重试的排不上号;鉴权失败与余额不足属于第三类,重试只会延迟告警。
- 然后单独处理超时,这是最能体现经验的一条:超时不是失败,是状态未知,对方队列里那个任务可能还在跑甚至已经成了。所以超时之后不能直接重提,要先按幂等键查一遍已有产物。
- 重试用尽之后要做三件事,缺一不可:把这一条标成失败并记下最后一次的错误码与请求参数、继续跑批次里剩下的任务不要中断、把失败清单汇总成一次可读的告警而不是每条发一次。
- 可以预期的追问:重试次数怎么定?按单价定。单价越高,允许的重试次数越少,而且高单价的失败更应该先送人复核再决定要不要重做。
Key points
- Do not bucket by the leading HTTP digit; generation APIs often hide the business error code inside an HTTP 200 body
- Use three questions — will waiting help, will changing the input help, or is a human required — mapping to back off, fix the request, alert
- Rate limits and server errors are retryable; invalid parameters and moderation blocks are not and waste rate-limit budget; auth and balance failures need an alert
- A timeout is unknown rather than failed: check the idempotency key for an existing artifact before resubmitting, or you pay twice
- When retries run out, mark the item failed with its error code and request parameters, keep the batch running, and aggregate failures into one alert; scale retry counts by unit price
答题要点
- 不要按状态码首位一刀切,生成类接口的业务错误码常常藏在 HTTP 200 的响应体里
- 判据是三个问题:等一等会不会好、改输入会不会好、还是必须叫人来,分别对应退避重试、修请求、立刻告警
- 限流与服务端故障可重试;参数无效与内容审核重试无用且会挤占限流额度;鉴权失败与余额不足必须告警
- 超时是状态未知不是失败,重试前先按幂等键查一遍已有产物,否则会重复计费
- 重试用尽后:标记失败并留下错误码与请求参数、不中断整批、把失败汇总成一次可读告警;重试次数按单价定
D5 Voiceover, Subtitles, and Audio Tracks: Multi-Character Voices, Timeline Alignment, and Subtitle Files
When the synthesized speech and the shot duration disagree, which side do you adjust, and why?语音时长和画面时长对不上,你会调哪一边?为什么?
Common in ChinaCommon overseasIntermediate#timeline#tts#pipeline-designHow to reason about it · think before answering
- Answering 'stretch the shot' alone scores nothing; the hinge is 'why'. They want the reasoning for which side yields, and whether you see that this choice fixes the order of the whole pipeline.
- State the criterion: which distortion does the audience notice? Clipped or sped-up dialogue is audible immediately; a shot running 0.8 seconds long is not. So the picture yields.
- Derive the pipeline order from that: generate video at the planned duration, synthesize speech, write the measured duration back onto the shot, and let the editor pad the picture. Why not synthesize first and generate video to fit? Because video APIs expose discrete duration options — you cannot ask for exactly 6.34 seconds.
- Add the engineering detail that cannot be skipped: the timeline must use durations measured from the rendered files, never character-count estimates. Estimation error accumulates line by line, and by the tenth line the subtitles visibly race the picture.
- Then the exception, which earns points: if a shot has intrinsic rhythm — a beat cut, a transition, an action match — the picture cannot simply be stretched, and the right fix is a shorter line in the script. That is why stretched shots should be flagged for human review rather than silently rewritten.
- Expect the follow-up: can't you just nudge the speaking rate? You can, but it costs you — rate changes affect timbre and delivery, and they change duration again, turning a one-way flow into a loop. Make the lead-in and tail padding adjustable and spend that budget before touching the rate.
分析过程 · 先想清楚再作答
- 这题只答「调画面」拿不到分,题眼在「为什么」——面试官要的是让步理由,以及你有没有意识到这个选择会决定整条流水线的排列顺序。
- 先给判断依据:哪一边的失真观众察觉得到。台词被切掉、或者被加速到语气变形,观众立刻听得出来;一镜比原计划长零点八秒,观众感觉不到。所以让步的是画面。
- 由这条判断反推流水线顺序:画面先按计划时长生成,语音合成完之后由真实时长回写镜头时长,剪辑台再去补足画面。为什么不倒过来先合成语音再按语音时长生成视频?因为视频接口的时长是有限档位的,你没法要求它精确生成 6.34 秒。
- 补一条不能省的工程细节:写进时间轴的必须是从落盘文件量出来的真实时长,不能是字数估算。估算误差是逐句累加的,第一句差两百毫秒,第十句就差两秒,成片上表现为字幕跟画面赛跑。
- 再说例外,这是加分项:如果这一镜的画面本身有强节奏(比如卡点、转场、动作衔接),画面就不能被随意拉长,这时候要回头改剧本把台词写短,而不是硬拉画面。所以被顶长的镜头应该被标记出来交给人复核,而不是程序默默改掉。
- 可以预期的追问:那不能微调语速吗?可以,但语速是有代价的——语速改变会同时改变音质与情绪表现,而且它会反过来再改一次时长,等于把一个单向流程变成了循环。留一点余量的做法是给留白参数一个可调区间,先动留白再动语速。
Key points
- Stretch the picture: clipped or sped-up dialogue is instantly audible, while a fraction of a second of extra shot length is not
- That fixes the pipeline order: generate video at planned duration, synthesize speech, write measured duration back, pad in the edit
- You cannot invert it and generate video to match speech, because video APIs only expose discrete durations
- The timeline must use durations measured from rendered files; character-count estimates accumulate error line by line
- Shots with intrinsic rhythm are the exception, so flag stretched shots for human review instead of silently rewriting them
答题要点
- 调画面:台词被切或被加速观众立刻察觉,镜头长零点几秒观众感觉不到
- 由此定下流水线顺序:画面按计划时长生成,语音合成后回写真实时长,剪辑台补足画面
- 不能倒过来按语音时长生成视频,因为视频接口的时长只有有限档位
- 时间轴必须用落盘文件量出的真实时长,字数估算的误差会逐句累加
- 画面有强节奏的镜头是例外,这类冲突应标记出来交人复核而不是程序默默改掉
Where do you get subtitle timestamps from, and what do you do when the API does not provide them?字幕的时间戳你会怎么拿?接口不给时间戳时有什么替代方案?
Common in ChinaCommon overseasIntermediate#subtitles#timelineHow to reason about it · think before answering
- This tests whether you would take a dependency on an optional vendor field. Name both paths and their costs; giving only one invites a follow-up you will not enjoy.
- Path one is the API: TTS endpoints often expose a subtitle flag returning sentence- or word-level timestamps. Three problems — it costs an extra request to fetch, the timestamps are relative to that single audio segment, and the field structure varies by vendor. The third is the worst, because it welds your subtitle module to one provider.
- Path two is local alignment: you already hold every clip's measured duration and every shot's start time, so accumulating them gives the episode timeline. Zero extra requests, zero vendor coupling, and you control segmentation — one line of dialogue per cue, which is exactly the rhythm short drama wants.
- The key insight is that path one does not free you from path two: API timestamps are segment-relative, so you still add the shot's offset within the episode. Since you must write the alignment code anyway, make it the single source of truth.
- The implementation has one rule: the subtitle cursor and the shot cursor share one origin and advance together. Add a check that every cue falls inside its own shot — overflow raises no error, it just floats the previous shot's line over the next shot's picture.
- Expect the follow-up: what about karaoke-style word-level subtitles? That genuinely requires word-level timestamps from the API. Treat it as an optional enhancement over a local-alignment main path, degrading to sentence level when word data is unavailable.
分析过程 · 先想清楚再作答
- 这题在考你会不会为一个可有可无的厂商字段引入依赖。两条路都要说得出来,还要说清各自的代价,只答一条会被追问到底。
- 第一条是接口给:语音合成接口通常有一个字幕开关,返回按句或按词的时间戳。它的问题有三个——要多发一次请求去取内容、时间戳是相对单段音频的、字段结构随厂商变化。第三条最要命,因为它让你的字幕模块和某一家厂商绑死了。
- 第二条是本地对齐:你手里已经有每段音频的真实时长和每一镜的起始时刻,累加就是整集时间轴。它零额外请求、零厂商依赖,而且断句由你自己控制——按台词行断,一句一条,天然符合短剧节奏。
- 关键在于**就算用第一条也逃不掉第二条**:接口给的是段内相对时间,你仍然要加上这一镜在整集里的偏移。所以本地对齐这套代码无论如何都要写,那不如让它成为唯一的真相来源。
- 对齐的实现只有一个要点:字幕游标和镜头游标必须共用同一个原点,逐镜推进。再配一个自检——每条字幕必须落在它所属的那一镜内,越界不会报错,只会让上一镜的台词飘到下一镜的画面上。
- 可以预期的追问:那按词级时间戳做卡拉OK式字幕呢?那种效果确实必须依赖接口的词级时间戳,本地对齐做不了。这时的正确做法是把它做成一个可选增强,主链路仍然走本地对齐,拿不到词级数据就降级成句级。
Key points
- Two sources: timestamps returned by the API, and local alignment accumulated from measured audio durations
- The API path costs an extra request, gives segment-relative timestamps, and couples you to one vendor's field structure
- Local alignment needs no extra request and no vendor coupling, and lets you segment per line of dialogue
- Even with API timestamps you must add each shot's offset within the episode, so the alignment code is unavoidable anyway
- The implementation rule is one shared origin for the subtitle and shot cursors, plus a check that each cue stays inside its own shot
答题要点
- 两条来源:接口返回的时间戳,以及由音频真实时长本地累加对齐
- 接口那条的代价是多一次请求、时间戳只相对单段音频、字段结构跟厂商绑定
- 本地对齐零额外请求零厂商依赖,断句按台词行控制,符合短剧节奏
- 即使用接口时间戳也仍要自己加上这一镜在整集里的偏移,所以本地对齐代码无论如何都得写
- 实现要点是字幕游标与镜头游标共用同一原点,并自检每条字幕是否落在它所属的镜头内
In a multi-character pipeline, how do you guarantee the same character keeps the same voice across episodes?多角色配音里,怎么保证同一个角色跨集用的是同一个声音?
Common in ChinaCommon overseasBasic#tts#consistency#provider-abstractionHow to reason about it · think before answering
- This looks like a voice question but is really about where state lives. 'Hardcode it in config' is not wrong, but stopping there shows no engineering judgment.
- Name the risk first: voice is part of a character's identity, and audiences are about as sensitive to it as to a face. Inconsistency across episodes has three usual causes — running each episode as an independent pipeline, picking voices from an ad-hoc or random mapping, and someone tweaking a character's global parameters while fixing the delivery of one line.
- The fix is to file the voice in the character record rather than in code: the record carries a voice id, and the dubbing step only reads it. Consistency then holds regardless of episode, run or operator — the same pattern as pinning appearance to a base reference image.
- Storing the voice id alone is not enough. Perceived sameness also depends on the baseline emotion and the speaking rate; the same voice at two different rates sounds like a different state of a person. Keep all three in the record, and allow per-line overrides of emotion only, never of rate.
- Add a defensive layer: record the voice id together with the model name in the artifact metadata. Vendors do retire and rename voices, and you want to be able to answer 'why does season two sound different' from data rather than memory.
- Expect the follow-up: what if the vendor retires that voice? Make voice selection part of the provider abstraction — the record stores the character's voice archetype, and the mapping to a concrete vendor voice lives in the adapter, so swapping vendors never touches the character records.
分析过程 · 先想清楚再作答
- 这题看着像配音问题,其实考的是状态该存在哪里。答「配置里写死」不算错,但只答到这一层看不出工程判断。
- 先说清楚风险来自哪:声音是角色身份的一部分,观众对它的敏感度不低于脸。跨集不一致的典型成因有三个——每集独立跑一次流程、音色靠临时映射或随机挑选、以及某次为了改一句台词的语气顺手改了这个角色的全局参数。
- 解法是把音色归档而不是归代码:角色档案里带一个音色字段,配音环节只读不写。这样一致性由档案保证,跟哪一集、哪一次运行、谁跑的都无关。这跟角色形象靠基准图归档是同一套思路。
- 但只存音色标识还不够,跨集听感一致还依赖另外两项:基调情绪与语速。同一个音色用两种语速念,听起来像两个人的状态。所以档案里要一起存这三项,单条台词只允许覆盖情绪,不允许覆盖语速。
- 再补一层防御:把音色标识连同模型名一起记进产物元数据。厂商下线或重命名一个音色是会发生的,你要能查出「第二季为什么听起来不一样」,而不是只能凭记忆猜。
- 可以预期的追问:如果厂商真的下线了那个音色怎么办?答案是把音色选择也做成 provider 抽象的一部分:档案里存的是角色的音色角色定位,映射到具体厂商音色的表放在适配层,换厂商或补映射时不动档案。
Key points
- Store the voice in the character record and have the dubbing step read it only, so consistency is independent of episode, run or operator
- Keep voice id, baseline emotion and speaking rate together; allow per-line emotion overrides but never rate overrides
- Write the voice id and model name into artifact metadata so you can explain why a later season sounds different
- Typical causes of drift are per-episode independent runs, ad-hoc mappings, and global tweaks made while fixing one line
- Fold voice selection into the provider abstraction: records hold the archetype, the adapter maps it to a concrete vendor voice
答题要点
- 把音色存进角色档案,配音环节只读不写,一致性与集数、运行次数、操作人无关
- 档案里要同时存音色标识、基调情绪与语速;单条台词只允许覆盖情绪,不允许覆盖语速
- 把音色标识与模型名一起写进产物元数据,便于回答「为什么这一季听起来不一样」
- 跨集不一致的典型成因是每集独立跑、临时映射、以及改一句台词时顺手改了全局参数
- 音色选择应纳入 provider 抽象:档案存角色的音色定位,具体厂商音色的映射放在适配层
D6 The Editing Bay: Assembling Footage Into One Vertical Cut With ffmpeg
What are the risks of letting an LLM generate ffmpeg command lines directly, and how would you redesign it?如果让大模型直接生成 ffmpeg 命令来合成视频,会有什么风险?你会怎么改造这个设计?
Common in ChinaCommon overseasDeep dive#prompt-injection#pipeline-design#reproducibilityHow to reason about it · think before answering
- This probes where you draw the line between model judgment and real execution. Saying 'injection risk' is the passing bar; missing reproducibility and debuggability signals you have not run a generative pipeline in production.
- The chain is short: model output is untrusted input, untrusted input into a shell is command injection, model output is also nondeterministic, nondeterministic commands mean the same input yields different files, and debugging then requires guessing what the model was thinking.
- The fix is not 'validate and forward'. Move the model: let it emit only structured choices drawn from an enum you fixed in advance (transition type, crop strategy, which shot the cover comes from), and compute the command yourself from the timeline with a pure function.
- Add the concrete detail: invoke external binaries with an argument array (execFile, not exec) so escaping stops being a class of bug, then whitelist-validate the model's choices and fall back to a default instead of erroring.
- Expect the follow-up 'so what is the model still good for here'. Answer: taste calls — tone, cover selection, whether to use a transition. Judgment to the model, execution to the program. That boundary generalizes to any agent with side effects.
分析过程 · 先想清楚再作答
- 这题考的是「Agent 到底能不能碰真实执行」这条边界,区分度在于你会不会主动说出安全之外的两条。只答「有注入风险」是及格线,答不出可复现与可调试就说明没在生产里跑过生成式流水线。
- 推导链很短:模型的输出是不可信输入 → 不可信输入进 shell 就是命令注入 → 而且模型输出天然不确定 → 不确定的命令意味着同样的输入产出不同的文件 → 排查时你还得先猜模型当时为什么那么写。三条风险分别对应安全、可复现、可调试。
- 改造的方向不是「加一层校验就放行」,而是把模型挪到另一个位置:让它只输出结构化的选择项,且每一项都从你定死的枚举里选(转场类型、裁切策略、封面取哪一镜),命令本身由你自己的纯函数从时间轴算出来。
- 补一句更硬的落地细节:调用外部程序不要走 shell 字符串,用参数数组(execFile 而不是 exec),从根上消掉转义问题;再加一层白名单校验,模型给出枚举外的值就退回默认值而不是报错。
- 可预期的追问是「那模型在这一环还有什么用」。答:用在需要审美判断的地方——情绪偏冷还是偏暖、封面选哪一镜、要不要转场。判断交给模型,执行留给程序,这是所有会产生副作用的 Agent 场景的通用分界。
Key points
- Three risks in order: command injection, non-reproducible output, undebuggable failures. Naming only the first is not enough.
- Turn the model into a parameter filler: structured choices constrained to a predefined enum.
- Generate the command from the timeline with a pure function, invoked via an argument array rather than a shell string.
- Whitelist-validate and fall back to defaults for out-of-enum values instead of surfacing an error.
- One-line boundary: the model decides, the program executes.
答题要点
- 三条风险按严重度排:命令注入、结果不可复现、报错不可调试;只说第一条不够。
- 改造成参数填充器:模型输出结构化选择项,取值必须落在预定义枚举里。
- 命令由程序的纯函数从时间轴生成,用参数数组调用而不是拼 shell 字符串。
- 白名单校验兜底,枚举外的值退回默认,而不是把错误抛给用户。
- 分界线一句话:模型负责判断,程序负责执行。
An auto-generated episode comes out with audio and video out of sync. What is your debugging order, and why that order?一集自动生成的短剧成片出现音画不同步,你的排查顺序是什么?为什么是这个顺序?
Common in ChinaCommon overseasIntermediate#debugging#av-sync#timelineHow to reason about it · think before answering
- The question is about ordering, not about listing causes. The interviewer wants to see you rank checks by hit rate divided by cost, not enumerate everything you can think of.
- Ask yourself first: where does time come from in this pipeline? If the answer is 'a structured timeline table', then step one is comparing planned durations in that table against the real durations of the media files. Highest hit rate, lowest cost, one ffprobe call.
- Step two is the upstream artifacts: when the voice track is longer than the shot, the line gets cut off. It sounds almost identical to drift but the root cause is different, and it should have been caught with a warning when the timeline was built.
- Step three is the compose stage: stream-copy concatenation requires identical parameters across segments, and misaligned timestamps shift things; adding crossfades shortens the final cut, so subtitles drift progressively unless their timecodes are recomputed.
- Also mention a general move: when all three fail, stop staring at the final cut and play the normalized per-shot segments to narrow the problem to one shot. Always shrink the search space before guessing.
- Expect the follow-up 'how do you stop relying on human ears'. Answer: assert at timeline-build time when planned and actual durations diverge beyond a threshold, and automatically verify that the final cut's duration matches the timeline total.
分析过程 · 先想清楚再作答
- 这题的题眼在「顺序」两个字,不在「有哪些原因」。面试官想看的是你会不会按「命中率乘以排查成本」来排,而不是把想到的原因罗列一遍。
- 先问自己一个问题:这条流水线上,时间是从哪里来的?如果答案是「一张结构化的时间轴表」,那么第一步必然是拿表里的计划时长和素材文件的真实时长去对——这一步命中率最高、成本最低,一条 ffprobe 就能查完。
- 第二步查上游的产物本身:配音时长超过镜头时长时,台词会被截断,听感和不同步几乎一样,但根因完全不同。这类冲突应该在生成时间轴时就打警告,而不是留到成片阶段靠耳朵发现。
- 第三步才查合成环节:流拷贝拼接要求各段参数一致,时间戳对不齐就会错位;加了转场则成片整体变短,字幕若没跟着重算,表现为越到后面偏得越多。
- 还有一条通用招式值得说出来:三步都查不出来时,不要在成片里死磕,去播归一化之后的单镜片段,把问题缩小到某一镜身上。排查多段合成的问题永远优先缩小范围。
- 可预期的追问是「怎么让这类问题不再靠人耳发现」。答:在时间轴生成阶段加断言(计划时长与素材真实时长的偏差超过阈值就失败),并把成片时长与时间轴总时长的一致性做成自动校验。
Key points
- Start with the timeline table: compare planned durations against the media files' real durations. Highest hit rate, cheapest check.
- Then check whether the voice track exceeds the shot duration and truncates the line. That should be warned about at timeline-build time.
- Only then look at compose: concat method, timestamp alignment, and crossfades shortening the cut without recomputed subtitle timecodes.
- General move: play the per-shot normalized segments to isolate one shot instead of guessing on the final cut.
- Long term, turn duration consistency into assertions and automated checks rather than relying on ears.
答题要点
- 先查时间轴表里的计划时长与素材真实时长是否一致,这一步命中率最高、成本最低。
- 再查配音是否超出镜头时长导致台词被截断,这类问题应在生成时间轴时就报警告。
- 最后查合成环节:拼接方式、时间戳对齐、转场是否让成片变短而字幕没重算。
- 三步之外的通用招式:播单镜片段把问题缩小到某一镜,不要盯着最终产物猜。
- 长期方案是把时长一致性做成断言与自动校验,不靠人耳兜底。
When can you concatenate video segments without re-encoding, and when must you re-encode?把多个视频片段拼成一条完整的视频,什么时候可以不重新编码,什么时候必须重编码?
Common in ChinaCommon overseasBasic#ffmpeg#encoding#media-pipelineHow to reason about it · think before answering
- This is a giveaway concept question, but it only gives points to people who state the precondition. 'Just use concat' and 'stream copy requires identical parameters' read as two different levels.
- There is exactly one criterion: does concatenation only need to move packets into a new container in order? If yes, stream copy works. If even one frame has to be newly computed, you must re-encode.
- Be able to recite the preconditions: resolution, frame rate, pixel format, codec, audio sample rate and channel layout must all match. Miss one and you get corruption, dropped audio, or a broken duration.
- Cases that force re-encoding: transitions (those frames are new), scaling and padding to a common canvas, mixing in a new audio track, or changing encoding parameters. AI-generated material varies in size and often lacks audio, so normalization is almost always required in practice.
- The conclusion is a combination: normalize each shot with its own filter graph pass, then stream-copy the now-identical segments together. Total re-encoding is still one pass, but you gain full control over each shot.
- Expect the follow-up 'how do you know whether the parameters match'. Answer: read the key fields of each segment with ffprobe and compare. That precheck belongs in any automated pipeline.
分析过程 · 先想清楚再作答
- 这是一道概念送分题,但送分的是「说出前提」的人。答「用 concat 就行」和答「参数一致才能流拷贝」,在面试官眼里是两个水平。
- 判据只有一条:拼接是不是只需要把数据包按顺序搬进新容器。只搬不算,就能流拷贝;只要有任何一帧画面是新算出来的,就必须重编码。
- 流拷贝的前提要能背出来:分辨率、帧率、像素格式、编码器、音频采样率、声道数全部一致。差一项,产物要么花屏掉音,要么时长错乱。
- 必须重编码的典型场景:转场(那几帧是新画面)、缩放补边到统一画布、混入新的音轨、改变编码参数。AI 生成的素材尺寸和音轨天然不一致,所以实际工程里几乎总要先归一化。
- 结论落在一个组合拳上:每一镜单独走一次滤镜图做归一化,然后用流拷贝把参数已经一致的片段拼起来。重编码的总量还是一遍,但换来了对每一镜的完全控制。
- 可预期的追问是「怎么判断素材参数一不一致」。答:用 ffprobe 把每段的关键字段读出来做一次比对,不一致就走归一化,这一步也是自动化流水线里必须有的前置检查。
Key points
- The criterion is whether concatenation only moves packets: if so, stream copy; if any frame is newly computed, re-encode.
- Stream-copy preconditions: identical resolution, frame rate, pixel format, codec, sample rate and channel layout.
- Transitions, scale-and-pad, mixing a new audio track, and changing encoding parameters all force re-encoding.
- The practical combination: normalize per shot first, then stream-copy concatenate. Total re-encoding stays at one pass.
- Use ffprobe to compare segment parameters as a pipeline precheck.
答题要点
- 判据是拼接是否只需要搬数据包:只搬就能流拷贝,有新算出来的帧就必须重编码。
- 流拷贝的前提:分辨率、帧率、像素格式、编码器、采样率、声道数全部一致。
- 转场、缩放补边、混入新音轨、改编码参数,这几类一定要重编码。
- 实践中的组合拳:先逐镜归一化,再流拷贝拼接,重编码总量仍是一遍。
- 用 ffprobe 比对各段参数,作为流水线里的前置检查。
D7 One Episode Wrapped: Stringing Six Stages Into an End-to-End Pipeline and Tallying the First Bill
In a multi-step generation pipeline, one step fails. What behavior do you want the system to have?一条多步骤的生成流水线,中间某一步失败了,你希望系统有什么行为?
Common in ChinaCommon overseasIntermediate#pipeline-reliability#idempotency#error-handlingHow to reason about it · think before answering
- The discriminator is whether you answer in layers. People who just say 'retry' assume all failures are transient. Anyone who has run one of these asks first: is this failure retryable, because that decides everything downstream.
- Split the behavior into three layers: what to do immediately, what to do for this run, and what to do for the next run. Immediately: classify the error and retry with bounds. Only rate limits, timeouts and 5xx deserve backoff; auth failures, insufficient balance and content-policy rejections will fail a hundred more times.
- For this run: preserve the value already produced. Persist artifacts, elapsed time and spend for every completed step, including the money the failing step itself already burned. An implementation that just rethrows loses exactly the data a post-mortem needs.
- For the next run: do not pay twice. Give every node an idempotency key, store artifacts content-addressed, and make a rerun a set difference — skip what is done, redo only what is not. The bar is hard: the second run should make zero paid API calls.
- This matters more in generative pipelines than in ordinary backends because per-step cost is extreme. Measured on one episode in this course, the video step is 98 percent of total spend, so a full rerun burns over ten yuan, predictably rather than occasionally.
- Expect the follow-up 'what goes into the idempotency key'. Answer: model id, prompt, duration and resolution — anything that changes the artifact — plus an implementation version and the fingerprints of all dependencies. Never the run id, a timestamp or a random value.
分析过程 · 先想清楚再作答
- 这题的区分度在于你会不会分层回答。只说「重试」的人默认失败都是瞬时的;真正做过的人会先问一句:这次失败是可重试的还是不可重试的,因为这一条决定了后面所有动作。
- 先把行为拆成三层:立刻要做的、这一次运行要做的、下一次运行要做的。立刻要做的是错误分类与有界重试,只有限流、超时、五开头这类瞬时错误才值得退避重试,鉴权失败、余额不足、内容审核不通过重试一百次也是白烧钱。
- 这一次运行要做的是保住已经产生的价值:把已完成步骤的产物、耗时、花费全部落盘,包括失败那一步自己已经花掉的钱。一个直接向上抛的实现会把这些一起丢掉,而它们恰恰是复盘时最该看的。
- 下一次运行要做的是不重复花钱:每个节点算一个幂等键,产物按内容寻址落盘,重跑时先做一次差集,已完成的跳过、只补做没做完的。判据非常硬——第二次运行的付费接口调用次数应当是 0。
- 在生成式流水线里这一条比传统后端更要紧,因为单步成本高得离谱:本课量过一集的账,视频那一环占了全部花费的九成八,从头重跑一次就是白烧十块多,而且是必然的,不是偶然的。
- 可预期的追问是「幂等键里该放什么」。答:模型 id、提示词、时长分辨率这类会影响产物的输入,加上实现版本号和全部依赖的指纹;绝不能放运行标识、时间戳、随机数,放了就永远不命中。
Key points
- Classify errors first: only retryable ones get backoff. Auth, balance and content-policy failures gain nothing from retries.
- On failure, preserve completed steps' artifacts, timings and spend, including what the failing step itself already cost.
- The next run uses idempotency keys and content-addressed artifacts to compute a set difference and redo only what is missing.
- The acceptance bar is zero paid API calls on the second run, not 'no errors in the log'.
- Per-step cost is extreme in generative pipelines, so this work converts directly into money on the bill.
答题要点
- 先做错误分类:可重试的才退避重试,鉴权、余额、内容审核这类重试没有意义。
- 失败时保住已完成步骤的产物、耗时与花费,失败那一步自己花的钱也要记。
- 下一次运行靠幂等键与内容寻址的产物做差集,只补做没做完的部分。
- 验收判据是第二次运行的付费接口调用次数为 0,而不是「日志里没报错」。
- 生成式流水线单步成本极高,这一条的收益能直接换算成账单上的金额。
How do you measure the cost of a generation pipeline, and what besides money should you measure?怎么度量一条生成流水线的成本?除了钱还要量什么?
Common in ChinaCommon overseasBasic#observability#cost-accounting#pipeline-designHow to reason about it · think before answering
- This looks like a giveaway, but the real question is 'besides money'. Anyone who reports a single total cannot make an optimization decision, because a total does not say where to act.
- First decide the granularity: break it down per stage. One number carries no information; a per-stage table immediately shows where the money and the time went. Measured on one episode here: five images cost 0.125 yuan, voice under two cents, three video shots 10.5 yuan — video is 98 percent. You only see that broken down.
- Second, measure three things besides money: elapsed time decides how many episodes per day, call count decides whether you hit provider rate limits, and artifact count is the crudest completeness check — four shots should yield four clips, and a missing one means something failed silently.
- Third, separate estimates from real spend. Offline or in load tests you have no real amounts, so derive them from published unit prices — but label them as estimates, and never mix the two on one code path or the books will never reconcile.
- Also worth flagging: offline timing rankings are usually fake. With the APIs stubbed, local encoding becomes the biggest slice, and optimizing against that chart targets the wrong thing.
- Expect the follow-up 'what do you optimize first'. Answer: whatever has a number attached. Here it is waste from failed reruns, because it equals money on the bill. Concurrency comes second — before output is stable, concurrency only burns money faster.
分析过程 · 先想清楚再作答
- 这题看着是送分题,题眼其实在「除了钱」。只报一个总金额的人,做不出任何优化决策,因为总金额不告诉你该动哪里。
- 第一步是确定度量的粒度:**按环节摊开**。一个总数没有信息量,一张按环节分列的表能立刻告诉你钱花在哪、时间花在哪。本课量过一集:五张图一毛二五、配音不到两分、三个镜头的视频十块五,视频占了九成八——这个结论只有摊开才看得见。
- 第二步是把「钱」之外的三样一起量:耗时决定一天能出几集;调用次数决定会不会撞上厂商的速率限制;产物数是最朴素的完整性校验,四个镜头就该有四个视频,少一个说明某处静默失败了。
- 第三步是把估算和真实分开。离线或压测时拿不到真实金额,可以按公开单价折算,但**必须标明它是折算值**,而且折算逻辑和真实金额不能混在一条路径上算,否则账永远对不上。
- 还要提醒一句常被忽略的:离线模式下的耗时排名往往是假的。接口被打了桩,本地的编码步骤反而成了大头,照着这张图做优化会优化错地方。
- 可预期的追问是「量完之后先优化哪一项」。答:先优化能被数字证明收益的那一项。这个场景里是失败重跑造成的浪费,因为它直接等于账单上的金额;并发排第二,因为在产出还不稳定时并发只会让你更快地烧钱。
Key points
- Break the cost down per stage; a single total cannot tell you where to act.
- Besides money, measure elapsed time, call count and artifact count — throughput, rate limits and completeness.
- Keep estimated and real spend on separate paths, and always label estimates as estimates.
- Offline timing rankings are unreliable; do not optimize against a stubbed profile.
- Prioritize by which improvement has a number attached, not by intuition.
答题要点
- 按环节摊开,不要只给一个总数,否则无法定位该优化哪里。
- 除了金额还要量耗时、调用次数、产物数,各自对应吞吐、限流、完整性。
- 估算与真实金额分开计算,估算必须标明是折算值。
- 注意离线模式下耗时排名不可信,别照着假图做优化。
- 优化顺序按「收益能不能被数字证明」排,不按直觉排。
After chaining several individually working steps into one pipeline, which problems appear that single-step debugging never shows?把多个已经各自跑通的环节串成一条流水线之后,哪些问题是单独调试时看不见的?
Common in ChinaCommon overseasDeep dive#integration#pipeline-design#observabilityHow to reason about it · think before answering
- This tests integration instinct. If the answer is only 'interfaces do not line up', you have only integrated synchronous pure functions. In generative pipelines the integration problems live in state and artifacts, not in signatures.
- The framing question is: during single-step debugging, who does the gluing? Your head does. You know where the last script wrote its files and which blob to feed forward. Chaining forces that implicit knowledge into code, and whatever you fail to move becomes an integration bug.
- That yields three concrete classes. First, artifact paths and naming: a fixed output path is fine in isolation, but the second run overwrites the first, and on failure you cannot tell which files belong to which attempt. The fix is a run id that every artifact hangs under.
- Second, partial intermediate state: a step produces incomplete output without erroring, the next step accepts it, and the error propagates until it explodes far from its origin. The fix is a completeness assertion after every step, such as an expected artifact count.
- Third, observability: six stages each log their own way, hundreds of lines scroll past, and you cannot tell which stage failed. The fix is one log contract — a scannable progress table on the terminal, details pushed to files.
- Expect the follow-up 'how do you catch these earlier'. Answer: agree on three things before chaining — the artifact directory layout, each step's input/output contract, and the log format. Fix those and most integration bugs never get written.
分析过程 · 先想清楚再作答
- 这题考的是系统集成的直觉。回答里如果只有「接口对不上」,说明你只集成过同步的纯函数;生成式流水线的集成问题主要出在状态和产物上,不在接口签名上。
- 拆解的角度是:单独调试时,是谁在做衔接?答案是你的脑子。你知道上一个脚本把文件写到哪、知道该拿哪份数据喂下一步。串起来之后这些隐式知识必须搬进代码,而搬漏的地方就是集成问题的来源。
- 由此可以推出三类具体问题。第一类是产物路径与命名:单独跑时随手写一个固定输出路径没问题,串起来跑第二遍就把第一遍覆盖了,失败时也分不清哪些文件属于哪一次。解法是每次运行分配一个运行标识,所有产物挂在它下面。
- 第二类是中间态:某一步的产物不完整但没报错,下一步照单全收,错误一路往下传,最后在离源头很远的地方炸掉。解法是每一步产出后做完整性校验,比如按数量断言。
- 第三类是可观测性:六个环节各打各的日志,几百行滚过去,出了事看不出是哪一环。解法是统一日志规格,终端上只留一张能一眼扫完的进度表,细节压到文件里。
- 可预期的追问是「怎么提前发现这些问题」。答:串联之前先约定三件事——产物目录布局、每一步的输入输出契约、日志规格。这三件事定下来,绝大多数集成问题在写代码时就被挡住了。
Key points
- In isolation a human does the gluing; chaining means moving that implicit knowledge into code.
- Artifact paths and naming: assign a run id and hang every artifact under it to avoid overwrites and confusion.
- Incomplete intermediate state that does not error propagates far before exploding; assert completeness after every step.
- Log flooding: adopt one log contract, keep a progress table on the terminal and push details to files.
- Prevent it by agreeing on directory layout, per-step I/O contracts and log format before chaining anything.
答题要点
- 单独调试时是人脑在做衔接,串联的本质是把隐式知识搬进代码。
- 产物路径与命名:每次运行一个运行标识,所有产物挂在它下面,避免覆盖与混淆。
- 中间态不完整却不报错,错误会传到很远的地方才炸;每一步产出后做完整性校验。
- 日志淹没:统一日志规格,终端只留进度表,细节压到文件。
- 预防手段是串联之前先定好目录布局、输入输出契约与日志规格三件事。