面试准备指南
面试准备指南
数字与细节一律以正文各篇为源:《架构总览》的模型与并发预算、《运维与验收》的测试分层。这里只给话术与问题索引。
1. 自我介绍
30 秒版:
我做的是一套单机自部署的多租户知识库:办公文档、聊天记录、照片进同一个库,切块建四路索引——语义向量、BM25、Postgres 子串、页级视觉,检索结果每条都能点回原文的页和框。默认生成是抽取式,原文不出本机;要接外部大模型必须显式配置,失败自动退回抽取式。
2 分钟版:
这个项目的核心问题是「找到」和「指回去」,不是「答案写得多漂亮」。
索引侧是四条腿:语义向量、BM25 关键词、Postgres 子串、页图视觉。四条腿分数不可比,用 RRF 只按名次融合;融合后按 query 意图调整各腿权重,再做按库启用的精排。视觉腿单独一个进程——它常驻两个多 GB 的模型、编码一页十几秒,放进 API 进程会把问答请求排到编码后面。
引用侧靠坐标:每个 chunk 记录自己在第几页的哪个框,坐标归一化存储,前端乘回页图像素画框。扫描件没有文本层,整页走视觉索引,回页图。
数据侧 Postgres 是唯一真相,Qdrant 可重建;点是内容寻址的,
(库, 文档, 第几块)哈希出稳定 ID,三条腿天然对齐、重建不换号。工程侧三件事:任务队列用 Postgres 表(同库外键随文档清理);巡检有三态,跳过不算健康;备份只备事实(Postgres + blobs),索引靠重建加点数对账兜底。
2. 三条链路,各一句话
| 链路 | 一句话 | 详见 |
|---|---|---|
| 写入 | 上传校验 → 内容寻址 → ingest 任务 → 解析 → 切分 → 嵌入 → 写三腿 → 视觉任务 → ready | 《文档摄取》 |
| 读取 | 四条腿并发 → RRF → 软删过滤 → 路由偏好 → 精排 → 证据组装 → 生成 → 引用校验 | 《检索与问答》 |
| 对外 | HTTP / MCP / A2A 三个入口,共用同一检索内核 | 《对外接口》 |
3. 高频追问
| 追问 | 一句话答 | 详见 |
|---|---|---|
| 为什么用 RRF,不做加权求和? | 四条腿分数量纲不同(余弦 0.2~0.9、BM25 可到 40+),加权让数值大的腿说了算 | 《小白概念指南》§4.1 |
BM25 的 k1 和 b 各管什么? | k1 管词频饱和(调到 0 退化成二值模型),b 管长度归一化(1 时得分完全由块长决定) | 《小白概念指南》§2.3 |
RRF 的 k 为什么取 60? | 相邻名次贡献只差 1.6%,奖励多腿共识而非单腿头部 | 《小白概念指南》§4.2 |
| 向量检索用什么索引? | HNSW,efSearch 换召回率;召回率拿精确检索的 top-k 对拍 | 《小白概念指南》§3.2 |
| ColBERT 多向量的代价? | 每 token 一个向量,存储与打分按 token 数放大,只对页级对象建索引 | 《小白概念指南》§6 |
| 精排能把召回漏掉的救回来吗? | 不能,真值不在候选集里就无从重排 | 《小白概念指南》§5 |
| 点 ID 撞了怎么办? | 2^63 空间百万级碰撞 10^-7 量级;十亿级换 UUID 或冲突加盐 | 《小白概念指南》§7.3 |
| 混合检索怎么调权重? | 不在融合层调,在路由层按意图换权重;photo 类的 3.0 是实测出的最小值 | 《检索与问答》§4 |
| 精排为什么按库启用、跨库不启用? | 否则跨库排序取决于「哪些库碰巧配了模型」 | 《检索与问答》§5 |
| 视觉腿为什么独立进程? | 常驻内存 2.65GB、单页编码 15s、6 路并发吃 8.7 核 | 《架构总览》§1 |
| 多 worker 时视觉模型怎么放? | 写侧走视觉服务(VISUAL_WRITE_VIA_SERVICE=true),否则每个 worker 各背一份 | 《架构总览》§5 |
| 为什么每条 DB 腿各拿一个会话? | 同一 AsyncSession 并发 execute 直接抛错,会静默退化成 dense 单腿 | 《检索与问答》§2 |
| 点 ID 为什么是哈希? | 自增号随重建漂移,外部引用错位;三腿还要维护映射表 | 《架构总览》§3.1 |
| 页级点怎么和块级点分开? | 页级 chunk_index 传 -(page_no+1) 恒为负,且加一避免第 0 页撞号 | 《架构总览》§3.1 |
| 删除为什么分两步? | 软删保回收站与引用,30 天后才走六步物理清理 | 《数据与一致性》§4 |
| 删除链漏一步会怎样? | 都不报错:df 只加不减、点删不掉、文件留下——都是静默劣化 | 《数据与一致性》§4.3 |
| 对账为什么分腿比、不能并集? | 并集会把「只有一条腿坏了」报成一致,而那正是真实故障 | 《数据与一致性》§5 |
| 对账为什么不自动删? | 摄取提交前那一瞬「点在行不在」是正常中间态,自动删会删掉正在写的点 | 《数据与一致性》§5 |
| 任务为什么不用 Redis? | 任务与业务同库,外键随文档清掉待办;规模几百条任务,无需另起队列 | 《运维与验收》§1 |
| 巡检为什么有三态? | 「没验过」不等于「通过」,跳过的项报告里标 ?,退出码按有问题算 | 《运维与验收》§3 |
| 权限怎么保证不越权? | 判定只在 auth.py 一个文件;检索只按 kb_id 过滤,范围来自 readable_kb_ids;AST 扫描 + key 白名单守卫 | 《多租户与权限》§3、§7 |
| 为什么不存在与无权限同码? | 区分开就给了攻击者探测资源存在性的信号 | 《多租户与权限》§4 |
| MCP 为什么无状态? | 鉴权每请求自带,没有会话状态可维持 | 《对外接口》§3 |
| 扫描件怎么检索? | 不 OCR,整页建 colSmol 视觉向量,引用回页图 | 《文档摄取》§6 |
| 抽取式和外部 LLM 怎么取舍? | 默认抽取式零外传;接外部模型要三项配置齐全才生效,失败降级并写原因 | 《检索与问答》§6-§7 |
| 20 人团队能直接上线吗? | 不能:无 RBAC、视觉无鉴权、本地盘存储,都是显式不做 | 《导读》 |
4. 必须讲清楚的八个判断
答不出「为什么是它、不是替代方案」,前面所有链路就只是背流程。对照表在《架构总览》§7:
- 任务用 Postgres 表,不是 Redis 或消息队列
- 三个进程分开,不是全塞进 API
- 点 ID 是三元组哈希,不是自增序号
- 融合用 RRF,不是分数加权
- dense 用 512 维 small 模型,不是 base / large
- 精排按库启用,不是全局默认
- 软删 + 30 天,不是直接物理删除
- pgvector 装了但向量进 Qdrant
5. 「怎么保证」的落点是守卫
被问深时要答守卫,不是「我注意过」:
| 问题 | 答什么 |
|---|---|
| 怎么保证没越权? | 三档真值表测试逐格比对;AST 扫描检索层无可见性判定;Qdrant 过滤 key 白名单 |
| 怎么保证检索没退化? | 每腿返回 n / ms / skipped,skipped 与零命中分开;证据质量三档 |
| 怎么保证索引没漂? | 三腿分开对账(只报告不自动删);巡检 + worker 空闲定期跑 |
| 怎么保证接口没弄坏? | 契约检查对「声明 / 实现 / 决议不做」三个数,另有文档指向守卫 |
| 怎么保证能恢复? | 备份后立即自检;恢复先进临时库逐表对账、逐个校验 blob sha256 |
| 怎么保证重试不无限? | attempts 上限 3;明确声明不可重试的异常第一次就终态 |
6. 面试前自查
必须能讲清楚
必须能回答
7. 简历描述
单机自部署多租户知识库:语义 / BM25 / 子串 / 页级视觉四路召回经 RRF 融合与按意图路由的权重,检索结果带块级坐标,可点回 PDF 或扫描页原始位置;Postgres 为唯一真相,内容寻址的点 ID 可无损重建索引;1335 项 pytest 与 82 端点契约对账作为交付门禁。
版面紧张时的三条短句版:
- 混合检索:四条腿 + RRF + 意图路由 + 按库精排。腿级
skipped与零命中分开,降级可观测。 - 引用溯源:chunk 存归一化 bbox,前端乘页图像素画框。扫描件走视觉索引。
- 一致性:内容寻址点 ID 重建不换号。三腿分开对账。备份只备事实,恢复后按点数对账。
上一章: 运维与验收