LLM 面试备考
首页/项目深挖

Race Bot (HKJC) — 项目深挖防守稿

项目:香港赛马会(HKJC)垂类对话机器人
时间:2024年09月 – 2025年02月
角色:设计与开发负责人
技术核心:Agentic Workflow + Text2SQL + 合成数据 + Verl 两阶段训练(SFT + GRPO)
面试权重:★★★
来源:CV;未做一手考证
相关知识点:01-fundamentals/02-post-training/(SFT / GRPO / 数据工程)、04-agent-architecture/(tool use / ReAct)


1. 三十秒叙事#

「这是给香港赛马会做的垂类对话机器人,服务公众用户。难点在于用户问题跨度极大 —— 从『明天第三场谁会赢』这种闲聊,到『近三年沙田 1200 米草地赛、骑师 X 的胜率是多少』这种需要查结构化数据库的复杂分析。

我的方案是 Agentic Workflow 编排:安全检测 → 话题分类 → 查询改写 → 意图识别 → 分流到知识库检索 / 联网搜索 / Text2SQL → 结果后处理。

其中最大的技术投入在 Text2SQL:垂域标注数据稀缺,我搭了合成数据流水线造训练数据,然后用 Verl 对 Qwen-32B 做两阶段训练(SFT 学语法和业务逻辑,再用 GRPO 做强化学习对齐),把端到端数据问答准确率从 63% 提到 92%。」

为什么这么开场:一句话里埋了四个可挖的钩子(Agentic Workflow / 合成数据 / Text2SQL 工程 / RL 训练)。面试官通常会挑最有兴趣的那个挖,而这四个你都有准备。


2. 架构与关键决策#

2.1 为什么用 Agentic Workflow 而不是一个大 prompt#

用户请求的类型差异太大 —— 闲聊、事实查询、结构化聚合分析,走的是完全不同的工具链。塞进一个 prompt 会导致:工具描述冗长、模型选错工具、无法对单步做评测和优化。

拆成编排的好处是每一步可独立替换和评测:意图识别错了就只修意图识别,不用重训整个模型。这是工程上的核心决策。

2.2 Text2SQL 为什么不用端到端生成#

直接让 LLM 生成 SQL 在这个场景下有三个硬伤:

问题 具体表现 对策
实体模糊匹配 用户说「告东尼」还是「Tony Cruz」,数据库里是标准写法 Elasticsearch 做模糊实体匹配,先标准化再进 prompt
Schema 太大 全表结构塞不进 prompt 表/列召回(recall),只注入相关 schema
语法/业务逻辑出错 生成的 SQL 跑不通,或跑通了但业务含义错 retry-and-fix(Reflection)重试机制 + 结果后处理

所以最终方案是多阶段流水线:关键词与实体抽取 → Elasticsearch 模糊匹配 → 表列召回 → 基于语义的 few-shot 范例检索 → SQL 生成 → 自修正重试 → 结果后处理。

注意这里的取舍:多阶段流水线比端到端更复杂、延迟更高,但可控性和可调试性远胜。对政府/公共服务的场景,可控性优先级高于极致延迟。

2.3 合成数据为什么要「多策略」#

垂域标注数据稀缺,且真实分布极度不均衡(简单问题多、复杂聚合少)。单一合成策略会造出同质数据,模型在边缘 case 上崩。

采用的三种策略各有分工:

  • 主题引导生成(topic-guided):按业务主题覆盖,保证广度
  • 字段聚合(field-based aggregation):专门造统计/聚合类查询
  • 困难样本构造(hard-case construction):针对已知的失败模式定向补数据

关键技术点:合成数据必须是 (自然语言问题, ground-truth SQL) 成对的,而且 ground-truth SQL 要实际执行验证过、能返回非空结果 —— 否则你是在教模型写一种语法正确但语义错误的 SQL。

2.4 为什么要 SFT + GRPO 两阶段,而不是只 SFT#

这是最可能被深挖的地方,想清楚这个链条:

  • 只做 SFT:模型学会了 SQL 的语法和业务逻辑模板,但 SFT 是模仿学习 —— 它只能模仿训练数据里出现过的模式。对于未见过的查询组合,它没有「尝试—修正」的能力。
  • 加 GRPO:让模型在多个候选 SQL 之间,通过奖励信号(SQL 能否执行、结果是否正确)学会朝着正确方向调整。这补上了 SFT 缺失的探索能力。

