Interview Bank
328 questions total; 28 shown with current filters.
42 more tagsShow fewer tags
RAG in 14 Days: From Retrieval to Trustworthy Answers
D1 Why Retrieve at All: Hallucination, Knowledge Cutoffs, and the Cost of Long Context; a Minimal Keyword-Only RAG
When should you use retrieval-augmented generation, when should you fine-tune, and when is stuffing the documents into the context window good enough?什么时候该用检索增强生成,什么时候该微调,什么时候直接把文档塞进上下文就够了?
Common in ChinaCommon overseasBasic#rag-basics#fine-tuning#long-contextHow to reason about it · think before answering
- This question shows up in almost every loop. The differentiator is not reciting three definitions, it is offering a decision rule the interviewer can reuse.
- Lead with the rule: is the model missing knowledge, or missing a way of speaking? Missing knowledge means retrieval; missing style or output shape means fine-tuning. That single cut covers most cases.
- Then line up the three options against three costs: cost of updating knowledge, cost per request, and whether the answer can be traced back to a source. Retrieval updates by editing a file, fine-tuning takes a retraining cycle, and long-context pays for the whole corpus on every call.
- Give long-context its fair case: when the corpus is small, changes rarely, and request volume is low, stuffing it in is the cheapest engineering decision you can make. It stops being cheap once the corpus grows or the same material is queried thousands of times a day.
- Close by naming when none of this applies: if the answer does not depend on any external document (rewriting, translating, reformatting), retrieval only adds noise, latency and cost.
- Expected follow-up: can you do both? Yes, and it is common. Fine-tuning controls format and refusal behaviour, retrieval supplies the facts.
分析过程 · 先想清楚再作答
- 这题几乎每场都问,区分度不在能不能背出三条定义,而在你会不会给一条判据。只说「RAG 适合动态知识、微调适合特定风格」的人一抓一大把,面试官等的是下一句。
- 先给一条能当场套用的判据:模型缺的是「知道什么」还是「怎么说」。缺知识走检索,缺风格与输出格式走微调,这一刀切下去能分掉八成场景。
- 再拿三笔账把三条路排开:知识更新的代价(改文件立刻生效 / 重训以天计 / 改文件立刻生效)、单次成本(只付取回的几段 / 只付推理 / 每次都付全量材料)、能不能归因(能 / 不能 / 能但材料一多定位会飘)。
- 把上下文直塞的适用边界说清楚:材料总量小、更新不频繁、对单次成本不敏感的场景它最划算,因为工程量近乎为零。一旦材料涨到几百篇,或者同一批材料每天要被问上万次,成本曲线立刻反超。
- 最后主动补一句「什么时候都不该用检索」——任务的答案不依赖任何外部文档时(改写、翻译、格式转换),加检索只会引入噪声、延迟和成本。能主动划出不该用的边界,比会背适用场景更能证明你做过。
- 可预期的追问:能不能既微调又检索?答案是可以,而且常见——微调管输出格式与拒答口径,检索管事实,两者解决的不是同一个问题。
Key points
- One rule: retrieval for missing knowledge, fine-tuning for a missing way of speaking.
- Retrieval updates instantly by editing files, supports citation, and costs scale with the retrieved passages rather than the corpus.
- Fine-tuning is good at locking in style and output schema, poor at loading facts, and offers no traceability.
- Long-context stuffing wins when the corpus is small, stable and queried infrequently; it loses on cost and on locating facts once the corpus grows.
- If the answer does not depend on any document, use none of them.
答题要点
- 一条判据:缺「知道什么」用检索,缺「怎么说」用微调。
- 检索改文件即时生效、可归因、成本只跟取回的几段有关,代价是要自己建一套会出错的检索系统。
- 微调擅长固化风格与输出格式,不擅长灌事实:数据一变就要重训,而且没法归因。
- 长上下文直塞在小型、低频、少变的语料上最划算,材料变多或调用量变大之后成本与定位稳定性都会恶化。
- 任务答案不依赖外部文档时三条路都不该用,直接调模型。
In BM25, what problems do term-frequency saturation and document length normalisation each solve? What happens if you set both k1 and b to zero?BM25 里的词频饱和与文档长度归一化分别在解决什么问题?把 k1 和 b 都设成 0 会发生什么?
Common in ChinaCommon overseasIntermediate#bm25#ranking#information-retrievalHow to reason about it · think before answering
- This checks whether you have actually read the formula rather than merely called a library. The test is whether you can map k1 and b onto specific terms and name the failure each one prevents.
- Start with the two holes in raw term frequency: keyword stuffing lets one document dominate by repeating a word, and long documents win by accident because they contain more words overall.
- k1 closes the first hole. Term frequency appears in both numerator and denominator, so the ratio approaches a ceiling instead of growing linearly. Fifty mentions are more relevant than five, but not ten times more relevant. A smaller k1 saturates sooner.
- b closes the second. The normalisation factor is one minus b plus b times document length over average length: at b equal to zero length is ignored entirely, at one it is fully penalised, and 0.75 is the conventional compromise.
- Now the trap in the question: k1 equal to zero collapses the ratio to a constant, so one occurrence scores the same as a hundred and matching becomes boolean. b equal to zero removes length entirely. Set both to zero and BM25 degenerates into a plain sum of inverse document frequencies.
- Expected follow-up: can you drop the IDF term? No. Without it, ubiquitous words drown everything else, and it is precisely IDF that lets BM25 work without a stopword list.
分析过程 · 先想清楚再作答
- 这题考的是你有没有真的读过公式,而不是有没有调过库。判据很明确:能不能把 k1 和 b 各自对应到公式里的哪一项,并说出去掉之后会被什么样的文档钻空子。
- 先说朴素词频的两个漏洞:一是重复刷词,一篇文章把关键词写五十遍就能霸榜;二是长文占便宜,文档越长越容易蒙中查询里的词。这两个漏洞正好对应两个修正。
- k1 管第一个漏洞。分子分母里都有词频 f,所以词频涨上去之后整个分式趋近一个上界而不是线性增长——写五十遍确实比写五遍相关,但绝不该相关十倍。k1 越小饱和越快。
- b 管第二个漏洞。归一化项是 1 减 b 加上 b 乘以本文长度除以平均长度,b 等于 0 时完全不看长度,b 等于 1 时完全按长度比例惩罚,0.75 是长期折中的默认值。
- 回到题干那个陷阱:k1 设成 0 会让分式退化成常数,词出现一次和一百次得分完全一样,等于只剩「有没有出现过」的布尔匹配;b 设成 0 则长度信息彻底消失。两个一起设成 0,BM25 就退化成对逆文档频率求和,跟词频再无关系。
- 可预期的追问:那逆文档频率去掉行不行?答案是不行,去掉之后「的」「我们」这类高频词会淹没一切——而且要顺带说明 BM25 因此天然不需要停用词表,这一句最能体现你读懂了公式。
Key points
- k1 controls saturation and prevents keyword stuffing: the score approaches a ceiling rather than growing linearly with frequency.
- b controls length normalisation and stops long documents from winning by sheer word count.
- Setting k1 to zero degenerates the scorer into boolean matching; one occurrence scores the same as a hundred.
- Setting b to zero removes document length from the equation entirely; both at zero leaves only a sum of IDF terms.
- IDF is the third component: it up-weights rare terms and removes the need for a stopword list.
答题要点
- 词频饱和由 k1 控制,防的是重复刷词:词频涨大后得分趋近上界而非线性增长。
- 长度归一化由 b 控制,防的是长文档靠词多蒙中查询,用本文长度比平均长度把它压回去。
- k1 设 0 会退化成布尔匹配,词出现一次和一百次同分;b 设 0 则完全不考虑文档长度。
- 两者都设 0 时 BM25 只剩逆文档频率求和,等于放弃了词频信息。
- 逆文档频率是第三块,让稀有词权重更高,也让 BM25 天然不需要停用词表。
A retrieval-augmented generation system gave a wrong answer. How do you determine whether retrieval or generation is at fault?一个检索增强生成系统答错了,你怎么定位是检索的锅还是生成的锅?
Common in ChinaCommon overseasIntermediate#debugging#failure-modes#evaluationHow to reason about it · think before answering
- The question asks how you localise the fault, not what the possible causes are. Listing causes loses; the interviewer wants an ordered procedure that ends in concrete actions.
- Give the cheapest first step: print the retrieved passages verbatim and read them. If the correct answer is not in there, retrieval is at fault. If it is in there and the model ignored it, generation is at fault. Thirty seconds, and it removes most of the guesswork.
- Then lay out the five stages — chunking, indexing, retrieval, context assembly, generation — with the rule: diagnose right to left, fix left to right. You see the generated answer first, but an error on the left is amplified by everything to its right.
- Add symptoms that pin down a stage: half-correct answers usually mean a rule was split across chunks; obviously irrelevant hits usually mean dirty parsing; the model ignoring the supplied material usually means the prompt never said it must; citation numbers that do not match their content point at generation.
- Land it in engineering terms: to run this procedure repeatedly you must log the retrieved hits, the passages that entered the context, and the final answer together, otherwise production issues are unreproducible. At scale this becomes a fixed question set with metrics rather than case-by-case reading.
- Expected follow-up: if retrieval missed the document, will prompt tuning help? No. Nothing in the prompt can conjure material that was never supplied.
分析过程 · 先想清楚再作答
- 题眼在「怎么定位」,不在「有哪些原因」。答成一串可能原因的罗列就输了,面试官想听的是一个有先后顺序、能落到具体动作的排查流程。
- 先给最省时间的第一步:把这次检索出来的几段原文原样打印出来,自己读一遍。正确答案不在里面就是检索的锅,在里面而模型没用上才是生成的锅。这一步三十秒,能省掉大半天的瞎猜。
- 然后把链路展开成五个环节——切块、建索引、检索、组装上下文、生成——并给出「排查从右往左、修复从左往右」这条口径:从右往左是因为你最先看到的是生成结果,从左往右是因为左边的错会被右边放大。
- 补充几个能把环节钉死的症状:答案「半对」多半是切块把一条完整规则切断了;检索结果里混着一眼不相干的东西多半是解析没做干净;模型无视材料用先验知识作答,通常是提示词里少了「只能依据资料回答」;引用编号和内容对不上,那是生成侧漏读或串了行。
- 最后落到工程做法:这套排查要能重复做,就必须把每次请求的检索结果、进上下文的段落、最终回答一起记下来,否则线上出问题时你根本复现不了。到了要批量做的时候,就得换成一批固定问题加指标,而不是一条条人工看。
- 可预期的追问:如果检索确实没捞到,改提示词有没有用?答案是没用——材料里没有的东西,再好的指令也只能换一种编法。这句话最能证明你分清了两层。
Key points
- Always start by printing the retrieved passages and checking whether the correct answer is present at all.
- Split the pipeline into chunking, indexing, retrieval, context assembly and generation; diagnose right to left, fix left to right.
- Use symptoms to pin the stage: half-correct answers point at chunking, irrelevant hits at parsing, ignored material at the prompt, mismatched citations at generation.
- If retrieval missed the document, prompt changes cannot help; the material simply is not there.
- Log retrieved hits, the passages that entered the context, and the final answer together, or production failures are unreproducible.
答题要点
- 第一步永远是把检索出来的原文打印出来读一遍,判断正确答案在不在里面。
- 把链路拆成切块、建索引、检索、组装上下文、生成五个环节,排查从右往左、修复从左往右。
- 用症状钉环节:半对多半是切块问题,混入无关结果多半是解析问题,无视材料多半是提示词缺约束,引用与内容对不上是生成问题。
- 检索没捞到时改提示词没有意义,材料里没有的东西模型只能编。
- 要能重复排查就必须把检索结果、进上下文的段落和最终回答一起记录下来。
Context windows are now in the millions of tokens. Does that make the retrieval step obsolete?上下文窗口已经做到上百万 token 了,检索这一步会被淘汰吗?
Common in ChinaCommon overseasDeep dive#long-context#cost#system-designHow to reason about it · think before answering
- This is a position question and it is easy to answer as a binary. The signal is whether you separate what fits technically from what is worth paying for on every request.
- Concede the valid half first: bigger windows genuinely absorb part of the use case. For an internal tool over a few dozen stable documents with low traffic, stuffing everything in is the right call and building a retrieval stack would be over-engineering.
- Then give three reasons it does not absorb the rest. Cost is the first: context is billed per request, so the same corpus is paid for on every one of ten thousand queries, whereas retrieval only pays for the passages it returns. Prompt caching softens this but does not remove it.
- Scale is the second: enterprise corpora run to hundreds of thousands of documents and no window holds them. Attribution and access control are the third: pointing an answer at a specific passage, and showing each user only what they are permitted to see, both have to happen before the material reaches the model.
- Add the empirical point: as the supplied material grows, models become less reliable at locating the one relevant fact inside it. More context is not automatically better; fewer and more precise passages often win.
- Expected follow-up: does retrieval change shape? Yes. Larger windows allow bigger chunks and more of them, which relieves pressure on reranking and compression. Retrieval gets coarser, it does not disappear.
分析过程 · 先想清楚再作答
- 这是一道立场题,容易答成非黑即白。判断你有没有做过的地方在于:会不会区分「技术上能不能塞进去」和「工程上该不该每次都塞」,只谈前者的答案一听就是纸上谈兵。
- 先承认对方有道理的部分:窗口变大确实吃掉了检索的一部分场景。几十篇文档、更新不频繁、调用量不大的内部工具,直接全塞是最省事的选择,为它建一套检索系统是过度设计。
- 再给三条它吃不掉的理由。第一是成本:材料是按次计费的,同一份材料被问一万次就要付一万次,而检索只付取回的那几段;预填充缓存能缓解但不能消除,缓存也有有效期和命中率。
- 第二是规模:企业知识库动辄几十万篇,再大的窗口也塞不下,检索是唯一的入口。第三是归因与权限:答案要指回具体某一段,以及不同的人只能看到自己有权访问的材料——这两件事必须在把材料喂给模型之前完成,窗口再大也不解决。
- 还要补一条经验事实:材料变多之后,模型在长上下文里定位关键信息的稳定性会下降,出现「读了但没读到」。所以「全塞」并不总是等于「效果更好」,很多时候少而准反而更好。
- 可预期的追问:那检索的形态会不会变?会——窗口变大之后,取回的块可以更大、条数可以更多,重排与压缩的压力变小,检索从「精挑几句」变成「粗筛一批」。趋势是检索的粒度变粗,不是检索消失。
Key points
- Separate whether it fits from whether it is worth paying for on every request.
- Small, stable, low-traffic corpora can legitimately be stuffed whole; building retrieval for them is over-engineering.
- Three reasons retrieval survives: per-request cost, corpora too large for any window, and attribution plus access control that must happen before the model sees the material.
- More supplied context reduces the reliability of locating a single fact, so stuffing everything is not automatically better.
- The trend is coarser retrieval — bigger chunks, more of them, less reranking pressure — not the removal of retrieval.
答题要点
- 先区分「能不能塞进去」和「该不该每次都塞」,前者是技术问题,后者是成本问题。
- 小规模、低频、少变的语料确实可以直接全塞,为它建检索系统是过度设计。
- 检索不会被淘汰的三个理由:按次计费的成本、几十万篇塞不下的规模、必须在喂给模型之前完成的归因与权限过滤。
- 材料越多,模型定位关键信息的稳定性越差,全塞不等于效果更好。
- 趋势是检索粒度变粗——块更大、条数更多、重排压力变小,而不是检索消失。
D2 Embeddings and Vector Search: Similarity, Dimensionality, and Model Choice; Storing Text in pgvector
When are cosine similarity and inner product equivalent? What goes wrong if you rank by inner product on vectors that are not normalised?余弦相似度和内积什么时候等价?如果向量没有归一化,用内积排序会出什么问题?
Common in ChinaCommon overseasBasic#embeddings#similarity#normalisationHow to reason about it · think before answering
- This starts as a giveaway, but the second half is where candidates separate. Many can say 'they are equivalent after normalisation'; few can describe what breaks without it.
- State the definition: cosine similarity is the inner product divided by the product of the two magnitudes. When both magnitudes are 1, the divisor is 1 and cosine reduces to the inner product. That is the whole argument.
- Then the failure mode: an un-normalised inner product mixes 'how aligned' with 'how long'. Longer texts tend to produce larger-magnitude vectors, so ranking drifts systematically toward long documents, the same bias BM25's b parameter exists to counter.
- Stress that this bug is silent. Nothing throws, results still look plausible, and only an offline evaluation reveals the drift. Hence the engineering rule: normalise once at the embedding boundary, never at each call site.
- Add Euclidean distance for completeness: on normalised vectors, squared L2 equals 2 minus twice the inner product, a monotone function of cosine distance, so all three metrics produce the same ranking.
- Expected follow-up: which pgvector operator should you use? Since the vectors are normalised, `<=>` and `<#>` rank identically; prefer `<=>` for readability and because it stays correct if someone later forgets to normalise.
分析过程 · 先想清楚再作答
- 这题是送分题,但区分度藏在后半句。只答「归一化之后两者等价」的人很多,面试官真正想听的是「没归一化会怎么坏」,因为那是线上真的会发生的事。
- 先把定义摆出来:余弦相似度等于内积除以两个向量模长的乘积。模长都是 1 时除数就是 1,所以余弦相似度就是内积——这一句话就是等价的全部理由,不需要额外的假设。
- 再说没归一化的后果:内积里混着「方向有多一致」和「向量有多长」两层信息。文本越长,模型输出的向量模长往往越大,于是排序会系统性地偏向长文档——这跟 BM25 里 b 参数要压的是同一个毛病,只是换了个地方冒出来。
- 点出这类 bug 的性质:它不报错。程序照常跑、结果照常出,只是名次悄悄偏了,你要跑一轮离线评估才可能发现。所以工程上的做法是在 embedding 的出口统一归一化一次,而不是靠每个调用点自觉。
- 补一句欧氏距离:向量都归一化之后,欧氏距离的平方等于 2 减去 2 倍内积,也就是余弦距离的单调函数,三种距离排出来的名次完全一致。这一句能说明你理解的是关系而不是三条并列的规则。
- 可预期的追问:那 pgvector 里该用哪个运算符?答案是既然已经归一化,`<=>`(余弦距离)和 `<#>`(负内积)名次一样,选 `<=>` 的理由是可读性和「就算哪天有人漏了归一化也不至于错」。
Key points
- Cosine equals inner product divided by both magnitudes; with unit magnitudes the divisor is 1, so they coincide.
- Without normalisation the inner product carries magnitude, and longer documents usually have larger magnitudes, biasing the ranking.
- The failure is silent, so normalise once at the embedding boundary and verify with offline evaluation.
- On normalised vectors L2 and cosine are monotonically related, so all operators rank the same.
- In pgvector the operators are `<->` for L2, `<#>` for negative inner product and `<=>` for cosine distance.
答题要点
- 余弦相似度 = 内积 / 两个模长之积,模长为 1 时除数为 1,两者等价。
- 没归一化时内积混入模长信息,长文档的向量模长普遍更大,排序会系统性偏向长文档。
- 这类错误不报错,只能靠离线评估发现,所以要在 embed 出口统一归一化。
- 归一化之后欧氏距离与余弦距离互为单调函数,三种运算符名次一致。
- pgvector 里对应 `<->`(L2)、`<#>`(负内积)、`<=>`(余弦距离)三个运算符。
What do you lose when you cut embedding dimensions from 1536 to 512, and when is that loss acceptable?把 embedding 维度从 1536 降到 512,你会损失什么?什么场景下这个损失可以接受?
Common in ChinaCommon overseasIntermediate#embeddings#dimensions#costHow to reason about it · think before answering
- This is a cost-modelling question. 'Lower dimensions are cheaper but less accurate' earns nothing; the interviewer wants a cost model and a decision order.
- Lay out three costs: storage and memory (vector count times dimensions times bytes per dimension, which an ANN index must hold in RAM), query latency (roughly linear in dimensions), and retrieval quality, whose returns diminish sharply at the high end.
- Explain why truncation works at all: models trained with Matryoshka representations pack the most important information into the leading dimensions, so truncating and re-normalising keeps the vector usable. It is still lossy, and how lossy is an empirical question on your own data.
- Give the decision order: derive a dimension ceiling from your memory budget, then step down two or three notches and measure the metric drop. Choosing the largest model first and optimising cost later usually means redoing the work.
- Name the acceptable cases: large corpora of low individual value, pipelines where a reranker recovers some of the loss, and latency-critical online paths. Be conservative where a single miss is expensive, such as legal or clinical retrieval.
- Expected follow-up: can different documents use different dimensions? No. Every vector in an index must share one dimension, so changing it means rebuilding the whole index, the same migration cost as changing models.
分析过程 · 先想清楚再作答
- 这题考的是你会不会算账。只说「维度越低越省、精度越低」的答案没有区分度,面试官在等一个具体的成本模型和一个决策顺序。
- 先把三笔账列出来:存储与内存(向量数量乘维度乘每维字节数,近似最近邻索引要把它放进内存,所以基本等于机器预算)、检索延迟(每次比较就是一轮乘加,维度大致线性影响耗时)、检索质量(收益递减,低维段每加一档提升明显,高维段加倍只换来很小的改善)。
- 再说清降维为什么可行:主流模型用套娃式表示训练,重要信息压在靠前的维度上,所以直接截短再归一化仍然可用,这不是另训了一个小模型。截短必然有损失,损失多少只能在自己的数据上跑评估才知道。
- 给出决策顺序:先按存储与内存预算倒推一个维度上限,再从上限往下试两三档,看指标掉多少,掉得能接受就用低的。反过来「先选最高维再想办法省钱」基本都会返工。
- 点出可接受的典型场景:库很大而单条价值不高(比如日志、工单)、召回之后还有重排兜底(重排能把粗排的损失补回来一部分)、或者对延迟极敏感的在线场景。反过来法务、医疗这类一条都不能漏的场景就要谨慎。
- 可预期的追问:能不能不同文档用不同维度?不能——同一个索引里所有向量必须同维,改维度等于全库重建,这跟换模型是同一类迁移成本。
Key points
- Three costs: storage and index memory, query latency, and retrieval quality; the first two scale with dimensions, the third has diminishing returns.
- Matryoshka representations make truncation viable, but it is lossy and the loss must be measured on your own data.
- Decide by deriving a ceiling from the memory budget, then stepping down and measuring.
- Truncation pays off for large corpora, low-value items, latency-sensitive paths, and pipelines with a reranker.
- All vectors in one index share a dimension, so changing it forces a full rebuild.
答题要点
- 三笔账:存储与索引内存、检索延迟、检索质量,前两笔随维度近似线性,第三笔收益递减。
- 套娃式表示让截短再归一化仍然可用,但一定有损失,损失多少要在自己的数据上评估。
- 决策顺序是先按内存预算定上限,再往下试档位看指标掉多少。
- 库大、单条价值低、后面还有重排兜底、对延迟敏感的场景,降维划算。
- 同一索引里维度必须一致,改维度等于全库重建。
Why do some embedding models require different prefixes for queries and documents? What happens if you skip them, and how would you catch it before shipping?为什么有些 embedding 模型要求查询和文档加不同的前缀?不加会怎样,你怎么在上线前发现这个问题?
Common in ChinaCommon overseasIntermediate#embeddings#model-selection#evaluationHow to reason about it · think before answering
- The core of this question is silent failure. Reciting 'e5 needs query: and passage: prefixes' is the baseline; explaining why nothing errors out and how you would catch it is what shows experience.
- The reason: these models are trained on pairs, short questions on one side and longer passages on the other, two genuinely different distributions. The prefix is a role marker learned during training. Omit it at inference and you are off-distribution.
- The consequence: the model still returns vectors, distances still compute, results still have an order, quality just degrades. Nothing throws, exactly like forgetting to normalise.
- How to catch it: run a small labelled question set against the same corpus twice, with and without prefixes, and compare hit rate. That is the evaluation gate built on day 8, and catching silent regressions is precisely what it is for.
- Mention the sneakier variant: prefixing at index time but not at query time, or using the same prefix on both sides. Everything sits in one coordinate space and looks healthier, yet the query-document alignment is wrong and the loss is just as invisible. Encapsulate prefixes in the embedding call convention rather than hand-writing them everywhere.
- Expected follow-up: do OpenAI models need prefixes? No, they are not in that family, so this is not a universal rule but a per-model detail you re-check on the model card every time you switch.
分析过程 · 先想清楚再作答
- 这题的题眼是「静默失效」。会背「e5 要加 query 和 passage 前缀」只能拿基础分,能说清它为什么不报错、以及怎么在上线前抓住它,才是做过的人。
- 先讲原因:这一族模型是拿成对数据训练的,一侧是短问句、一侧是长段落,两者的分布本来就不一样。前缀是训练时给模型的角色标记,告诉它这一段该按查询编码还是按文档编码。推理时不给,模型就落在了训练分布之外。
- 再讲后果的性质:不加前缀模型照样输出向量、照样能算距离、名次照样有先后,只是整体质量下滑。**没有任何报错**——这跟忘了归一化是同一类问题:错误不会自己浮出来。
- 怎么发现:唯一可靠的办法是一小份标注问题集,用同一批文档跑两遍(加前缀与不加前缀),比命中率。这就是第 8 天要做的评估闸门,它的价值恰恰在于抓这类静默错误。上线前跑一遍,比读十遍文档管用。
- 补一个更容易踩的变体:**建库时加了前缀、查询时忘了加**,或者两边加成同一个前缀。这种情况下所有向量都在同一个坐标系里,看起来更「正常」,但查询与文档的对齐关系是错的,掉分同样查不出来。所以前缀应该封装在 embed 的调用约定里,而不是散在各处手拼。
- 可预期的追问:OpenAI 的模型要不要加前缀?不需要——它不属于这一族。所以这不是一条普遍规则,而是**每换一个模型都要重新读模型卡片确认**的事。
Key points
- These models are trained on question-passage pairs; the prefix marks which role a text plays, and omitting it puts you off-distribution.
- Skipping prefixes never errors, it only degrades quality, so the failure is silent.
- The reliable detection is an A/B run over a small labelled question set, comparing hit rate.
- A subtler bug is mismatched or identical prefixes on both sides, which looks healthier but misaligns queries and documents.
- Keep prefixes inside the embedding call convention, and re-read the model card whenever you switch models.
答题要点
- 这类模型用问句与段落的成对数据训练,前缀是区分两种角色的标记,缺了就落在训练分布之外。
- 不加前缀不会报错,只会整体掉分,属于静默失效。
- 唯一可靠的发现方式是拿一份标注问题集跑 A/B 对比命中率。
- 更隐蔽的错法是两边前缀不一致或用了同一个前缀,看起来更正常但对齐是错的。
- 前缀应封装在 embed 的调用约定里;换模型必须重读模型卡片,它不是普遍规则。
Can vector search fully replace keyword search? Give a query where vectors are bound to fail, and say how you would fix it.向量检索能完全取代关键词检索吗?举一个向量必然失手的查询,并说说你会怎么补。
Common in ChinaCommon overseasIntermediate#hybrid-search#embeddings#retrieval-failureHow to reason about it · think before answering
- This is a stance question where the stance matters less than the counter-example. Without a concrete, reproducible failing query, the rest of the answer reads as theory.
- Enumerate the failure classes up front: error and status codes, version numbers and SKUs, names and employee IDs, order or document identifiers, and negation. The first four share one property: their value lies in exact literal identity, which embeddings deliberately blur into semantic neighbourhoods.
- Give a reproducible example: ask whether rate limiting returns 429. BM25 lands on the API document that literally contains 429, while vector search may rank a topically similar product manual that never mentions the code.
- Call out negation separately: 'supports PDF export' and 'does not support PDF export' sit almost on top of each other because they discuss the same thing. Vectors cannot carry that distinction; the generation step reading the source has to.
- The fix: run both retrievers and fuse the rankings, BM25 on the lexical side and nearest neighbour on the vector side, combined with reciprocal rank fusion. That is hybrid search, covered on day 9. Fusion helps precisely because the two systems fail on different queries.
- Expected follow-up: could you drop the keyword path and rewrite queries instead? Rewriting helps with vocabulary mismatch, but it cannot rescue exact identifiers, since there is no paraphrase of 429.
分析过程 · 先想清楚再作答
- 这题是典型的「立场题」,答「能」或「不能」都不重要,重要的是你能不能举出一个具体到能复现的反例。举不出例子,前面说得再漂亮也会被判成没做过。
- 先给失手的类型,一次给全:错误码与状态码(429、E1032)、版本号与型号(v2.3.1、X20 Pro)、人名与工号、订单号与文档编号、以及否定表达。前四类的共同点是**这些词的价值在于字面唯一,而向量只保留语义邻近**,模型会把 429 和「限流」「超时」这些话题相近的东西编到一起,反而把真正写着 429 的那篇挤下去。
- 拿一个能复现的例子说:问「限流超了返回 429 吗」,BM25 稳稳命中写着 429 的接口文档,向量却可能把话题相近但没提 429 的产品手册排在前面。这个现象在本课第 2 天的实验里就能亲眼看到。
- 否定表达要单独强调:「支持导出 PDF」和「不支持导出 PDF」在向量空间里几乎重合,因为它们谈的是同一件事。指望向量区分肯定与否定一定翻车,这一层要靠生成侧读原文来判断。
- 怎么补:两路并行跑再融合,关键词一路用 BM25、向量一路用最近邻,用倒数排名融合把两个名次合成一个。这就是混合检索,本课第 9 天展开。要点是**两套的错法不一样**,所以合起来才有增益——如果两套错在同一批查询上,融合是白做的。
- 可预期的追问:那关键词一路能不能扔掉、改成让模型改写查询?可以缓解一部分(第 10 天的查询改写),但改写救不了字面唯一的标识符——你没法把 429 改写成别的说法。
Key points
- No: codes, version numbers, names and IDs matter as exact literals, which embeddings blur into neighbourhoods.
- Concrete example: asking whether rate limiting returns 429, where BM25 hits the document containing 429 and vectors surface a topically similar one that never mentions it.
- Negation is a second failure class, since affirmative and negative statements sit almost on top of each other.
- The remedy is hybrid retrieval: run both paths and merge with reciprocal rank fusion.
- Fusion pays off because the two paths fail differently; query rewriting helps vocabulary mismatch but not exact identifiers.
答题要点
- 不能取代:错误码、版本号、人名、单号这类词的价值在于字面唯一,向量只保留语义邻近。
- 具体反例:问「限流超了返回 429 吗」,BM25 命中写着 429 的文档,向量把话题相近却没提 429 的文档排前面。
- 否定表达是另一类失手:肯定句与否定句在向量空间里几乎重合。
- 补法是混合检索:两路并行再用倒数排名融合合并名次。
- 融合有增益的前提是两套的错法不同;查询改写能缓解词汇不匹配,但救不了字面唯一的标识符。
D3 Getting Documents In: Parsing PDF and HTML, Tables and Scans, Cleaning Rules, and Metadata You Must Keep
The text extracted from a PDF comes out in the wrong order. How do you diagnose and fix it?一份 PDF 解析出来的文字顺序是乱的,你会怎么排查和修复?
Common in ChinaCommon overseasIntermediate#pdf-parsing#ingestion#data-qualityHow to reason about it · think before answering
- This checks whether you have actually parsed a PDF yourself. The first sentence is the differentiator: a PDF has no reading order at all, only drawing instructions with coordinates.
- Start with the diagnostic step: dump the extracted fragments together with page, x, y and font size instead of looking at the concatenated string. The cause is always in the coordinates.
- Then classify the symptom. Lines alternating between left and right means multi-column layout was not detected. Fragments with y jumping backwards means the content stream was written in drawing order. Clean text sprinkled with a repeated short line is not disorder at all, it is a header or footer that was never stripped.
- Match the fix to the symptom. For columns, rebuild the order: sort the left edges of the fragments on each page, take the widest gap as the column boundary, then sort by column, then y descending, then x ascending. For headers and footers, cut fixed bands at the top and bottom and print how many fragments you dropped so you can confirm you did not cut into the body.
- Add the production-grade part: the fix needs a regression signal, not an eyeball check. Compute an out-of-order score by walking the sorted fragments and counting backward jumps within a column plus right-to-left column jumps. It needs no ground truth, so it can run on every ingest.
- Expected follow-up: what if column detection is wrong? Keep the detector conservative, treating a narrow gap or a lopsided split as single column, and make sure the assertion still fires when a two-column page is misread as one. Missing a fix is better than silently corrupting the order.
分析过程 · 先想清楚再作答
- 这题在考你有没有真的动手解析过 PDF。区分度在第一句:能不能说出「PDF 里根本没有阅读顺序」这个前提。答不出这句的人,后面只会说「换个库试试」。
- 先给排查顺序:把抽出来的文本片段连同页码、坐标、字号一起打印出来,别只看拼好的字符串。乱序的原因几乎都藏在坐标里,看纯文本永远看不出来。
- 然后按现象分三类。左右两栏一行一行地交替,是多栏没识别;同一段话被拆成很多短片段且 y 值有回跳,是内容流按绘制顺序写的;文字整体没问题但夹着重复出现的短句,那不是乱序,是页眉页脚没剔。
- 修法对应着来:多栏就重建阅读顺序——把每页文字块的左边界排序找最大空隙当分栏线,再按「栏号、y 从大到小、x 从小到大」重排;页眉页脚按固定的 y 值带切掉,并打印剔除条数确认没误伤。
- 补一条能证明你在生产里干过的话:修完要有可回归的判据,不能靠肉眼。用乱序疑似度——顺着排好的顺序走一遍,统计「同栏内往回跳」和「从右栏跳回左栏」的比例,它不需要标准答案,可以挂进流水线天天跑。
- 可预期的追问:多栏识别错了怎么办?回答分两头——把分栏判定做保守(空隙不够宽、或者一侧内容占比太低就按单栏处理),并且让断言在双栏被误判成单栏时同样会报警,宁可漏修也不要悄悄改错。
Key points
- State the premise: a PDF stores only drawing instructions, so paragraphs and reading order are inferred, not read.
- Debug by dumping fragments with page, coordinates and font size; plain text hides the cause.
- Three common causes: undetected multi-column layout, content stream written in drawing order, and headers or footers left in.
- Fix columns by finding the widest gap between left edges and sorting by column, then y descending, then x ascending.
- Add a ground-truth-free regression metric such as an out-of-order score so the fix stays fixed.
答题要点
- 前提先说清:PDF 只存「在某页某坐标画某段文字」,段落和阅读顺序都是解析时推出来的。
- 排查时把片段连同页码、坐标、字号一起打印,纯文本看不出乱序的原因。
- 三种典型成因:多栏没识别、内容流按绘制顺序写、页眉页脚没剔除。
- 多栏的修法是找最大 x 空隙定分栏线,再按「栏号、y 降序、x 升序」重排。
- 修完要有不依赖标准答案的回归指标,比如乱序疑似度,能挂进摄取流水线。
Which metadata should a document parsing stage preserve, and which downstream feature breaks if you drop each one?文档解析阶段应该保留哪些元数据?少了其中某一项会在哪个环节出问题?
Common in ChinaCommon overseasIntermediate#metadata#ingestion#access-controlHow to reason about it · think before answering
- The trap here is answering with a bare list. The differentiator is pairing every field with a concrete downstream feature. Listing eight fields without naming who consumes them shows you never designed one.
- Give the selection rule first: can this be recovered from the original file later? If not, it must be captured at parse time. Formatting and whitespace can be dropped because the original still has them.
- Then map fields to consumers: a stable chunk id makes citations verifiable, a heading path tells the user which section a sentence came from and enables structure-aware chunking, page numbers make citations land on the right page, an access-control label enables filtering inside retrieval, an updated-at date resolves conflicting sources, and a content hash enables incremental sync.
- Take two of them all the way to cost. Without the access label you must re-parse the whole corpus when access control lands, and worse, people work around it by filtering at generation time, which means the content already reached the context and the leak already happened.
- Without a content hash, every sync is a full rebuild: re-parse, re-chunk, re-embed. For a few thousand documents synced daily, the embedding bill alone settles the argument.
- Expected follow-up: what about a field you are unsure of? Be conservative. Storage is the cheapest part of the pipeline, and adding a field costs far less than re-running a full parse.
分析过程 · 先想清楚再作答
- 这题最容易答成列清单。区分度不在你能列出几个字段,而在能不能给每个字段配一个具体的下游功能——列了八个字段却说不出谁在用,等于没设计过。
- 用一条判据把字段选出来:删掉之后还能不能从原件重新恢复。不能恢复的,解析时就必须留;能恢复的(比如格式、空白)可以放心丢。
- 然后一一对应地说:块编号支撑可验证的引用,没有它引用就只能靠模型自觉;标题路径支撑「这句话出自哪一节」和按结构切块;页码支撑引用精确到页;权限标签支撑检索层过滤;更新时间支撑材料冲突时的取舍;内容指纹支撑增量同步。
- 挑两个讲透代价。权限标签少了,等到要做访问控制时只能全量重新解析一遍;更糟的是有人会图省事在生成阶段过滤,那等于内容已经进了上下文,泄露已经发生。
- 内容指纹少了,每次同步都是全量重建:重新解析、重新切块、重新向量化。一份几千篇的知识库每天重算一次,光 embedding 的账单就够说服任何人。
- 可预期的追问:字段拿不准要不要留怎么办?答保守——存储是整条链路上最便宜的一环,加一个字段的代价远小于重跑一次全量解析。
Key points
- The rule is recoverability: if it cannot be recovered from the original later, capture it at parse time.
- Chunk ids back verifiable citations, heading paths back localisation and structure-aware chunking, page numbers make citations land precisely.
- Access-control labels must be attached during parsing, otherwise enabling ACL means re-parsing everything, and teams end up filtering at generation time where the leak has already occurred.
- Updated-at lets you present conflicting sources side by side; a content hash enables incremental sync instead of full rebuilds.
- When unsure, keep the field: storage is far cheaper than a full re-parse.
答题要点
- 判据是「删了还能不能从原件恢复」,不能恢复的必须在解析时留下。
- 块编号服务于可验证的引用,标题路径服务于定位与按结构切块,页码服务于引用精确到页。
- 权限标签必须在解析时打上,否则做访问控制时要全量重解析,且容易被错误地放到生成阶段过滤。
- 更新时间用于材料冲突时并列两种说法,内容指纹用于增量同步,少了它每次都要全量重建。
- 拿不准就保守保留:加一个字段的成本远低于重跑一次全量解析。
OCR output from scanned documents carries a non-trivial error rate. How does that noise propagate into retrieval and generation, and how do you mitigate it?扫描件走光学字符识别之后错字率不低,这些噪声会怎样影响检索和生成?怎么缓解?
Common in ChinaCommon overseasDeep dive#ocr#data-quality#hybrid-searchHow to reason about it · think before answering
- This tests whether you can trace propagation rather than recite that OCR makes mistakes. The differentiator is separating how retrieval fails from how generation fails, because the two failure modes are entirely different.
- Retrieval first. Chinese OCR errors are mostly visually similar characters. Keyword search is literal, so one wrong character makes the term unmatchable, and bigram tokenisation makes it worse because a single wrong character corrupts two adjacent tokens. Recall drops quietly and nothing raises an error.
- Generation second. The model usually reads through minor noise, but when the corrupted token is a key entity such as a name, a model number, an amount or a date, it answers confidently with the wrong value. Citation checking degrades too: verifying against a source that is itself wrong proves nothing.
- Mitigate in three layers. At ingest, use an empty-text assertion to decide whether the PDF even needs OCR, and keep a link to the original image so a human can verify.
- At retrieval, hybrid search absorbs some of the damage because dense retrieval is less sensitive to a single wrong character than literal matching. At generation, mark low-confidence pages so the answer can state that the source came from a scan and may contain recognition errors.
- Expected follow-up: can you auto-correct? Yes, but carefully. Dictionary or model based post-processing fixes some errors and breaks correct proper nouns. Restrict correction to low-confidence spans and keep the raw text so you can fall back.
分析过程 · 先想清楚再作答
- 这题考的是你会不会顺着链条推传导,而不是背「OCR 会有错字」这句废话。判据是有没有分别说清「检索侧怎么错」和「生成侧怎么错」——它们的失效方式完全不同。
- 先说检索侧。中文 OCR 的错主要是形近字,「已」认成「己」、「板」认成「版」。关键词检索是字面匹配,一个字错了这个词就查不到;更隐蔽的是二元组分词会连带毁掉相邻两个词元,一个错字影响的其实是两处。这一路的表现是召回悄悄掉下去,而且不报错。
- 再说生成侧。错字进了上下文,模型往往能读懂大意,但一旦是关键实体(人名、型号、金额、日期)出错,它会照着错的答,而且答得很自信。更麻烦的是引用校验也会跟着失效——原文本身就是错的,校验通过了也没意义。
- 缓解按三层说。入口层:先用空文本比例这类断言判断这份 PDF 有没有文本层,有就别走 OCR;真要走,保留原图链接以便人工复核。
- 检索层:靠混合检索兜底,向量一路对个别错字不敏感,能补上关键词一路的失手,这是 D9 那套东西在这里的具体价值。生成层:把低置信度的页面标出来,让模型在引用它们时明确提示「该材料来自扫描件,可能有识别误差」。
- 可预期的追问:能不能自动纠错?可以但要克制——用词典或模型做后处理会修好一批,也会「修」坏一批原本正确的专有名词。稳妥的做法是只对置信度低的片段做纠错,并且保留原文以便回退。
Key points
- Retrieval: visually similar characters break literal matching, and bigram tokenisation lets one bad character corrupt two tokens, so recall drops silently.
- Generation: the model reads through general noise but confidently repeats corrupted entities, and citation verification against a corrupted source proves nothing.
- At ingest: check for a text layer before running OCR at all, and keep the source image for human verification.
- At retrieval: hybrid search helps because dense retrieval tolerates a single wrong character better than literal matching.
- At generation: flag low-confidence sources in the answer, and restrict auto-correction to low-confidence spans while keeping the raw text.
答题要点
- 检索侧:形近字让字面匹配直接查不到,二元组分词还会让一个错字毁掉相邻两个词元,表现是召回悄悄下降且不报错。
- 生成侧:模型能读懂大意,但关键实体出错时会自信地答错,引用校验也失去意义。
- 入口层缓解:先判断有没有文本层再决定要不要 OCR,并保留原图链接供人工复核。
- 检索层缓解:混合检索里的向量一路对个别错字不敏感,能兜住关键词一路的失手。
- 生成层缓解:标出低置信度来源,让回答显式提示可能存在识别误差;自动纠错只对低置信片段做并保留原文。
Why is parsing quality the ceiling on retrieval quality? Walk through one concrete chain of propagation.为什么说解析质量决定了检索质量的上限?举一个具体的传导链条。
Common in ChinaCommon overseasBasic#ingestion#data-quality#failure-analysisHow to reason about it · think before answering
- This is a giveaway question that many people answer with a slogan. The only test is whether you produce a chain that lands on a concrete symptom instead of repeating garbage in, garbage out.
- Place it first: parsing sits before chunking, indexing, retrieval, context assembly and generation. Its errors are amplified by every later stage, and none of those stages can detect the problem because each is faithfully processing text that is already wrong.
- Give the chain: a pricing table in a PDF loses one column separator and comes out with cells shifted. Chunking splits on those wrong boundaries, so a plan name ends up next to the neighbouring column value. The index records the wrong term pairing. A user asks about that plan's storage quota, the corrupted chunk scores highest, and the model, faithfully answering only from the provided material, returns a wrong answer carrying a correct-looking citation.
- Name the nastiest part: nothing on that chain raises an error, and the answer even comes with a source, so it looks more trustworthy than usual. Parsing errors cannot be caught after the fact, only by assertions at ingest.
- Explain the word ceiling: every later optimisation, dense retrieval, hybrid search, reranking, query rewriting, improves how well you pick from the candidates. If the material itself is wrong, picking better still returns something wrong, so parsing caps all of them.
- Expected follow-up: how do you prove parsing is at fault? Reuse the habit from day one. Diagnose right to left and print the retrieved passages verbatim. If the source text is already scrambled, there is no point looking at the generation side.
分析过程 · 先想清楚再作答
- 这是一道送分题,但很多人答成口号。判据只有一个:有没有给出一条能落到具体现象上的链条,而不是重复一遍「垃圾进垃圾出」。
- 先说清位置:解析在切块、建索引、检索、组装、生成这五环之前,是第零环。它的错误会被后面每一环放大,而且后面每一环都无法察觉——它们只是在忠实地处理一段已经错了的文字。
- 给一条具体链条:一张套餐配额表在 PDF 里丢了一列分隔符,抽出来串了行;切块照着错误的边界切,「专业版」和隔壁那一栏的值被切进同一块;索引把错误的词对记进倒排表;用户问「专业版存储配额多少」,这一块分数很高被排到第一;模型只依据给定材料回答,于是给出一个错误但带着正确引用编号的答案。
- 点破最要命的一句:这条链上没有任何一环会报错,回答甚至是带出处的,看起来比平时更可信。所以解析的错误不能靠事后发现,只能靠入口处的断言拦。
- 反过来说明「上限」二字:后面所有优化——向量、混合检索、重排、查询改写——优化的都是「从候选里挑得更准」。材料本身错了,挑得再准也是错的,所以它们的天花板由解析封死。
- 可预期的追问:那怎么证明是解析的锅?答案接回 D1 那条习惯——排查从右往左看,把检索出来的原文打印出来自己读一遍,如果原文本身就是串行的,那就不用再往生成侧查了。
Key points
- Parsing is stage zero, before the five-stage pipeline; its errors are amplified downstream and invisible to every later stage.
- Concrete chain: a shifted table, chunking on wrong boundaries, wrong term pairs in the index, that chunk ranked first, and a wrong answer delivered with a citation.
- The dangerous part is that nothing errors out and the answer carries a source, so it looks more credible than usual.
- Later techniques only improve selection from candidates; if the material is wrong, better selection still returns something wrong.
- Diagnose right to left: print the retrieved passages first, and if the source text is already broken, stop looking at the generation side.
答题要点
- 解析是五个环节之前的第零环,它的错误会被后面每一环放大,而后面每一环都察觉不到。
- 具体链条:表格串行 → 切块按错误边界切 → 倒排表记进错误词对 → 检索把它排第一 → 模型据此给出带引用的错误答案。
- 最危险的是全程零报错,且答案带着出处,看起来比平时更可信。
- 后面所有优化解决的是「挑得更准」,材料本身错了就都无效,所以上限由解析封死。
- 定位方法是排查从右往左:先把检索到的原文打印出来读一遍,原文错了就不必再查生成侧。
D4 Chunking Strategies: Five Approaches — Fixed, Recursive, Structure-Based, Parent-Child, and Semantic — and Choosing by Evaluation, Not Intuition
How do you decide on chunk size? Name two metrics you would look at, and one counterexample.你怎么决定切块大小?说出你会看的两个指标和一个反例。
Common in ChinaCommon overseasIntermediate#chunking#evaluationHow to reason about it · think before answering
- The question is about method, not about a number. Answering with a specific default (512 tokens, 1000 characters) already loses it — the interviewer wants to hear that you have a procedure.
- State the tension first: large chunks dilute the signal and cost context; small chunks lose the surrounding meaning so the model cannot use them. The two metrics you name should map onto those two failure modes.
- Metric one is retrieval-side hit rate: did a document that actually answers the question make it into the context. Metric two is generation-side usability, cheaply proxied by the fraction of chunks that end mid-sentence, and more seriously by faithfulness and whether citations resolve.
- Add the point that separates candidates: both metrics must be compared under the same token budget, never under a fixed top-k. With fixed k, bigger chunks simply buy more text and win for the wrong reason.
- Make the counterexample concrete: raising chunk size from 400 to 1200 characters can lift hit rate purely because whole short documents now fit in one chunk, which means retrieval stopped doing anything and you are back to stuffing full documents. The metric improved while the system got worse.
- Expect the follow-up: where do you start on day one. Pick the strategy from the document type first (structural splitting whenever headings exist), start around 300 to 500 characters with 10 to 20 percent overlap, then build a golden set immediately and iterate. A starting point is not a conclusion.
分析过程 · 先想清楚再作答
- 这题的题眼是「怎么决定」,不是「多大合适」。答一个具体数字(512 token、1000 字符)就已经输了——面试官想看的是你有没有一套定法,而不是你记得住哪个默认值。
- 先把矛盾摆出来:块大则信噪比低、上下文贵,块小则单块缺语境、模型答不出所以然。切块大小就是在这两头之间找位置,所以两个指标必须分别对应这两头。
- 第一个指标是检索侧的命中率——答案文档有没有进上下文。第二个是生成侧的可用性,最省事的代理指标是切碎率,也就是有多少块结尾停在半句话上;再往前一步就是忠实度和引用是否可定位。
- 关键补一句:两个指标必须在**同一个 token 预算**下比,不能按「取前 k 块」比。k 固定时块越大塞进去的字越多,大块切法会赢在买得多而不是切得准上。这一句往往是这道题的区分点。
- 反例要具体。最好用的一个是:把块从 400 字调到 1200 字,命中率不降反升——但那是因为一整篇短文档被当成一块塞了进去,检索其实什么都没做,等于退化成了全文投喂。指标涨了,系统更差了。
- 可预期的追问是「那你第一次上手时从哪个数字起步」。答:先按文档类型选切法(有标题层级就按结构切),块长从 300 到 500 字起步、重叠取一到两成,然后立刻建一组标准问题跑评估,用两三轮迭代把它调到位。起步值是起步值,不是结论。
Key points
- Choose the strategy from the document type first, then tune length: split on headings whenever the structure survives parsing.
- Watch two metrics: retrieval hit rate on one side, mid-sentence break rate (then faithfulness and citation resolvability) on the other.
- Compare under an equal token budget, never a fixed top-k, or larger chunks win by buying more text.
- Counterexample: hit rate rises after enlarging chunks because whole documents now fit in one chunk and retrieval has effectively stopped working.
- Start near 300 to 500 characters with 10 to 20 percent overlap, then iterate against a fixed question set instead of guessing.
答题要点
- 先按文档类型选切法,再调长度:有标题层级就按结构切,没有结构才谈固定长度或语义。
- 看两个指标:检索侧的命中率,生成侧的切碎率(进一步是忠实度与引用可定位性)。
- 两个指标必须在同一个 token 预算下比,不能按「取前 k 块」比,否则大块只是买得更多。
- 反例:块调大后命中率上升,但那是因为整篇被当成一块,检索退化成全文投喂。
- 起步值 300 到 500 字、重叠一到两成,然后靠一组固定问题迭代,不靠直觉定稿。
What does parent-child chunking buy you, and when does it slow the system down instead?父子切块的收益是什么?它在什么情况下反而会拖慢系统?
Common in ChinaCommon overseasIntermediate#chunking#parent-childHow to reason about it · think before answering
- This question checks whether you know that the retrieval unit and the context unit can be two different things. Without that sentence, everything else is recitation.
- State the benefit compactly: small chunks go into the index so they are easy to match, and once a child is hit you follow the parent pointer and hand the model the whole section. You stop trading precision against completeness.
- Derive the slowdown from the costs. First, the context budget: every new child may drag in an entire parent, so an equal budget holds fewer distinct pieces and result diversity drops.
- Second, the write path: two levels to maintain, both recomputed on every document update, and chunk ids become harder to keep stable, which makes incremental sync noticeably more complex.
- Third, the condition under which the benefit disappears: when sections are already short, the parent and the child are nearly the same text, so you paid for two indexes and bought nothing. Parent-child suits long sections and deep hierarchies, not already fine-grained knowledge bases.
- Expect the follow-up: how is this different from simply using bigger chunks. Bigger chunks put the noise into the index; parent-child puts the noise only into the context. What gets matched stays short and clean.
分析过程 · 先想清楚再作答
- 这题考的是你有没有意识到「检索单位」和「上下文单位」可以是两个东西。答不出这句话,后面说什么都是复述。
- 收益一句话说清:小块进索引,信噪比高、容易被找到;命中之后顺着父指针把整节回填给模型,语境完整。精度和完整度这次不用二选一。
- 拖慢的场景要从代价一条条推。第一条是上下文预算:每命中一个新子块可能拖进来一整个父节,同样的 token 预算装不下几条,检索结果的多样性反而变差。
- 第二条是写入侧:父子两套都要维护,文档更新时两边都要重算,块 id 的稳定性也更难保证,增量同步的复杂度明显上升。
- 第三条是收益消失的条件:当文档本身的小节就不长时,父块和子块差不多大,你付了两套索引的钱,什么也没多买到。所以父子切块适合长节、深层级的文档,不适合结构本来就细碎的知识库。
- 可预期的追问是「那和直接把块切大有什么区别」。答:切大是把噪声一起放进索引,父子是只把噪声放进上下文、不放进索引——被检索的那一段始终是干净的短文本,这是本质区别。
Key points
- The core idea is decoupling the retrieval unit from the context unit: small chunks get found, large chunks get understood.
- The payoff is precision and completeness at the same time instead of trading one for the other.
- Cost one: a single hit can drag in a whole parent, so an equal context budget holds fewer distinct results and diversity suffers.
- Cost two: two index levels to maintain and recompute, which makes incremental sync on document updates considerably harder.
- It stops paying off when sections are already short, because parent and child are nearly identical and you bought nothing for the extra cost.
答题要点
- 核心是把检索单位和上下文单位拆开:小块负责被找到,大块负责被读懂。
- 收益是精度与完整度同时拿到,不用在信噪比和语境之间二选一。
- 代价一:一次命中可能拖进整个父节,同样的上下文预算装得下的条数变少,结果多样性下降。
- 代价二:父子两套索引都要维护与重算,文档更新时增量同步的复杂度明显上升。
- 失效场景:文档小节本来就短时父子块差不多大,多付一套成本却没多买到东西。
What overlap ratio would you use, and what concretely goes wrong when the overlap is too large?重叠区设成块长的百分之多少合适?重叠过大会带来什么具体问题?
Common in ChinaCommon overseasBasic#chunking#overlapHow to reason about it · think before answering
- This is a giveaway question, but the marks are in the second half, not the percentage. Stopping at 'usually ten to twenty percent' reads like someone who has never run it.
- Say what overlap is patching: fixed-length splitting cuts sentences in half, and overlap guarantees the broken sentence survives intact in at least one of the two neighbours. It is a patch for careless splitting, not an optimisation of its own.
- That yields the first conclusion: with structural or recursive splitting the boundaries already land on semantic positions, so the need for overlap drops sharply and can legitimately be zero. The ratio question is meaningless without naming the strategy.
- Give three concrete costs. Storage and tokens: at 400-character chunks, moving overlap from 0 to 80 grows total index tokens by roughly fifteen percent, which is storage cost in the vector store and comparison work at query time.
- Retrieval redundancy: the more neighbours overlap, the more likely the top results are three versions of the same passage. You think you handed the model three pieces of evidence; you handed it one, three times. Nothing fixes this before reranking.
- Citation resolution: when a sentence lives in two chunks, which one does the model cite. Expect the follow-up on deduplication: merge at the result layer using a content fingerprint or longest common substring, not by tweaking the chunker.
分析过程 · 先想清楚再作答
- 这是一道送分题,但送分点不在那个百分比上,而在后半句。只答「一般一到两成」就停住的人,面试官会认为他没跑过。
- 先说清重叠在补救什么:固定长度切法会把句子从中间切开,重叠让被切开的那句话至少在相邻两块之一里是完整的。它是给「乱切」打的补丁,不是一个独立的优化。
- 由此推出第一个结论:如果你用的是按结构切或递归切,边界本来就落在语义位置上,重叠的必要性会大幅下降,甚至可以是零。**重叠比例这个问题的前提是切法**,脱开切法谈比例就是背数字。
- 过大的代价要说三笔,越具体越好。存储与 token:块长 400、重叠从 0 加到 80,索引 token 会涨一成半左右,这笔钱在向量库是存储费、在检索时是比对量。
- 检索冗余:相邻块越像,前几名越可能是同一段话的三个版本,你以为给了模型三条证据,其实是一条说了三遍。这一条在重排之前基本无解。
- 引用定位:同一句话出现在两个块里,模型标出处该标哪一个,这会直接变成引用校验环节要处理的边界情况。可预期的追问就是「那你怎么去重」,答按内容指纹或最长公共子串在结果层合并,而不是在切块层想办法。
Key points
- Ten to twenty percent of chunk length is the working range, but that number assumes fixed-length splitting.
- With structural or recursive splitting the boundaries are already semantic, so overlap can be small or zero.
- Cost one: index tokens and storage grow noticeably; at 400-character chunks, an 80-character overlap adds roughly fifteen percent.
- Cost two: neighbouring chunks become near-duplicates, so the top results are several versions of one passage and the evidence diversity is illusory.
- Cost three: a sentence spanning two chunks complicates citation attribution and forces result-level deduplication.
答题要点
- 经验区间是块长的一到两成,但这个数字的前提是你用的是固定长度切法。
- 按结构或递归切时边界本来就在语义位置上,重叠可以很小甚至为零。
- 过大代价一:索引 token 与存储明显上涨,块长 400 时重叠加到 80 大约涨一成半。
- 过大代价二:相邻块高度相似,检索前几名变成同一段话的多个版本,证据多样性是假的。
- 过大代价三:同一句话跨块出现,引用标注和去重都要额外处理。
Semantic chunking costs considerably more than recursive splitting. How would you prove to your team that the money is well spent?语义切分比递归切分贵不少,你怎么向团队证明这笔钱值得花?
Common in ChinaCommon overseasDeep dive#chunking#evaluation#costHow to reason about it · think before answering
- This looks like a technical question but it tests whether you can run a controlled technical argument. Launching into how semantic chunking works answers a different question.
- Step one is to concede that it may well not be worth it. The gain comes from documents that have no usable structure; if your knowledge base is well-formed documents, the authors' heading hierarchy already did the semantic split for free and the money is likely wasted.
- Step two is translating 'worth it' into three measurable numbers: how much the metric moved (hit rate on the same golden set under the same token budget), how much latency moved (chunking is offline, but the end-to-end update path changes), and how much it costs (the initial full embedding pass plus recomputation amortised over update frequency).
- Step three is the control. Recursive splitting is the baseline, semantic chunking the treatment, and they must share the corpus, the questions, the context budget and the retriever. Change one variable only; a two-variable experiment proves nothing.
- Step four is a decision threshold rather than an impression. For example: below three points of hit-rate gain, no; above five points with recomputation inside the monthly budget, yes; in between, roll it out on one document class first. Fix the threshold before you run the numbers, or you will quietly bend it to fit them.
- Expect the follow-up: is there a cheaper way to the same gain. Yes — try structural splitting first, since it is free and often nearly as good, and if the structure really is unusable, apply semantic chunking only to the high-value subset rather than the whole corpus.
分析过程 · 先想清楚再作答
- 这题表面问技术,实际考的是你会不会做一次带对照组的技术论证。上来就讲语义切分原理的人,答的是另一道题。
- 第一步是先承认它可能不值。语义切分的收益来自「文档没有可用的结构」;如果知识库是结构良好的文档,作者的标题层级已经免费替你做完了语义切分,这时候花的钱大概率打水漂。**先说清适用前提,再谈证明,这一步就把大多数候选人区分开了。**
- 第二步是把「值不值」翻译成可测的三笔账:指标涨了多少(同一批标准问题、同一个 token 预算下的命中率)、延迟涨了多少(切块是离线的,但更新链路的端到端时间会变)、钱涨了多少(首次全量 embedding 的费用,加上按更新频率折算的重算费用)。只报第一笔的论证不成立。
- 第三步是设计对照。递归切分是基线,语义切分是实验组,两组必须用同一份语料、同一批问题、同一个上下文预算、同一个检索器,只改切法这一个变量。改两个变量的实验,结论一文不值。
- 第四步是给决策一个门槛,而不是给一个感想。比如:命中率相对基线提升低于三个百分点就不上;提升超过五个百分点且重算成本在月度预算内就上;中间地带先在一类文档上灰度。**门槛要在跑数字之前定好**,否则你会不自觉地去迁就已经跑出来的结果。
- 可预期的追问是「有没有更便宜的办法拿到同样的收益」。答有:先试按结构切,它零成本且效果常常接近;结构确实不可用时,再考虑只对高价值的那一部分文档做语义切分,而不是全量上。
Key points
- Start with the precondition: the gain comes from documents without usable structure, so on well-formed documents it usually is not worth it.
- Translate 'worth it' into three numbers — hit rate, latency, and cost. Reporting only the first is not an argument.
- Run a controlled comparison: same corpus, same golden set, same context budget, same retriever, with the splitting strategy as the only variable.
- Fix the decision threshold before running the numbers so you cannot bend it to fit the result afterwards.
- Try free structural splitting first, and if semantic chunking is genuinely needed, apply it to the high-value subset rather than the entire corpus.
答题要点
- 先讲适用前提:语义切分的收益来自文档没有可用结构,结构良好的文档上它大概率不值。
- 把「值不值」翻译成三笔账:命中率涨多少、延迟涨多少、钱涨多少,只报第一笔不算论证。
- 做对照实验:同语料、同问题集、同上下文预算、同检索器,只改切法一个变量。
- 决策门槛必须在跑数字之前定好,避免事后迁就结果。
- 先试零成本的按结构切;确需语义切分时也优先只覆盖高价值文档,而不是全量上。
D5 Vector Indexes and Store Selection: HNSW vs. Inverted File, Quantization to Save Memory, Filtered Queries and Multi-Tenant Isolation
How do you choose between an HNSW index and an IVFFlat index? Give one scenario that forces each choice, and name the parameter you would tune first in each.分层可导航小世界图和倒排文件索引你会怎么选?各说一个必须选它的场景,以及各自最该调的参数。
Common in ChinaCommon overseasIntermediate#vector-index#hnsw#ivfflatHow to reason about it · think before answering
- The differentiator is not describing both structures, it is naming the condition that forces one over the other. Saying 'HNSW is faster, IVFFlat is cheaper' is what everyone says.
- Describe the structures in one line each: HNSW is a layered neighbour graph you navigate from sparse upper layers down to dense lower ones; IVFFlat clusters vectors into lists and only scans the lists closest to the query.
- Map the knobs: HNSW builds with m and ef_construction and queries with ef_search; IVFFlat builds with lists and queries with probes. Tune the query-side knob first, because it needs no rebuild and is the only one you can still move after launch.
- Give two forcing scenarios in opposite directions. Minute-level write traffic with tight memory and a short build window forces IVFFlat, since an HNSW graph keeps growing and is expensive to rebuild. A largely static corpus with a hard latency SLA forces HNSW, since it hits the same recall at lower latency.
- Add the operational detail people forget: IVFFlat clusters reflect the data at build time, so recall degrades silently as the distribution drifts and you need a scheduled rebuild. HNSW avoids that but its index is often larger than the table.
- Expected follow-up: what are the defaults? probes is 1 and ef_search is 40. Volunteer that leaving probes at 1 means scanning a single list, which is the single most common IVFFlat mistake.
分析过程 · 先想清楚再作答
- 这题的区分度不在能不能背出两种结构,而在你会不会给出触发条件。只说「HNSW 快、IVFFlat 省内存」的人一抓一大把,面试官等的是「什么情况下我必须选另一个」。
- 先用两句话把结构说清:HNSW 是分层的邻居图,查询从稀疏的上层跳到稠密的下层,逐步逼近;IVFFlat 是先聚类成若干个列表,查询时只在最近的几个列表里扫。一个是图上导航,一个是分区搜索。
- 再把参数对应上去:HNSW 建图有 m 与 ef_construction,查询有 ef_search;IVFFlat 建索引有 lists,查询有 probes。**先调查询侧参数**,因为它不用重建索引、能逐次查询调整,是唯一一个上线之后还能动的旋钮。
- 给两个反向的必须场景:数据分钟级高频写入、且内存和建索引窗口都紧张时必须选 IVFFlat,因为 HNSW 的图会持续膨胀、重建代价高;反过来,数据相对静态、查询延迟有硬性 SLA 时必须选 HNSW,因为同等召回下它的延迟更低。
- 补一条容易被忽略的工程细节:IVFFlat 的聚类是建索引那一刻的数据决定的,数据分布漂移之后召回会悄悄下滑,所以它需要一条定期重建的运维流程;HNSW 没有这个包袱,但它的索引往往比表本身还大。
- 可预期的追问:probes 和 ef_search 的默认值分别是多少?答 1 和 40,并且要主动说出 IVFFlat 默认 probes = 1 意味着只看一个列表,建完索引不设 probes 基本等于没调过——这是新手最常见的事故。
Key points
- HNSW is a layered neighbour graph; IVFFlat clusters first and scans a subset of lists. HNSW favours query quality, IVFFlat favours build cost and memory.
- Tune the query-side knob first: ef_search for HNSW, probes for IVFFlat. Neither needs a rebuild.
- Heavy write traffic with tight memory and build windows points to IVFFlat; a static corpus with a hard latency SLA points to HNSW.
- IVFFlat clusters drift with the data and need scheduled rebuilds; HNSW does not, but its index is often larger than the table.
- Know the defaults: probes 1, ef_search 40. Leaving probes at 1 wastes the index.
答题要点
- HNSW 是分层邻居图,IVFFlat 是先聚类再局部扫描;前者查询质量优先,后者建索引与内存开销优先。
- 先调查询侧参数:HNSW 调 ef_search,IVFFlat 调 probes,两者都不需要重建索引。
- 高频写入、内存与建索引窗口紧张选 IVFFlat;数据相对静态、延迟有硬性要求选 HNSW。
- IVFFlat 的聚类会随数据漂移失真,需要定期重建;HNSW 没这个问题但索引常常比表还大。
- 默认值要记住:probes 是 1、ef_search 是 40,建完索引不调 probes 等于没用上索引的能力。
Why does a vector search with a WHERE clause return fewer results than expected, and what are the fixes and their costs?为什么加了 WHERE 条件的向量检索会漏结果?有哪几种修法,代价分别是什么?
Common in ChinaCommon overseasDeep dive#filtering#iterative-scan#recallHow to reason about it · think before answering
- This is the question that separates people who ran a demo from people who ran this in production. The tell is whether you distinguish missing rows from mis-ordered rows.
- State the mechanism in one sentence: with approximate indexes, filtering is applied after the index scan. The index first collects ef_search candidates by distance, and only then applies the WHERE clause to that batch.
- Do the arithmetic out loud: a condition matching 1% of rows against a default candidate list of 40 leaves well under one row on average. That is why the query looks broken even though the rows exist.
- Split the failure into two kinds. Too few rows returned is one; enough rows but the wrong ones ranked first is the other. They have different fixes, and conflating them signals inexperience.
- Fix one is iterative scanning, available since pgvector 0.8.0: when too many candidates are filtered out, keep scanning more of the index until enough results are found. Strict ordering keeps exact distance order, relaxed ordering trades slight reordering for better recall, and both cost latency.
- Fix two is making the filter apply first: a plain index on the filter column for highly selective conditions, a partial index when there are only a few distinct values, list partitioning when there are many. The costs are losing the approximate speedup, index count exploding per value, and DDL plus operational complexity.
- Expected follow-up: how do you pick? Check the returned row count first. Too few means iterative scanning; enough rows with low recall means raising probes or ef_search, or switching to pre-filtering.
分析过程 · 先想清楚再作答
- 这题是本天的核心,也是最能筛掉「只跑过 demo」的人的一题。题眼在「漏」这个字:能不能说清楚漏的是条数还是排序,直接决定你被归到哪一档。
- 先讲机制,一句话就够:近似索引的过滤发生在索引扫描之后。索引先按距离取回 ef_search 个候选,然后才拿 WHERE 去筛这一批。条件命中率越低,活下来的越少——命中 1% 的条件配默认的 40 个候选,平均只剩零点几条。
- 然后把漏召回拆成两类,这是拿分点:一类是**结果条数不够**,十条只给了一两条;另一类是**条数够但排序不对**,十条都在只是排错了。两类的修法完全不同,混为一谈说明没真跑过。
- 修法一是迭代扫描(pgvector 0.8.0 起):候选被过滤掉太多时自动回索引里继续扫,直到凑够。它只解决第一类。两种模式的取舍要说清楚——严格顺序保证结果按距离排好,宽松顺序允许略微乱序换更高召回,代价都是延迟明显上升。
- 修法二是预过滤,即让过滤条件先生效:条件很挑剔时给过滤列建普通索引走精确检索,取值只有少数几个时建部分索引,取值很多时按值做列表分区。代价分别是失去近似索引的加速、索引数量随取值爆炸、以及 DDL 与运维复杂度上升。
- 可预期的追问:怎么判断该用哪一种?给一条可执行的判据——先看返回条数够不够。不够是第一类,先试迭代扫描;够了但召回低是第二类,只能加大 probes 或 ef_search,或者干脆改成预过滤。
Key points
- With approximate indexes the filter runs after the index scan, so a selective condition wipes out most candidates and the query returns too few rows.
- There are two failure modes: too few rows, and enough rows in the wrong order. Always check the returned count first.
- Iterative scanning fixes only the first. Strict ordering preserves distance order, relaxed ordering gives better recall, and both raise latency noticeably.
- Pre-filtering is the alternative: index the filter column for exact search, use a partial index for a few distinct values, partition by value for many. Costs are losing the approximate speedup, index sprawl, and operational complexity.
- The second failure mode is only fixed by raising probes or ef_search; iterative scanning does nothing for it.
答题要点
- 近似索引的过滤发生在索引扫描之后,条件命中率低时候选几乎被筛光,所以返回条数不够。
- 漏召回分两类:条数不够,和条数够但排序不对。判断顺序永远是先看返回条数。
- 迭代扫描只修第一类,严格顺序保序、宽松顺序召回更高,代价是延迟明显上升。
- 预过滤是另一条路:过滤列建索引走精确检索、取值少建部分索引、取值多按值分区,代价依次是失去索引加速、索引数量爆炸、运维复杂度上升。
- 第二类只能靠加大 probes 或 ef_search,迭代扫描对它完全无效。
If you switch your vectors from full precision to half precision or binary quantisation, how do you verify that recall has not dropped materially?把向量从全精度换成半精度或二值量化,你会用什么方法确认召回没有明显下降?
Common in ChinaCommon overseasIntermediate#quantization#evaluation#recallHow to reason about it · think before answering
- The question looks like it is about quantisation, but it is really about whether you know how to evaluate. Answering 'try a few queries and eyeball it' fails immediately.
- Pin down ground truth first: it must come from an exhaustive scan with the index disabled. Using index results as ground truth is the classic self-deception, because recall then looks close to 100% no matter what you changed.
- Give the procedure: fix a query set of at least a few dozen covering short and long queries across topics, compute ground truth at full precision, rerun with the quantised representation, and report recall at k. Report index size, build time, and median plus p95 latency alongside it, because recall alone is not a decision.
- Add the judgement rule: quantisation loss depends on your vector distribution, so published numbers do not transfer. Sparse vectors suffer badly under binary quantisation because only the sign bit survives and zeros collapse together.
- Land on something actionable: half precision is usually near lossless and raises the indexable dimension ceiling from 2000 to 4000, so it is a safe first step. Binary quantisation loses real recall and should be used as a cheap first pass, re-ranked with the original vectors over a wider candidate window.
- Expected follow-up: how much loss is acceptable? It depends on what comes next. With a re-ranker downstream, a couple of points off first-stage recall is usually invisible; if retrieval feeds the prompt directly, one point means one more unanswerable question per hundred. Tie the threshold to a product metric, not to a number you made up.
分析过程 · 先想清楚再作答
- 这题表面问量化,实际问的是你会不会做评估。只回答「跑几个问题看看结果对不对」的人会被直接判为没做过——面试官想听的是一套可复现的量法。
- 先把真值这件事说死:真值必须来自暴力全量比对,也就是把索引关掉、全表算距离取前 k。拿索引结果当真值是最常见的自欺,因为那样量出来的召回永远接近 100%,你会以为量化无损。
- 然后给流程:固定一批查询(几十条起步,覆盖长短查询和不同主题),先用全精度算出真值,再换量化重跑,计算召回率@k。同时记录三件事——索引大小、建索引耗时、查询延迟的中位数与 p95,只报召回是不够的。
- 补一条判据:量化损失有多大取决于向量分布,别人的数字不能抄。稀疏向量对二值量化尤其不友好,因为二值化只保留符号位,零和负数会被压成同一个值,信息几乎被抹平。所以换方案必须在自己的数据上重新量一次。
- 结论要给可操作的建议:半精度通常近乎无损,还能把建索引维度上限从 2000 提到 4000,是默认可以先上的一档;二值量化损失明显,标准用法是拿它粗筛一批候选,再用原始向量在这一小批里精排,粗筛窗口越宽召回补得越多、延迟也越高。
- 可预期的追问:召回掉了多少算可以接受?答这取决于下游——后面还有重排时,粗排召回掉两三个点通常无感;如果检索结果直接进提示词,掉一个点就意味着每一百次回答里多一次缺材料。要把这个判断挂到业务指标上,而不是拍一个阈值。
Key points
- Ground truth must come from an exhaustive scan with indexes disabled; using index output as truth pins recall near 100%.
- Run one fixed query set before and after, report recall at k together with index size, build time and latency percentiles.
- Quantisation loss depends on your own vector distribution, so measure it on your data instead of quoting benchmarks.
- Half precision is usually near lossless and raises the indexable dimension limit from 2000 to 4000, making it a safe default.
- Binary quantisation loses real recall; use it as a cheap first pass and re-rank with the original vectors over a wider window.
答题要点
- 真值必须来自关掉索引的暴力全量比对,拿索引结果当真值会让召回永远接近 100%。
- 固定一批查询,量化前后跑同一批,报召回率@k,同时报索引大小、建索引耗时和延迟分位数。
- 量化损失取决于向量分布,别人的数字不能抄,必须在自己的数据上重新量。
- 半精度通常近乎无损,还能把索引维度上限从 2000 提到 4000,可以作为默认第一档。
- 二值量化损失明显,正确用法是粗筛加原始向量重排,粗筛窗口越宽召回补得越多、延迟越高。
When should you move your vectors out of PostgreSQL into a dedicated vector database? Give measurable triggers, and also make the case for staying.什么时候应该把向量搬出 PostgreSQL?给出可量化的触发条件,也说说不该搬的理由。
Common in ChinaCommon overseasIntermediate#vector-database#architecture#trade-offsHow to reason about it · think before answering
- This tests engineering judgement, not tooling preference. Opening with 'dedicated vector databases are better' invites follow-ups you cannot answer.
- State the default position and justify it: keep the first version in PostgreSQL, because transactions, backups, point-in-time recovery, permissions, joins with business tables and the tooling your team already knows all come free. A second datastore adds synchronisation, a consistency surface and an on-call burden that selection documents rarely price in.
- Then give four measurable triggers: data volume (the test is whether the index still fits in memory, not the raw row count), write frequency (minute-level streaming updates distort clusters and inflate graphs), filter complexity (arbitrary combinations of a dozen attributes defeat both partial indexes and partitioning), and operational capacity.
- Expand on filter complexity, because it is most often the real reason: dedicated vector databases push filtering into the index structure instead of applying it after the scan, which is a mechanical advantage rather than a reputational one.
- Volunteer the alternative people skip: many 'vector search is not good enough' problems are actually solved by hybrid retrieval plus re-ranking, not by a new database. Add the keyword path and a re-ranker first, then decide.
- Expected follow-up: how would you migrate? Dual-write, compare recall and latency on shadow traffic, shift read traffic gradually, and only then retire the old path. Stop at any step where the metrics regress.
分析过程 · 先想清楚再作答
- 这题考的是工程判断,不是技术偏好。开口就说「专用向量库更专业」的人会被追问到答不上来;面试官想看的是你有没有把迁移成本算进去。
- 先给默认立场并给出理由:第一版留在 PostgreSQL,因为事务、备份、时间点恢复、权限、跟业务表 JOIN 和现成的运维工具全是白送的。多一个数据库就多一份同步、一份一致性问题、一份值班负担,这些成本很少被写进选型文档。
- 然后给四条可量化的触发线:数据量(判据不是行数而是索引还塞不塞得进内存)、写入频率(分钟级流式更新会让聚类失真、让图持续膨胀)、过滤复杂度(十几个属性的任意组合让部分索引和分区都排列组合不过来)、团队运维能力(没人愿意长期照看第二个数据库,前三条再成立也别搬)。
- 第三条要展开一点,因为它最常是真正的原因:专用向量库把过滤做进了索引结构本身,而不是扫完索引再筛,所以在复杂过滤下天然占优。把这一点说出来,说明你理解的是机制而不是口碑。
- 还要主动给一条常被忽略的替代路径:很多「向量检索不够用」的问题,真正的解法是混合检索加重排,而不是换数据库。先把关键词一路加回来、把重排接上,再决定要不要搬——顺序搞反了会白搬一次。
- 可预期的追问:真要搬怎么迁?答分三步——先双写并在影子流量上比对两边的召回与延迟,再把读流量按比例切过去,最后才停掉旧路径。中间任何一步指标不达标就停下,这比一次性切换安全得多。
Key points
- Default to staying in PostgreSQL: transactions, backups, recovery, permissions, joins and familiar tooling are free, and a second store adds sync and on-call cost.
- Trigger one is data volume, measured by whether the index still fits in memory rather than by row count.
- Trigger two is write frequency: minute-level streaming updates distort clusters and inflate graphs.
- Trigger three is filter complexity: dedicated stores push filtering into the index structure, a mechanical advantage under complex predicates.
- Trigger four cuts the other way: without people to run a second database, do not move even if the first three hold. Often hybrid retrieval plus re-ranking is the real fix.
答题要点
- 默认留在 PostgreSQL:事务、备份、恢复、权限、JOIN 和现成运维都是白送的,多一个库就多一份同步与值班成本。
- 触发线一是数据量,判据是索引还塞不塞得进内存,而不是行数本身。
- 触发线二是写入频率,分钟级流式更新会让聚类失真、让图持续膨胀。
- 触发线三是过滤复杂度,专用库把过滤做进索引结构,复杂过滤下有机制上的优势。
- 触发线四反过来看:没有长期运维第二个数据库的人手,前三条成立也不该搬;很多问题的真正解法是混合检索加重排。
D6 The Generation Side: Ordering Context, Labeling Citations, When You Must Refuse to Answer, and Streaming Responses
How do you make sure a model's citations are real rather than fabricated? Describe a scheme that does not rely on the model behaving well.怎么让模型的引用是真的而不是编的?说出一个不依赖模型自觉的方案。
Common in ChinaCommon overseasIntermediate#citation-verification#grounding#hallucinationHow to reason about it · think before answering
- The phrase to catch is 'not relying on the model behaving well'. Any answer that boils down to 'tell the model to be accurate in the prompt' fails, because the prompt is exactly the part that cannot enforce this.
- Split the problem in two. Verifiability requires that a citation be a symbol from a closed set, not free text. So step one is numbering the blocks at assembly time and telling the model it may only cite the numbers it was given. 'According to the storage handbook' cannot be checked, because the title is a string the model can invent.
- Step two is post-hoc checking, with two gates. Gate one is existence: you handed out 1 through 5, so an 8 is fabricated, and that is a one-line check. Gate two is substantive overlap, which catches the sneakier case where the number is real but the block says something else. Measure what fraction of the sentence's terms appear in the cited block and reject below a threshold.
- Mention the trap in the overlap metric: drop terms that appear in most blocks first, otherwise generic words let any citation pass. It is the same reasoning behind inverse document frequency in BM25.
- On failure, feed the specific reason back and regenerate once, not repeatedly. Two fabricated drafts in a row means the material does not support the question, so refuse instead. Also verify against the original chunk text, never against a compressed or rewritten version, otherwise 'verified' says nothing about what the user sees.
- Expected follow-up: why not ask the model to self-check? Self-checking shares the generator's bias and has no independent source of truth, whereas number checking is deterministic, essentially free, and reproducible.
分析过程 · 先想清楚再作答
- 题眼在「不依赖模型自觉」这半句。回答里只要出现「在提示词里强调请确保引用准确」,这题就答砸了——面试官问的正是提示词管不住的那部分。
- 先把问题拆成两半:引用要能验证,前提是它是一个**闭集里的符号**,不是一段自由文本。所以第一步是组装上下文时给每块材料一个编号,提示词里明确只能引用发出去的编号。让模型写「根据《某某手册》」是没法验证的,标题是它可以随口生成的字符串。
- 第二步是事后核对,两道闸缺一不可。第一道查编号存在性:发出去的是 1 到 5,出现 8 就一定是编的,一行代码判掉。第二道查实质重合:编号是真的、内容却对不上,这类更隐蔽,要算这句话的词元有多大比例能在被引块原文里找到,低于阈值判不通过。
- 算重合度时有个坑要主动说出来:先剔掉在多数块里都出现的高频词元,否则「文件」「系统」这种词会让随便哪一块都及格。这跟 BM25 用逆文档频率压常见词是同一个道理。
- 校验不过怎么办:把具体原因写成反馈打回去重生成一次,只给一次机会;连着两版都编说明材料本来就不支持,该走拒答而不是第三次重试。另外校验必须拿原文比对,不能拿压缩或改写过的材料比对,否则「校验通过」保证不了用户点开看到的东西。
- 可预期的追问:为什么不让模型自己再检查一遍?因为自检和生成是同一个模型的同一种倾向,它对自己编的东西没有独立信息源;而编号核对是一个确定性判断,成本几乎为零、结果可复现,这两点自检都做不到。
Key points
- Citations must be closed-set symbols such as block numbers, not free-text titles: verifiability comes from the closed set, not from wording.
- Two gates: the number must exist, and the sentence must substantively overlap the cited block's original text, which is what catches real-number-wrong-content fabrication.
- Strip terms that occur in most blocks before scoring overlap, or any citation will pass.
- On failure, regenerate once with the concrete reason fed back; two bad drafts means refuse instead.
- Always verify against the original text the user can open, never against a compressed or rewritten copy.
答题要点
- 引用必须是块编号这种闭集符号,不能是自由文本的文档标题——可验证性来自闭集,不来自措辞。
- 两道闸:编号存在性,以及这句话与被引块原文的实质重合度,后者才拦得住「编号是真的、内容对不上」。
- 算重合度前剔掉在多数块里都出现的高频词元,否则随便引哪一块都能及格。
- 校验不过就带着具体原因打回重生成一次,只给一次机会,两版都编就转拒答。
- 校验对象必须是用户能点开看到的原文,不是压缩或改写后的材料。
Does the ordering of retrieved passages in the context affect answer quality? If so, how would you order them?上下文里材料的排列顺序会影响回答质量吗?如果会,你会怎么排?
Common in ChinaCommon overseasBasic#context-assembly#prompt-engineering#orderingHow to reason about it · think before answering
- This is a warm-up question, but 'sort by relevance descending' only earns half the credit. The interviewer wants to know whether you treat position itself as a variable.
- State the conclusion first: it does matter. Models attend more reliably to material at the start and the end of the context, and are most likely to miss what sits in the middle. Plain descending order therefore parks your second-best passage in the worst spot.
- Give the ordering: rank one first, rank two last, rank three second, rank four second-to-last, folding inward. Whatever ends up in the middle is by construction the least important, so the cost of it being skipped is smallest.
- Round it out with the other assembly steps, which shows you have written this code: a deterministic tiebreaker (otherwise block numbers drift between runs and your logs stop matching), dedupe on normalised text, and a token budget that skips rather than stops when a block does not fit.
- Expected follow-up: how would you verify this? Do not guess. Hold the question set fixed, vary only the ordering, and measure. Position effects differ by model and context length, so treat it as a parameter to measure on your own data rather than a universal law.
分析过程 · 先想清楚再作答
- 这是一道送分题,但答成「按相关性从高到低排」就只拿到一半分。面试官想听的是你知不知道位置本身是个变量。
- 结论先说:会影响。模型对上下文开头和结尾的材料明显更敏感,正中间的最容易被读漏。所以简单按分数从高到低顺排,等于把第二重要的材料放进了最不容易被读到的位置。
- 给出排法:第 1 名放开头、第 2 名放结尾、第 3 名放第二位、第 4 名放倒数第二位,依次往里收。这样按分数排下来越靠中间的块本来就越不重要,被读漏的代价最小。
- 顺带把排序之外的三道手续说全,显得你真的写过这段代码:同分要有决胜键(否则块编号会在两次运行之间飘,日志对不上)、要按归一化文本去重(同一段话常在手册和问答里各出现一次)、要有 token 预算并且塞不下时不要直接停。
- 可预期的追问:这个结论怎么验证?答案是别猜——固定一批问题,只改排列顺序跑对照,看指标差多少。位置效应在不同模型、不同上下文长度上强弱不一样,把它当成一个要在自己数据上量的参数,而不是一条普适定律。
Key points
- Yes: material at the head and tail is used more reliably, the middle is most often skipped.
- Put the strongest at both ends: rank one first, rank two last, rank three second, folding inward.
- Assembly also needs a deterministic tiebreaker for stable numbering, dedupe on normalised text, and a token budget that skips oversized blocks instead of stopping.
- The strength of the effect varies by model and context length, so measure it on your own data instead of quoting it as a law.
答题要点
- 会影响:开头和结尾的材料更容易被用上,正中间的最容易被读漏。
- 排法是最重要的放两端:第 1 名开头、第 2 名结尾、第 3 名第二位,依次往里收。
- 组装还要做三件事:同分给决胜键保证编号稳定、按归一化文本去重、控 token 预算且塞不下时跳过而不是终止。
- 位置效应的强弱因模型与上下文长度而异,要在自己的数据上做对照实验量出来,不能当普适定律照搬。
How do you set the refusal threshold for a knowledge-base assistant, and what does it cost you when the threshold is too high or too low?知识库问答的拒答阈值怎么定?定高了和定低了各自的代价是什么?
Common in ChinaCommon overseasDeep dive#refusal#thresholds#evaluationHow to reason about it · think before answering
- What is really being tested: do you know that refusal is several rules rather than one threshold, and do you set thresholds from data. An answer that mentions only a score cutoff shows you have only touched the surface.
- Break refusal into three rules with different timing. Score too low: decidable before generation, saving a model call. Sources conflict: also decidable before generation, by finding differing numbers about the same thing across blocks. You then either present both with their update dates, or pick the newer one when an authoritative signal backs it, such as meeting notes that flagged the discrepancy. Which of the two is a product decision, but silently letting the model pick is never an option. Question outside coverage: only decidable after generation, when citation verification leaves you with zero verified citations.
- Stress that the three responses must read differently. 'Nothing relevant in the knowledge base, try rephrasing or check whether the document was ingested' is a different instruction to the user than 'we found related documents but none of them answers this'. Collapsing both into 'sorry, I don't know' throws away information.
- Then the cost half. Too high: answerable questions get blocked, the user is told nothing was found while the material is in fact indexed. That is the most trust-damaging failure and it is nearly invisible in logs. Too low: weak passages enter the context and the model answers from irrelevant material, which is worse because the answer still looks cited.
- How to set it: run a set of questions with known answers and known non-answers, look at where the two score distributions separate, and pick a point according to which error you fear more. Scores have no absolute scale, so the deliverable is the procedure, not the number.
- Expected follow-up: what if one score threshold is not enough? Add signals rather than tuning the number: the gap between top and second score, the number of hits above threshold, and the post-generation verification result are all steadier than the raw score.
分析过程 · 先想清楚再作答
- 这题真正在考的是:你有没有意识到拒答不是一个阈值,而是好几条判据;以及你定阈值靠不靠数据。只谈一个分数阈值的回答,说明只做过最浅的一层。
- 先把拒答拆成三条线,它们的触发时机完全不同。检索分数太低:生成之前就能判,省一次模型调用。材料互相矛盾:也在生成之前判,代码在块之间找同一件事的不同数字,检出后要么并列两种说法与各自的更新日期,要么在有权威信号(比如一份点破了这条不一致的会议纪要)时按更新日期择一——选哪条是产品决策,但无论如何不能让模型自己悄悄挑一个。问题超出材料覆盖范围:只能在生成之后判,判据是跑完引用校验一条有效引用都没有。
- 强调三种话术必须不同。第一种要说「库里没有相关材料,换个说法或确认资料是否入库」,第三种要说「找到了相关文档但里面没有能直接回答的内容」——用户的下一步动作完全不同,混成一句「抱歉我不知道」等于把信息扔了。
- 再答代价这一半。定高了:能答的问题被挡在门外,用户看到查不到而材料其实在库里,这是最伤信任的一种错,而且它在日志里几乎不可见。定低了:低分噪声材料进上下文,模型拿着不相关的东西硬答,错误反而更隐蔽,因为回答看起来还带着引用。
- 怎么定:拿一批已知有答案和已知没答案的问题跑一遍,看两组的分数分布在哪里分开,按你更怕哪种错来取点。分数是没有绝对量纲的,换语料、换检索方式都要重定,所以真正要交付的是这套定阈值的流程,不是那个数字。
- 可预期的追问:单一分数阈值不够怎么办?答案是加判据而不是调数字——最高分与次高分的差、命中块数、以及生成后的引用校验结果,都是比原始分数更稳的信号。
Key points
- Refusal is three rules, not one: low score and source conflict decided before generation, out-of-coverage decided after generation from the verification result.
- On conflict, presenting both versions versus picking the newer one is a product decision; picking only holds up when an authoritative signal backs it.
- The three responses must be worded differently because each implies a different next action for the user.
- Too high blocks answerable questions; the user is told nothing exists while it does, which is the most damaging and least visible failure.
- Too low lets weak passages in, producing errors that are harder to spot because the answer still carries citations.
- Set it by comparing score distributions over answerable and unanswerable question sets, then choose based on which error is worse; re-tune whenever the corpus or retriever changes.
答题要点
- 拒答不是一条线而是三条:分数过低、材料冲突(都在生成前判)、超出材料覆盖范围(只能生成后按引用校验结果判)。
- 冲突检出后并列两说还是按更新日期择一,是产品决策;只有在有权威信号背书时择一才站得住,否则老实并列。
- 三种情况的话术必须不同,因为它们给用户的下一步动作不同。
- 定高了会把能答的问题挡住,用户看到查不到而材料其实在库里,最伤信任且日志里看不见。
- 定低了会让噪声材料进上下文,错误更隐蔽,因为回答看起来仍然带着引用。
- 定法是拿已知有答案与已知没答案的两组问题跑分数分布,按更怕哪种错取点;换语料或换检索方式都要重定。
In a streaming setup, how do you make sure nothing you have already sent needs to be retracted because its citation failed verification?流式输出的场景下,你怎么保证吐出去的内容不会因为引用校验失败而需要撤回?
Common in ChinaCommon overseasDeep dive#streaming#citation-verification#api-designHow to reason about it · think before answering
- This tests a real architectural conflict: streaming wants the first token out early, citation verification cannot run until a statement is complete. Listen for whether the candidate names the trade-off and prices it.
- Name the conflict: once a token reaches the browser you cannot take it back. Discovering at the end that the third sentence cited a fabricated block leaves you posting 'please ignore that last sentence', which is worse than not streaming at all.
- Give the solution: buffer by sentence. As soon as a complete sentence lands, verify it, and only then emit it together with its verified citations; drop the whole sentence otherwise. The cost is that time-to-first-token becomes time-to-first-sentence, typically a few hundred milliseconds, which users barely notice, whereas a bad citation on screen costs trust.
- Add two implementation details that prove you have built it. Streaming cannot use JSON output because JSON is only parseable once closed, so switch to plain text with inline markers, while keeping exactly the same verifier as the non-streaming path. Strip the markers out of the prose and send the numbers as structured data after verification.
- Add the ordering point: the two rules decidable before generation, low score and source conflict, should be emitted before the stream starts, so the user never sees half an answer being withdrawn. The rule that needs generation shows up as 'no sentence was ever emitted', so close the stream with a refusal event.
- Expected follow-up: does this kill the streaming feel? No. Sentence-level streaming is still visibly progressive on long answers. If you need finer granularity, stream a 'checking sources' placeholder, but never stream unverified prose.
分析过程 · 先想清楚再作答
- 这题在考一个真实的架构矛盾:流式要尽早出字,引用校验要等话说完才能核对。看回答里有没有出现「取舍」两个字,以及有没有把代价说清楚。
- 先说清矛盾在哪:一旦一个 token 发到了浏览器就撤不回来,你在末尾才发现第三句引用是编的,那句话已经在用户屏幕上了,只能补一句「刚才那句请忽略」,体验比不流式还糟。
- 给方案:按句缓冲。攒够一个完整句子就立刻校验一次,通过了才把这句连同已核实的引用发出去,没通过就整句丢掉。代价是首字延迟从一个 token 变成一句话,通常两三百毫秒,用户几乎察觉不到,而错误引用一旦上屏赔的是信任。
- 补两个实现细节,它们能证明你写过:流式模式没法用 JSON 输出(要等右花括号闭合才能解析),所以改成纯文本加行内标记,但校验必须和非流式共用同一套;标记要从正文里剥掉,正文保持干净,编号单独走校验再作为结构化数据发出去。
- 再补一条顺序上的讲究:生成前就能判的两条拒答线(分数过低、材料冲突)要在流开始之前发出去,用户不会先看到半句回答再被收回;生成后才能判的那条,在按句缓冲之下表现为一句都没发出来,收尾补一个拒答事件即可。
- 可预期的追问:那用户体验上的流式感是不是就没了?没有,句级流式在中文长回答里仍然是明显的渐进呈现;真要更细,可以在句子发出前先流一个「正在核对」的占位态,但不要流未校验的正文。
Key points
- The conflict: emitted text cannot be recalled, while a citation can only be checked once its sentence is complete.
- The fix is sentence-level buffering: verify each completed sentence, emit only if it passes, drop the whole sentence if it does not.
- The cost is time-to-first-sentence instead of time-to-first-token, which is affordable and worth paying.
- Streaming cannot use JSON, so use inline markers in plain text while sharing one verifier with the non-streaming path; strip markers from the prose and send numbers as structured data.
- Emit pre-generation refusals before the stream opens; the post-generation one manifests as an empty stream and is closed with a refusal event.
答题要点
- 矛盾在于发出去的内容撤不回来,而引用只有一句说完才能核对。
- 解法是按句缓冲:攒够一句校验一次,通过才发,没通过整句丢掉。
- 代价是首字延迟从一个 token 变成一句话,这个代价必须付也付得起。
- 流式用不了 JSON,改纯文本加行内标记,但校验逻辑与非流式共用同一套;标记从正文剥出,编号作为结构化数据单独发。
- 生成前能判的拒答要在流开始之前发出去,生成后才能判的那条以「一句都没发」的形式收尾补事件。
D7 Week One Capstone: Assembling Six Days of Parts Into a One-Command Question-Answering Service, and a Retrospective
How would you draw the module boundaries of a RAG system, and which layer most needs to be swappable? Why?你会怎么划分一个检索增强生成系统的模块边界?其中哪一层最应该做成可替换的,为什么?
Common in ChinaCommon overseasBasic#architecture#modularity#embeddingsHow to reason about it · think before answering
- This question separates people who have maintained such a system from people who have only built a demo. Reciting the pipeline diagram is not an answer; where you cut it is.
- Offer a reusable criterion first: cut where a layer is most likely to be replaced wholesale, not by lines of code or by tidy functional names.
- Apply it. Embedding models change several times a year, and each change invalidates every stored vector, so that layer must be an interface. Storage may move from PostgreSQL to a dedicated vector database, and both ingestion and query talk through it, so it is the single shared boundary. Chunking changes daily during tuning, so it belongs in config, not in code.
- Conclusion: the embedding layer is the one that must be swappable, because the swap is both likely and expensive, not because interfaces are good style.
- Name the cost of abstraction too: every indirection is one more hop while debugging, so the test is whether the change will actually happen.
- Expected follow-up: should the generation model be abstracted as well? Yes, but at lower priority, because swapping it does not force recomputation of stored data and rollback is cheap. It is a config value, not a layer.
分析过程 · 先想清楚再作答
- 这题考的是你有没有真的维护过这类系统。只按「解析、切块、检索、生成」复述一遍流程图,面试官会判定你只搭过 demo——流程图人人都会画,切口画在哪才是经验。
- 给一条可复用的判据再往下推:切口应该落在「将来最可能被整个换掉」的地方,而不是按代码量或者功能名称均分。
- 用它过一遍:embedding 一年会换好几次,换一次库里所有向量作废、必须全量重算,所以它必须是接口;存储可能从 PostgreSQL 换成专用向量库,而且摄取和查询都要通过它,所以它是两条链路的唯一交界;切块策略在调优期天天改,所以它必须是配置项而不是硬编码。
- 结论:最该做成可替换的是 embedding 那一层,理由不是「设计模式」,而是「换模型这件事真的会发生,且发生时代价极高」。
- 顺手点出抽象的代价:每多一层间接就多一次跳转和一份心智负担,所以判据是「那件事会不会真的发生」,不会发生的别抽象。
- 可预期的追问:那生成模型要不要也抽象?答案是要,但优先级低——换生成模型不需要重算任何存量数据,回滚也便宜,所以它是配置项而不是一层接口。
Key points
- Lead with the criterion: cut where a layer is most likely to be replaced wholesale.
- The embedding layer is the one to abstract: swapping models invalidates every stored vector and forces a full recompute.
- Storage is the single boundary shared by ingestion and query, so define its interface before either implementation.
- Chunking and retrieval routes belong in configuration because they change most often during tuning.
- Abstraction costs indirection, so only abstract changes that will actually happen.
答题要点
- 先给判据:切口落在最可能被整体替换的那一层,不按代码量或功能名称均分。
- embedding 是最该抽象的一层:换模型意味着存量向量全部作废、必须全量重算,代价高且真的会发生。
- 存储层是摄取与查询唯一的交界,接口要先定下来再谈两边实现。
- 切块与检索路数做成配置项,因为它们在调优期改动最频繁,改一次不该动代码。
- 抽象有成本,判据是那件事会不会真的发生;不会发生的抽象就是过度设计。
What should the ingestion path and the query path share, and what concretely goes wrong when you over-share?摄取链路和查询链路应该共享哪些代码?强行复用会带来什么具体问题?
Common in ChinaCommon overseasIntermediate#architecture#ingestion#retrievalHow to reason about it · think before answering
- The word to notice is 'over-share'. The interviewer wants the boundary, not a recital of DRY.
- Start from how the two paths differ. Ingestion is batch: tens of seconds, and a failure just means rerunning it. Query is online: hundreds of milliseconds, and a failure is visible to the user immediately. Error handling, timeouts and concurrency are simply not the same problem.
- Hence the rule: share the interface, not the flow. The only genuinely shared thing is the storage interface, plus the embedding function signature.
- Name the symptom of over-sharing: the extracted module fills up with isIngest branches, every change has to be verified on both paths, and eventually nobody dares touch it.
- Add the one thing that truly must match: chunks and queries must be embedded by the same model. That is shared configuration, not shared code, and the model name belongs in the vector table so a silent mismatch is detectable.
- Expected follow-up: what about chunking? The query path never chunks. Even when it needs a parent block, it reads it back through storage rather than importing the chunker.
分析过程 · 先想清楚再作答
- 题眼在「强行」两个字。面试官想看的是你能不能说出复用的边界,而不是背诵「不要重复自己」。
- 先说清两条链路的性质差异:摄取是批处理,几十秒跑完,失败重跑一遍就行;查询是在线请求,几百毫秒要出结果,失败用户当场看到。错误处理、超时、并发策略天然不同。
- 所以结论是:**共享接口,不共享流程**。两边唯一该共享的是存储层的那个接口,以及 embedding 的函数签名——注意后者共享的是签名和模型选择,不是调用流程。
- 给出强行复用的具体症状:抽出来的公共模块里开始出现 isIngest 这类分支,一个改动要同时验证两条链路,最后没人敢动它。
- 补一条真正必须一致的东西:给块算向量和给问题算向量必须用同一个模型。这不是复用代码,是复用配置——而且要把模型名写进向量表,否则模型换了没人发现,检索会静默地返回垃圾。
- 可预期的追问:那切块逻辑呢?查询侧压根不切块,所以它只属于摄取链路;真要在查询侧用到(比如 D11 的父子回填),走的也是存储层读回大块,不是把切块器搬过来。
Key points
- Share the interface, not the flow: storage is the only boundary, plus the embedding signature.
- The two paths have different error handling and latency budgets; batch can rerun, online must fail fast.
- Over-sharing shows up as isIngest branches and changes that must be verified twice.
- What must match is the model choice, not the code: record the model name alongside every stored vector.
- Chunking belongs to ingestion only; the query path reads larger units back through storage.
答题要点
- 共享接口不共享流程:唯一的交界是存储层,加上 embedding 的函数签名。
- 两条链路的错误处理与延迟约束根本不同,批处理可以重跑,在线请求必须快速失败。
- 强行复用的症状是公共模块里长出 isIngest 分支,改一次要验两条链路。
- 必须一致的是模型选择而不是代码:块与查询要用同一个 embedding 模型,并把模型名记进向量表。
- 切块只属于摄取;查询侧需要大块时通过存储层读回,而不是把切块器搬过去。
What three checks would you run before shipping a retrieval QA service, and why those three?一个检索问答服务上线前你会做哪三项检查?为什么偏偏是这三项?
Common in ChinaCommon overseasIntermediate#production-readiness#citations#refusalHow to reason about it · think before answering
- The discriminator is not how many checks you list but whether you can justify the three. Ten items with no ranking suggests you have never had to prioritise.
- Derive them by consequence: the failures that are invisible to users and most damaging go first.
- First, citations must be verifiable: every cited id resolves to a real chunk, and that chunk genuinely overlaps the sentence citing it. This ranks first because a wrong citation is undetectable by the user, and citations are the only source of trust this system has.
- Second, refusal must actually fire: ask a question the corpus cannot answer and confirm the system says so instead of inventing. Also invisible, and one discovered fabrication zeroes out trust in the whole product.
- Third, ingestion-to-retrieval consistency: freshly ingested documents are retrievable immediately, and the keyword and vector paths cover the same set. This guards against the 'one route finds it, the other does not' failure, which is the hardest to diagnose.
- Expected follow-up: why not latency and cost? Because those failures are visible. Users complain about slowness and the bill reports overspending; nobody will ever report the three above.
分析过程 · 先想清楚再作答
- 这题的区分度不在你能列几项,而在你能不能说清「为什么是这三项」。列十项而每项都不给理由,反而说明你没有排过优先级。
- 推导方式是按后果排序:哪种故障用户看不出来、又损失最大,哪一项就该排在前面。
- 第一项是引用可查证:每条引用的编号都能回查到真实存在的块,且那一块确实与该句有实质重合。这一项排第一是因为引用错了用户根本发现不了,而它恰恰是这类系统唯一的信任来源。
- 第二项是该拒答时真的拒答:构造一个语料里没有答案的问题,看它是回那句拒答话术还是开始编。这一项也属于用户看不出来的故障,且一旦编造被发现,整个系统的可信度归零。
- 第三项是摄取到检索的一致性:摄取完之后新文档立刻能被检索到,且关键词与向量两路的覆盖数量对得上。这一项防的是「一路能查一路查不到」这种最难排查的故障。
- 可预期的追问:为什么延迟和成本不在前三?因为它们是**看得见**的故障——慢了用户会抱怨,贵了账单会告诉你;而上面三项不检查就永远不会有人告诉你。
Key points
- State the ranking rule first: prioritise failures users cannot see but that cost the most.
- Check one, verifiable citations: every id resolves to a real chunk that overlaps the sentence citing it.
- Check two, refusal actually fires on a question the corpus cannot answer.
- Check three, ingestion and retrieval agree: new documents are immediately retrievable on both routes.
- Latency and cost matter but rank lower because those failures announce themselves.
答题要点
- 先给排序依据:优先检查用户发现不了、但后果最重的故障。
- 第一项引用可查证:编号能回查到真实的块,且该块与被引的那句话有实质重合。
- 第二项拒答生效:用一个语料里没有答案的问题验证系统会说查不到,而不是开始编。
- 第三项摄取与检索一致:新入库的文档立刻可检索,关键词与向量两路覆盖对得上。
- 延迟和成本重要但排在后面,因为它们是看得见的故障,会自己找上门。
What is the biggest risk in the RAG service you just assembled, and how would you prove that judgment?你刚拼出来的这个检索问答系统,现在最大的风险在哪里?你打算怎么证明这个判断?
Common in ChinaCommon overseasDeep dive#evaluation#risk-assessment#retrospectiveHow to reason about it · think before answering
- There are two halves here and the second is the real question. Naming a risk is easy; giving a method that could falsify your own claim is what separates answers from opinions.
- Rule out two common wrong answers: 'hallucination' is too vague to act on, and 'latency' mistakes a visible problem for the biggest one.
- The biggest risk is the absence of evaluation. Chunk size, top-k, thresholds and route weights were all guessed, and that makes every other risk unverifiable: you cannot even say whether a change helped.
- How to prove it: build a question set from the corpus with known answer documents, deliberately including unanswerable and multi-hop questions; implement recall and ranking metrics; produce a baseline for the current configuration; then move one parameter back and forth and watch whether the metrics move. If they do not move at all, the evaluation set is wrong, not the system.
- Add the accounting rule: every optimisation reports three numbers, metric gain, latency added and cost added. A claim with only the first is not usable.
- Expected follow-up: how large must the set be? Start with roughly twenty questions covering the main question types to catch obvious regressions, then grow toward the real distribution once you have actual user questions. Chasing size first only yields questions you invented yourself.
分析过程 · 先想清楚再作答
- 这题有两半,后半句才是题眼。说出一个风险不难,难的是给出一个能证伪你自己判断的方法——答不出后半句,前半句就只是意见。
- 先排除两个常见的错误答案:说「幻觉」太笼统,没有指向任何可动的地方;说「延迟」则是把看得见的问题当成最大风险。
- 真正的最大风险是**没有评估**:切块大小、取几条、门槛定多少、两路怎么加权,全是拍出来的。它最重要的地方在于它让所有其他风险都无法验收——你连「改了之后变好还是变坏」都说不出口。
- 怎么证明:先从语料反向出一份带标准答案文档的问题集,刻意掺进无答案问题和需要跨文档的多跳问题;再实现召回率与排序指标,给当前配置跑出一个基线;然后把一个参数来回改两次,看指标动不动。如果指标对参数完全不敏感,说明是评估集有问题,不是系统没问题。
- 补一句成本口径:每一项优化都要同时报三笔账——指标涨了多少、延迟涨了多少、钱涨了多少。只报第一笔的结论不能用。
- 可预期的追问:评估集多大才够?先做二十题能覆盖主要问题类型的小集,用它挡住明显的退步;等真实用户问题攒起来,再按真实分布扩到几百题。一上来就追求规模,只会得到一堆自己出的、跟真实用法无关的题。
Key points
- The biggest risk is having no evaluation: every parameter was guessed, so no change can be judged.
- Prove it by building a golden set with known answer documents, including unanswerable and multi-hop questions, then baseline the current configuration.
- Validate the set itself by perturbing parameters: metrics that never move mean the questions are wrong.
- Report three numbers per optimisation: metric gain, added latency, added cost.
- Start small but well covered, then grow toward the real question distribution.
答题要点
- 最大的风险是没有评估:所有参数都是拍的,导致任何改动的好坏都无法判断。
- 证明方式是先建标准答案集,刻意包含无答案问题与多跳问题,再跑出当前配置的基线。
- 用参数扰动反过来验证评估集本身:指标对参数完全不敏感,说明题出得有问题。
- 每项优化同时报三笔账:指标、延迟、成本;只报指标的结论不能用。
- 评估集先小而全,覆盖问题类型即可,等真实问题攒起来再按真实分布扩大。