面试知识库

15. 没做好的地方,和重做会怎么改#

本文由本地速背站(docs/review-site)第 18 章转出,文中「第 N 章」指速背站章节号,不是本站编号。

本章 3 句话

  • 不足分三类说:项目定位上没打算做的、数据限制做不了的、工程上没做完的。
  • 每一条都要配一句「重做会怎么改」,面试官听的是你知不知道差在哪,不是道歉。
  • 本章所有问题都在当前代码里核过出处;读代码发现但没复现的,卡里会写明「没复现」。

面试官问「项目有什么不足」,怎么答?#

L1 口诀:三类:没打算做、做不了、没做完

分三类答:定位上没做的、数据限制做不了的、工程上没做完的,每条配重做的改法。

我会分三类说。第一类是定位上就没做的,比如真实下单、支付、物流,项目一开始就定成 Agent 主线加基础设施。第二类是数据限制做不了的,比如商品没有材质字段、库里几乎都是 Amazon。第三类是工程上没做完的,比如运费重量是默认值、对比结果不回到会话。每一条我都能说重做会怎么改。

展开:三类各有哪些、本章卡片索引

三类一张表#

类别例子本章哪张卡
定位上没做下单 mock、静态汇率关税c02、c03
数据做不了无材质字段、Amazon 独大、类目脏c04、c05、c06
工程没做完对比不回会话、单份状态文件c07、c08
读代码发现WebSocket、断路器、存储层c09、c10、c11

项目文档里明确写了「不覆盖」的#

真实平台 OAuth、下单 / 支付 / 物流、精细汇率对账、多模态图像检索、反爬风控、库存一致性、隐私合规。这些一开始就没打算做,面试时直接说是定位,不用解释成遗憾。

同一段文字还写着「不做训练 / 微调」,但后来训练做了三件(第 17 章)。文档没有跟着改,面试时以第 17 章为准。

怎么组织回答#

先说一条最大的,说清根因和改法,再说「还有几条小的,要不要展开」。不要一口气报十条,面试官记不住,也显得项目很糙。

出处:CLAUDE.md:29(不覆盖列表)

追问链:面试官接着会问什么

最大的遗憾是哪一条?

商品没有材质、重量这类结构化属性。它同时卡住了硬约束过滤、运费估算和评测里的一条红线。重做会在清洗阶段先把属性抽出来。

这些不足影响线上用户了吗?

影响最大的是「不要塑料」这种约束会漏判,和搜手机出配件。前者只能靠标题关键词,后者已经放到收尾那次模型调用里判了。

为什么不先把数据补好再做 Agent?

项目重点是 Agent 主线和基础设施,数据用的是公开数据集。属性抽取要跑一遍全库,成本不小,当时排在后面。

再给你一个月先做哪个?

先做属性抽取写进向量库 payload,材质、重量、整机还是配件一次解决三个问题。

下单是模拟的,具体缺什么?重做怎么补?#

L1 口诀:只出卡,不下单

下单工具只生成一张确认卡,用户点按钮走 HTTP 才写库;没有支付、物流、库存。

下单这块是模拟的。工具只准备一张确认卡,用户在页面点同意,请求走 HTTP 接口才真正写订单表。模型说「用户已确认」不算数,也没有参数能跳过确认。没有支付、物流和库存扣减。重做的话我会接支付网关,订单加状态流转,库存做预占再扣减。

展开:现在有什么、缺什么、重做清单

现在有的#

  • 确认卡写进 trade_confirmations 表,刷新页面、重启进程都还在。

  • 商品信息按 id 从本轮候选表取,模型不传标题和价格,避免记错要写进数据库的钱。

  • 幂等键由「用户 + 会话 + 商品和数量」派生,同一轮重试不会成两单。

  • 订单只能在 CONFIRMED 状态取消,取消前要先查订单。

缺的和重做怎么补#

缺什么重做怎么补
支付接支付网关,回调按支付流水号做幂等
订单状态待支付 → 已支付 → 已发货 → 完成,每步记录
库存下单先预占,支付成功再扣,超时释放
物流接物流商回调,订单表加运单号

出处:app/tools/create_order.py:1(模块说明写明「mock 交易域」、决议只走 HTTP)、app/trade/usecases.py:41(幂等键)

追问链:面试官接着会问什么

模型能不能绕过确认卡直接下单?

不能。工具没有「已确认」这个参数,落库的接口只有页面按钮会调,写权限也由 PermissionEngine 单独放行。这是第 04 章讲的机制。