SFT 先建立「能产出合理格式 SQL」的起点 —— 这一步不做,RL 阶段奖励信号无从谈起(模型一开始全在产垃圾 SQL,全是负奖励,梯度没有信息量)。

GRPO 相对 PPO 的选择理由:GRPO 用同一 prompt 采样一组回答的组内相对优势替代价值网络(critic),省掉一个和策略同规模的模型,显存和工程复杂度都显著下降。在 Verl 框架里这是现成支持的。

⚠️ 边界必须自己先说:这个项目是单轮 RLVR —— 一个 prompt 采样多条 SQL,奖励由「能否执行 + 结果是否与 ground truth 等价」判定。那正好是 GRPO 好用的场景(短 horizon、强 verifier、一条 response 就是一次决策)。

它不覆盖多轮工具调用的 RL。 多轮场景下会同时冒出四个问题:credit 太粗(整条轨迹共用一个 advantage)、组内 advantage 常归零、组内比较掺进环境噪声、rollout 成本与 policy lag —— 即 Agentic RL,见 01-fundamentals/02-post-training/08-agentic-rl.md。

面试官顺口问「那多轮呢」,正确答法是先划边界再讲理解:「我跑的是单轮,多轮我没有一手经验,我的理解来自……」。等被问出来再解释,比主动说清要吃亏。


3. 面试官会怎么往下挖#

这是本篇最重要的部分。按挖掘深度分层,每层都要能接住。

第一层:澄清与动机#

Q:63% 到 92% 这个数字,具体测的是什么?

⚠️ 这题必被问,且答不上口径会让整个项目失分。

要能立刻说清:① 指标定义(端到端问答准确率 = 最终答案与标准答案一致的比例,不是 SQL 语法正确率,也不是 SQL 执行成功率);② 测试集构成(规模、是否与训练集去重、是否含困难样本);③ baseline 是什么(63% 是 SFT 之后的版本,还是原始 prompt 版本 —— 这个一定要说准)。

诚实策略:如果测的是内部构造的评测集而非公开 benchmark,主动说明「这是我们按业务场景自建的评测集,不是公开 benchmark,所以我不能声称它能横向对比」。主动说比被问出来好。

Q:为什么不直接用现成的 Text2SQL 方案 / 更大的模型?

答:业务 schema 私有且复杂、领域实体需要专门标准化、且成本上要给公众用户扛量。现成方案在通用 benchmark 上强,但在 HKJC 的表结构和赛马术语上直接上会大面积出错。

第二层:技术细节#

Q:合成数据会不会泄漏到测试集?怎么保证评测可信?

⚠️ 这是最尖锐的一问。 必须能答:去重(问题级和 SQL 级双重去重)、主题/实体级别的切分、以及是否做过「留出真实用户数据做验证」。

如果确实存在污染风险而你没处理 —— 承认它,并说清「如果重做我会怎么切分」。面试官吃这一套,硬撑不吃。

Q:GRPO 的奖励信号具体怎么设计的?

要点:可执行性(SQL 能否跑通)+ 结果正确性(执行结果是否匹配 ground truth)+ 格式合规。要能说清每一项的权重和理由,以及当奖励可被 hack 时你怎么办(例如模型学会生成总是返回空集但永远能执行的 SQL —— 所以「执行成功」不能单独作为奖励,必须绑定结果比对)。

Q:Text2SQL 的 retry-and-fix 循环怎么防止无限重试或者越修越错?

要点:重试次数上限、每次是否注入上次的错误信息、以及兜底策略(重试失败后返回什么 —— 降级到澄清追问,还是返回部分结果)。

Q:Elasticsearch 模糊匹配是怎么做的?为什么不用向量检索?

要点:实体匹配需要精确的字符级相似(人名、马名),BM25 + 编辑距离这类稀疏方法在专有名词上往往比稠密向量更稳;且实体名是有限闭集,可以配合同义词表。也可以答「其实两者结合,向量负责语义召回,ES 负责精确匹配」—— 但只说你真做了的部分。

Q:Agentic Workflow 里意图识别错了怎么办?错误会怎么传播?

要点:错误传播(cascading error)是编排式 agent 的核心风险。对策:每步设置置信度阈值、低置信时降级为澄清追问而不是硬走错分支、以及端到端兜底。

