使用方式:每课练习对应
tutorial.md同编号课程;第 12 部分为跨课程模拟面试主问题与追问链(面试场景使用)。默认不附标准答案——答不出的回到对应课程/源码定位。 答题要求:凡问"为什么/怎么"的题,先给结论,再指出源码中的关键文件与行为证据(文件名 + 方法/行为),不接受"大概是"式回答。
- 画出
POST /api/chat/ask从 Controller 到返回的完整调用链,标注每一层的输入与输出类型。 - 为什么用户消息要先落库、再进管线?如果把顺序反过来,失败场景下会丢什么?
- 管线抛异常时,HTTP 状态码是什么?query_log 里哪些字段会变化?(提示:status / engine / errorMsg)
sessionId参数一路传到Nl2SqlService.answer,pipeline 模式下它被用了吗?agent 模式呢?- 追问:如果同一用户两秒内重复点两次发送,两次请求都会完整走管线吗?哪一层先挡住?
- "你好,帮我看看上月奶量"为什么不会被判为闲聊?指出判定条件的三个组成部分。
- 时间解析为什么用半开区间
[start, end)而不是BETWEEN?对索引和月末数据各有什么影响? SemanticCache的 key 由哪三部分组成?"总销售额?"和"总 销售额!"为什么命中同一条缓存?- 缓存为什么只写不缓存 fallback 结果?如果缓存了会导致什么问题?
- 缓存命中时为什么逐字段拷贝而不是直接返回缓存对象?
- 追问:这个缓存是"归一化文本精确匹配",离真正的"语义缓存"差什么?升级成向量相似度检索后,时间区间怎么办?
- 复述打分规则(alias +3 / columnName +2 / synonyms +2),并解释"命中字段排前面"对 LLM 生成的实际意义。
LinkedSchema的两个产物分别流向哪里?(一个进 prompt,一个进守护)- 业务黑话"奶量"是怎么变成
SUM(m.milk_yield)的?经过哪张表的哪几个字段? - 追问:如果两个同义词同时命中不同字段,当前打分会怎样?这种简单打分在什么问题类型下会失效?
- 完整画出降级链,并标注每一段失败时 engine 字段的最终取值。
- 为什么"生成阶段失败"不进自修复,只有"守护/执行阶段失败"才进?
fallback-to-rule: false时行为有什么不同?这个开关适合什么场景?- 自修复 prompt 里除了失败 SQL 还带上了什么?为什么带上它修复成功率才高?
LangChain4jClient为什么懒构建模型实例?mock 模式下这个设计带来什么收益?extractJson要容忍哪两种模型输出形态?- 追问:温度设为 0.0 是为了什么?NL2SQL 场景为什么不希望模型有创造性?
- 列出规则引擎的分支判断顺序,并解释为什么环比/同比必须排在趋势之前(或说明顺序敏感性体现在哪)。
metric(q)里"长词优先"防的是什么 bug?举一个若不这样做会出错的输入。- 规则引擎认不出问题时返回什么?这个返回值如何变成用户看到的兜底提示?
- 规则引擎为什么不用
SqlGenContext里的 schemaText 和 whitelist?这说明两条引擎对"语义"的依赖方式有何不同? - 追问:规则引擎的维护成本随问题形态增长线性上升,什么信号出现时你应该停止扩规则、转向 LLM?
- 列出从模型输出到结果集之间的全部五道防线,并指出每道防线的实现位置。
TablesNamesFinder收集的是 AST 里的表名,为什么这比正则匹配FROM xxx更可靠?举一个正则会漏的例子(子查询/CTE)。- 一条 SQL 同时含注释和第二条语句,守护在哪一步拒绝?拒绝消息是什么?
- PlainSelect 和 UNION 的 LIMIT 处理为什么走不同分支?
setQueryTimeout与setMaxRows分别防什么?只靠一个为什么不够?- 追问:表白名单能防"跨库读 mysql.user",那同库内未授权列的读取靠什么约束?(提示:提示词软约束 vs 守护硬约束的分界)
- 复述图表决策顺序,说明每一步用到的是"结果形态"信号还是"问题意图"信号。
looksLikeTime有哪两路证据?"3月"这种字符串列名不含时间词时靠哪一路?- 长表透视
pivot()输入输出各是什么形态?类别超过 8 个时怎么处理? - 追问:为什么占比问题类别 >8 就不推荐饼图?这是经验规则还是硬性正确?如果 12 个类别但头部 3 个占 90%,你会怎么改进?
- 对比 pipeline 与 agent:第 3~5 步的编排权分别在哪?外壳六步中哪些步骤在两种模式下完全一致?
- 三个工具各自解决模型哪种失败模式?(编造列名 / 编造维度值 / SQL 写错)
AgentRunContext.tryConsume超限时返回字符串而不是抛异常——这个设计为什么让框架循环"天然有界"?如果改成抛异常会有什么不同?executeSql为什么要等getSchema之后才能用?这个约束靠什么强制(提示词还是代码)?- ThreadLocal 上下文为什么必须 try-finally 清理?不清会发生什么具体事故(结合线程池复用)?
getColumnValues对 tableName/columnName/keyword 分别做了什么防注入处理?- 追问:预算值 maxSqlExecutions=3 是怎么定的?如果评测显示两轮重试后的成功率曲线仍陡峭上升,你会调到几?依据是什么?
assemble有哪三个分支?每个分支的成本与风险各是什么?- 双键登记(原始 SQL + 守护重排版)解决什么问题?
normalizeSql折叠了哪些差异? - 模型返回一条从未执行过的 SQL 时,系统会怎么做?哪几步可能失败?最终兜到哪?
- 为什么回填时用
guardedSql而不是模型原文对外展示? - 追问:"任何执行出去的 SQL 一定过了守护"——在 agent 路径上逐条指出守护发生的所有位置,验证这个不变量。
- 画出 JWT 从签发到 ThreadLocal 的链路,标注每一步的类与方法。
- 会话不存在和会话不属于你都返回 404——为什么故意不区分?(结合越权探测讨论)
AuthInterceptor.afterCompletion清理 ThreadLocal 和AgentOrchestrator.runLoop的 finally 清理,解决的是不是同一类问题?- 追问:JWT 无法主动失效(登出/改密后旧 token 仍有效),演示版怎么接受这一点?生产上你会加什么机制?
- 评测器怎么在 pipeline 与 agent 之间切换?切换通过什么机制影响同一份
Nl2SqlService代码? - 评测为什么用一次性 memoryId?不这样会发生什么具体的错误结论?
- 你改动提示词后,应跑哪几组对比?结果文件落在哪里?
- 追问:"结构准确率 100%"衡量的是什么?它不衡量什么?(提示:SQL 可执行/结构正确 ≠ 口径正确)
按追问深度组织:每个主问题下 3~5 个追问由浅入深,追问 3 以后通常会触及设计权衡或反事实("如果没有 X 会怎样")。
主问 1:介绍一下你这个 ChatBI 的整体链路,一次提问是怎么变成图表的?
- 追问 1:六步里哪些是确定性代码、哪些依赖 LLM?为什么这么划分?
- 追问 2:LLM 挂了整个系统会怎样?描述完整的降级路径。
- 追问 3:为什么自修复只做一次?怎么判断一次够不够?
- 追问 4:如果把规则引擎也去掉,只剩 LLM,系统少了什么能力?
主问 2:为什么同时保留 pipeline 和 agent 两条引擎?
- 追问 1:两条引擎共享哪些组件?不共享哪些?
- 追问 2:怎么用同一评测集对比两条引擎?对比哪些指标?
- 追问 3:agent 模式上线策略是什么?出问题怎么一键切回?
- 追问 4:什么时候你会认为 agent 可以完全取代 pipeline?现在到那一步了吗?
主问 3:NL2SQL 的提示词怎么设计的?怎么防止模型幻觉表名列名?
- 追问 1:SideInfo 注入今天日期和时间区间,为什么不把"上个月"这种词留给模型理解?
- 追问 2:few-shot 例子选哪三类?选例的原则是什么?
- 追问 3:提示词约束("只用 Schema 表列")和守护约束(表白名单)是什么关系?只留一个行不行?
- 追问 4:模型返回的不是纯 JSON 怎么办?你的解析器怎么兜?
主问 4:Agent 模式下模型怎么"自主"完成一次查询?
- 追问 1:工具循环是谁驱动的?你的应用代码里有没有手写循环?
- 追问 2:模型陷入"改 SQL→失败→再改"的死循环怎么办?
- 追问 3:预算超限时返回文本拒绝而不是抛异常,为什么?两种做法模型行为有何差异?
- 追问 4:0.36 版本没有 ToolContext,你用 ThreadLocal 传递请求上下文,这个方案有什么坑?怎么防?
主问 5:模型生成的 SQL 直接执行,安全问题怎么解决的?
- 追问 1:从模型输出到结果集,列一遍全部防线。
- 追问 2:AST 级表名校验比正则强在哪?举个正则漏判的例子。
- 追问 3:强制 LIMIT 对 UNION 子句怎么生效的?为什么分支处理?
- 追问 4:只读连接 + queryTimeout + maxRows,三者各挡住哪类事故?
- 追问 5:如果模型生成的 SQL 合法但全表扫描 8 秒超时,这个错误信息会流向哪里?(考察"错误即数据")
主问 6:你的语义缓存怎么设计的?命中率怎么提升?
- 追问 1:归一化 key 折叠了哪些差异?还剩哪些"同义不同 key"的漏网情况?
- 追问 2:缓存对象为什么不直接返回引用?
- 追问 3:TTL 600 秒和 maxSize 512 怎么定的?数据更新后缓存里的旧结果怎么办?
- 追问 4:升级向量语义缓存,时间区间和 dataset 隔离怎么融进相似度检索?
主问 7:Agent 的行为不透明,你怎么知道它每一步干了什么、钱花在哪?
- 追问 1:trace 里记了哪些字段?怎么保证它不会无界增长?
- 追问 2:从 trace 能统计出哪些运营指标?(平均工具调用数/SQL 重试率/预算触顶率)
- 追问 3:query_log 审计表记了什么?engine 字段有哪几种取值,各自说明什么?
- 追问 4:如果线上有用户反馈"回答错了",你怎么用这两样东西定位问题?
主问 8:这个项目怎么证明你的改动没有让质量变差?
- 追问 1:评测集多大?结构准确率怎么定义?
- 追问 2:单元测试覆盖哪些最关键的行为?(提示:SqlGuard 8 个安全测试/TimeRangeParser/SemanticCache)
- 追问 3:评测跑的是函数还是整条链?为什么这个选择重要?
主问 9:业务人员说的"奶量""头数"怎么映射到物理表的?
- 追问 1:语义层存哪几个关键字段?改同义词要重启服务吗?
- 追问 2:Schema 召回的打分公式是什么?它的局限在哪?
- 追问 3:口径(如"产奶量=SUM")同时写进了规则引擎和提示词,两处重复会不会不一致?怎么治理?
- 追问 4:如果换一个业务域(比如电商),哪些代码要改、哪些不用改?(考察规则引擎硬编码 vs 通用链路的边界)
主问 10:这个项目里你用了两处 ThreadLocal,分别解决什么问题?
- 追问 1:线程池复用场景下忘清理会发生什么?你分别在哪个生命周期点清理的?
- 追问 2:LangChain4j 的 AiServices 代理在哪个线程上执行 @Tool 方法?ThreadLocal 在那个线程上可见吗?(进阶:如果框架换线程池执行工具,你的方案会失效吗,怎么兜)
- 追问 3:懒构建模型实例的双检锁,为什么要 volatile?不加上会怎样?
- 能否在 5 分钟内白板画出 pipeline 主链 + agent 分支 + 降级链三合一图?
- 每个追问若答不出,能否定位到 tutorial.md 对应课与源码文件重读?
- 是否还有"大概是/应该是"式结论?逐条换成"源码第 X 行行为是 Y"或标注"待确认"。