接了支付以后,回调重复怎么办?

支付流水号在订单表做唯一约束,重复回调查到已处理就直接返回成功。

库存超卖怎么防?

两种做法:数据库里 UPDATE ... WHERE stock >= n 靠行锁;或者 Redis 用 Lua 原子扣减,再异步同步到数据库。

确认卡 30 分钟有效期怎么定的?

经验值,代码里没有推导依据。重做会按用户从看到卡到点按钮的实际分布定。

汇率、关税、运费是怎么算的?哪里不准?#

L1 口诀:三张静态表 + 半公斤

汇率、关税、运费都是写死的表;商品没有重量字段,运费一律按 0.5 公斤估。

到手价这条线是简化模型。汇率是一张静态表,不接实时汇率源。关税按品类关键词给近似税率,再加免征额,不查 HS 编码。运费是起步价加按重量加价,但商品数据没有重量,代码里一律按 0.5 公斤的默认值算。重做我会接汇率 API 加缓存,再按品类给一个重量先验。

展开:三张表现状与重做
项现在问题重做
汇率静态表,1 币种 ≈ 多少美元会过时接汇率 API,缓存 1 小时
关税品类关键词 → 税率 + 免征额命不中给默认 7%HS 编码表 + 原产国
运费起步价 + 每公斤加价,分区域重量永远是默认值按品类估重先验

重量为什么永远是默认值#

候选商品结构里有 weight_kg 字段,但从数据到候选的整条路上没有任何地方给它赋值,永远是空。运费估算拿到空就用 0.5 公斤。一个行李箱和一副耳机算出来一样的运费。

做对了的一点#

关税先判「发货国是否等于收货国」,国内单直接免税。不然 Amazon 美国发货寄到美国也会被收一笔进口税。

出处:app/recall/fx.py:4(静态汇率表)、app/recall/duty.py:21(税率表)、:40(默认 7%)、:116(国内单先判)、app/recall/shipping.py:38(默认 0.5 公斤)、app/tools/schemas.py:71(weight_kg 默认空)

追问链:面试官接着会问什么

汇率过时会有多大影响?

主流货币一年波动多在个位数百分比,比价结论一般不会反转。但项目定位就说了不做精细汇率对账,面试时直接承认。

接了汇率 API,它挂了怎么办?

缓存上一次成功的值继续用,并在结果里标「汇率时间」。现在的静态表就是最后的退路。

重量先验从哪来?

两个来源:品类知识库里每个品类的典型重量;或者从标题抽「500g」「2kg」这类数字。抽不到再用品类默认。

为什么关税命不中给 7% 而不是 0?

给 0 会让跨境商品显得便宜,用户到手才发现要补税。宁可估高一点。

用户说「不要塑料的」,系统能过滤吗?#

L1 口诀:没有字段,只能匹标题

商品数据没有材质字段,「不要塑料」只能拿关键词匹标题,评测里这条红线判不了。

商品数据里没有材质字段。现在的做法是 planner 把材质当排除关键词,拿它去匹配标题,标题没写材质就漏掉。所以评测里材质这条红线其实判不了,我们决定不把它当回归看。重做我会在数据清洗阶段用模型把材质、颜色这些属性抽出来,写进向量库的 payload,检索时直接过滤。

展开:现在怎么处理、为什么只做排除、重做方案

现在的处理#

  • 「不要 X」进排除关键词,命中标题就淘汰。

  • 「喜欢 X」进偏好关键词,命中只加分,不淘汰。

  • 正向没有硬淘汰档:数据没有可靠的材质字段,只保留命中的会误杀一大片。

评测上的后果#

评测集里有一条「不能出现塑料制品」的红线细则。标题不写材质时,judge 和系统都判不出来。这条细则的分数在 0 和几十分之间来回跳,和改动无关,所以决定不当回归指标。

重做方案#

步骤做法
抽取清洗阶段用模型从标题和描述抽材质、颜色、重量
存储写进 Qdrant 的 payload,和平台、价格一样可过滤
质量只对高频品类做,抽样人工核对
成本全库 138 万条各调一次模型,费用数字待补

出处:app/tools/planner.py:343(正向不做硬淘汰的原因)、:381(材质、颜色填排除关键词)、app/recall/category_kb.py:8(品类知识库有「该看哪些维度」,没有商品级取值)

追问链:面试官接着会问什么

为什么不训一个材质分类器?

没有标注数据,而且材质值域开放,分类器不如直接让模型抽取。抽取一次写进库,线上零成本。