第三层:工程与生产#

Q:线上延迟是多少?用户能接受吗?

有数字给数字,没数字就讲你是怎么平衡的:多阶段流水线天然延迟高,所以做了哪些优化(并行化独立步骤、缓存高频查询、小模型做意图识别而不用 32B)。呼应 QueWI 里做模型路由的经验。

Q:这个系统上线了吗?有多少用户?

⚠️ 红线:如实说。涉及政府/马会客户,很多数据不能披露 —— 就说「具体数据受客户保密约束,我能讲的是技术方案和它的效果验证方式」。不要编数字。

Q:出错了怎么排查?

要点:链路追踪(每一步的输入输出都记)、SQL 生成失败的 case 归档、以及定期从线上失败 case 里挖新的困难样本回灌训练集 —— 这个闭环非常加分,说明你理解「上线不是终点」。

第四层:反思与延伸#

Q:现在重做这个项目,你会改什么?

⚠️ 这题一定要有准备,它考察的是反思能力,答「没什么要改的」等于自杀。

可用的方向:① 合成数据的去重和评测切分做得更严格;② 用更强的基座或加 self-consistency 采样;③ 把意图识别和 Text2SQL 的耦合解开,让 Text2SQL 模块能被其他项目复用;④ 引入更系统的离线回归评测,防止迭代时能力回退。

Q:如果用户问的是「预测下一场谁会赢」,你怎么处理?

考察边界意识。赛马预测涉及合规和风险,正确答法是「这类请求应该在话题分类阶段就识别出来并走安全分支 —— 系统做的是信息查询和统计,不做预测性建议」。展示你懂得哪些不该做。


4. 线上故障复盘#

米哈游面经:「所有技术点必须绑定业务场景 + 线上问题 + 量化结果」。这一节按 README.md《故障题的四段结构》准备。

⚠️ 下面三类是这套架构必然会长出来的故障(由设计推导),不是替你编的经历。你要做的是把每一类对应到自己真实遇到的那一次;确实没遇到的,就如实说没遇到,再讲你为它加了什么预防。

# 故障类型 现象(先给可观测的表象) 该往哪查 修法与复盘要点
1 实体匹配错了人 / 马 SQL 执行成功、结果非空,但答的是另一个骑师的胜率 —— 系统「成功地」答非所问 把「SQL 执行成功」与「结果与 ground truth 等价」拆成两个指标分别统计;看空结果率与实体命中率 ES 模糊匹配补同义词表 + 置信度阈值,低置信转澄清追问;奖励里把可执行性绑定结果等价。复盘:只奖励可执行性会训出「永远跑得通但答非所问」的策略
2 Reward hacking:恒真 / 空集 SQL 训练 reward 稳定上涨,但人工抽检看不出模型变好;线上空结果回复增多 抽高分样本看 SQL 结构:恒真条件、缺 WHERE、极端 LIMIT 空结果与异常行数加惩罚项;每一项奖励都做对抗检验(问「模型怎样不完成任务却拿到这一项的分」)。复盘:奖励分项本身也要当被测对象
3 零梯度组吃掉算力 loss 曲线平、reward 不动、迭代很慢、GPU 利用率低 —— 但看起来「没报错」 统计同组奖励全同(全对 / 全错)的比例,看 pass rate 分布 按 pass rate 过滤或分层采样,让 batch 落在「有对有错」区间;把「零梯度组占比」做成一等监控指标。复盘:训练不动常常是数据难度分布问题,不是超参问题

面试官还会接着问#

Q:上线后发现某类问题答得特别差,你会先怀疑哪一环?

按流水线顺序逐环排除,不要直接改 prompt:① 实体标准化(ES 命中了吗);② 表列召回(需要的表进 prompt 了吗);③ few-shot 范例(召回的范例和问题同类吗);④ SQL 生成;⑤ 结果后处理。关键是先定位到环,再动手 —— 直接调 prompt 是最常见也最没依据的做法。

Q:你怎么知道模型上线后没有悄悄变差?

固定回归评测集 + 线上失败 case 回流训练集。但必须主动承认局限:垂域问题分布会漂移(赛事、马匹、骑师都在变),所以评测集需要按业务周期更新,不能建一次用一年。


5. 数字口径速查#

被问到数字时,按这个顺序确认(先确认定义,再给数字):

