第48题:问数 Agent 整体架构、意图识别、历史上下文与 NL2SQL
1. 来源边界
原表明确标注:
本题属于 T5 技术扩展题,可以用于备考,不能表述为已经核验的相关真实面试题。
同时需要注意一个来源边界。
题目虽然写了:
- 整体架构;
- 意图识别;
- 历史上下文;
- NL2SQL;
但原表参考回答实际详细展开的主要内容是:
历史上下文与任务状态管理。
原表直接支持的内容包括:
- 不要把全部 Conversation 当作任务状态;
- 建立 Task / Subtask ID;
- 区分 Active / Suspended / Cancelled;
- 保存不可丢失约束;
- 保存关键 Decision;
- 保存 Artifact Reference;
- Summary 必须可重建并保留 Provenance;
- 用户切换话题时显式确认挂起或取消;
- 撤销旧子任务的 Worker Lease;
- 忽略取消任务的 Late Result;
- 通过 Constraint Replay 和 Regression Sample 检测 Context Compression Loss;
- 验收要覆盖越权、注入、重复执行、依赖故障、人工接管和回滚。
下面“整体架构、Intent Routing、NL2SQL”部分属于基于题目措辞和外部技术资料进行的扩展。
2. 核心回答
如果让我设计一个企业问数 Agent,我会把它拆成六层:
User
↓
Conversation / Task State
↓
Intent Router
↓
Business Semantic Layer
↓
NL2SQL Planning & Validation
↓
Read-only Data Execution
↓
Result Validation & Explanation
进一步展开:
用户问题
↓
Session / Task Manager
↓
Intent Classification
↓
Entity / Metric / Time Extraction
↓
Business Glossary Retrieval
↓
Schema Linking
↓
SQL Generation
↓
SQL AST / Permission / Cost Validation
↓
Read-only Execution
↓
Result Validation
↓
Natural Language Answer
↓
Trace / Audit / State Update
系统成功的标准应同时满足:
BusinessCorrect∧SQLCorrect∧Authorized∧ResultCorrect BusinessCorrect \land SQLCorrect \land Authorized \land ResultCorrect BusinessCorrect∧SQLCorrect∧Authorized∧ResultCorrect
只生成语法合法的 SQL 远远不够。
3. 整体架构可以怎么设计
一个比较完整的问数 Agent 可以包含:
┌────────────────────────────┐
│ User / BI Frontend │
└──────────────┬─────────────┘
↓
┌────────────────────────────┐
│ Session & Task State │
│ Task / Subtask / Context │
└──────────────┬─────────────┘
↓
┌────────────────────────────┐
│ Intent Router │
│ Intent + Slots + Confidence│
└──────────────┬─────────────┘
↓
┌────────────────────────────┐
│ Semantic Layer │
│ Metric / Dimension / Rule │
└──────────────┬─────────────┘
↓
┌────────────────────────────┐
│ Schema Retrieval │
│ Table / Column / Join │
└──────────────┬─────────────┘
↓
┌────────────────────────────┐
│ NL2SQL Planner │
└──────────────┬─────────────┘
↓
┌────────────────────────────┐
│ SQL Guard │
│ AST / ACL / Cost / Limit │
└──────────────┬─────────────┘
↓
┌────────────────────────────┐
│ Query Executor │
│ Read-only DB Credential │
└──────────────┬─────────────┘
↓
┌────────────────────────────┐
│ Result Validator │
└──────────────┬─────────────┘
↓
┌────────────────────────────┐
│ Answer Generator │
│ Result + Metric Definition │
└────────────────────────────┘
4. 为什么要先做 Intent Recognition
用户问数并不总是在请求 SQL。
例如:
销售额是多少?
属于:
Metric Query
用户问:
销售额这个指标怎么算?
属于:
Metric Definition
用户问:
为什么华东地区下降了?
可能属于:
Drill-down / Diagnostic Analysis
用户说:
把刚才那个改成按月份看。
属于:
Follow-up Transformation
用户说:
把这些数据导出成 CSV。
属于:
Action / Export
因此第一阶段需要判断:
Intent(x) Intent(x) Intent(x)
再选择对应执行路径。
5. Intent 可以怎样分类
一个基础分类可以包括:
| Intent | 说明 |
|---|---|
metric_query | 查询一个指标 |
trend_query | 时间趋势 |
comparison_query | 维度比较 |
drilldown_query | 下钻分析 |
metric_definition | 询问业务口径 |
nl2sql_query | 需要执行数据库查询 |
followup_modify | 修改上轮分析条件 |
export | 导出结果 |
clarification | 信息不足,需要澄清 |
unsupported | 当前系统无法处理 |
真正实现时,分类数量应由具体业务决定。
6. Intent Router 最好输出结构化结果
例如用户:
帮我看今年华东地区各季度的净收入。
Router 可以输出:
{
"intent": "trend_query",
"metric": "net_revenue",
"dimensions": ["region"],
"filters": {
"region": "华东"
},
"time_range": "current_year",
"time_granularity": "quarter",
"confidence": 0.94,
"need_clarification": false
}
然后由代码判断:
intent == trend_query
↓
进入 Data Query Pipeline
这种设计更容易进行:
- Test;
- Trace;
- Debug;
- 权限判断;
- 回归测试。
7. Intent Confidence 低时应该怎么办
例如用户问:
看一下增长情况。
缺少:
- 什么指标;
- 什么时间;
- 什么对象。
此时 Agent 不应该强行生成 SQL。
可以输出:
{
"intent": "clarification",
"missing": [
"metric",
"time_range"
]
}
然后询问:
你希望看哪个指标,以及哪个时间范围?
这样可以降低:
WrongAssumption→WrongSQL WrongAssumption \rightarrow WrongSQL WrongAssumption→WrongSQL
的风险。
8. 为什么企业问数需要 Business Semantic Layer
这是 NL2SQL 中非常关键的一层。
例如用户问:
GMV 是多少?
数据库中可能没有:
gmv
这个字段。
业务定义可能是:
$$
GMV
\sum order_amount
$$
同时还可能规定:
order_status != cancelled
也可能进一步规定:
退款发生后是否扣除
或者:
税前还是税后
因此需要保存:
Metric Definition
Dimension Definition
Business Rule
Synonym
Owner
Version
例如:
metric: net_revenue
definition:
paid_amount - refund_amount
filters:
payment_status = "PAID"
time_column:
payment_time
owner:
finance
version:
2026-03
9. 为什么只给数据库 Schema 还不够
假设数据库有:
orders.amount
orders.pay_amount
orders.final_amount
finance.net_amount
用户问:
收入是多少?
Schema 无法直接告诉模型:
公司正式财务口径使用哪一列?
企业数据通常还有:
- 内部指标定义;
- 报表约定;
- 特殊过滤规则;
- 历史兼容规则;
- 数据延迟规则。
所以企业 NL2SQL 更合理的输入是:
Question+Schema+BusinessSemantics+Authorization+Context Question + Schema + BusinessSemantics + Authorization + Context Question+Schema+BusinessSemantics+Authorization+Context
仅有:
Question+Schema Question + Schema Question+Schema
通常不足以确定正确业务答案。
10. Schema Linking 是什么
确定业务指标之后,需要找到对应:
- Database;
- Schema;
- Table;
- Column;
- Join Path。
例如:
用户问题:
华东地区净收入
业务指标解析:
Metric:
net_revenue
Schema Linking:
orders.payment_amount
refund.refund_amount
customer.region
Join Path:
orders.customer_id
=
customer.id
以及:
refund.order_id
=
orders.id
Schema Linking 的质量通常会直接影响最终 SQL 的正确性。
10.1 净收入中的一对多关联陷阱
企业 NL2SQL 中需要特别检查一对多关联产生的重复聚合问题。
假设存在一笔订单:
order_id = 1001
order_amount = 100 元
该订单发生两次退款:
refund_1 = 10 元
refund_2 = 20 元
正确净收入应为:
100−10−20=70 100-10-20=70 100−10−20=70
如果直接关联订单表和退款表:
SELECT
SUM(o.order_amount) - SUM(r.refund_amount) AS net_revenue
FROM orders o
LEFT JOIN refunds r
ON o.order_id = r.order_id
WHERE o.order_id = 1001;
Join 后可能得到:
order_id | order_amount | refund_amount
---------|--------------|--------------
1001 | 100 | 10
1001 | 100 | 20
此时:
SUM(order_amount) = 200
SUM(refund_amount) = 30
最终得到:
200−30=170 200-30=170 200−30=170
该结果在 SQL 语法和执行层面都可以成功,但业务结果明显错误。
更稳健的处理方式是先按照订单粒度聚合退款:
WITH refund_by_order AS (
SELECT
order_id,
SUM(refund_amount) AS total_refund
FROM refunds
GROUP BY order_id
)
SELECT
SUM(
o.order_amount - COALESCE(r.total_refund, 0)
) AS net_revenue
FROM orders o
LEFT JOIN refund_by_order r
ON o.order_id = r.order_id;
此时对于订单 1001:
order_amount = 100
total_refund = 30
net_revenue = 70
这类指标至少需要覆盖三种回归样例:
| 场景 | 订单金额 | 退款记录 | 期望净收入 |
|---|---|---|---|
| 未退款 | 100 | 无 | 100 |
| 部分退款 | 100 | 10 | 90 |
| 多次退款 | 100 | 10 + 20 | 70 |
因此,Schema Linking 不能只判断 Join Path 是否存在,还需要判断:
Join Cardinality
Aggregation Grain
Metric Grain
是否一致。
对于一对多关系,可以把检查过程写成:
订单粒度指标
↓
识别一对多退款关系
↓
退款先按 order_id 聚合
↓
恢复到订单粒度
↓
计算订单级净收入
↓
再进行地区、时间等上层聚合
这个例子说明,NL2SQL 的正确性还依赖于对数据粒度和关联基数的理解。
11. 为什么不应该把整个数据库 Schema 都塞进 Prompt
真实企业数据库可能包含:
1000+ columns
甚至更多。
完整塞入会带来:
- Context 太长;
- Token Cost;
- 无关字段干扰;
- 同名字段混淆;
- Schema Version 问题。
因此可以先做:
Question
↓
Metric Retrieval
↓
Relevant Table Retrieval
↓
Relevant Column Retrieval
↓
Join Path Retrieval
最后只向 SQL Generator 提供相关子图。
12. NL2SQL Pipeline 可以怎么设计
我会设计成:
Question
↓
Intent + Slots
↓
Metric Resolution
↓
Schema Retrieval
↓
Join Planning
↓
SQL Draft
↓
AST Parse
↓
Permission Check
↓
Cost Check
↓
Read-only Execute
↓
Result Validation
↓
Answer
其中:
Generate SQL
只占整个链路中的一环。
13. 为什么 SQL 生成后还需要 AST Validation
假设模型生成:
DELETE FROM orders;
语法完全正确。
问数 Agent 显然不应该执行。
所以执行前需要 Parse SQL AST。
只允许例如:
SELECT
WITH ... SELECT
拒绝:
INSERT
UPDATE
DELETE
DROP
ALTER
TRUNCATE
GRANT
REVOKE
还可以进一步检查:
- Table Allowlist;
- Column Permission;
- Function Allowlist;
- Subquery;
- External Function;
- Cross-database Access。
14. 数据库本身仍然应该使用只读权限
应用层 SQL Validator 存在出错可能。
数据库 Credential 也需要做到:
Read Only
+
Least Privilege
形成两层控制:
SQL Policy
↓
Database Permission
例如 PostgreSQL 可以使用 Read-only Transaction。
在 Read-only Transaction 中,大量写操作和 DDL 会直接被禁止。
这样即使生成层漏检:
UPDATE
数据库层仍可拒绝。
15. 为什么还要做 Row / Column Permission
即使执行:
SELECT *
FROM salary;
仍可能发生越权。
所以数据库访问还需要结合:
User
Tenant
Role
Department
Data Classification
例如:
Allowed(user,column)=true Allowed(user,column)=true Allowed(user,column)=true
才允许选择该列。
可以通过:
- View;
- Row Level Security;
- Column-level Permission;
- Query Rewrite;
等方式实现。
权限应尽量在 Data Access Layer 强制执行。
16. SQL 执行前为什么还要检查 Cost
只读 SQL 同样可能造成事故。
例如:
SELECT *
FROM trillion_row_table;
虽然没有修改数据,却可能:
- 扫描大量数据;
- 占满数据库资源;
- 导致其他查询变慢;
- 产生高额云数仓费用。
因此可以在执行前做:
EXPLAIN
获得 Query Plan 和估计 Cost。
如果:
EstimatedCost>Cmax EstimatedCost>C_{max} EstimatedCost>Cmax
则:
Reject
或者:
Ask User
17. 还需要设置哪些执行限制
例如:
query_timeout
row_limit
bytes_scanned_limit
concurrency_limit
可以自动向查询增加:
LIMIT 1000
但需要注意:
对:
COUNT
SUM
AVG
等 Aggregate Query,不能简单在错误位置追加 LIMIT。
所以这类修改最好基于:
SQL AST
完成。
18. SQL 执行失败后怎么办
模型第一次生成的 SQL 可能出现:
- Column Not Found;
- Type Mismatch;
- Dialect Error;
- Join Error;
- Function Error。
可以有限度进行:
Generate
↓
Validate
↓
Execute
↓
Error
↓
Repair
但需要设置:
max_repair_attempts
例如:
Nrepair≤2 N_{\text{repair}}\le2 Nrepair≤2
防止进入:
Generate → Error → Generate → Error
的无限循环。
19. SQL 执行成功也不代表结果正确
例如用户问:
今年平均客单价是多少?
模型生成:
SELECT AVG(amount)
FROM orders;
SQL:
Syntax Valid
并且:
Execution Success
但如果业务规定:
只统计已支付订单
结果依然错误。
前面的净收入一对多退款案例也属于同一类问题。
SQL 可以:
Parse Success
Execution Success
但错误的 Join Cardinality 会造成订单金额重复聚合。
因此需要区分:
SQL Validity
Execution Success
Business Correctness
Result Correctness
20. Result Validation 怎么做
20.1 空结果
例如:
0 rows
可能意味着:
- 用户条件真的没有数据;
- 时间字段错了;
- Join 错了;
- 权限过滤过度。
需要进一步区分。
20.2 数值异常
例如:
收入 = -10^15
可能需要执行异常检查。
20.3 单位
例如数据库:
amount_cent
查询结果:
10000
最终应该解释成:
100 元
20.4 时间口径
例如:
2026 年 8 月
需要明确:
- Calendar Month;
- Fiscal Month;
- 时区。
20.5 聚合粒度与关联基数
对于净收入等涉及多表关联的指标,还应检查:
Metric Grain
Join Cardinality
Aggregation Order
例如订单与退款存在一对多关系时,需要确认退款已经先聚合到订单粒度。
至少验证:
未退款订单
部分退款订单
多次退款订单
三个代表性场景。
如果:
100 元订单
+
10 元退款
+
20 元退款
最终结果必须保持为:
70 元 70\text{ 元} 70 元
该测试能够直接发现订单金额因一对多 Join 被重复计入的问题。
21. 用户看到的最终答案应该包含什么
一个问数 Agent 最终可以输出:
结论:
2026 Q2 华东地区净收入为 1.23 亿元。
口径:
净收入 = 已支付金额 - 已退款金额。
时间范围:
2026-04-01 至 2026-06-30。
数据更新时间:
2026-08-30 15:00。
SQL:
[可展开查看]
数据源:
finance.orders_v3
finance.refunds_v2
这样用户能够知道:
- 结果;
- 指标定义;
- 时间;
- 数据新鲜度;
- 来源;
- SQL。
这有利于结果复核。
22. 原表关于历史上下文的核心原则是什么
原表最明确的一句话是:
不要把全部对话当状态。
建议至少区分:
Conversation History
Task State
Business Constraint
Artifact
External State
这些数据具有不同生命周期。
23. Conversation History 和 Task State 有什么区别
Conversation History 例如:
User:
看一下今年销售额。
Assistant:
今年销售额是...
User:
再按地区拆一下。
Task State 应抽象成:
{
"task_id": "T100",
"intent": "sales_analysis",
"metric": "revenue",
"time_range": "2026",
"dimensions": ["region"],
"status": "active"
}
后续模型主要依赖:
Current Task State
这样可以避免每次都从几十轮历史中重新推断当前任务。
24. 为什么需要 Task / Subtask ID
一个用户可能同时存在多个任务:
T1:
分析销售额
T2:
解释 GMV 定义
T3:
导出昨天的数据
每个任务需要独立维护:
task_id
status
constraints
artifacts
worker
这样可以避免异步 Tool Result 返回以后无法判断其所属任务。
25. 状态至少要有哪些生命周期
原表明确提出:
Active
Suspended
Cancelled
还可以根据实现增加:
Pending
Running
Completed
Failed
例如:
ACTIVE
↓
SUSPENDED
↓
ACTIVE
↓
COMPLETED
或者:
ACTIVE
↓
CANCELLED
Cancelled 任务的 Late Result:
直接忽略
不能重新污染当前会话。
26. 用户突然换话题怎么办
例如:
用户:
帮我分析华东销售额。
Agent:
正在查询数据库...
用户:
先不用了,帮我看看利润率定义。
此时旧任务可能还在数据库执行。
原表要求:
显式确认:
Suspend 还是 Cancel?
例如:
旧任务 T1 → CANCELLED
然后:
Revoke Worker Lease
后续 T1 的查询结果即使晚到:
Ignore
不能重新写入当前任务状态。
27. 为什么需要 Artifact Reference
例如查询产生:
SQL
Result Table
Chart
CSV
Metric Definition
这些内容不适合全部写进 Conversation Summary。
状态中保存:
artifact_id
例如:
{
"sql_artifact": "A102",
"result_table": "A103",
"chart": "A104"
}
真正内容保存在 Artifact Store。
这样可以减少:
- Context Token;
- Summary Loss;
- 重复传输。
28. Summary 为什么必须保留 Provenance
例如摘要写:
用户希望分析净收入。
系统还应该知道这条信息来自:
user_turn_27
或者:
metric_definition_v3
形成:
Summary Claim
↓
Provenance
↓
Original Event / Artifact
这样摘要被质疑时可以回溯原始来源。
29. Context Compression 怎么防止丢关键约束
假设历史里用户说过:
所有销售额都按人民币计算。
100 轮后进行 Summary。
如果压缩时丢掉这条约束,后续查询可能产生错误单位。
因此原表要求定期进行:
Constraint Replay。
例如维护:
non_lossy_constraints
单独保存:
{
"currency": "CNY",
"timezone": "Asia/Shanghai",
"tenant": "A"
}
这些关键约束不依赖自然语言摘要保存。
30. 如何测试 Context Compression Loss
可以准备 Regression Case:
Turn 1:
所有金额用人民币。
Turn 20:
...
Turn 50:
...
Turn 80:
帮我算收入。
经过多次:
Summary / Compaction
以后检查最终 SQL 是否仍然使用正确:
Currency
Timezone
Metric Definition
Tenant
可以定义:
$$
ConstraintRetentionRate
\frac{
N_{\text{retained constraints}}
}{
N_{\text{required constraints}}
}
$$
31. NL2SQL 应该怎么评估
我会分四层评测。
31.1 Intent 层
例如:
Intent Accuracy
Macro-F1
Confusion Matrix
同时评估:
- Metric Extraction;
- Dimension Extraction;
- Time Range Extraction。
31.2 SQL 层
评估:
- Parse Success;
- Execution Success;
- Execution Accuracy;
- Forbidden SQL Rate。
例如:
$$
ExecutionAccuracy
\frac{
N_{\text{queries producing expected result}}
}{
N_{\text{test}}
}
$$
SQL Exact Match 可以作为辅助指标。
两个 SQL 字符串不同,仍可能产生相同正确结果。
31.3 Business 层
测试:
- Metric Definition Correctness;
- Filter Correctness;
- Time Grain Correctness;
- Join Correctness;
- Unit Correctness;
- Join Cardinality Correctness;
- Aggregation Grain Correctness。
对于涉及一对多关系的指标,需要加入专门回归样例。
例如净收入:
Case 1:
100 元订单,无退款
Expected = 100 元
Case 2:
100 元订单,退款 10 元
Expected = 90 元
Case 3:
100 元订单,退款 10 元和 20 元
Expected = 70 元
这类测试可以直接检查:
一对多 Join
↓
订单金额是否重复
↓
退款是否先按订单聚合
↓
最终业务指标是否正确
31.4 End-to-End 层
最终看:
用户问题
↓
正确结果
↓
正确解释
可以定义:
$$
TaskSuccessRate
\frac{
N_{\text{correct end-to-end answers}}
}{
N
}
$$
32. 为什么传统 Text-to-SQL Benchmark 不足以代表企业问数
Spider 2.0 的公开研究已经表明,真实企业 Text-to-SQL 通常需要:
- 大型 Schema;
- 多种数据库;
- SQL Dialect;
- Metadata Search;
- 多条 SQL;
- 数据转换;
- 项目代码;
- 长上下文。
Spider 2.0 中很多数据库拥有超过:
1000 columns
其任务复杂度明显高于传统单条 Text-to-SQL。
2026 年 EntSQL 又进一步研究:
企业 SQL 经常依赖内部业务文档和指标定义。
这与问数 Agent 的实际问题高度一致。
系统需要同时完成:
理解数据库
以及:
理解企业业务语义
33. NL2SQL 安全测试应该覆盖什么
33.1 Unauthorized Table
用户没有权限的表:
必须拒绝。
33.2 Sensitive Column
例如:
salary
phone
id_card
未经授权不能查询。
33.3 Write SQL
模型生成:
DELETE / UPDATE
必须阻断。
33.4 Expensive Query
超大扫描:
Reject / Require Approval
33.5 Prompt Injection
数据库 Metadata 中出现恶意自然语言时:
不能改变系统权限。
33.6 Cross-Tenant
Tenant A:
无法读取 Tenant B。
34. 整个系统需要记录什么 Trace
建议记录:
trace_id
session_id
task_id
subtask_id
intent
intent_confidence
metric
business_rule_version
schema_version
selected_tables
sql
sql_ast_hash
permission_decision
query_plan
execution_time
rows_returned
result_artifact
answer
state_transition
这样出现错误时可以判断:
Intent 错了?
Metric 错了?
Schema Linking 错了?
SQL 错了?
权限错了?
数据库数据错了?
Answer 解释错了?
35. 一个典型执行例子
用户:
今年华东地区净收入同比增长多少?
35.1 Intent
{
"intent": "comparison_query",
"metric": "net_revenue",
"region": "华东",
"time_range": "current_year",
"comparison": "YoY"
}
35.2 Business Semantic Retrieval
得到:
net_revenue
=
paid_amount - refund_amount
并读取其:
version
owner
time_column
35.3 Schema Linking
找到:
orders
refunds
customers
同时需要检查:
orders : refunds
=
1 : N
如果退款表允许一笔订单对应多条退款记录,则应先将退款聚合到:
order_id
粒度,再与订单表关联。
35.4 SQL Planning
分别计算:
Current Year
Previous Year
并保证净收入的计算遵循:
Refunds
↓
GROUP BY order_id
↓
Orders LEFT JOIN Aggregated Refunds
↓
Order-level Net Revenue
↓
Time / Region Aggregation
35.5 SQL Guard
检查:
SELECT only
Authorized tables
Authorized columns
Query cost
35.6 Execution
使用:
Read-only Credential
35.7 Result
假设:
2026 = 120M
2025 = 100M
计算:
$$
YoY
\frac{120-100}{100}
20%
$$
35.8 Final Answer
2026 年至今华东地区净收入同比增长 20%。
口径:
净收入 = 已支付金额 - 已退款金额。
比较区间:
2026 年至今 vs 2025 年同期。
并提供:
SQL / Metric Definition / Data Freshness
供用户复核。
36. 面试官如果问“为什么不直接把历史都塞进去”
可以回答:
全量历史适合保留审计和重放,但不适合直接等同于当前业务状态。长期对话中会同时存在旧话题、已取消任务、历史 Tool Result 和过期业务约束,如果全部直接交给模型,容易产生状态污染和 Token 成本。
我会单独维护 Task State,包括 task/subtask ID、当前 Intent、Metric、Time Range、Active/Suspended/Cancelled 状态、不可丢失约束和 Artifact Reference。Conversation History 仍保留,但当前执行主要读取结构化 Task State。
Summary 可以用于压缩上下文,但必须保留 Provenance,并通过 Constraint Replay 和 Regression Case 验证关键条件没有在压缩过程中丢失。
这一部分最贴近原表参考答案。
37. 面试官如果问“NL2SQL 最难的地方是什么”
可以回答:
企业 NL2SQL 最难的部分通常包含业务语义、Schema Linking、权限、数据粒度和结果正确性几个方面。
例如“净收入”可能不是数据库字段,而是公司定义的指标公式。所以系统需要先从 Metric Glossary 找到业务定义,再检索相关表、字段和 Join Path。
Schema Linking 还需要处理关联基数。例如一笔订单可能对应多条退款记录。直接关联后再汇总订单金额会产生重复计数,因此需要先把退款聚合到订单粒度,再计算净收入。
SQL 生成以后还要经过 AST、ACL、Cost 和 Read-only 校验。执行成功以后还要检查结果口径、单位、时间范围、聚合粒度和异常值。
所以我的验收标准是最终业务结果正确,同时满足权限和资源约束。
38. 面试时可以压缩成下面这段
问数 Agent 我会拆成 Session/Task State、Intent Router、Business Semantic Layer、Schema Retrieval、NL2SQL、SQL Guard、Read-only Executor 和 Result Validator 几层。
首先对用户问题做结构化 Intent Recognition,识别 Intent、Metric、Dimension、Filter、Time Range 和 Confidence。信息不足就先 Clarification。
NL2SQL 之前需要先做 Business Semantic Resolution,因为企业里的“GMV、净收入、活跃用户”通常都有具体业务口径,单靠数据库 Schema 不一定能确定。确定指标后再做 Schema Linking,找到相关表、字段和 Join Path。
Schema Linking 还需要判断数据粒度和 Join Cardinality。例如一笔 100 元订单存在 10 元和 20 元两次退款,正确净收入是 70 元。直接连接订单和退款后汇总可能重复计算订单金额,所以应先按 order_id 聚合退款,再与订单表关联,并用未退款、部分退款、多次退款三类样例做回归验证。
SQL 不能直接执行。我会先 Parse AST,限制为允许的只读语句,再检查表列权限、Tenant、查询 Cost 和 Row Limit,最后使用最小权限的 Read-only Database Credential 执行。执行成功后还需要验证结果范围、单位、时间口径、关联基数和业务规则。
历史上下文方面,我不会直接把全部 Conversation 当成状态。我会维护 task/subtask ID、Active/Suspended/Cancelled、不可丢失约束、Decision 和 Artifact Reference。用户换话题时显式挂起或取消旧任务,并撤销旧 Worker Lease,Late Result 不再写入新任务。Summary 必须可重建并保留 Provenance,还要用 Constraint Replay 验证压缩没有丢关键信息。
评测时分别看 Intent Accuracy、Slot Extraction、SQL Execution Accuracy、Business Correctness、Unauthorized Query Rate 和 End-to-End Task Success。
一句话总结:
问数 Agent 的关键链路是“理解业务问题 → 解析业务口径 → 找到正确 Schema 和数据粒度 → 安全地产生并执行 SQL → 验证结果 → 管理好多轮任务状态”。
39. 当前资料能够确定到什么程度
39.1 原表直接支持
原表明确支持:
- Conversation 不能直接等同 Task State;
- Task / Subtask ID;
- Active / Suspended / Cancelled;
- 不可丢失 Constraint;
- Decision;
- Artifact Reference;
- Summary 可重建;
- Provenance;
- 话题切换时确认 Cancel / Suspend;
- 撤销旧 Worker Lease;
- Late Result 丢弃;
- Constraint Replay;
- Regression Sample;
- Context Compression Loss;
- 越权测试;
- Prompt Injection 测试;
- Duplicate Execution;
- Dependency Failure;
- Human Takeover;
- Rollback;
- Trace;
- Audit。
39.2 原表未提供、由外部资料扩展
原表没有具体给出:
- 问数 Agent 完整模块架构;
- Intent Taxonomy;
- Intent Confidence;
- Metric Semantic Layer;
- Schema Linking;
- NL2SQL Prompt;
- SQL AST Validator;
- Read-only Transaction;
- EXPLAIN Cost Gate;
- Execution Accuracy 指标;
- 一对多 Join 的聚合粒度校验。
这些内容属于本次外部研究后的技术扩展,不能归因于原始面经答案。
40. 来源
- 原始题目表,第 48 题(T5):问数 Agent 整体架构、意图识别、历史上下文与 NL2SQL。
- OpenAI Agents SDK — Agent Orchestration / Handoffs / Running Agents:当前文档提供结构化分类后由代码路由、Handoff,以及 Session/Conversation State 管理模式。
- LangGraph Documentation — Memory Overview:说明短期 Memory 可以包含 Conversation History 和其他 Agent State,并指出长历史可能增加成本、延迟和旧信息干扰。
- Spider 2.0: Evaluating Language Models on Real-World Enterprise Text-to-SQL Workflows:说明真实企业 Text-to-SQL 涉及大型 Schema、元数据检索、SQL 方言和复杂多步工作流。
- EntSQL: A Benchmark for Grounding Text-to-SQL in Long-Context Enterprise Knowledge, 2026:说明企业 NL2SQL 经常依赖私有业务指标、报表规则和企业内部知识。
- OWASP SQL Injection Prevention Cheat Sheet:强调数据库账号最小权限,并可使用 View 等机制限制数据访问范围。
- PostgreSQL Documentation — SET TRANSACTION / Read-only Transaction:说明 Read-only Transaction 会禁止多种数据修改和 DDL 操作。
- PostgreSQL Documentation — EXPLAIN:说明可在执行前查看 Query Plan 与估计执行 Cost。

1405

被折叠的 条评论
为什么被折叠?