标题关键词误杀怎么办?

只做排除不做保留,误杀范围就限制在「标题明确写了塑料」的商品。漏掉的比误杀的多,这是有意的取舍。

这算算法的问题还是数据的问题?

数据的问题。算法层能做的是不假装能过滤,在结果里如实说「按标题匹配」。

抽取错了怎么发现?

抽样人工核对,加上线上用户反馈。抽取结果带置信度,低置信度的不参与过滤。

召回库里 Amazon 占绝大多数,跨平台比价还成立吗?#

L2 口诀:一家独大,决定不修

库里 Amazon 占绝大多数,搜全平台几乎只出它;eBay 已剔除;决定不修。

库里 Amazon 商品占绝大多数。搜全平台时向量近邻基本都是 Amazon,其它平台很难露面。eBay 整个剔除了,因为它的卖家名被掩码、描述全空。我们决定不修,因为用户指定平台可以单搜,跨平台由主环在同一轮里分平台各发一条搜索。重做我会按平台分桶各取前 k 条再合并。

展开:现状、为什么不修、重做方案

现状#

  • 全库 138 万点。Amazon 占比具体数字待补,代码注释原话是「占绝大多数」。

  • 平台参数是枚举:all、amazon、walmart、shein、lazada、shopee。没有 eBay。

  • 「all」等于本轮启用的全部平台合到一起搜,不做平台配额。

为什么决定不修#

跨平台比价靠的是主环同一轮发多条搜索,每条指定一个平台,框架并发执行。这样每个平台都有自己的召回结果,比价在这一步已经成立。「all」只是用户没说平台时的默认。

重做方案#

建库时按平台平衡采样,或者检索时按平台分桶各取前 k 条再合并。代价是各平台的相似度分数不可比,合并后要重排。

出处:app/recall/qdrant_store.py:280(「库里 amazon 占绝大多数」)、app/tools/item_search.py:142(eBay 剔除原因)、:146(平台枚举)、:368(「all」= 启用平台集合)

追问链:面试官接着会问什么

用户没说平台,其它平台怎么露面?

提示词里有一段并行策略,告诉模型跨平台时同一轮发多条搜索、每条指定平台。这是模型的决定,不是机制保证。

为什么不建库时就平衡采样?

其它平台的数据量本来就少,平衡采样等于把 Amazon 砍掉大半,召回质量会掉。分桶取前 k 条更合适。

分桶合并后怎么排?

各平台的向量分数不可比,合并后过一遍 reranker 统一打分,第 11 章讲过。

eBay 不能只用标题和价格进库吗?

可以,但描述全空、卖家名掩码,向量只靠标题,质量会明显差一截。当时判断不值得。

搜手机为什么会出手机壳?最后怎么处理的?#

L2 口诀:类目脏,两方案都证伪

根因是数据的类目字段脏;黑名单和品类过滤都实测无效,最后交给收尾那次模型判。

搜手机常搜出手机壳、贴膜。根因是数据的 category 字段不可信,整机和配件在同一个类目。我试过两种确定性方案,关键词黑名单和品类过滤,用真实数据标定,两边分数完全交叠,都证伪了。最后放在收尾那次模型调用里判,它本来就在逐件读标题写理由,顺手标出不符合意图的商品。重做我会在清洗阶段重新分类。

展开:证据、两个失败方案、现在的做法

数据有多脏#

整机和配件在同一个类目;有电视被标成游戏机类目。商品卡里刻意不显示类目,因为显示出来只会误导用户。

两个失败方案#

方案为什么不行
关键词黑名单「case」「film」也是正常商品词,误杀
按类目过滤类目字段本身就是错的
挑货阶段打分阈值配件和真商品的分数完全交叠,任何阈值都两头错

现在的做法#

收尾工具那次模型调用本来就要逐件读标题写推荐理由。让它同时输出「和本轮品类明显不符的商品 id」,排版时剔掉。多出来的成本接近零。搜索结果展示头 5 条标题,也是为了让主环有机会自己察觉跑偏。

出处:app/tools/shopping_summary.py:84(类目值域乱)、:199(为什么放收尾判)、:210(off_intent 字段)、app/tools/item_picker.py:179(分数交叠的实测数据)、app/tools/item_search.py:108(展示 5 条的原因)

追问链:面试官接着会问什么

交给模型判,会不会误杀真商品?

会有。但它是在读完标题、写完理由之后判,信息比任何规则都全。实测里它自发写出过「这是配件」,所以才把这个判断正式化。