数字 口径必须说清
63% → 92% 端到端问答准确率;自建评测集(说明规模与去重方式);baseline = SFT 后版本
Qwen-32B 训练的是 SQL 生成组件,不是整个机器人
SFT + GRPO 两阶段 框架是 Verl;第一阶段学语法与业务逻辑,第二阶段 RL 对齐
合成数据策略 主题引导 / 字段聚合 / 困难样本,三者分别覆盖广度、聚合、已知失败模式

⚠️ 一个数字如果说不清口径,宁可不说,改说趋势和方向。 面试官对「大概提升了很多」的容忍度,高于对「92%,呃,具体怎么测的我记不清了」的容忍度。


6. 红线#

不要 claim:

  • ❌ 不要把所有工作说成自己一个人做的 —— 你是负责人,但合成数据流水线、后处理模块可能有他人参与。被问细节时明确边界是加分项。
  • ❌ 不要声称这是公开可验证的 benchmark 结果。
  • ❌ 不要透露客户的具体业务数据、用户量、内部系统细节。
  • ❌ 不要把「SQL 执行成功率」和「答案准确率」混着说 —— 面试官一追问就露馅。

不要主动说:

  • 不要一上来就讲 92% 这个数字。先讲问题和方案,让面试官问出数字,这样你是在回答而不是在炫耀,且你有机会先铺垫口径。
  • 不要主动提客户名以外的敏感信息(政府/马会的合规敏感度高)。

要主动说:

  • ✅ 主动讲清楚权衡和失败过的方案(比如「一开始试过端到端生成 SQL,失败在实体匹配上」)。
  • ✅ 主动指出当前的局限和「如果重做会怎么改」。
  • ✅ 主动划 RL 的边界:这是单轮 RLVR,不覆盖多轮工具调用的 RL(Agentic RL)。自己先说,比被问出来强 —— 而且能顺势展示「知道 GRPO 在哪失效」这一层(见 §2.4 的边界框与 08-agentic-rl.md)。
  • ✅ 主动提一个具体的线上故障(见 §4)—— 这是「真做过」最有效的证据。

7. 自测#

1. 面试官问「92% 是怎么测的」,请给出一个完整的、经得起追问的回答。

答案要点

必须包含四点:① 指标定义 —— 端到端问答准确率,即最终自然语言答案与标准答案一致的比例,并明确它不是 SQL 语法正确率、也不是 SQL 执行成功率;② 测试集 —— 规模、与训练集的去重方式(问题级 + SQL 级)、是否含困难样本;③ baseline —— 63% 对应的是哪个版本(通常指仅 SFT 后);④ 局限 —— 主动说明是自建评测集而非公开 benchmark,因此不声称可横向对比。

2. 为什么不能只用 SFT,还需要 GRPO?请从「SFT 的能力边界」角度回答。

答案要点

SFT 是模仿学习,只能学会训练数据中出现过的模式,对未见过的查询组合缺乏「尝试—修正」的能力。GRPO 通过组内相对优势提供探索信号,让模型在多个候选 SQL 之间朝着可执行且结果正确的方向调整。同时,SFT 是 RL 的必要前置:没有 SFT 建立合理的输出格式起点,RL 阶段奖励全为负、梯度没有信息量。

3. 如果你的合成数据污染了评测集,会表现出什么症状?如何在流程上避免?

答案要点

症状:评测指标异常高且与线上表现严重不符,或模型在评测集上表现远好于同分布的留出集。避免:问题级与 SQL 级双重去重、按主题/实体切分而非随机切分、并用真实用户数据留出集做交叉验证。

4. 把「SQL 执行成功」单独作为 RL 奖励会产生什么问题?

答案要点

奖励可被 hack:模型会学会生成永远能执行但返回空集或无意义的 SQL(例如恒真/恒假条件),因为这类 SQL 执行成功率最高。因此执行成功必须与结果正确性绑定,并对空结果、异常行数做惩罚。

5. 面试官问「这个系统上线后有多少用户」,而数据受客户保密约束,你怎么答?

答案要点

先明确说明受客户保密约束无法给出具体数字,然后把话题转向可讲的东西:技术方案、效果验证方式、以及上线后通过失败 case 回灌训练集的迭代闭环。绝对不要编造数字 —— 一旦被追问细节就不可挽回。