Text-to-SQL 在 Agent 中如何应用?存在哪些风险和限制?
未标记
考查重点:自然语言查询与执行风险。Agent先读授权schema生成SQL,执行前解析、权限与成本检查,再解释真实结果;只读账号和超时硬限制,不能直接执行模型任意SQL
本题目录
参考答案
核心回答
Text-to-SQL 可以作为 Agent 的结构化数据查询能力:把用户问题映射为业务指标与表字段,生成候选 SQL,在受限执行环境里查询,再依据实际结果解释答案。它适合查订单、库存或经营指标;开放式知识解释可以结合文档检索,不能用模型记忆代替当前数据库结果。
推荐链路是:识别查询意图与歧义 → 检索授权的结构和业务规则 → 生成 SQL → 独立校验权限、语法和成本 → 执行 → 核对并解释结果。 Agent 负责组织步骤,后端查询网关负责是否允许执行。
主要风险与限制
SQL 能运行,业务也可能算错。 把支付时间当下单时间、把含税金额当净收入、一对多连接重复求和,数据库都可能正常执行。生成前要明确指标公式、粒度、单位、时间边界和连接关系;口径没有唯一答案时先澄清。
只读也可能泄露或拖垮系统。 SELECT 能读取敏感信息,宽范围扫描和复杂连接也会消耗大量资源。身份来自后端,表列和行级范围由独立策略落实,再配合专用账号、操作允许列表、超时、并发和结果上限。提示词、工具描述及模型自检不能替代这些约束。
数据库和元数据会变化。 表字段重命名、指标规则更新、字段取值漂移,都可能让旧示例失效。检索内容要带来源与版本,执行前对照当前结构检查。外部文档或库中备注里的指令也应视为不可信输入,不能据此扩大工具权限。
如何控制错误传播
失败时按原因处理:缺口径就澄清,未知字段就刷新元数据,语法错误可以带受控错误信息重新生成;不能把任何失败都交给模型无限重试,更不能把敏感数据库错误原样回传。修正后的 SQL 重新走完整校验,并限制循环次数。
结果解释保留统计时间、单位、筛选条件和数据来源;空结果只代表当前条件下没有匹配记录,不自动等于业务值为零。准确率、越权阻断和查询耗时应分别评估,不能用“工具调用成功”代表整个问数任务成功。
SQLBotPython
核心回答
SQLBot 把自然语言问数拆成相关表选择、结构与业务知识组装、SQL 生成、执行和结果展示。表备注、人工表关系、术语与 SQL 示例帮助模型理解该查什么、怎样关联;生成后仍需由程序检查实际 SQL,并依据数据库返回的数据回答。
这里要区分三件事:模型按格式返回了 SQL、SQL 通过现有执行检查、查询结果符合业务口径。前两项成立,也不能证明日期条件、连接粒度和统计公式都正确。
生成结果怎样进入执行?
check_sql() 从模型返回中提取 JSON,读取 success、sql 等字段,并检查 SQL 非空。它负责响应格式和生成结果解析,不是完整的语法、安全或成本审核。
随后程序用 sqlglot 从 SQL 本身提取真实表名,与本次允许的 table_name_list 比较,不直接信任模型附带的 tables 字段。没有成功提取表或出现白名单外表时拒绝继续。这个检查使用裸表名,不能据此推导已经完成任意数据库、Schema、列和行级权限校验。响应解析、真实表提取与白名单。
exec_sql() 执行前还会调用 check_sql_read()。该函数检查允许的首关键字、危险模式、解析出的语句类型和危险函数;默认允许 SELECT/WITH,元数据命令另受配置控制。它形成了一层读取操作检查,但现有写类型判断主要针对每条语句的顶层节点,不能直接称为已经证明所有嵌套表达式都安全的完整 AST 沙箱。执行前检查、读取操作检查。
查询失败后会自动反复修正吗?
这条对话链路没有同一轮自动重试循环。数据库执行异常会被包装、保存并作为错误返回,本轮随后结束;下一轮初始化时,程序查询同一会话的最新记录,如果它属于 exec-sql-err,才把错误放入 <error-msg> 供模型参考。连接失败、格式错误等情况不能统一当成这条执行错误反馈。错误保存与结束、下一轮错误上下文。
若要增加自动纠错,应限制次数,区分可纠正的语法、结构错误与权限拒绝,并让修正后的 SQL 重新通过执行检查。这是进一步完善方案,不能写成该版本已经具备的行为。
实际落地还要验证什么?
首先核对业务结果。例如一对多连接可能让库存数量重复累加,SQL 却能顺利执行;要用明确的样例数据和参考查询检查粒度、时间及过滤条件。术语和示例是生成依据,不是正确性证明。
其次按数据源核对运行限制。不同连接器的连接、驱动和执行超时配置并不相同,不能统一称为查询的硬截止时间;提示词中的结果行数要求也不等于所有分支都有后端强制上限。生产接入还应配置适当的数据库账号与权限、结果上限和查询资源约束,再验证越权、慢查询与错误反馈。这里的源码审查不替代这些部署测试。
对应教程
- 《电商问数:SQL生成与执行闭环》:阅读生成、数据库解析校验、校正与执行的分工;本文补充权限、成本和业务结果校验。
参考资料
- 国内:飞致云:智能问数常见问题:采用表描述、关联和上下文配置影响问数质量的经验,说明结构上下文的重要性。
- 国内:飞致云:术语配置:采用业务术语与同义词管理,解释语法正确之外的口径风险。
- 国内:阿里云:DMS权限:采用查询、导出及细粒度数据权限的区分,说明只读仍有泄露风险。
- 国内:阿里云:数据库开发SQL审核:参考独立
SQL审核与优化规则,组织执行前检查。 - 国外:OWASP:AI Agent Security Cheat Sheet:采用不可信输入、最小权限和执行层授权原则,限定Agent可做的操作。
- 国外:Oracle/MySQL:EXPLAIN Statement (MySQL 8.4):核对计划检查与真实执行的差异,说明资源限制不能仅依赖生成阶段。
WrenAIPython / Rust
核心回答
WrenAI 可以作为现有 Agent 的语义查询层:Agent 根据问题和业务上下文,编写引用 MDL 模型的 SQL;Python SDK 负责策略检查、规划与连接器执行,Rust 引擎负责展开模型、计算字段及关联语义。模型中维护的指标与关系可以复用,Agent 不必每次从物理表重新猜测口径。
这条链路要区分三种正确性:查询符合执行策略、模型定义展开正确、最终统计符合业务要求。 只读检查和模型对象限制主要约束前一项;语义模型帮助稳定计算定义,但不能证明模型定义本身、Agent 选择的日期条件或聚合粒度一定正确。
Agent 怎样把问题交给语义层
当前代码提供 SDK、CLI 及 Agent 工具集成。以 LangChain 集成为例,WrenToolkit 暴露列出模型、规划和查询等工具;启用项目记忆后,还能读取相关结构与业务上下文、召回已确认的查询示例。Agent 据此写引用模型名称和字段的 SQL,交给 wren_query,而不是把自然语言直接交给 WrenEngine 自动完成全部推理。工具集成。
例如问“本月订阅实收净额”,应先确定订阅付款、退款及其时间归属,再选相应模型和指标。业务说明提供理解依据,MDL 中可执行的表达式承接已建模的计算;仅在说明文件里写一句口径,不等于查询引擎已经强制实现了该口径。
只读与严格模式分别限制什么
WrenEngine._plan() 用目标数据库方言解析输入,调用 validate_sql_policy()。其中只读检查始终执行:除检查查询根节点外,还遍历整棵语法树,拒绝写入、建表、修改会话状态、SELECT INTO、写意图锁等节点,因此不会只看开头是不是 SELECT。规划入口、只读检查。
strict_mode 默认是 False。开启后,额外检查表引用是否对应 MDL 中的模型或视图,并检查已知的数据读取型函数,防止通过文件、外部数据库等入口绕过模型范围;denied_functions 则是另行配置的函数禁用集合。这些策略不能等同于任意函数和方言都安全的沙箱,模型对象检查也不能替代按用户配置的行列权限和数据库授权。默认配置、严格模式与函数检查。
模型怎样展开成数据库查询
策略检查后,程序解析查询引用的模型或视图,抽取所需的 MDL;抽取还会保留关联模型、视图依赖及相关规则依赖。CTERewriter 识别实际使用的模型和列,调用经 PyO3 暴露的 Rust 语义引擎展开模型定义,将结果作为 CTE 注入查询,再输出目标数据库方言。模型抽取、CTE 重写、逐模型展开。
策略错误会直接抛出,不会靠回退绕过。模型抽取遇到普通异常时,仅在未开启严格模式且没有函数禁用配置的情况下,才允许改用完整模型继续规划。改写后还会调用 validate_planned_sql() 检查展开内容中的写操作;但该函数遇到输出重解析失败会直接返回,不能把它描述为所有方言下都严格拒绝不确定输出的完整安全证明。抽取回退与输出检查、输出重解析边界。
dry_plan() 返回展开后的查询,不访问数据库;dry_run() 再调用连接器做数据库侧检查;query() 才执行并返回 PyArrow 表。例如当前 MySQL 连接器的 dry_run() 使用普通 EXPLAIN,它不会验证业务统计值是否正确,也不等同于真正运行查询测量耗时。三个入口、MySQL 检查方式。
通过规划后为什么仍可能算错
模型展开不会自动纠正 Agent 在外层查询中写错的连接条件、过滤条件或聚合。假设一笔订阅付款有两笔退款,直接连接后累加付款金额,可能重复计算实收;即使引用的模型都合法、查询成功执行,订阅实收净额仍然错误。
业务集成应明确订阅付款与退款粒度、日期归属和空值处理,必要时先按各自粒度聚合,再按确定的键组合。用一对多退款、无退款、跨月退款等样本与参考查询比较,检查最终数值;语义模型变更后也复查这些样本。这是验证设计,不是已经取得的效果数据。
生产执行还要依据真实用户配置访问范围,限制查询时间、并发及返回结果。只读查询仍可能读取敏感数据或进行昂贵扫描;dry_plan() 成功、模型名称合法、数据库能够解析,都不能替代这些运行约束与业务验收。