为什么不在挑货那一步判?

挑货是纯确定性打分,没有模型。要判「这是不是配件」必须读懂标题,只有模型能做。

重做重新分类用什么?

清洗阶段用模型按标题做「整机 / 配件」二分类,再结合价格分布交叉验证。结果写进 payload,检索时直接过滤。

这个问题怎么发现的?

评测集里的手机和相机两条 query 出了坏结果,逐条看候选才定位到类目字段。

对比栏按钮为什么不走 Agent?代价是什么?#

L2 口诀:按钮直达,结论不回会话

对比栏直接调 HTTP,一次快模型出结果,不经主环;代价是结论不进会话。

对比栏的「帮我比一比」是一条 HTTP 接口,不走 Agent 主环。用户已经亲手勾了商品,意图完全确定,再让主环规划一遍,多几十秒还不一定出结构化表。所以一次快模型调用直接填对比表。代价是这个结论不会写回会话,下一轮模型不知道用户比过。重做我会把结果作为一条消息写回会话状态。

展开:两条入口、取舍、重做

两条入口共用一个实现#

模型调工具前端按钮
触发用户在对话里说「比一比」用户勾选后点按钮
路径主环 → 结束工具HTTP → 一次快模型
结论进会话进不进

两条路都调同一个 compare_items,输出结构一样,不会出现两套逻辑。

三条 id 检查#

只收本会话展示过的商品 id;会话归属校验;商品信息从候选表按 id 取,前端不传标题和价格。

重做#

接口返回后,把对比结论作为一条助手消息追加进会话状态文件。下一轮模型就能引用「刚才比的那件」。

出处:app/api/orders.py:190(compare_endpoint,文档字符串写明「不走 AgentLoop」和原因)

追问链:面试官接着会问什么

用户下一轮说「刚才比的那个便宜的」怎么办?

现在模型看不到那次对比,只能靠候选表里的商品猜。这就是要重做写回会话的原因。

为什么不直接往会话里塞一条隐藏的用户消息?

可以,但用户消息会触发一整轮主环,几十秒往返又回来了。写一条助手消息更轻。

这种「按钮直达」的模式还用在哪?

找相似商品也是 HTTP 直达。原则是:用户意图已经完全确定的操作,不经过 Agent 规划。

怎么防止拿别人会话的商品 id?

会话归属校验先过,再查本会话的候选表,不在表里的 id 直接拒绝。

会话状态只存一份文件,坏了怎么办?#

L2 口诀:一份文件,坏了就从头

会话状态只存一份 session.json,读坏就当新会话,不回放消息表。

续聊恢复只有一条路,读上一轮写的 session.json。读不到或解析失败,就当新会话开始,不去回放消息表。这是有意的取舍,一份坏文件让整个会话起不来,比少一段上下文更糟。写文件是先写临时文件再改名,不会留半截。缺点是多副本要共享目录,也没有版本。重做我会把状态放数据库或对象存储,按轮次版本化。

展开:存什么、为什么不回放、缺什么

文件里存什么#

整个 AgentState 序列化成 JSON:消息、框架压缩后的摘要、会话级偏好。消息表只给前端侧栏回看,不参与恢复。

为什么不从消息表回放#

消息表是给人看的投影,工具结果已经被排版过。用它重建模型上下文,要把工具结果反推回原始结构,容易错。第 02 章讲过,以前有 5 份产物和一条回放腿,后来都删了,只留这一份。

现在缺什么、重做怎么补#

缺什么后果重做
多副本共享要挂共享目录或固定路由放数据库或对象存储
版本写坏一次就全丢按轮次保留最近几版
写失败只记日志,下轮从头写失败告警并重试

出处:app/agent/orchestrator.py:12(读坏即空开局、不回放消息表)、:93(恢复是加成不是前提)、:104(解析失败记 warning)、:113(先写临时文件再改名)、:121(写失败只记日志)

追问链:面试官接着会问什么

用户刷新页面会丢上下文吗?

不会。每轮结束都写文件,刷新后下一轮从文件恢复。丢的只有正在跑的那一轮。

为什么不每轮都存数据库?

文件是几十 KB 的整块 JSON,写文件最简单,单机部署够用。多副本时再改成数据库,这是没做完的部分。

写到一半进程被杀会怎样?

临时文件留一半,正式文件还是上一轮的完整版。改名是原子操作,所以正式文件不会是残片。

50 轮以后文件会不会太大?

框架在上下文超过阈值时会压缩成摘要,摘要也在这份文件里,第 07 章讲过。

