Skip to content

08 压力面 · 量化指标 · 反问清单 ​

怎么用这篇:前面 01–07 篇是"防守"(把项目讲清楚),这篇是"进攻"(应对逼问、展示判断力)。 字节面试的特点是连续追问同一件事直到你答不上来。所以这篇的核心不是给你更多知识,而是给你答不上来时的标准姿势:划定边界 → 给出方法 → 不编数字。 背三个东西就够:第二节的「效果问题标准答法」、第三节的「容量问题标准答法」、第七节的「反问清单」。


一、先清点你的"数字库存" ​

被问量化问题时,脑子里要立刻分清三类数字:

A 类:可以自信报出的数字(代码/配置里有依据) ​

类别数字
检索topK 10(两路各取)、RRF k=60、权重 0.7/0.3、BM25 k1=1.2 b=0.75
分块chunk_size 512(部署配置 500)、overlap 50、heading_level 2
上下文2048 token 预算、最多 5 条引用、历史最多 10 条
入库worker 默认 5(代码默认 2)、轮询 500ms、重试 3 次、退避 2s/4s/8s(1<<retryCount,退避写在 updated_at)
外部调用Embedding 批 100(部署 10)、重排 top_n 5 / 超时 30s / 重试 3 次 / QPS 10
安全与协议MCP 6 个只读 Tool、审计参数截断 2000 字符、扫描件阈值 20 字符、JWT 有效期 1200 分钟(代码默认 120)
工程规模Go 63 个测试文件 / 405 个测试函数;前端 vitest 37 例;Python pytest 86 例;30+ 条 REST 路由(我的 review 报告里记为 34 条);35 组阶段文档(spec/plan/task/checklist)

怎么用:这些数字报出来之后主动说明来源——"这是配置里的默认值,我们部署时调成了 X"。这比干报数字可信得多。

B 类:不能说"没有",但也不能编数字的(要用方法回答) ​

  • 端到端延迟、QPS、并发上限、单文档入库耗时
  • 内存占用(尤其是 BM25 索引)
  • 准确率、Recall@K 具体值、幻觉率
  • 成本(每千次问答的 token 花费)

统一答法模板(背下来):

"这个数字我没有实测基线,所以我不编。但我能说清三件事:一,它由哪几个环节决定;二,我能用什么方法测出来;三,定性的瓶颈在哪。如果您希望,我可以现在推一遍测量方案。"

唯一例外(要记住并主动限定):仓库里确实有一组真实的评测数字,来自 docs/35-ragas评测/验收报告.md 的一次冒烟验收——7 条样本(其中 2 条无 reference、1 条 kb_id 是错的):faithfulness=1.0、answer_relevancy=0.78、context_precision=0.83、context_recall=0.95,judge 的 JSON 解析失败率 0.0417。 引用它的正确姿势是自己先把样本量说出来:

"我有一组真实的评测数字,但样本只有 7 条,是个冒烟验证不是基线——我报出来是给你看链路通没通,不是给你看效果好不好。faithfulness 1.0 在 7 条样本上意义有限,因为只要样本少就容易满分。" ⚠️ 另外注意:docs/15-rag优化计划.md 里写过"预期 Recall 提升 10%+"——那是预期值不是实测值,如果面试官扫过仓库文档并提到它,一定要立刻澄清:"那是计划里的预期,不是跑出来的结果,我至今没有 Recall 的实测基线。"

C 类:绝对不能报的(报了就是造假) ​

  • "召回率提升了 40%"(没有标注数据集)
  • "支持 1000 QPS"(没有压测)
  • "单机支持百万级文档"(没有容量测试)
  • "用户反馈很好"(没有用户)

⚠️ 最重要的一条纪律:这一整套面试里,唯一会让你翻车的不是"没做过",而是"编了数字"。面试官只要追问一句"怎么测的、样本多大、对比基线是什么",编的数字就会崩。而"我没测但我能设计测法"是一个完全可接受的答案。


二、效果类逼问:标准答法(必背) ​

Q:你这个系统召回率多少?准确率多少? ​

口述回答:

"我没有可信的线上数字,原因很实在:这个项目没有真实用户和真实标注数据,我的评估集是自己构造的,样本量太小,报出来的 Recall 没有统计意义,所以我不报 Recall。 唯一一组真实跑出来的效果数字,是 RAGAS 那套指标在一次 7 条样本的冒烟验收上的结果:faithfulness 1.0、answer_relevancy 0.78、context_precision 0.83、context_recall 0.95。我自己先说清楚:7 条样本、其中 2 条还没有标准答案,这个样本量下的数字只能说明链路是通的,不能说明效果好坏——尤其 faithfulness 满分,在 7 条上很容易出现,我不会拿它当结论。 但我把评估能力建起来了,这是我认为更重要的事。Go 侧有一个 cmd/eval CLI:输入一份数据集(每条样本是 question + 标准答案 + 期望命中的 chunk ID),它会跑三种模式——纯检索算 Recall@K(K 取 1/3/5)、检索+问答、以及全量模式再加 LLM-as-Judge 打分。检索评估不调 LLM、可以快跑;判分用的是两个维度:准确性(对照标准答案给 0-10 分)和忠实度(判断回答是否完全基于引用资料、有没有编造,是个二值判定)。这两项都用 temperature=0 保证可复现。 另外我还单独起了一个 Python 的 RAGAS 服务,算 faithfulness、answer_relevancy、context_precision、context_recall 四个标准指标,Go 侧通过反向代理调它。之所以拆成独立服务,是因为 RAGAS 生态在 Python,而 Recall@K 需要进程内访问我的 retriever,只能留在 Go —— 这是有意的分工。前面那四个数字就是它跑出来的。 所以我的答案分两层:指标体系已经落地、跑通过;但 Recall@K 的基线还没有,效果结论我不给。这是我明确的欠账。"

备注:

  • 这段要背得很熟,因为它是唯一能同时回答"效果如何"和"你怎么知道改进了"的答案。
  • 「我不报没有统计意义的数字」这句话本身就在展示工程素养——字节面试官对"造数据"极其敏感。
  • 如果被追问"那你总有个感觉吧",可以给定性判断:"在我自构造的小评估集上,混合检索相比纯向量,对含专有名词/编号的查询更稳定;但这是观察不是结论。"
  • 主动交代一个已知的评估缺陷(非常加分):Go 的评估 CLI 装配时新建的是空的 BM25 索引,没有回灌数据,检索里的 DocCount()>0 门控会跳过 BM25,所以 CLI 报告实际只测了纯向量检索,和线上 hybrid 行为不可比。 这个 bug 我是在 review 检索链路时发现的,修法和启动回灌一起做。

Q:那你怎么防止幻觉? ​

口述回答:

"我做了三层,但都很轻,我不夸大。 第一层是 prompt 约束:system prompt 里明确写"严格基于检索到的资料回答;资料未覆盖的部分,明确指出'资料未覆盖该方面',不要编造",并且要求按 [编号] 标注引用。 第二层是引用可溯源:回答里的 [1][2] 编号和返回的 sources 数组下标严格对应,sources 里带文件名、标题路径、页码、视频时间戳和锚点,用户可以点开原文核对。可溯源不等于不幻觉,但它让幻觉可被人工识破,这是产品的兜底手段。 第三层是检索为空时的硬兜底:如果一条都没召回,我不让模型自由发挥,直接返回"未找到相关资料",并且不调 LLM。 我要承认没做的:没有做 NLI 之类的自动幻觉检测,也没有在回答生成后做一次引用一致性校验(比如检查回答里的每个论点是否真的出现在引用的 chunk 里)。这两项是我的待办。另外提示注入我也没有专门防护——如果上传的文档里写了'忽略以上指令',理论上可能影响回答,这是企业知识库场景必须补的一环。"

备注:最后那段"提示注入没防护"是必须主动说的,因为面试官一定会想到(企业知识库最大的攻击面就是文档内容本身)。

Q:如果检索到的资料是错的/过期的怎么办? ​

口述回答:

"目前我没有做时效性治理,这是个真问题。现状是:文档更新靠重新上传同一份文档——入库前我会按 document_id 把旧向量和旧 BM25 记录删掉再写新的,所以不会有新旧两份同时存在。但没有版本管理、没有生效时间、没有过期标记,也不能做'只搜最近三个月'这类时间过滤。 要做的话我分三步:一是元数据里落文档的版本和生效时间,检索时做时间过滤(Qdrant payload 支持范围过滤);二是文档更新改成生成新版本而不是覆盖,保留历史以便追溯;三是在回答里带上文档版本信息,让用户知道答案基于哪一版。第一步成本最低,收益也最直接。"


三、性能与容量逼问:标准答法 ​

