PROD欧洲主权BaaS平台打开仪表板 →

原生人工智能 · 8 最小读取值

教程:在 Postgres 上构建 NL2SQL 端点

Affane Daylami · Fondateur · 2026年8月28日

返回博客

本教程展示了如何接收法语问题,将其转换为经过验证且有界的 SQL 查询,然后返回结果 - 无需执行未经检查的 SQL。每一步都会显示实际生成的 SQL,而不仅仅是最终结果。

该英文文本是根据法文原文自动生成的,尚未经过审查。
该页面已自动翻译。英文版具有权威性。

Aurabase 的 NL2SQL 引擎是原生 AI 的一部分,集成到 后端中:不是放在一起的第三方服务。遵循本指南的先决条件:现有的 Aurabase 项目、示例的简单数据库架构以及项目 API 密钥。

#
目的

你将构建什么

接收自然语言问题、将其转换为经过验证且有界的 SQL 查询,然后返回结果的端点。引擎绝不会在没有控制的情况下执行生成的 SQL:每个查询在到达数据库之前都会经过语法验证。

信息

本教程使用 @aurabase/aurabase-js JavaScript SDK 和等效的原始 HTTP 调用,因此您可以使用任何语言进行操作。

#
在引擎盖下

NL2SQL 引擎如何工作

该问题通过已配置的 LLM——OpenAI、Anthropic (Claude) 或 Gemini,这三个本地提供商——生成候选 SQL。此 SQL 永远不会按原样执行:它通过解析其语法树 (sqlparser) 的验证器,仅允许简单的 SELECT 查询,并在缺少时添加有界 LIMIT 。

验证器显式拒绝 CTE/WITH、子查询、UNION、锁定子句 (FOR UPDATE) 以及白名单之外的任何函数 (count、 sum、 avg、 min、 max、 lower、 upper、 coalesce、 date_trunc、 now)。支持多表连接。

问题→LLM(OpenAI/Claude/Gemini)→AST验证(sqlparser)→有界LIMIT→SELECT执行

您的请求永远不会提供查询的图表:它是从项目的真实基础进行内省的。在请求正文中发送的 schema、 allowed_schema 或 schema_context 字段会被显式拒绝(400 错误),而不是默默地忽略 - 服务器单独决定实际存在的内容。

#
步骤1

配置 NL2SQL 端点

通过 JavaScript SDK,Aurabase 客户端公开 aura.ai.nl2sql()。签名是 nl2sql(question, options):模式不是它的一部分,它在服务器端进行内省。

app/api/ask/route.tstypescript
import { aura } from '@/lib/aurabase'

export async function POST(req: Request) {
  const { question } = await req.json()

  const { data, error } = await aura.ai.nl2sql(
    question,
    { limit: 50 }
  )

  if (error) return Response.json({ error }, { status: 400 })
  return Response.json(data)
}

在原始 HTTP 中,端点是 POST /v1/ai/{project_id}/nl2sql,由项目 API 密钥进行身份验证。

terminalbash
curl -X POST https://<votre-gateway>/v1/ai/<project_id>/nl2sql \
  -H "apikey: <votre-cle-api>" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "Combien de commandes ont été passées ce mois-ci par des clients premium ?",
    "limit": 50
  }'
服务器拒绝的字段

不要在请求正文中发送 schema、 allowed_schema、 schema_context :查询的模式由服务器确定,这些字段将被显式拒绝(400)而不是默默地覆盖。

#
步骤2

用法语进行真实问题测试

发送的问题是:“本月高级客户下了多少订单?”。以下是实际呈现的 SQL 形式(表名和列取决于您的架构):

回应(摘录)json
{
  "data": {
    "sql": "SELECT count(*) FROM orders WHERE customer_plan = 'premium' AND created_at >= date_trunc('month', now()) LIMIT 50",
    "explanation": "Compte les commandes de ce mois pour les clients premium.",
    "confidence": 0.85,
    "tables": ["orders"],
    "columns": ["customer_plan", "created_at"],
    "limit": 50,
    "limit_injected": false
  },
  "meta": null
}

limit_injected 指示 LIMIT 是来自模板还是由服务器添加。 confidence 是对响应形式(是否格式良好的 SQL 块)的启发式方法,而不是对生成的 SQL 语义正确性的衡量标准。措辞不当的问题会返回显式错误,而不是幻觉的 SQL:例如,如果生成的 SQL 查询不在您的模式中的表,则消息会命名实际可用的表。

#
步骤3

安全生产

部署前进行三项检查:行上限 (LIMIT) 是否适合您的卷,引擎使用的 Postgres 角色是否仍受限于项目架构,以及敏感表是否具有活动的 RLS 策略 - NL2SQL 与应用程序的其余部分查询相同的数据库,默认情况下没有扩展访问权限。

  • 默认线路上限可在服务器端配置;高于服务器上限的请求值会被明确拒绝,而不是默默减少。
  • 无论您的 RLS 策略如何,验证器都会阻止对系统目录(pg_catalog、 information_schema)和非项目架构的访问。
  • RLS 仍然是敏感表的最后一道防线:验证器限制 SQL 的形式,而不是数据的业务权限。
#
诚实

需要注意的当前限制

引擎是严格可读的:仅接受 SELECT 请求。模板生成的INSERT、 UPDATE、 DELETE、 DROP、 CREATE 或 ALTER 的任何尝试在执行前都会被拒绝 - 这不是提示约定,而是在语法树级别强加的规则。

其他结构限制:没有子查询、没有 CTE/WITH、没有 UNION 以及十个 SQL 函数的封闭白名单。自然需要子查询(“从未订购过的客户”)的问题必须重新表述以适合简单的 SELECT,或者在应用程序端进行不同的处理。

#
走得更远

RAG 和代理

NL2SQL 涵盖有关关系数据的结构化问题。对于有关非结构化内容(文档、注释、票据)的问题,Aurabase 的原生 RAG 依赖于 pgvector 和 HNSW 搜索。这两种功能以及如何将它们组合在代理中的详细信息请参见 Postgres 上的 Native AI 页面。

#
常见问题解答

常见问题解答

NL2SQL 是否可以使用复杂的模式(多个联接)?+
验证器支持多表连接。另一方面,子查询和 CTE/WITH 被明确拒绝:自然需要子查询的问题必须重新表述以适合带有连接的简单 SELECT,或者在应用程序端进行处理。
为 NL2SQL 选择哪个 LLM 提供商?+
验证器对三个本地提供程序(OpenAI、Anthropic/Claude、Gemini)一视同仁:在生成的 SQL 验证方面,没有一个提供程序具有结构优势。成本和延迟取决于为您的项目配置的特定模型 - 根据您自己的数量进行比较,而不是遵循通用建议。

准备好部署了吗?

五分钟内完成您的后端。

无需信用卡 · 500 MB 免费 · 50,000 MAU