读代码发现的 WebSocket 问题有哪些?#

L3 口诀:首连早断,任务不起

首连在 ws_ready 前断开会走重连,重连不发任务请求,界面却显示运行中。

这是我读代码发现、没有实际复现的问题。首次连 WebSocket 时,如果在收到 ws_ready 前断线,前端会按重连处理。重连分支不再发任务请求,任务不会启动,界面却显示运行中。修法是单独记「任务请求发过没有」,不用「是不是重连」来判断。另外还有前端不发心跳、一会话只登记一条连接这些小问题。

展开:问题清单与修法
问题影响修法
首连早断走重连任务不启动,界面假运行单独记「请求发过没有」
前端从不发 ping后端 ping 分支是死代码前端定时发,或删后端分支
一会话一条连接第二个标签页顶掉第一个按会话存连接列表
事件同步发送慢客户端拖慢 Agent加发送队列,满了丢非关键事件
重连间隔无随机大量客户端同时重连加随机抖动

第一条为什么会发生#

前端用一个布尔值「这是不是重连」决定要不要发任务请求。首连的 onclose 里,只要状态还没到结束,就以「重连」身份再连一次。而重连分支的设计前提是「任务已经在后台跑」,这个前提在首连早断时不成立。

出处:frontend/src/hooks/useShoppingXTask.ts:429(重连不发请求)、:427(状态设为 running)、:592(onclose 以重连身份再连)、app/api/server.py:928(ping 分支)、app/api/connection.py:50(一会话一条连接)

追问链:面试官接着会问什么

为什么说没复现?

这是读代码推出来的,触发条件是握手成功后、服务端发 ws_ready 前断线,本地很难碰到。面试时如实说是代码审查发现,没有线上记录。

换成 SSE 会不会更简单?

会。浏览器发回后端的消息只有澄清回答一种,走 HTTP 就够。第 15 章的答法是「SSE 也能满足」。

慢客户端拖慢 Agent 怎么解?

发送放到独立队列,Agent 只往队列里放。队列满了先丢掉进度类事件,保留结果类事件。

两个标签页应该都收到吗?

应该。按会话存一个连接列表,广播给所有连接。现在是后连的顶掉先连的。

断路器和下单幂等,哪里不严格?#

L3 口诀:半开不锁,重买当重试

断路器半开状态没限制成单个探测;同一会话再买同样的东西会被当成重试合并。

两个已知的不严格。一是断路器的半开状态没有限制成只放一个探测请求,并发下可能放过一两个。代码注释里写明了,低频外呼不值得加锁。二是下单幂等键由用户、会话、商品和数量派生,同一会话里用户真的想再买一份同样的东西,会被当成重试。重做我会给半开加一个探测令牌,幂等键加上客户端生成的请求 id。

展开:两处的设计理由与修法

断路器#

  • 用连续失败计数,不用失败率。一次购物只调几次外部服务,滑动窗口样本太少,失败率会被一两次抖动放大。

  • 状态读写都在同步段,单线程 asyncio 下计数不会错。

  • 半开期没有限制成单探测。修法:半开时发一个令牌,拿到令牌的请求才能探测,其余直接拒绝。

幂等键#

成分为什么
用户 + 会话隔天新会话再买,是两笔真实订单
商品 + 数量,排序后顺序无关,同一批货一个键
不含时间戳含了同一轮重试会各自成单

漏洞:同一会话里真想买第二份,键完全一样,会被合并成一笔。修法是前端每张确认卡生成一个请求 id 并持久化,幂等键加上它。

出处:app/utils/circuit_breaker.py:15(连续失败计数的理由)、:19(半开未限单探测,注释自认)、app/trade/usecases.py:41(幂等键组成)

追问链:面试官接着会问什么

半开放多个探测,最坏会怎样?

下游还没恢复时多打过去一两个请求,多一两次失败。对低频外呼没有实际影响,所以当时没改。

幂等键存在哪里?

订单表上做唯一约束。重复请求插入失败,查出已有订单直接返回。

客户端请求 id 丢了怎么办?

确认卡本身在服务端有记录,请求 id 可以跟卡一起存。刷新页面后从卡里取回。

为什么不用 Redis 做幂等?

订单本来就要写数据库,唯一约束是免费的。多一个 Redis 只是多一处会不一致的地方。

存储层还有哪些读代码看出来的小问题?#

L3 口诀:随机主键、多余索引、TTL 不抖

读代码列出的:随机主键、多余索引、TTL 固定、锁不比较值、Redis 单机。