Q:这个系统能支撑多少 QPS?瓶颈在哪? ​

口述回答:

"我没有做过压测,所以给不出 QPS 数字。但我可以讲清瓶颈的形状——瓶颈肯定不在我自己的 Go 代码,而在两个外部依赖和它们的串行关系。 一次问答的耗时组成是:检索(Embedding 一次 HTTP 调用 + Qdrant 一次 RPC + BM25 内存打分 + 一次重排 HTTP 调用,前两者并行)→ 组装 → LLM 流式生成。这里面:Embedding 和重排都配了 QPS 限流(默认 10),也就是说单实例的检索吞吐上限很可能被这两个外部服务的限流卡住;LLM 生成是流式的,占的是长连接,它更吃并发连接数而不是瞬时 QPS。入库侧是 worker 池 + Embedding 批量,入口有异步队列缓冲,所以入库的尖峰不会直接打到检索。 真要测,我会分三段做:一是检索段的压测(固定 query 集合,只调 retriever,看 P50/P99 和限流触发率);二是生成段的并发压测(用流式请求算首 token 延迟和并发连接上限);三是入库吞吐测试(大文件并发上传,看任务积压和 worker 饱和点)。这三段分开测的原因是可以定位瓶颈到底在哪一段,而不是只拿到一个混合的端到端数字。"

备注:

  • 「分段压测」这个思路本身就能得分,比一个编造的 QPS 数字值钱得多。
  • 记住"限流默认 10 QPS"这个事实——它是最可能成为天花板的地方。

Q:如果文档涨到 100 万篇,你这套还撑得住吗? ​

口述回答:

"会先坏在三个地方,我按坏的顺序说。 第一个坏的是 BM25 内存索引——它是单机内存结构,没有分片、没有淘汰、没有上限,而且没有持久化。百万篇文档的倒排表放在一个进程里,内存压力和重启恢复时间都会失控。所以到了这个量级,我会把 BM25 换成 Elasticsearch 或者 OpenSearch 的 BM25,我的 BM25Index 本来就是接口,换实现不动上层。 第二个是 Qdrant 单集合的过滤性能,因为我现在没有给 kb_id 建 payload 索引,过滤是无索引的。数据量上来必须建索引,更好的做法是用 Qdrant 的 tenant 索引,或者按大租户分片。 第三个是入库管道:现在是 worker 轮询 + 单条认领,没有背压,也没有死信队列;大批量导入时会积压。要改的话是引入消息队列(Kafka/Redis Stream)+ 批量入库 + 背压控制。 另外还要补两件事才能叫生产可用:一是可观测性——现在没有 metrics 和 trace,只有 slog 日志,百万级文档下没有监控等于盲开;二是多实例一致性——BM25 是每实例独立的内存索引,水平扩容会立刻不一致,这也是必须换外部引擎的原因。"

备注:这段的价值在于给出了扩容的失败顺序,也就是"我知道系统会怎么死"。这比"能撑"或"撑不住"都有说服力。

Q:单次问答的延迟有多少?首 token 多久? ​

口述回答:

"没有实测数字,但我能拆出耗时的结构:检索段(并行)≈ max(Embedding + Qdrant 查询, BM25 内存打分) + 重排;生成段 = 首 token 延迟 + 流式吐字。检索里最贵的是重排(cross-encoder 要在线算)和 Embedding(一次外部 HTTP)。 如果开了可选增强,还要额外加:Query 改写是一次 LLM 调用;多查询是"一次 LLM 生成变体 + N 路检索";HyDE 是"一次 LLM 生成假设文档 + 一次 Embedding + 一次向量检索";路由判定又是一次 LLM 调用。这些默认全是关的,就是因为每一次都直接加在首字节延迟上——这是有意的默认值选择,不是没实现。 我做过的优化只有一个方向:引用先行。检索完成就把 sources 事件推给前端,用户立刻能看到命中了哪些文档,感知延迟比等第一个 token 低很多。"


四、方案对比类逼问(为什么不用 X) ​

