问数 Agent 整体架构、意图识别、历史上下文与 NL2SQL

第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 BusinessCorrectSQLCorrectAuthorizedResultCorrect

只生成语法合法的 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 WrongAssumptionWrongSQL

的风险。

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 1001020=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 20030=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

这类指标至少需要覆盖三种回归样例:

场景订单金额退款记录期望净收入
未退款100100
部分退款1001090
多次退款10010 + 2070

因此,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 Nrepair2

防止进入:

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. 来源

  1. 原始题目表,第 48 题(T5):问数 Agent 整体架构、意图识别、历史上下文与 NL2SQL。
  2. OpenAI Agents SDK — Agent Orchestration / Handoffs / Running Agents:当前文档提供结构化分类后由代码路由、Handoff,以及 Session/Conversation State 管理模式。
  3. LangGraph Documentation — Memory Overview:说明短期 Memory 可以包含 Conversation History 和其他 Agent State,并指出长历史可能增加成本、延迟和旧信息干扰。
  4. Spider 2.0: Evaluating Language Models on Real-World Enterprise Text-to-SQL Workflows:说明真实企业 Text-to-SQL 涉及大型 Schema、元数据检索、SQL 方言和复杂多步工作流。
  5. EntSQL: A Benchmark for Grounding Text-to-SQL in Long-Context Enterprise Knowledge, 2026:说明企业 NL2SQL 经常依赖私有业务指标、报表规则和企业内部知识。
  6. OWASP SQL Injection Prevention Cheat Sheet:强调数据库账号最小权限,并可使用 View 等机制限制数据访问范围。
  7. PostgreSQL Documentation — SET TRANSACTION / Read-only Transaction:说明 Read-only Transaction 会禁止多种数据修改和 DDL 操作。
  8. PostgreSQL Documentation — EXPLAIN:说明可在执行前查看 Query Plan 与估计执行 Cost。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小白羊丨

开始面试题与解析

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值