这些是读代码列出来的小问题,没有在线上验证。主键大多是随机字符串,写入会打散 B+ 树。几张表在联合唯一约束外又给 user_id 单独建了索引。检索缓存过期固定 900 秒没加随机,重建锁的值固定、解锁不比较。Redis 单机、没配最大内存。每条我都知道怎么改,但当前流量下都不是瓶颈。

展开:清单与出处
问题出处重做
主键是 uuid4 随机串models.py 多处有序 id,如时间前缀
联合唯一外又建 user_id 单列索引models.py:218、:222删掉,最左前缀已覆盖
会话列表排序缺联合索引accounts.py:145(user_id, updated_at)
缓存 TTL 固定 900 秒search_cache.py:46加随机量防同时过期
重建锁值固定、解锁不比较search_cache.py:218、:232值用随机串,Lua 比较再删

另外线上 Redis 是单机、没有从库、没有配 maxmemory。这三条依据是对 docker/ 目录搜索无结果,容器有没有被手工改过配置没有核对。

怎么讲这些#

说明是代码审查得出的判断,没跑过 EXPLAIN、没做过压测。当前流量下都不是瓶颈,所以排在后面。面试官要的是你看得出来,不是你全改了。

出处:app/db/models.py:218、:222、app/api/accounts.py:145、app/recall/search_cache.py:46、:218、:232

追问链:面试官接着会问什么

随机主键真的有影响吗?

写入量小时几乎没有。量大了随机插入会让 B+ 树页分裂、缓存命中下降。改成有序 id 是常规做法。

TTL 不加随机会怎样?

同一批缓存同时过期,请求一起打到向量库。加几十秒随机量就能错开。

锁不比较值,最坏后果?

误删别人持有的锁,多一次并发重建,多查一次向量库。这把锁只为省一次查询,后果可接受。

Redis 挂了系统会怎样?

各处都有降级:缓存失效直接查库,令牌桶和断路器放行。第 14 章讲过,但停 Redis 的演练没有做过。

训练做了三件,为什么只上线一件?还有什么没标定?#

L3 口诀:离线涨了,线上没换

reranker、planner 离线涨了但没上线;收藏权重 0.2 没标定。

训练三件事只有 embedding 上线。reranker 离线排序指标涨了,但线上用它挡无关商品,不是排序,训练目标和用途没对上。planner 强化学习 reward 涨了,域判定却退步,线上还用 API 模型。收藏加分的权重 0.2 是拍的初值,没标定。重做我会先定清线上用途,再选训练目标。

展开:三件事为什么没上线、权重怎么标定
项离线结果为什么没上线重做
embedding召回率 +12.6%上线了—
rerankerndcg@8 +26%线上用途是挡无关,不是排序按「挡无关」定训练目标
plannerreward 0.790 → 0.813域判定退步,比不过 API 模型reward 里加域判定项

三个数字取自第 17 章引用的提交正文,本地没有评测原始文件。

收藏加分权重#

挑货打分里有一项「收藏推断的偏好命中」,权重默认 0.2,代码注释写的是弱正向。同一个词至少出现在 2 件收藏里才算偏好。0.2 是拍的初值,没有用评测集扫过。

怎么标定#

固定评测集,权重从 0 到 0.5 扫几个点,看端到端得分曲线。没有峰就说明这一项没用,直接删。

出处:app/tools/item_picker.py:165(PICK_W_AFFINITY 默认 0.2)、:784(弱正向加分)、app/memory/affinity.py:34(至少 2 件证据)、docs/handbook/11、12(训练结果)

追问链:面试官接着会问什么

离线涨了线上不换,训练是不是白做?

不是。结论是「训练目标要从线上用途倒推」,这个教训直接决定了重做怎么选目标。模型和数据都留着。

训练目标怎么和线上用途对上?

先写清线上这一步的输入输出和判定标准,再用同一个标准做离线评测集。离线指标和线上指标是同一个,才算对上。

为什么权重没标定就上线?

它是弱加分,最坏只影响并列商品的顺序。先上线收集收藏数据,有数据了再标定。

GPU 充足会先做哪个?

planner。它决定意图拆解,上游错了下游全错。reward 加上域判定项再训一轮。

合上页面自测 3 题#

  1. 不足分哪三类?每类各说一条,配一句重做怎么改。
  2. 搜手机出手机壳,根因是什么?哪两个确定性方案被证伪了?
  3. 运费重量、汇率、关税各是怎么来的?重做各改成什么?