面试官问回答要点(30 秒版)
为什么不用 LangChain / LlamaIndex?"生态主要在 Python,而我的技术栈选择是 Go(单二进制部署 + 自然的并发模型)。我自研的部分集中在混合检索、RRF、分块这些算法不复杂但需要精细控制的地方,用库反而要读源码才能调参。反过来说,我在评估这一层用了 Python 生态——单独起了 RAGAS 服务,这是按生态优势做分工,不是排斥生态。"
为什么不用 Elasticsearch(连 BM25 带向量一起)?"ES 确实能同时做 BM25 和向量,是很成熟的选择。我没选的直接原因是:ES 作为主存储的运维重量和我的部署目标(一个 docker compose 起来)不匹配,而且它的 Go 客户端在向量检索这块不如 Qdrant 的官方 gRPC 客户端顺手。但我承认,如果目标是企业级大规模,ES 才是更稳的选择——我现在自研的 BM25 在持久化、分片、内存控制上都弱。"
为什么用 Qdrant 不用 pgvector?"pgvector 的优势是不引入新组件、事务和元数据天然一致;它的劣势是数据量大之后 ANN 索引(HNSW)的构建和查询性能、以及过滤下推能力不如专用向量库。我的场景里过滤是核心(多租户按 kb_id 隔离),所以我选了过滤能力更强的 Qdrant;代价是向量和元数据分两个存储,需要自己保证一致性——我用'按 document_id 补偿删除'来处理重试。"
为什么不用 Kafka 做入库队列?"我的入库是'任务持久化在 PostgreSQL + worker 轮询原子领取',这在单实例、中等吞吐下够用,而且重启恢复天然由数据库状态保证(启动时把 processing 重置为 pending)。Kafka 带来的好处是削峰和跨实例消费,代价是多一个必须运维的组件。所以我把它列为"上量之后再做"的事,不是不知道它。"
为什么 MCP 要单独做,不是只留 REST?"因为受众和调用方式不同。REST 是给人/前端写的,接口契约是我定的;MCP 是给外部 Agent 用的,Tool 带 JSON Schema 描述,模型自己决定调哪个、怎么填参数。另一个理由是 MCP 是标准协议,Claude Desktop、Cursor 这类客户端配一行 URL 就能接,我不需要给每个平台做适配。"
和 Dify / RAGFlow 这类开源平台比,你的价值在哪?"平台化的东西开箱即用,但在链路中间层没有控制权——比如我想改 RRF 的融合策略、想按 kb 维度在算分前过滤、想只给外部 Agent 开放 6 个只读能力,这些在平台上要么改不动、要么要绕。我这个项目的定位是把 RAG 的关键链路自己实现一遍,所以我对每一层的取舍、每个缺陷都清楚。作为产品它不如平台成熟,作为技术验证它的深度更高。"

备注:所有对比都要遵守一个模板——先承认对方的优势 → 再给出我场景下的取舍理由 → 最后说明什么条件下我会换成它。这个结构能让面试官看到"判断力"而不是"偏见"。


五、ownership 与自我批判类逼问 ​

Q:讲一个你在这个项目里犯的错误,以及你怎么发现的。 ​

口述回答(推荐讲这个,细节最真实):

"讲一个我自己抓出来的比较典型的:评估模块的忠实度指标一直是无效的。 忠实度是让 LLM 判断"回答是否完全基于引用资料",但我在调用 judge 的时候,把 sources 参数传成了 nil——也就是说它一直在拿空资料做判断,那这个指标要么恒真要么恒假,等于没测。这个问题是匿名的、不报错的、结果看起来还正常的,所以它能一直存在。 我是通过一次全量代码 review 发现的:当时我按模块分了四路并行检查,其中一路专门看数据流,就是从"这个参数谁传进来、传的是什么"这条线摸到调用点的。发现之后我在 review 报告里把它列为 P0,和另外几个 P0 一起修了——同一批里还有前端的 Markdown 渲染没做 XSS 消毒(存储型 XSS)、流式接口在引擎为 nil 时会 panic、评测样本的并发没有 recover 导致单样本 panic 会崩整个进程。 这件事给我的教训是:"没有报错"和"逻辑正确"是两件事。尤其是评测和监控这类"元代码",它们错了不会有人受伤,只会安静地给你错误结论——所以这类代码更需要断言和自检。我后来给评估模块补的一条自检就是:如果 judge 拿到的资料为空,应该直接报错而不是继续评分。"

备注:

  • 这个例子好在:错误真实、隐匿性强、是你自己发现的、有系统性修复、还总结出了可迁移的教训。
  • 结尾那条"元代码错了只会给你错误结论"是很好的收束,面试官会记住。
  • 别讲那些"我犯了错但其实是环境问题"的例子。

Q:你怎么保证 AI 生成的代码质量?(如果面试官继续追 vibe coding) ​

口述回答:

"四个机制。一,先写验收标准再写代码:每个阶段我写 spec.md(需求+验收标准)和 checklist.md(可执行、可观察的验收项),checklist 我要求每条都写成"验证:怎么做、观察什么",比如"上传含 <script> 的文档,提问后页面不弹 alert"。这样验收不依赖我的主观判断。 二,测试是硬门槛:CI 里 go build + go vet + go test ./... 全绿才算过,前端有 vitest 和 vue-tsc 类型检查。现在 Go 侧有 63 个测试文件、405 个测试函数。 三,定期做全量 review 而不是只看新代码:我做过一次四模块并行的全量 review,产出 6 个 P0 + 12 项标号 P1(另加两项 spec 与实现的 gap),然后分两轮修(docs/33-review-2026-08/ 和 docs/34-review-p1-fix/)。这个动作是我认为对 AI 辅助开发最重要的补偿——因为 AI 很容易写出"看起来对"的代码。 四,对 AI 写的部分划出我的能力边界:有些模块我是"行为验证"而不是"源码级掌握",比如多媒体抽帧的 ffmpeg 参数、Wails 桌面打包细节。我会明确告诉你哪些是这一类,而不是假装都懂。"

Q:如果让你重做这个项目,你会怎么安排? ​

口述回答:

"我会把顺序调一下,核心变化是先建可观测性和评估,再扩功能。 现在的顺序是功能驱动:加载器 → 分块 → 检索 → 问答 → API → 前端 → 评估 → MCP → 登录。结果是评估做得太晚,中间很多决策(chunk_size 多少、权重多少、要不要 oversample)在实现时只能凭经验定,后面想回头调又没有基线。 重做的话我会在'检索+问答'跑通之后立刻做三件事:一,把评估 CLI 和一份固定的评测集建起来,跑出第一版基线;二,加最小可观测性——检索耗时、召回条数、重排是否降级的日志与计数;三,加一个检索链路的超时预算。这三样都不大,但它们让后面的每一次改动都可验证。 另外有个具体的教训:服务重启一次就该发现 BM25 索引失效。我做功能测试时很少重启服务,所以这个静默退化一直没暴露。所以'重启后行为是否一致'应该进验收清单——这是我现在会加进去的一条。"


六、白板 / 手撕题(和这个项目强相关的高频题) ​

题目你的准备要点
手写 RRF 融合用 map 累加分数:scores[id] += w / float64(k+rank+1);再转切片按分数降序排。记得说 tie-break(否则同分顺序不定)和复杂度(O(N log N + N))。
手写 BM25 打分讲清三件事:倒排表结构(term→postings(docID, tf))、docLen/avgLen 的维护、以及 IDF 的 +1 兜底。主动提"删除时怎么维护 avgLen"——这是面试官爱问的细节。
实现 SSE 服务端Go 侧:设 Content-Type: text/event-stream + Cache-Control: no-cache,每个事件用 event: xxx\ndata: {...}\n\n 格式写,每次写完必须 Flush,否则数据被缓冲住不发出。要提:客户端断连靠 c.Request.Context().Done() 感知。
设计一个令牌桶限流器直接用 golang.org/x/time/rate:rate.NewLimiter(rate.Limit(qps), burst)。要主动说 burst=0 会导致 Wait 直接报错(我在 reranker 里专门做了 qps<=0 兜底)。
一个任务队列,支持重试和重启恢复用数据库状态机 + UPDATE ... WHERE id IN (SELECT ... FOR UPDATE SKIP LOCKED / status='pending') RETURNING 的原子领取;退避可以把下次执行时间写进 updated_at,轮询时过滤 updated_at <= now()。启动时把 processing 重置为 pending。这套就是我在项目里的实现,可以直接讲。
怎么给知识库做多租户隔离单集合 + payload 过滤(Must + tenant keyword 索引);讲清"过滤下推到检索"而不是"检索完再筛";以及"nil 过滤 = 全库"这个危险语义的防御。
Top-K 检索结果里有重复文档怎么办我目前的做法是按 chunk 去重(天然唯一 ID),但不做文档级去重——所以同一篇文档可能有多个 chunk 进上下文。这其实是个优化点:可以按 document_id 聚合、限制单文档最多 N 条,避免一篇文档霸占上下文。这题我没做,被问到要诚实说。

七、反问面试官(务必准备 3–5 个,按场景挑) ​

关于团队与业务(安全、有诚意)

  1. "这个团队的知识库/检索场景里,现在最大的技术挑战是召回质量还是工程稳定性?"
  2. "团队现在有没有一套 RAG 效果的评估基线?是人工标注还是用模型判分?"
  3. "知识库类产品的迭代节奏是怎样的——是每周都在调检索策略,还是主要在做平台化和接入?"

关于技术(展示你真的在做这件事) 4. "你们线上向量检索和关键词检索是怎么融合的?是 RRF 还是加权求和?召回和重排的条数比例大概是多少?"(问出去就说明你懂这一层) 5. "你们现在向量库的规模量级和部署形态是什么?单集合多租户还是分库?" 6. "团队对 RAG 幻觉的容忍度是怎样的?有没有做引用一致性校验或者 NLI 检测?" 7. "如果我进来做这块,第一件该做的事是补评估基线,还是先解决某个具体的线上问题?"

关于成长(真诚型) 8. "从您角度看,做好 RAG 这个方向,最容易被低估的能力是什么?" 9. "如果我这次没能通过,您觉得我最该补的短板是哪一块?"(慎用:适合氛围已经放松的终面,问好了非常加分)

不要问的:加班多不多、几点下班、能不能远程(这些可以问 HR,不要问技术面试官);也不要问"你们用什么技术栈"这种官网能查到的。


八、最后 30 秒总结(收尾话术) ​

面试官最后常说"你还有什么想补充的"或"用一句话总结你的项目"。不要重新讲一遍架构,用这段:

"我就补一句总结。这个项目对我最大的价值不是它实现了多少功能,而是它让我把 RAG 的每一层都自己走了一遍——BM25 的公式、RRF 为什么只用排名、cross-encoder 为什么不能预计算、上下文预算怎么裁、异步入库怎么做到可重试可恢复。也正因为是自己写的,我清楚地知道它哪里是坏的:BM25 重启会静默失效、召回没有 oversample、没有 metrics。 我认为做 RAG 系统最难的不是把链路搭起来,而是知道自己搭的这条链路什么时候在骗你——所以我下一步最想做的就是把评估基线和可观测性补齐,让每一次调参都有依据。 如果贵团队有真实的知识库场景和评估数据,我很想看看这套东西在真实数据上会暴露什么新问题。"

备注:这段的作用是**把话题从"我的项目完不完善"转到"我的判断力和学习姿势"**上——这才是面试真正的评分项。


九、压力面速查表(考前 5 分钟看) ​

被逼问一句话应答骨架
效果数字?"没有可信基线,我不编 Recall。唯一真实的一组是 RAGAS 在 7 条样本冒烟验收上的四个指标(faith 1.0 / relevancy 0.78 / precision 0.83 / recall 0.95)——样本量我先说了,它只证明链路通,不证明效果好。"
能撑多少 QPS?"没压测不出数字。瓶颈在外部限流(默认 10 QPS)和重排的在线计算;我会分检索段、生成段、入库段三段分别压。"
百万文档?"先坏在 BM25 内存索引(无持久化无分片)→ 再坏在无 payload 索引的过滤 → 再坏在入库无背压。换 ES 的 BM25 + Qdrant tenant 索引 + 消息队列。"
最大的 bug?"BM25 重启失效,而且是静默的——只有 trace 里 method 从 hybrid 变 vector 能看出来。"
最大的架构缺陷?"重排候选池 = topK,没有 oversample,重排只能改排序救不了召回。"
为什么用 Go?"并发/单二进制/部署,代价是放弃 Python 的 RAG 生态——所以评测我用 Python 服务补上。"
是 AI 写的吧?"是 AI 辅助。我先写 spec 和可验证的 checklist,做了一次全量 review 修掉 6 个 P0 + 十几项 P1,并且我能说清哪些模块我只做到了行为验证。"
那你说说哪里你不懂?"多媒体 ffmpeg 抽帧参数、Wails 打包细节、建表迁移的每一列——这些是 AI 生成、我只做行为验证的部分。"(分层坦白,不要全盘接受也不要全盘否认)
最大的失误?"评估的忠实度指标把 sources 传成 nil,一直在评判空资料。教训:没报错 ≠ 逻辑对,元代码错了只会给你错误结论。"
重做会怎么排?"先建评估和可观测性再扩功能;并且把'重启后行为是否一致'写进验收清单。"

持续学习,持续构建。